Power Subboard v1.1

This board takes in up to three power supplies – USB micro, single-cell LiPo battery, and a coin cell battery – and outputs 3.3V. The supplies are hot-swappable and the ORing circuitry will connect the load to the largest supply automatically. A voltage supervisor and load switch disconnect the LiPo when it reaches 3.5V and reconnects it when the voltage rises to 3.7V. A charging IC allows the USB supply charge the LiPo at 100mA (configurable by resistor). There was no stand-alone v1.0 for this board. Instead, the v1.1 comes from a portion of the Sensor Node board albeit it with a few modifications.

Copies of the board may be ordered on OSHPark and the design files are available on GitHub.

LiPo Undervoltage Protection

LiPo undervoltage protection

A protection circuit is needed to prevent the LiPo cell from damage due to over-discharge. It is implemented by a voltage detector (U2) and a load switch (U3). When the LiPo voltage is above 3.5V, U2’s output floats. Once the voltage drops below 3.5V, however, U2 grounds its VOUT pin. This opens the internal switch of U3 and disconnects the LiPo cell from the rest of the board. U2 has hysteresis and will continue to ground VOUT until the LiPo cell voltage is above about 3.605V – 3.78V (3.675V typical). Note than even when U3 has disconnected the LiPo cell, there will still be a discharge of 0.35mA through R3.

LiPo-USB Switch

Output LiPo or USB voltage

Assuming the undervoltage protection isn’t activated, the LiPo cell voltage will pass through U3 and reach U4 – an automatic battery back-up switch. U4 will output whichever input voltage is higher and indicate which source is being used by the SBAR and PBAR open drain outputs. Since USB power is 5V and higher than a fully-charged LiPo cell, U4 will always switch to USB power when it is present. This allows the LiPo cell to be charged by USB without also having to power a load.

In the first revision there were pullup resistors for SBAR and PBAR. This resulted in a continuous 0.33mA current draw and was not negligible based on the overall power budget. Removing the resistors allows the final application to decide if 0.33mA is acceptable or if a solution based on a microcontroller’s internal pullups or GPIO would be better (see this application note for an example).

LDO and Coin Cell Switch

pwr_sub_ldo_outputAn LDO (U6) is used to step either the LiPo cell or USB voltage down to 3.3V. The NOR gate U5 is used to disable the LDO to save power when neither the USB nor LiPo cell are present. Finally, the LDO output joins with the coin cell at the power switch U7. U7 selects which input to use based on the EN pin and the voltages at the two inputs. By connecting EN to IN1, U7 will use the LDO output when present and otherwise switch to the coin cell. The full truth table is found on page 3 of the datasheet.

LiPo Charge Circuit


A LiPo charge circuit almost straight from the datasheet is present so that the battery may charge when USB is connected. The charge current can be modified by populating a different resistor for R1 (e.g. 500mA with a 2k). The STAT pin is broken out to a external pin so the final application can decide whether it wants to connect an LED or microcontroller GPIO for determining charge status.


I recently finished some boards for a 915MHz/2.4GHz network. Their design files will go up on github soon but until then here’s a summary.

Sensor Node

This was the first board and was meant to be flexible. It had two radios – 915MHz (MRF89XAM9A) and Bluetooth LE (BL600-SA) along with environment sensors and hot-swappable power supply circuitry. The sub-components passed initial testing but the BASIC programming language required on the BL600 chip proved to be less convenient than I had hoped. Along with a high BOM (~$40) I determined it would be better to break it up into smaller sections.

Sensor Subboard

Temperature, pressure, altitude (MPL3115A2)
Visible light, IR, IR proximity, UV index (SI1145)
Humidity, temperature (SI7020)
Sound (MAX4468 + electret mic)

Power Subboard

This board takes in up to three power supplies – USB micro, single-cell LiPo battery, and a coin cell battery – and outputs 3.3V. The supplies are hot-swappable and the ORing circuitry will connect the load to the largest supply automatically. For example, if you’re running off a coin cell then plug in USB, the coin cell will be disconnected and the load will use the USB power instead.

A voltage supervisor and load switch disconnect the LiPo when it reaches 3.5V and reconnects it when the voltage rises to 3.7V. A charging IC allows the USB supply charge the LiPo at 100mA (configurable by resistor).

Leaf Node

This board is meant to be the furthest out on the network yet hopefully capable enough of running a limited version of the Contiki OS. The LPC812 was picked for the cost ($1.58) and memory (16kB flash, 4kB RAM). The board has a temperature sensor but since the LPC812 doesn’t have an ADC I added some passive components to make a sigma-delta ADC. There’s also a header for a nRF24L01+ radio to plug in. The total BOM ended up being about $5.

I’ve been meaning for a while now to cycle back and work on the SSMU project again. The Hackaday Prize entry submission deadline was quickly approaching so I decided to put something together for motivation. Most of the details will be tracked over on their projects site:

The idea is still the same – integrate core functions from lab equipment over the audio frequency range and integrate with software running a circuit simulator. Instead of sticking to through hole components and an MSP430, I’m going to use a STM32L100RBT6 and a custom PCB. The current planned features are the following:

1-2* voltage sources (0-15V, 1MSps DAC)
1 current source (up to about 50mA)
2+ voltage measurements (12bits, 1MSPS ADC)
2 current measurements
2 Bode plot measurements (gain and phase up to 100kHz)
Fixed and adjustable power supply (3.3V, 5V, 0-9V)
Adjustable current limits for 0-9V rail and DAC output
Protocol analyzer (at least I2C, SPI, and UART)
LCR meter
Speaker output stage
USB and wireless (nRF24L01+) connectivity

*One voltage source is used for the current source but will be accessible when the current source is not in use

I’ve picked most of the components except for some current and voltage protection chips. The BOM is sitting somewhere around $20-25 so I’m on track to not break the bank.

Instead of measuring magnitude and phase by brute force sampling and software, I’m going to extract it with a few op amps. In the picture below, U1 attenuates the voltage at the DUT (can range up to 9-15V) and optionally provides amplification for lower amplitude signals. C2 compensates for some of the input capacitance the DUT might present. U2 and D1 form a precision rectifier and along with C1 constitute a peak detector. This relatively stable voltage can then be sampled by the microcontroller’s ADC as the magnitude of the waveform.

This value is then divided and compared with the input waveform again to produce a digital output representing when the waveform is above or below this fixed voltage. When compared with the digital output for the other Bode circuit (one at either side of the DUT) the microcontroller can determine the phase shift.



I recently bought a Intel® Centrino® Advanced-N 6235 Mini PCI card to enable WiFi communication for my Intel Galileo board. Since I needed to add wireless display capabilities to my SSMU project, I decided to do a mini project to become familiar with sending and receiving data over WiFi.

The libGDX app launches and waits for the user to enter the IP address and port number the client (phone/tablet/computer) should use to connect to the server (Galileo). Once connected, the Galileo can send commands to draw shapes, text, and images based on the Arduino TFTLibrary API.

To save communication bandwidth, the Galileo only sends new images to the client which then caches the image. This way subsequent draw commands for that image only require the client to fetch the image from its local storage.

The python class and associated executables can be downloaded from my GitHub account along with the current list of known issues and planned features. I will be releasing the full source of the libGDX app shortly.

The video below shows Galileo simultaneously drawing the above demo image to four devices (phone, tablet, laptop, and desktop). I believe the lag for the tablet was due to an application trying to update itself since the Galileo had completed sending commands.


This project started out as a way to see how much useful work I could get out of a MSP430G2553. Since the closest thing I have to a personal electronics lab is a National Instruments myDAQ from college, I decided to try and replicate some of its functionality (namely the ability to act as a SMU) as well as integrating with a circuit simulator. The project goals were the following (in no particular order):

  • Low cost (< $100)
  • Through hole components when possible/feasible
  • At least 200ksps ADC
  • Sample window of at least 0.15 seconds (enough for 3 cycles of a 20Hz wave)
  • Sweepable sine wave output (20Hz – 20kHz)
  • Source and measure current (specific specs TBD)
  • Integration with Intel Galileo board running ngSpice
  • GUI on desktop and Android
  • Support both wired (USB) and wireless (WiFi) connections from Galileo

Currently I have a desktop GUI (written in Java with the libGDX framework) connected over USB to the Galileo. Based on what commands the GUI sends, the Galileo will either run a ngSpice simulation file or request new data from the MSP430 ADC. The results will be written to a file and sent back to the GUI. After some file parsing to determine how many signals were in the file and the number of samples, the GUI updates the plot as shown below.

Voltage in (red), voltage out (white) ngSpice signals plus ADC (green).

Voltage in (red), voltage out (white) ngSpice signals plus ADC (green).

Here the simulated circuit was a resistor divider (factor of 2) with a 7.1kHz sine wave input. When new ADC data is requested, the MSP430 starts stepping through a look-up table and outputs the value it reads to the DAC (TLV5618). The internal ADC is then configured to start a block of conversions and to use the DMA channel. This way results are directly copied to memory with low jitter (1-3 MCLK, or 0.0625us – 0.1875us for the 16MHz clock) and without interrupting the CPU.

In the above picture, the DAC was outputting a sine wave with 16 steps per period at about 7.1kHz. The green data points are from the ADC which was running at 62.5ksps.

Currently, the fastest sine wave the MSP430 can synthesize is 7.5kHz with 16 steps per period. I might be able to double this by using a DAC that only requires a single byte to update its output instead of two bytes like the TLV5618. I included a picture of the myDAQ’s oscilloscope reading below. It doesn’t quite agree with 7.1kHz but I’ve seen it jump a few hundred hertz based on what the timescale is.


Since there’s 512 bytes of RAM, only 30 10-bit ADC results can be stored at a time before I start to see stack overflows. Even though 8-bits would provide acceptable data, the ADC and its DMA channel always copy both bytes for each conversion.

My next steps for the project are the following:

  • Add an external SPI RAM chip to buffer more samples. The Galileo and MSP430 will trade off reading and writing to it.
  • Determine the specs required for current measurement and order the appropriate parts.
  • Provide more signal conditioning so voltages aren’t limited to 0-3.3V.
  • Add an interface to the GUI for editing ngSpice files. Currently I have a telnet window open to make changes.
  • Test GUI on Android which will mean sending the data over WiFi.
  • Test out a clock-tunable RC low-pass filter + VCO IC for lower distortion sine waves over the entire 20Hz-20kHz range.

In this demo, the Galileo communicates with a MSP430G2553 microcontroller via the nRF24L01+ 2.4GHz transceiver. The MSP430 sends an encrypted block of data representing the state of six of its pins. This message is received by the sketch running on the Galileo and stored in shared memory. A Python script then wakes up, decrypts the message, and prints which keys were pressed to the screen. The purpose of this demo is to show how a simple sketch can take advantage of a different user space program on the Galileo to do something as complex as decryption.

Edit: There is now an Instructable version here. The updated code is now hosted on my GitHub – (support for multiple readers/writers, larger buffers, full source code).




There are 6 pins on the MSP430 configured as inputs with their internal pull-up resistor connected to act as keys for the user to press. When a key is pressed (pin grounded by the long red wire shown wrapped around a pencil) or released (pin is pulled high by internal resistor) the MSP430 reads the state of all 6 pins, encrypts with AES-128 in ECB mode, and transmits to the Galileo. The board accepts up to 26V for input power and regulates it down to 3.3V with the LM2937. The nRF24L01+ (found on eBay for as low as $1 per board) draws about 26uA during standby, 11.3mA during transmit, and 13.5mA during receive (these values can be lowered by reducing the chip’s antenna output power and/or data rate). The radio is set to transmit at 2Mbps but can be programmed to 1Mbps or 250kbs to extend the range of the transmission. So far I’ve only tested indoors with direct line of sight up to about 15 feet. The AES code used comes from Texas Instruments. They make no promises about being safe from side channel attacks, but for now all I need is a correct implementation that will fit in the MSP430G2553’s limited memory. The library used to communicate with the nRF24L01+ comes from here with only a few modifications needed to port the code to the MSP430 and Galileo.


The sketch running on the Galileo runs code similar to the MSP430 except that it handles receives from the nRF24L01+ instead of transmits. In the setup() method, the sketch creates three IPC objects: a shared memory segment one AES block length in size (16 bytes) and two semaphores. Together these form the control needed to make a queue with a single producer (sketch) and single consumer (Python script). Semaphore sem_space is initially 1 and represents how much space is available in shared memory for new encrypted messages. After receiving a new message, the sketch attempts to decrement the count of sem_space. The sketch will idle if sem_space is already 0 (indicating that the Python script hasn’t read the previous message out of shared memory). After storing the encrypted message in shared memory, the sketch increments sem_data (initially 0) to signal to the Python script that new data is available. You can enter ‘cat /proc/sysvipc/shm’ or ‘cat /proc/sysvipc/sem’ in the command prompt to see the current list of shared memory and semaphore objects, respectively.

Defining IPC object values (before setup())

#define SHM_SIZE 16 // bytes of shared memory to create
#define SHM_QUEUE_LENGTH 1 //number of AES blocks that will fit
int shmid; // shared memory for received encrypted data
int sid_data; // data in queue ready for decryption
int sid_space; // room in queue
// hard-coded keys
key_t key_shmid = 123456;
key_t key_sid_data = 654321;
key_t key_sid_space = 987654;    
uint8_t* shared_memory;

struct sembuf sem_down = {0, -1, 0};
struct sembuf sem_up = {0, 1, 0};

Setup IPC objects with calls to galileo_ipc library

// temp contains the error code: 0 on success, 1 or 2 on error
temp = startMem(&shmid, key_shmid, &shared_memory, SHM_SIZE);
temp = startSem(&sid_data, key_sid_data, 0);
temp = startSem(&sid_space, key_sid_space, SHM_QUEUE_LENGTH);

Writing to shared memory

    semop(sid_space, &sem_down, 1); // -1 to space in queue
    memcpy(shared_memory, rx_data_array, 16);       
    semop(sid_data, &sem_up, 1);  // +1 to data in queue

The galileo_ipc library (WIP)

#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "galileo_ipc.h" // currently only contains function prototypes

union semun{ 
  int val;
  struct semid_ds *buf;
  ushort *array;
  struct seminfo *__buf;
  void *__pad;

union semun semopts; 

uint8_t startMem(int* shmid, key_t key, uint8_t** mem, uint8_t size){
  // Setup shared memory
  if ((*shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) < 0){
     return 1;

  // Attach shared memory
  if ((*mem = (uint8_t *)shmat(*shmid, NULL, 0)) == (uint8_t *)-1){
     return 2;
  return 0;

uint8_t startSem(int* sid, key_t key, uint8_t val){
  // Setup semaphore
  if ((*sid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0660)) < 0){
   return 1;

  // Initialize count
  semopts.val = val;
  if ((semctl(*sid, 0, SETVAL, semopts)) < 0){
   return 2;
  return 0;


The Python script accesses the three IPC objects using their hard-coded key values (see the Limitations/Future Improvements section for details on this behavior). It then tries to decrement sem_data, going idle if the sketch has not placed any new encrypted message in shared memory. When the decrement to sem_data succeeds, the message is read from shared memory and sem_space is incremented so the sketch can place a new message in shared memory. In the code below, the strings “one”, “two”, etc are just large strings from an ASCII art generator. I’ve omitted them from this post to save space. I cross-compiled the PyCrypto and sysv_ipc Python modules from an Ubuntu virtual machine on my Windows 8 desktop.

from Crypto.Cipher import AES
import sysv_ipc
import os
numbers = {'1':one,'2':two,'3':three,'4':four,'5':five,'6':six,'0':zero}

keys = {'0x3b':1,'0x3d':2,'0x3e':3,'0x37':4,'0x2f':5,'0x1f':6,'0x3f':0}

key_shm = 123456
key_sem_data = 654321
key_sem_space = 987654

key = "000102030405060708090a0b0c0d0e0f".decode('hex')

# get ipc objects created by sketch
mem = sysv_ipc.SharedMemory(key_shm)
sem_data = sysv_ipc.Semaphore(key_sem_data) # initially 0
sem_space = sysv_ipc.Semaphore(key_sem_space) # initially 1

last_key = 0;
current_key = 0;

    sem_data.acquire() #wait here until encrypted data is ready
    val =  
    sem_space.release() #indicate data has been read from shm
    msg = obj.decrypt(val) 
    #print(map(hex,map(ord,msg))) #print decrypted data

    current_key = keys[hex(ord(msg[0]))]
    if(current_key == 0):
        print("Key " + str(last_key) + " released.\n")
        print("Key " + str(current_key) + " pressed.\n")
    last_key = current_key

Demo Video

I noticed the majority of the delay here was due to printing those large ASCII art numbers (connected over Ethernet to Galileo). Without the extra printing, the message of which key was pressed was nearly instantaneous (from the timescale of a human of course). I apologize for how dark the Galileo board looks – I brought a lamp over for more light but my phone still didn’t adjust fast enough.

Limitations/Future Improvements

While the MSP430 transmits the state of all 6 pins (i.e. multiple keys could be pressed at the same time) only single key presses are demonstrated in the video. It was annoying enough to keep both board and screen in frame while holding the camera and pressing different keys (eventually I’ll set up some sort of small tripod to make future videos easier).

As mentioned above, using ECB mode for AES isn’t the best idea in the world. Granted, the point of this demo was not to demonstrate a complete security solution (that would require a key exchange protocol, better AES mode, etc). Even then there would most likely be side channel attacks on both PyCrypto and whatever code is on the MSP430.

Instead of hard-coding keys for the IPC objects (done here for simplicity) you could use the ftok(3) function. However, there’s still the possibility for there to be a key collision. The sketch needs a reasonable way to respond to such an error so that the Python script doesn’t try to access an IPC object that doesn’t exist. The IPC_EXCL flag is OR’d in for shmget() and semget() to make sure you don’t end up opening an object created by a different program. I noticed that the IPC objects would be cleaned up if the sketch was killed but not if you re-programed the sketch. The best practice is to clean up the IPC objects yourself (I added a serial command that results in calls to shmdt() and shmctl() to take care of this). If you leave off the IPC_EXCL flag for this demo, the sketch will still acquire the old IPC objects and run properly since it re-initializes the semaphores. However, there might still exist a race condition with the Python script if you don’t kill it before re-programming the sketch.

Data only flows from the sketch to the Python script here due to the nature of the data. It would be trivial to copy and modify the above code to set up another shared memory producer-consumer queue. This would be useful in a project where the sketch needs to use the decrypted data to transmit a new message over the radio. Increasing SHM_QUEUE_LENGTH and SHM_SIZE appropriately would allow for the sketch to load more than one message for the Python script to decrypt.

The galileo_ipc library will be formatted so that conforms to the built-in Arduino libraries. That way its functions will be in a familiar form (something like IPC.createShm() with syntax highlighting).  I’ll need IPC in my next project so I will be updating galileo_ipc along the way (switching from SysV to POSIX-style IPC objects/functions for starters).