Lately I have had the need for a device to do some simple logging. After some brianstorming I made this list of features:

  • Battery operated.
  • Self contained.
  • Log data readable wirelesly.

I came to the conclusion that the events I wanted to log, were on/off type events, like logging whenever my doorbell is rung. Using an ESP8266 module (ESP12), to log the events to the flash memory on the module, seemed feasible even using battery power, since the module only needed power when an event triggered it. To keep track of the time, when the ESP8266 was off, a real-time clock was needed.

  • Use the ESP8266 as microcontroller, log storage and wireless interface.
  • Use a DS3231 RTC module to keep the time.
  • Leave the RTC running at all times.
  • Power the ESP8266 only when an event needs to be logged.

The ESP8266 firmware performs the following tasks. GitHub

  • Write a log entry whenever power is applied. The log entry is written to a ring buffer, ensuring that the data will not overflow. If the flash memory is full, the firmware starts overwriting the oldest entries.
  • Try connecting to a predefined access point. When logging at some remote connection, simply create the access point using the phones WIFI hotspot feature.
    • Update the ESP8266 clock and the RTC from an NTP server.
    • Create a WebSocket server. This serves the log to the phone, and enabled configuration of the predefined access point.
    • Delete the logs from flash memory.

The client is Android specific, I have no I-devices (except an Ipod), and Microsoft, well ya'know... GitHub

  • Download the log from the WakeLog device.
  • Export the log (Google spreadsheet?).
  • Configure the access point used by the WakeLog hardware.

Since I began programming the ESP8266, I have been struggling to get the TCP network API of the SDK working consistently without crashes. I think that I have cracked it at last. Here are some notes, so that I may never forget, and maybe help someone else.

ESP8266 TCP server.

This post is about using the ESP8266 as TCP server, but the information is useful if you want to know how to tackle ESP8266 networking in general. First lets set up a server like the SDK tells us to do it:

  • Initialise struct espconn parameters according the protocol type you want (ESPCONN_TCP).
  • Register connect callback and reconnect callback functions.
  • Call espconn_accept to start listening for packets.
  • When a connection has been made on the listening connection, the registered connect callback is called.

Some code to do this:

bool ICACHE_FLASH_ATTR tcp_listen(unsigned int port)
    int ret;
    struct espconn *conn;

    //Get some memory for the connection information.
    conn = os_zalloc(sizeof(struct espconn));
    if (conn)
        //Set up TCP connection configuration.
        //TCP connection.
        conn->type = ESPCONN_TCP;
        //No state.
        conn->state = ESPCONN_NONE;
        //Set port.
        conn->proto.tcp->local_port = port;

        //Register SDK callbacks.
        espconn_regist_connectcb(conn, tcp_connect_cb);
        espconn_regist_reconcb(conn, tcp_reconnect_cb);
        espconn_regist_disconcb(conn, tcp_disconnect_cb);

        ret = espconn_accept(conn);
        if (ret != ESPCONN_OK)
            os_printf("Error when starting the listener: %d.\n", ret);
    os_printf("Could not allocate memory for the listening connection.\n");


The SDK network API is event based. The way this works is that you register some functions for the API to call when certain events happen (connected, disconnected, data received, and so on). Your callback function receives a parameter called arg, from the SDK, which is a pointer to an espconn struct (defined in espconn.h in the SDK). This struct contains the connection information. You will probably need a way to identify a connection as it triggers the callbacks. I have additional data from my own application coupled to the connection, that I need to handle when an event happens to the connection. In fact I have a list of all open connections using my own data structures. When I first started using the ESP8266 I ignored the part of the Programming Guide, that told me to not use the arg pointer from the callbacks, to distinguish one connection from another. The following is an example of a struct I was using at the time to keep track of connections.

struct tcp_connection
    //Pointer to the struct espconn structure associated with the
    struct espconn *conn;
    //Pointer to the data meant for the current callback.
    struct tcp_callback_data callback_data;
    //Is the connection sending data.
    bool sending;
    //Are the connection closing.
    bool closing;
    //A pointer for the user, never touched.
    void *user;
    //Pointers for the prev and next entry in the list.
    struct tcp_connection *prev;
    struct tcp_connection *next;

When ever the program entered a callback, the code would compare the arg pointer to the one stored in the conn member of tcp_connection, and couple my private data to the connection that way. This works most of the time, but fails in couple if cases.

  1. The SDK tells us not to do this, which in my book tells me, that sometime later the SDK may change internally enough, that this could stop working.
  2. The reconnect and disconnect callbacks gets an arg parameter passed, that point to the listening connection, not the one that the event happened too.

There are ways around the second problem that works quite well, but why bother when the whole thing may break with some later version of the SDK, and there is a nicer option outlined in the Programming Guide?

The solution from the Programming Guide is to use the remote address and port to identify each connection. This took a little more code, but when done, revealed a few things about the flow of the connections in the API.

Connection flow in the ESP8266 API.

Let us look at some excerpts of debug log files from my HTTP server:

Listening connection.

Just after the espconn_accept call the situation looks like this:

Connection 0x3fff3158 (0x3fff3480) state "ESPCONN_LISTEN".
 Remote address
 SDK remote address
1 connection.

This is the listening connection. This connection is the one that the remote computer connects to, and has to remain open as long as the server is expected to serve connections. 0x3fff3480 is a pointer to the struct espconn data for the connection. 0x3fff3158 is the connection data, that I am keeping. The struct looks somewhat like this:

struct tcp_connection
    //SDK connection data.
    struct espconn *conn;
    //Remote IP.
    uint8 remote_ip[4];
    //Remote port.
    unsigned int remote_port;
    //Local IP.
    uint8 local_ip[4];
    //Remote port.
    unsigned int local_port;
    //Pointer to the data meant for the current callback.
    struct tcp_callback_data callback_data;
    //Pointers to callback functions for handling connection states.
    struct tcp_callback_funcs *callbacks;
    //Is the connection sending data.
    bool sending;
    //Is the connection closing.
    bool closing;
    //Pointers for the prev and next entry in the list.
    struct tcp_connection *prev;
    struct tcp_connection *next;

As will later become clear, espconn may be deallocated by the SDK. Any data that you may need to preserve to keep track of the connection should be copied somewhere else, hence the IP addresses and ports in the above struct.

New connection.

Next up someone is connecting to the server:

TCP connected (0x3fff3cb8).
Connection 0x3fff3158 (0x3fff3480) state "ESPCONN_CONNECT".
 Remote address
 SDK remote address
1 connection.

0x3fff3cb8 is the address of a new espconn struct, that the SDK has created for the incoming connection. This is where I create a new tcp_connection struct, and add it to the list of connections. The Remote address is the one saved when the connection was created, and the SDK remote address is the one currently in the espconn struct.

Data received.

A request comes in:

TCP received (0x3fff3cb8).
Connection 0x3fff3158 (0x3fff3480) state "ESPCONN_CONNECT".
 Remote address
 SDK remote address
Connection 0x3fff3d18 (0x3fff3cb8) state "ESPCONN_READ".
 Remote address
 SDK remote address
2 connections.

The callback gets a pointer to the newly created espconn struct, but still according to the docs we can not expect this behaviour.

Sending the answer.

To answer the request, find the connection that has a remote address of and use the espconn pointer (0x3fff3cb8) when calling espconn_send. After calling espconn_send you have to wait for the sent callback before sending any more data. I have not seen any mention of the data size limit of espconn_send in the official docs, but I have seen 1440 bytes mentioned elsewhere. You may have to split your data and do more than one espconn_send, wait, sent callback cycle.

This is what the situation looks like when entering the sent callback:

TCP sent (0x3fff3cb8).
Connection 0x3fff3158 (0x3fff3480) state "ESPCONN_CONNECT".
 Remote address
 SDK remote address
Connection 0x3fff3d18 (0x3fff3cb8) state "ESPCONN_CONNECT".
 Remote address
 SDK remote address
2 connections.

This is where the penny finally dropped for me. Notice the SDK remote addresses? It may be obvious, but the listening connection tracks the state of the currently sending connection. It looks like listening connection does the actual sending.

Closing the connection.

What happens when the connection is closing, or an error (reconnect) occurs, makes sense after seeing the above, but eluded me for a long time.

TCP disconnected (0x3fff3480).
Connection 0x3fff3158 (0x3fff3480) state "ESPCONN_CLOSE".
 Remote address
Connection 0x3fff3d18 (0x3fff3cb8) state "ESPCONN_CLOSE".
 Remote address
2 connections.

The SDK is a harsh mistress, and deallocates the espconn connection data before calling the disconnect/reconnect callback. That is why there is no SDK remote addresses and also why I saved the remote address in my own connection data earlier. The espconn pointer returned in the arg parameter of the callback still contain the remote address of the closing connection (and points to the listening connection). The code uses this to look up the connection and deallocate my stuff.

Calling SDK disconnect.

According to the SDK docs, rather than calling the disconnect function from a network callback function, it should be invoked through a task. My code has mostly worked without doing this, but it will give the SDK time to do some processing in between the callback and the disconnect, and I am going to try this in time.

Following up on the general notes, here I some notes on programming for the ESP8266 in C. I use Linux for development, but most of this is OS independent.


  • Prefixing a function with "ICACHE_FLASH_ATTR" places it in flash, not doing so places the function in RAM.
  • The IoT SDK is single tasked and event driven. I've always found event driven programming a pain, but this implementation stinks. There is no way to return to the system, in the middle of processing, to not stall the system tasks. The docs, says that you not may stay in a function for more than 10 ms, without the system code getting behind. If I were to start over I would try the FreeRTOS SDK, unfortunately it seems that Espressif is giving it less love.


  • Some basic code for connecting to a WIFI. GitHub
  • The connect callback returns a pointer to the struct espconn in the arg parameter. It is not the same as the one used by espconn_accept.
  • The disconnect_callbackreceives a pointer to the listening connection, not the active connected one, at least when in TCP server mode.
  • In struct espconn, member reverse, seems to be free to use., except in the disconnect callback, where it suddenly has a new value.


  • It seems the file system of choice is best placed after the code in flash.
  • On suggestion from Dave Hylands, I use a ZIP file as file system image. The file is uncompressed and used as a simple container.

The buggers have been lying around while life happened, and I was waiting for the last one I ordered, which was on a neat breakout board. Well I got tired of waiting, and started playing with the ESP12 version. These are some random notes, of things I have discovered during my experiments.

  • My ESP12's have their GPIO4 & GPIO5 pins swapped on the silkscreen.
  • The toolchain for the Arduino ESP8266 IDE seems to be 64-bit.
  • I cannot reliably program using a PL2303 adaptor, but my Raspberry Pi Model B's serial port works fine.
  • In SoftAP mode, the SDK seems to set up a DHCP server on, all without me doing anything but setting the mode, and the AP config.
  • Baud rate at boot is 74880.
  • Untested Zero-wire auto-reset. ( needs a modification to send the break signal).

When using the Enrf24 library with Enegia these are the connections for the NRF24L01 module.

NRF24L01 MSP430 Stellaris
CE P2.0 PE1
CSN P2.1 PE2
SCK P1.5 PD0
IRQ P2.2 PE3

I have some PIC18F4550s lying around, and I want to play with the USB features of this chip, therefore I made this breakout board. It contains enough components to get the PICMicro running, and nothing more, all the pins are routed to pin-headers to use with an experimenter board.


  • ICSP connector (In-Circuit Serial Programming, AKA PicKit 2 & 3)
  • USB-B Connector
  • 20Mhz clock crystal

Eagle files:  PIC18F4550 USB ICSP breakout board

Energia IDE

I never really caught on to the Arduino craze, not because of any dislikes as such, but because I was familiar with Microchips PICMICRO range. I had the parts, the programmer, and the knowledge to program them in both asm and C, so I guess I have had no need for the Arduino platform.

It turns out that the Arduino IDE has been ported to both the Stellaris Launchpad, and the MSP430 Launchpad from Texas Instruments. and is called Energia. This is nice, since it is then quite easy to port the vast amount of sketches and libraries from the Arduino IDE to Energia IDE and the Texas Instruments Launchpads.

Getting it going on Gentoo Linux

First to run Energia, 32-bit java support is needed, so


needs to be emerged. When running Energia you must make sure


is selected as user VM with eselect. Create a file called /etc/udev/rules.d/62-stellarpad.rules with these contents:

ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0660", GROUP="plugdev"

Reload udev and add yourself to the "plugdev" group, plug-in in the Launchpad and you should be good to go!

While designing a fan control into another microcontroller project, I stumpled upon this nice design using only an external diode and capacitor. I used a 1N4148 standard diode and a 560pf capacitor.

I have gathered together the schematics for the non oversampling TDA1545 DAC. Mind that I am only responsible for the shunt regulators, the microcontroller, and the input selector. The digital input circuitry was developed after reading some post from Jocko Homo on the forum. The TDA1545 circuit is mostly from the Philips data sheet. The I/V stage is from rbroer on DIYAudio.

At some point in time I have made the following block diagram, and from memory it seems correct.

From the top here is the input selector board, the micro controller for the relays are on a second board, as per the block diagram.

After the relays, comes the SPDIF buffer/amplifier circuit based on Jocko Homo's. The CS8412 converts the SPDIF signal into the correct I2S format, I2S data goes both to the DAC board, and the micro controller board. The micro controller signal is buffered by one of the 7404 inverters, in the hopes that any noise from the micro controller, will be isolated.

The shunt regulators, are duplicates of the similar valued ones in the shunt regulator schematic, you do not need to build these twice!

Here is the DAC circuit.

Everything is in the puzzling Philips data sheet. The relay shuts off the data, while the micro controller scan through the inputs.

Here comes the shunt regulators

The one at the bottom is the one for the DAC, and the one that is not duplicated on the input selector board.

Here comes the I/V from rbroer, which is fed from the unregulated DC supply.

And the micro controller schematic.

I have redesigned the PCB layout's without saving the ones I used in the working DAC. Therefore they have not been tested, and I would rather not publish them, and have them blow up in some poor persons face.

I have just finished testing a prototyping board I have designed for the PIC18F2550, that I will be using in a project I am doing for a friend. The board is designed to interface with the PICKit 2, programmer/debugger, has an on board 5 Volt regulator, and pads for a serial port through the MAX232 line driver/receiver. This is not rocket science, just a nice PIC18F2550 to breadboard converter.


Cadsoft Eagle project files:

The code is not quite done yet, an horribly inefficient. Just thought I would add it here so that others could use it.


Hi-TECH C code for the Frequency meter

Generated on 2018-05-03 01:14:21.916539