A simple NTP client for ESP8266

Once you have a real time clock working on the ESP8266, you might actually want to set it. As they have a backup battery you may just set it before you connect it to the ESP8266 and forget about it, but that’s not ideal. These cheap RTCs probably aren’t perfectly accurate and if it stops for any reason (e.g. dead backup battery) you’ll need to reset it. The DS3231 has a flag to indicate it’s been stopped – ideally this should be checked on startup and the clock set via NTP if there has been any interruption.

I did find one other simple NTP implementation but it’s incomplete, there is no timeout and it doesn’t clean up the connection when it’s finished (so it’ll leak memory). I think my version should work a little better, but I can’t guarantee it’s bug free so please let me know if you find any. As well as getting the time, the code is a nice simple example of a UDP client.

To use simply call ntp_get_time( ). The NTP request is asynchronous so you get the time in the ntp_udp_recv callback function, have a look there for two simple examples of what you could do with your newly received NTP time (print it out or set an RTC).

Code now on GitHub: https://github.com/raburton/esp8266

AT24c32 for the ESP8266 (C code)

The AT24C32 (24c32) is a small eeprom that comes on popular, dirt cheap, RTC boards (but of course is also available separately). Using the datasheet it’s easy enough to get working on the ESP8266. All the AT24C series chips work the same, except for an extra address bit in the 1Mb version, so the example code below can be used with any model (see the note in the header file about the 1Mb chip).

The chip basically has two operations:

  • Read from current position.
  • Write to specified position.

Technically there is no read from specified position. To do this you must make a dummy write, as the datasheet refers to it. This basically means starting a write operation, which begins by setting the address, then not sending any actual data (or an I2C stop). Instead you perform an I2C start again and perform a read as normal.

When reading you can read as much data as you like. When writing you can only write up to 32 bytes at a time. A write operation is restricted to a single 32 byte page (or part of one). You do not need to start at the beginning of the page. Regardless of where you start in a page, if you continue to write after reaching the end of the page you will wrap back to the start of it and continue writing there. This means you need to keep track of how much you are writing and where the next page boundary is.

The example driver code attached, written for the C API of the official Espressif SDK, handles all the issues above. You can write as much as you like, wherever you like – it will perform multiple write operations across pages as you’d expect. You can can also read from specified locations and the driver will perform the dummy write for you to set the starting address. You can still read from the current position and write inside a looping page if you like. You should be able to drop this code straight into your ESP8266 project, set the I2C address in the header file (according to your address pins) and start reading and writing to your eeprom with ease.

Code now on GitHub: https://github.com/raburton/esp8266

Feeding the watchdog on ESP8266

I wanted to do some waiting in a tight loop on the ESP8266, but that can lead to a watchdog timeout and a reset. I figured there must be a way to stop that but there isn’t anything in the documentation. Grepping the libs I found a couple of candidates and, after trying them all out, I found exactly what I was looking for – slop_wdt_feed. Declare the following in your header:

extern void slop_wdt_feed();

Now just call it in any long running loops or functions and it’ll keep the  dog off your back. Note this isn’t necessarily good practice!

At time of writing google returns exactly one result for this function name (just a listing of functions in the library) so I don’t think this is currently widely know.

Update: As of SDK v1.1.1 (possibly a little earlier) this no longer works. You can now use these (from Pete Scargill’s blog):

extern void pp_soft_wdt_stop();
extern void pp_soft_wdt_restart();

Mutex for ESP8266

I don’t know what can interrupt user code on the ESP8266 or what might do the interrupting, the documentation is lacking in that area, but something seems to be causing me a timing condition. With a really low time out on an NTP call I seemed to end up in the receive and the timeout code at the same time. The timeout kills the connection and the receive disarms the timeout, so in theory only one should ever be run, but what happens if the timeout occurs between the receive code being called and it actually disarming the timeout? Will the timeout interrupt the receive, kill the connection and then allow the receive code to continue? That is what it looked like, so I did the obvious thing and searched the API for some kind of mutex. No joy, but the whole API isn’t documented so I grepped the SDK libraries for any function name that might be relevant, still no joy. I’ve come to the conclusion the SDK does not provide any such functionality, so I had to get my hands dirty with some assembler…

Armed with a copy of the Tensilica Xtensa Instruction Set Architecture reference manual I tested out the S32C1I operation. The GCC compiler doesn’t know this instruction or the special register it uses (SCOMPARE1), so I wrote something similar and patched the right opcodes into the assembled object file. Unfortunately trying to write to this register reset the device, so it looks like the ESP8266 does not support the ‘Conditional Store Option’, darn.

So, I’m not sure how I ended up at it but I found some Linux kernel code with what appears to offer the solution and forms the basis of my esp8266 mutex code. The code is easy enough to use – declare a mutex_t, call CreateMutux against it, then GetMutex and ReleaseMutex as required.

Code now on GitHub: https://github.com/raburton/esp8266

Simple timezone support for the ESP8266

I suggest you run your RTC on GMT (aka UTC, if you’re French). If you’re just using it for data logging or the like you can probably run entirely in GMT. If you want to display it to a user you probably want to do that in localtime. The ESP8266 C API doesn’t have support for timezones, so you’ll need to add your own. Adding or subtracting a few hours is easy enough, but applying daylight savings time (DST) during the summer is a little more tricky. A quick google search found a few examples but they all assumed the adjustment happened at midnight, so I’ve created an extended version that changes at 2am, as happen here in the UK. This is an example and will need to be modified if you’re not in the UK. Ideally the function would parse a string with timezone specific definitions rather than having hard coded rules, if you want to do this hopefully this code will serve as a starting point.

Code now on GitHub: https://github.com/raburton/esp8266

Real time clock (DS1307/DS3231) for the ESP8266

Cheap DS1307 "TinyRTC" board

Continuing the time theme, I’ve recently been playing with the ESP8266 wifi soc and the common real time clocks (RTCs) DS1307 and DS3231. It seems to be popular to program these devices with LUA using NodeMCU firmware, but I can’t work out why. LUA seems to be pretty awful, but I guess if you’re new to programming it’s an easy way to get started and you aren’t likely to notice how odd LUA is. Real men use C (or assembler, if they’re showing off).

(TL;DR – skip to the bottom of the post for the attached C code.)

So you can program for them in C, using the SDK supplied by the manufacturer (which is what NodeMCU itself is built with). Actually they supply two SDKs: The first is the one they are actively pushing for development and offer bug bounties for. The second one (FreeRTOS based) seems to use more standard APIs and appears to have a few more features, but it’s future isn’t clear. It’s a bit confusing, but I’ve decided to stick to the first SDK.

So, back to the RTCs… These are easily obtained from China for about 53p from AliExpress, shipped to the UK! Amazing when you consider you can’t even send a letter inside the UK for that price. You basically have a choice of two boards, one based on the DS1307 (pictured above) and one with the DS3231 (below). The DS1307 has less features than the DS3231 and the boards, generally labelled as TinyRTC, seems to be pretty flaky – my advice would be to avoid them. Lots of people find they don’t work without modification. Mine works (after mods), but only with power applied, it doesn’t maintain it’s timekeeping on battery.

Cheap DS3231 board

The DS3231 is more accurate, has more features and the boards seems to work fine. As they’re the same price I’d go for these every time. Note that both boards are designed to be used with a rechargeable lithium cell battery, and if you put in a normal CR3032 it will try to charge them and they might explode! On the DS3231 board you can simply remove the diode to disable the trickle charge circuit. Also of note, both boards come with an AT24C32 i2c eeprom on board, which might be handy for something.

So why do you need a RTC? The device has wifi so why not just get the time from an NTP server? Well you might not want wifi enabled all the time, especially if you intend to run the ESP8266 from battery. Getting the time from the RTC is quicker than NTP,  and easier to do synchronously. You can also do other neat things, like use the alarm on the DS3231 (not available on the DS1307) to wake the ESP8266 from sleep, it could then connect to the network check in with a server to send data/ receive instructions, then go back to sleep again. The DS3231 can even tell you the temperature.

I found a few simple examples of using these RTCs for LUA, but nothing much for the C API, so I’ve written drivers for both. I think they are pretty comprehensive in their support for the features of the chips and the code is thoroughly commented so you should be able to work out how to use/ modify it easily.

Code now on GitHub: https://github.com/raburton/esp8266

 

The slightly different striking control

Strike control mechanism - lifting projection

We assumed the striking and chiming control mechanisms were the same, however we found a subtle but important difference. At first we were unable to get the mechanism to run correctly. It just didn’t work from any obvious starting point of the two pin pinion.

The significance of the two pin pinion is that the ratchet wheel does not move in a continuous manner but rather in steps (two per revolution of the arbour). The equivalent wheel on the chiming train moves continuously.

This is important because the ratchet wheel, which contains the lifting pin, must move at the start of the striking process (to allow the horizontal arm to drop) and at the end (to lift the arm back up). For the striking train it moves one step per hour being struck. Considering the striking of one o’clock, where the ratchet wheel only moves one tooth, it is clear that there must be movement of half a tooth at the start and half a tooth at the end of striking. That means the rest position of the ratchet wheel must be mid-movement, so the spring pawl cannot sit in a fully engaged position at rest, it needs to sit half way between teeth. This doesn’t seem like a natural resting position, but it does work. When at rest one of the pins is engaged with the ratchet wheel and when the pin comes out of mesh the pawl is engaged. The result is that either a pin or the pawl is always engaged with the ratchet wheel to prevent it moving inappropriately.

The fly arbour rotates five times per tooth of the ratchet wheel / strike of the bell.

To strike one o’clock:

  • The first rotation of the fly arbour moves the ratchet wheel half a tooth, the two pin pinion disengages from the ratchet wheel and the spring pawl engages. This movement is enough for the horizontal arm to drop off the lifting pin on the ratchet wheel.
  • The fly arbour then rotates freely for four turns, the two pin pinion remains out of mesh with the ratchet wheel.
  • In the final half rotation the second pin in the pinion engages with the ratchet wheel and moves it half a turn. This causes the lifting pin to raise the horizontal arm and stop the striking mechanism.
  • The rest of the mechanism works just like the chiming mechanism.

The lifting projection has to be very slim so it isn’t able to accommodate much of a ramp – the pictured projection doesn’t look like it would work but it does, in fact it works very well. Note the pictures showing the resting positions of the ratchet wheel, pawl and two pin pinion. There is also a picture showing how the positions of the blocks were prototyped in wood (attached with double sided tape).

Completed chime control mechanism

Finished chime control mechanism

The control mechanism for the chiming train is now complete (all but for pinning the rotating arm to the fly arbour). Read the previous two posts on this mechanism for background.

I’ll repeat the explanation (improved and modified slightly) from the earlier post of how the process works, with pictures of the finished product.

Starting position before chiming

Chime control mechanism - raised on stopping pin

The horizontal arm is held just above the rest pin. It is held there by the downward projection from the arm which has been lifted onto one of the four pins around the large wheel attached to the barrel.

Chime control mechanism - locked position

The rotating arm on the fly arbour is always trying to rotate clockwise but is obstructed because the square block projecting from it is locked against the square block projecting from the catch plate. Note the horizontal arm is above the rest pin.

Chiming process

Chime control mechanism - first stage of unlocking

The horizontal arm is lifted (note the increased gap between the rest pin and the arm) briefly by the going train, on each quarter hour. This unlocks the rotating arm, attached to the fly arbour so its projecting block can pass below the block on the catch plate.

Chime control mechanism - temporary locking stage

The projecting block of the rotating arm now briefly locks against the upright (angled) block on the catch plate, awaiting its final release.

Chime control mechanism - final release

The lifting mechanism from the going train disengages, causing the horizontal arm to drop back to it’s starting position (still above the rest pin). This unlocks the rotating arm again and allows the projecting block on the arm to pass over the upright block.

Chime control mechanism - starting to rotate

The fly arbour begins to rotate, which means the rest of the striking train moves too.

Chime control mechanism - off the lifting pin

About half way through the first rotation of the fly arbour the large wheel on the barrel has rotated far enough that the downward projection from the horizontal arm drops off the pin.

Chime control mechanism - rotating freely

The horizontal arm drops down, below it’s starting point, and finally rests on the rest pin. This allows the rotating arm to rotate freely, it’s projecting block passing over the horizontal block on the catch plate.

Chime control mechanism - raised on stopping pin

When the chime barrel reaches the end of the tune, the next pin on the wheel reaches the point where it raises the horizontal arm.

Chime control mechanism - locked position

The block on the rotating arm now collides with the horizontal block on the catch plate causing the arbour, and rest of the train, to stop abruptly (except the fly, which is able to come to  rest gradually thanks to its ratchet drive).

Completed fly arbour pinions

Completed fly arbour lantern  pinion, angled view

The completion of the flies meant the lantern pinions could be attached to the fly arbours. They are now pinned though the centre section, just like the originals, and the pins have been machined perfectly smooth with the pinion body.

The pins have been cut to length and hardened. Then the brass end cap was attached – a simple tight push fit. The end cap has then been machined to a perfect match with the body and a little bevel put on, which helps to mask any visible line at the join.

Compare the pictures of the two new pinions with one of the originals when I originally discussed their construction. Note the bronze dot just visible between the trundles where it is pinned to the arbour.

 

Completed maintaining power

Maintaining power pawl, riding over teeth of great wheel.

The maintaining power is now completely finished. The lever has a weight. The pawl to advance the great wheel has been made and attached (welded to the arbour). There is even a stop to prevent the lever being lifted too high and to prevent it dropping below the level of the winding peg.

From the fully charged position (lever all the way up) there is approximately four minutes to wind the going train. It actually takes about six minutes to return to resting position but because it passes in front of the winding peg it would rest on the winding handle if it were still attached beyond four minutes. Passing in front of the winding peg is deliberate, it means you have to charge it before you are able to wind the going train. You don’t want a turret clock slowing down on you else you employees might be late for work!

As we currently have no weights to wind up we have no idea how long winding will take. Luckily if it takes more than the time allowed the maintaining power can be recharged mid-wind as many times as needed.

The pictures show the pawl in three positions, from fully charged to resting gently on the teeth of the great wheel as it rotates beneath it (which it always does when not charged).