Bela is a maker platform for creating beautiful interactions. It consists of a Beaglebone black, with a shield or hat that has 2 audio inputs, 2 audio outputs, 8 analog inputs, and 8 analog outputs. It is complemented with a very slick web interface that allows you to write and very easily compile and run your code. And very cool is that the web interface features an oscilloscope.
I am planning to build a purely analog EEC/EMG/ECG amplifier, similar to this design on Instructables. As that involves making choices on the filter settings: a low-pass filter to remove electrode drift, a notch filter for line noise, high-pass anti-aliasing filter matched to audible frequencies. Hence I started thinking on how to determine the combined effect of all those filters, together with the multiple amplifier stages. It occurred to me that the Bela can act both as a signal generator and as a digital recorder and oscilloscope.
On this GitHub page I am sharing a Bela project that outputs a sine wave on the analog output, which can be fed through an external circuit, and subsequently measured using the analog inputs. The project computes a real-time discrete Fourier transform of the output signal and compares the amplitude and phase to the input signal. Using a LaunchControl XL MIDI controller (or alternatively using a small EEGsynth path for an on-screen MIDI controller), I can select the frequency, and start/stop a sweep over the whole frequency range. The amplitude and phase response at each frequency is logged to disk.
Here you can see the frequency response when the Bela analog output is directly fed into the analog input. It is very nicely uniform with a unit gain and no observable phase shift up to the upper limit of 22050Hz.
And here is the frequency response when the Bela audio (headphone) output is directly fed into the audio input. You can see that – as expected – it is DC-coupled with a high-pass filter and with an anti-aliasing filter at the high end.
From the Bode plot figures it is clear that something funky is going on with the phase estimates. I suspect that to be due to numerical errors accumulating in my computation of the DFT. There are fancy algorithms for single bin sliding DFTs. However, I want the DFT algorithm to run in the (hard) real-time audio loop, which means that it should have a very low computational cost. Furthermore, I want it to be memory efficient, which means that I don’t want to hold a large buffer with many samples.
I also tried it with a simple passive first-order low-pass filter on a breadboard with a 100nF capacitor and a 10kOhm resistor, which should have a (theoretical) cutoff frequency of 159Hz. The resulting frequency response up to 5000Hz is given here:
And If I connect the same capacitor and resistor to form a high-pass filter, I get the following frequency response up to 5000Hz . Note that the output of the high-pass filter cannot fully be recorded with the analog input (which is 0-4V only), hence I used the audio input.
While assembling the touch-proof enclosure for the OpenBCI Cython/Ganglion biosensing amplifier boards, I realized that with the board in the middle of the enclosure, there is little space for the Dupont wires connecting the pins of the OpenBCI to the touch-proof connectors. Trying to squeeze the board in place, some of the solder joints broke off. After repeatedly re-soldering the wires to the connectors, I was able to get it all properly in place. However, this was definitely a design flaw.
I designed a new version that has the OpenBCI PCB board rotated by 45 degrees and shifted a bit to the corner. This gives more space for the wires and reduces the stress on the joints. Here you can see the new enclosure printed for a 4-channel Ganglion board.
OpenBCI touch-proof enclosure version 3 – with the PCB board in the corner
Compared to the previous one for the Cython, the difference is also in the colour of the connectors: I used 4 pairs of red and blue connectors for each bipolar channel, one black connector for ground, and one blue connector as the common reference. Using the 4 channels (i.e. the red connectors) relative to the common reference requires toggling the micro-switches on the Ganglion PCB board. Using a common reference is handier for EEG measurements, whereas the bipolar configuration is convenient for ECG/EMG, but with some extra electrodes also works fine for EEG. The Cython version has 8 red connectors, one blue connector for the reference, and one black connector for ground.
Another change is aesthetic; thanks to the nice post and configuration files from Rainer I figured out how to 3D print with multiple colours. I updated the Fusion 360 design of the enclosure to include the EEGsynth logo. The logo is embedded in blue and white in the black background of the box.
The NAD D3020 is a hybrid digital audio amplifier with a combination of analog and digital inputs. I have been using it for quite some years now to play the sound of my Samsung smart TV over the living room speakers and for digital radio, iTunes and Spotify from my Mac Mini. The Samsung is connected with an optical Toslink cable, the Mac Mini is connected with a USB cable.
In the way the D3020 is placed in our media cabinet, its on/off button is not so easy to access. The D3020 remote control is really crappy and I find it anyway annoying to have to use multiple remotes to switch the power of all devices. Also, the status LEDs of the D3020 are dim and got considerably worse over time, especially for the OPT1 and the USB inputs which are for the TV and the Mac Mini. I guess that it uses OLEDs, which have degraded over time. Consequently, it happened quite often that we forgot to switch the amplifier off for the night.
However, the D3020 features a 12V trigger input port which allows the amplifier to be switched automatically on/off along with other gear. Of course, neither TV nor the Mac Mini has a 12V output port, but both are connected to my home network; hence it is possible to detect over the network whether these are powered on.
I built an ESP8266-based trigger which allows switching D3020 using the 12V trigger. This is combined with a small Node.js application running on a Raspberry Pi which pings my TV and my Mac Mini over the network every 5 seconds. If either one returns the ping – and hence is powered on – an HTTP request is made to the ESP8266 to switch the trigger on. If neither TV nor Mac Mini returns the ping, an HTTP request switches the trigger off.
The hardware is implemented using a Wemos D1-mini ESP8266 board. The ESP8266 uses 3.3V logic which is not enough. However, 5V turns out to be sufficient to trigger the amplifier. I tried using a logic level converter, but it did not produce enough output current on the 5V side, causing the voltage to sag and remain below the trigger threshold. Therefore I designed a circuit in which one of the 3.3V GPIO pins is used to switch an opamp. The output side of the opamp is connected to the 5V USB input voltage of the Wemos board. Although the output voltage does not fully reach 5V, it turns out to be enough for the trigger input of the D3020.
The design follows that of a MIDI input, see here on Sparkfun and here on the Teensy forum. The difference is that the optocoupler input comes from the microcontroller GPOI pin at 3.3V, and the output is pulled up to 5V from the Vin pin. I also added a diode to protect the electronics from reverse voltage spikes that might come from the amplifier.
The PC900v datasheet specifies a maximum forward current of 50 mA, which would require a 66 Ohm resistor at 3.3V. However, the maximum current that can be drawn from a single GPIO pin is 12mA, hence I decided to use a 270 Ohm resistor.
Here you can see the design on a breadboard for testing:
And the final implementation just prior to fixing it with hot glue:
I am using the ESP8266-based 12V trigger (which is actually a 4.8V trigger) in combination with a small Node.js script running on a Raspberry Pi that constantly monitors whether either TV or computer are powered on. The code for this is found in on here on Github.
My previous post on building an Art-Net to DMX interface using an ESP8266 seems to be getting a lot of attention. However, from the comments it is clear that a lot of people that build it themselves have difficulties to get it to work, or don’t get it to work at all. This post investigates this in more detail.
We have not been using these interfaces in our performances for quite some time, and started wondering whether there is something wrong my firmware. My implementation goes back to April 2017. Over the course of time there have been some updates to my code. Furthermore, the Arduino IDE has been updated, as well as the ESP8266 core for Arduino.
Recently I received all three interfaces back that I had built for my 1+1=3 collaborators and decided to update the firmware and to test them. One of them did not work at all due to a broken connection between the power supply and the Wemos D1 mini; two of them started just fine. After fixing the broken wire and updating the firmware on all three of them; they started up just fine, showing the green light (indicating a connection to the WiFi network) and on the monitor page of the web interface I cold see that Art-Net packets were being received. However, with my DMX controlled light it did not work at all.
I found detailed schematic information about the timing of the DMX protocol on this page. Searching for oscilloscope images of DMX signals, I also found this page with information.
Comparing the output voltage with the DMX512 schematics, it became clear that something was wrong in the signal. To make it easier to see the full signal on the oscilloscope, I configured only three DMX output channels, all set to zero. The oscilloscope shows 5 similar blocks; changing the value for DMX channel 1, I see that the 3rd block changes – that is apparently the first channel. Prior to that should be a “start code” with value 0, so the last 4 blocks make sense. But the first block is too short; there is also a very short pulse all the way at the start which does not match the specification.
Output voltage with the initial firmware:
By connecting the Enttec Open DMX to my DMX controlled light, I could confirm that the combination works and that the DMX interface to my light is not broken. Connecting the Enttec Open DMX to the oscilloscope, I see that it has a much longer 1st block which is the “space for break” (labeled 1 according to this), and slightly different 2nd block which is the slot with the “start code”. Following is a whole series of blocks/slots corresponding to the DMX channels. In this case I cannot limit the number of DMX channels, so the series contains a full universe of 512 channels, each of them set to zero. Changing the values of the first few channels in Lighting DmxControl, I can see the corresponding change in the signal on the oscilloscope.
Since a static photo of the oscilloscope screen does not show that there is quite some jitter, especially in the first part of the signal, I uploaded a short video recording of the Enttec Open DXM signal.
Output voltage of the Enttec Open DMX:
As the initial “break” signal was apparently not correctly implemented in my firmware, I changed the code to use the low-level implementation of the break that was contributed here. Using 3 DMX channels again, this results in a good DMX signal.
Output voltage with the firmware, using the low-level break:
I investigated the problem with the original code, which consists of switching to a slower baud rate, sending a single byte as the break signal, and switching back to the original baud rate of 250000. Given that the “break” appears just as long as the other bytes, the switching of the serial port speed apparently fails. On the Arduino forum I found a post that suggested to flush the serial port prior to and after changing the speed; I implemented this and now the break signal looks fine again.
I think that the reason that it broke is due to updates in the Arduino version that I am using, and/or updates to the ESP8266 Arduino core. I guess I must have been lucky with my buggy initial implementation; this may explain why it failed for some people and worked for others.
Output voltage with the firmware, using the slow serial break:
DMX512 universe size
Connecting my Art-Net to DMX512 adapter with updated firmware to the DMX controlled light initially did not work; increasing the size of the DMX universe that is is passed on by my Art-Net to DMX512 adapter solved this. After some trial and error it turned out that – although I had configured the DMX light for three channels (R, G, B) – it would not work if it would receive less than 8 channels. I suppose this is because the light has a 3, 4, and 8-channel DMX mode, and that 8 channels is apparently the minimum for DMX input to be properly handled.
Comparing the timing of the three systems
Looking back at the videos, I see that the timing of the Enttec Open DXM controller is the worst, especially in the space for break and the mark after break (MAB). This is actually a known characteristic of the Open DMX, since timing is controlled by the serial (USB) port of the computer rather than by a dedicated microprocessor; that is also the reason why it is not recommended for serious applications.
My own EXP8266 firmware with the low-level code for the break shows less jitter for the break. Using the “slow serial byte” the jitter is totally gone for the break itself, but there is still some jitter in the duration of the MAB.
Regardless of the jitter, all three are working fine with my DMX controlled light! Having seen the timing of the signals in detail, I am also more confident that they should work with other DMX equipment. One thing I noticed however and don’t have a solution for right now, is that the differential voltage of the Max485 modules that I am using is considerably lower at ~3.5V than that of the Enttec at nearly 8V.
To summarize, I was glad to have the Enttec Open DMX USB adapter for testing, and especially for having the DS203. If you are doing electronics like this, I can really recommend to get an oscilloscope!
Besides testing with the Lightning DmxController software, I was also able to confirm that it all works smoothly again with our EEGsynth, using a patch consisting of the redis, inputcontrol and outputartnet modules.
The OpenBCI Cyton and Ganglion boards are open hardware and maker-friendly biosensing systems. Although there are alternatives, such as Bitalino and OpenEEG and some companies and/or projects are currently working on new hardware (see e.g. EEG.io), the OpenBCI boards are in my opinion at this moment still the best.
The maker-friendlyness of the OpenBCI boards is somehow also a disadvantage: the OpenBCI systems come as bare PCB boards with a Dupont-style header. OpenBCI (the company) focusses on using it in combination with dry electrodes mounted in a 3D printed headset. I personally don’t value dry electrodes that much; I don’t see the problem with a little bit of gel in the participants hair, and I don’t like the pressure needed on dry electrodes to provide a decent signal. Electrodes with gel or Ten20 paste usually provide better and more robust signal quality. However, it depends on the situation: dry (or saline, like the Emotiv Epoc) electrodes are great if you quickly want to swap the EEG system from one participant to the other.
For the 1+1=3 performances using the EEGsynth setup, we not only use EEG recorded from the scalp, but also EMG recorded from muscle and ECG recordings from the heart. The standard in research and clinical applications is to use touch-proof connectors, technically known as DIN 42802 connectors. These are available in many versions, such as cup electrodes for EEG and snap electrodes for EGC and EMG.
The Dupont-style headers are ubiquitous in the Arduino scene, therefore I previously designed an 8-channel head-mounted system based on a sweat band with the amplifier mounted at the back. It is comfortable and works quite well during performances, but it is still a bit fragile, especially when replacing the battery (see below). Furthermore, after prolonged use the gold-plating of the electrodes wears off, and replacing the electrodes is a hassle. The advantage of touch-proof connector is that it is much easier to switch between different types (cup versus stick-on) and to replace worn-out electrodes. I guess this is also one of the motivations for OpenBCI also selling a Touch Proof Electrode Adapter. Connecting the adapter to the correct pins of the 11×2 header is not trivial, and results in a relatively fragile and bulky setup, i.e. not ideal in demonstrations/performances where I want stuff to be robust.
Another issue that I have with the OpenBCI boards is that they use a two-pin JST connector to connect the LiPo battery to the board. These JST connectors are not designed for frequent connect/disconnect cycles. To disconnect the battery for recharging, you have to pull the cable and I have accidentally pulled off the header from the cable more than once…
Based on these experiences I decided to make an enclosure for the OpenBCI boards that is robust in performance/demonstration settings, that uses touch-proof connectors so that it can be used with EEG/EMG/ECG equally well, that is compatible both with the Cyton and Ganglion, and that includes an easy to charge LiPo battery.
The 8-channel Cyton board exposes a lot of the flexibility of the ADS1299 analog frontend like common reference versus bipolar, and normal ground versus active bias, but I typically use it with a common reference and the normal ground. Consequently it needs 10 connectors (8x active, REF, GND). The Ganglion board has 4 channels and can be configured with jumpers for either unipolar and bipolar reference schemes. It hence needs 6 (4x active + common REF + GND) electrode connectors, or 9 (4x active + 4x bipolar REF + GND) electrode connectors. An enclosure design with 10 connectors (4x active, 4x bipolar REF, 1x common REF and 1x GND) therefore supports both reference schemes for the Ganglion.
The external dimensions of the enclosure are 100x100x30 mm. The height is needed for the 10 connectors, but also has the advantage that it should be possible to mount a WiFi shield on top of the board.
The internals of the enclosure are shown here. At the top you see a 850 mAh LiPo battery, connected to a LiPo charger/protector module with micro-USB connector. The on/off switch is this one and the LED is 5 mm diameter. I used a RGB LED, since that was the only that I had available, but I am only using a single color (green) connected through 470 Ohm resistor to the on/off switch. Both the OpenBCI board inside and the lid are secured with 2.5 mm screws. I purchased the touch-proof connectors from Medcat; these are actually the most expensive component of the enclosure.
Here you can see it with the OpenBCI board mounted, but still without the leads between the OpenBCI header and the touch-proof connectors.
The 3D design for the enclosure can be downloaded in STL format or as Fusion 360 project from ThingiVerse.
As my electronics designs are getting more complex and my patience for soldering air-wires for all connections on a perfboard is decreasing, I started looking into making my own PCBs. Although there are professional PCB fabrication companies that are not very expensive, I am not so confident yet with my Eagle PCB design skills. Hence I decided to start fabricating some simple PCB boards myself to get a better insight in all aspects relevant for PCB boards.
Reading about the different options for etching PCBs, and following a instruction evening organized at the Hackerspace Nijmegen on using a small CNC mill for PCB fabrication, I opted for toner transfer using a laser printer and using HCl and H2O2 as described here.
My first attempt was with 10% HCl from the local hardware store (dat zeg ik, Gamma!) and 3% peroxide from the drugstore. Directly following mixing, etching went OK-ish, but rather slow. It took some 10 minutes for the 1-sided PCB board to be clean. The etchant turned into a nice green color. The second time (a month later) the etchant would not really work any more, and th ePCB only got dark. Rejuvenating the solution with some additional H2O2 as per instruction did not change anything. I guess the concentrations were too low, and after a few hours I abandoned the attempt and took the board out.
For the second attempt I ordered 30% Hcl and 10% peroxide in an online store. Using my old etchant solution, I diluted the H2O2 to approximately 3% and mixed that with the HCl in a 2:1 ratio (adding the acid to the HO2O, to prevent a strong exothermic reaction). I popped in my board (from the previous attempt, which had gotten quite dark). The result was a very nice etching process. The process was clearly visible and there were no bubbles.
The result of the etching is quite nice.
I am happy with the result of the etching. The ill-defined traces on the board are due to poor toner transfer; I had to make some corrections with a permanent marker (fine liner) on the board. Measuring the connection between all pads revealed that there was one short-circuit (on the left side of the board). I was able to remove that with an x-acto knife.
The next time I will design the traces in Eagle to be slightly wider and to have more space between them. In the Eagle design rules I used a 6 mil minimum trace width (the default), and a 12 mil clearance. And I have to practice more with the toner transfer… to be continued.
Most of the time I am using Wemos D1 mini development boards in combination with the Arduino IDE to make my own firmware to run directly on the ESP8266 chip. But I also have some bare ESP-01 and ESP-12 modules lying around, and recently I came up with the plan to use one of them.
The specific project requires very well controlled timing of an ADC, for which I will use a regular ATmega328P-based Arduino board. In this project the ESP8266 will only be used to transmit the data over WiFi. Neither my ESP-01, not my ESP-12 still have the original AT firmware, since I have been experimenting with various other firmwares.
This is where the challenge starts, since my plan required restoring my ESP-12 to the AT firmware and use a library like ESP8266wifi or WiFiEsp. I realize that I have been struggling with different firmwares before, hence this post to give a short review and to keep some notes for my own future reference.
Module form factor
The ESP8266 microchip comes on various development boards that include an USB interface, such as the Wemos D1 Mini and the NodeMCU board, but also as bare modules such as the ESP-01, 02, etc. This page on the ESP8266 wiki has an overview of all modules and this page has comparison of some of the raw modules with some of the development boards.
Flash memory capacity
Besides the number of GPIO pins that is exposed by each of the modules, another important feature is their flash memory capacity. The AI-Thinker website has a module list table that includes this. The ESP-01 module comes with 512kB flash (old modules) or 1MB (now more common). The ESP-12 module comes with 4MB. Note that there are development boards such as the Wemos D1 mini pro that even have more.
As the ESP8266 is nowadays fully supported in the Arduino IDE, I prefer to develop my own custom firmware for the ESP8266 using C/C++ and the Arduino IDE and libraries. So the most confusing aspect of the ESP8266 for me is that there are multiple “standard” firmwares available for it, which I often accidentally confuse. These include
The NodeMCU firmware, which includes a LUA interpreter.
The MicroPython firmware, which includes a Python interpreter.
The NodeMCU project is more centrally managed/organized and includes a website where you can compile customized firmwares with support for specific hardware add-ons.
Restoring the AT firmware
To flash the firmware to an ESP8266, you will need to wire it up and get it in the right boot loader mode. There are many online tutorials for this and I won’t elaborate here. You will also need software to write the new firmware, I am exclusively using esptool.py.
I tried various options to flash my ESP-12 with the original firmware, most of which failed. The challenge is to figure out which firmware is compatible with my specific module, and to which flash memory locations to write the different pieces of the firmware. In the next section I will describe three things that worked, going from the oldest to most recent firmware versions.
Following the instructions here and using a rather obscure version of the firmware contained in a single binary file from here, I had success with:
esptool.py --port /dev/tty.usbserial-FTG54BPS --baud 115200 write_flash --flash_mode dio 0x00000 boot_v1.2.bin
esptool.py --port /dev/tty.usbserial-FTG54BPS --baud 115200 write_flash --flash_mode dio 0x01000 at/512+512/user1.1024.new.2.bin
esptool.py --port /dev/tty.usbserial-FTG54BPS --baud 115200 write_flash --flash_mode dio 0x7C000 esp_init_data_default_v05.bin
esptool.py --port /dev/tty.usbserial-FTG54BPS --baud 115200 write_flash --flash_mode dio 0x7E000 blank.bin
I also had success and was able to connect in a terminal program with 115200 bps. This resulted in the following response
AT version:22.214.171.124(Apr 13 2018 11:10:59)
compile time:Jun 7 2018 19:34:26
Bin version(Wroom 02):1.6.2
I did not have success with the 3.0 release from the Espressif NONOS_SDK repository. That one does not have the “512+512” directory, only the “1024+1024” directory, which I could not get to work on my ESP-12. Suggestions to make this work are welcome.
For the EEGsynth project I have developed a full-body 8-channel motion capture system. It is based on the MPU9250 9-DOF inertial motion unit, which contains a three-axis accelerometer, gyroscope and magnetometer. I have combined this with the Madgwick AHRS algorithm, which takes the raw sensor data and computes the yaw, pitch and roll.
The design is based on one battery operated main unit that is worn for example in a Fanny pack around the waist, and up to 8 sensors that are attached to the arms, legs, etc.
The main unit contains a Wemos D1 mini, which is based on the ESP8266 module. It uses the TCA9548 I2C multiplexer to connect a maximum of 8 MPU9250 sensors.
The data from the IMU sensors is streamed using the Open Sound Control (OSC) format. The sampling rate that can be achieved with one sensor is around 200 Hz, the sampling rate for 8 sensors is around 60 Hz.
For initial configuration of the WiFi network it uses WiFiManager. After connecting to my local WiFi network, it has a web-server through which the configuration can be set, which includes the number of sensors and the destination host and port for the OSC UDP packets.
My friend Vladimir recently demonstrated a single-channel EEG system that he got at a hackathon in London. When he mentioned that it only costs €20 (or actually 20 GBP to be more precisely) I immediately decided to order one myself. The ICI-BCI system is a low cost open source brain computer interface.
The bag clearly and rightfully indicates that it is a totally experimental system, and that it should be used with caution.
The basic idea of the amplifier is that it takes an 1000 Hz analog audio signal from the computer or mobile phone, which is amplitude modulated by the ExG signal and subsequently fed back as microphone signal. So the system is fully analog and requires the DAC to be done by the audio input of the computer or phone.
I have a Multitech MDOT-BOX for testing. Configuring it for TTN requires the following connection to a computer, after which AT commands can be used to probe and set parameters. The following resets the MDOT to factory defaults and shows the configuration overview.
Library : 0.0.9-14-g4845711
Device ID: 00:80:00:00:00:00:b3:76
Frequency Band: FB_868
Public Network: off
Network Address: 00000000
Network ID: 6c:4e:ef:66:f4:79:86:a6
Network ID Passphrase: MultiTech
Network Key: 1f.33.a1.70.a5.f1.fd.a0.ab.69.7a.ae.2b.95.91.6b
Network Key Passphrase: MultiTech
Network Session Key: 00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00
Data Session Key: 00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00
Network Join Mode: OTA
Tx Data Rate: SF_7
Tx Power: 11
Log Level: 6
Maximum Size: 242
Minimum Size: 11
Maximum Power: 20
Minimum Power: 2
After adding a device to application page on the TTN console with OTA activation, the following identifiers/keys are listed on the TTN console page for the device
From the Multitech documentation: In OTA mode, the device only needs to be configured with a network name (+NI=1,name) and network passphrase (+NK=1,passphrase). The network session key, data session key, and network address are all automatically configured.