Category Archives: Hardware

NeoPomodorino: A Pomodoro style timer

This is a simple Pomodoro style timer I made using a Proto Shield, an Arduino clone, a NeoPixel 24 LED ring clone, and various bits and pieces from my parts drawer.

The NeoPomodorino in action

The NeoPomodorino in action

The single button is wired to pin 3 of the Arduino using a simple RC debounce circuit featured some time ago on Hackaday. It’s probably not needed, but what the hell.

Debounce circuit

Debounce circuit

The LED ring is wired to pin 6 (like it is in every NeoPixel code example I’ve seen so far). As suggested a few places, I have a 470 ohm resistor in series with the data pin, and a electrolytic capacitor across VCC and GND. Like the debounce circuit, these are also probably not needed.

Usage

  • Long button presses (> 500ms) will turn the device on and off. This also resets the timer.
  • Short button presses will add 1 minute to the current timer.
  • Each pomodoro consists of 25 minutes of work (red color) followed by a short 5 minute pause (yellow color).
  • Every fourth pause is a longer one of 25 minutes (green color).
  • Between each pomodoro, the device will briefly flash which number is (blue color). 1 quarter of the ring = 1 pomodoro.

Get the code on GitHub.

Happy Hacking! 🙂

RPIWeather: Adding off-the-shelf wireless sensors

So, the last couple of years I have been developing and using my own home-built wireless thermometer/hygrometer system called RPIWeather (which is open source). Then the other day I discovered that the previous owners of our house (my in-laws) had left a few items outside. To be more precise, they left a couple of wireless thermometer sensors from old weather stations. The weather stations are long gone by now and, needless to say, the batteries were quite dead. But that doesn’t mean the devices themselves don’t work. Hmm.. It might even be possible to add these into my own system. I always like a good challenge…

Let’s have a look…

Three wireless thermometers

Three wireless thermometers

The devices all looked a bit gnarly, but after a bit of clean-up I powered them on one by one and had a look using my RTL-SDR receiver. All three devices worked and transmitted on 433MHz. Yay! But as my RPIWeather base station only supported the nRF24L01 2.4GHz transceivers, I had to make and add a new 433MHz receiver to it.

Setting up a prototype receiver

At first I toyed with the idea of simply adding an RTL USB-dongle to my Raspberry Pi and simply use GNU Radio (or some other SDR framework) to receive the signals. But that seemed a bit overkill. And I’m not even sure a first generation Raspberry Pi is powerful enough for this to work properly. Fortunately, the usual Chinese Ebay sellers offer a few different generic 433MHZ ASK/OOK receiver modules.

RXB12

RXB12

I ended up choosing one called RXB12 which features a Synoxo SYN470R IC. It’s reasonably sensitive across the 433MHz spectrum, but doesn’t offer any I/O besides a continuous stream of binary data (which is just random noise most of the time).

The rest of the prototype was an Arduino Uno, but any old Arduino will do.

The protocols

In parallel with my prototype Arduino setup, I also hooked up my logic analyzer (a cheap Cypress-based Saleae Logic clone) to eavesdrop on the serial data stream from the radio chip.

OBH

OBH unit

OBH unit

The protocol appears to be the one known as “Oregon Scientific V1”, which is a somewhat old protocol exclusively used for temperature-only sensors.

Signal sample

Signal sample

Europe Supplies Ltd. TX3

TX3 unit

TX3 unit

Once you realize that this is identical to a LaCrosse TX3, you are done. This is a very popular sensor and its protocol is quite well known. It is unfortunately not the TX3-TH variety that also reports relative humidity, but at this price (free) I’ll take it.

Signal Sample

Signal Sample

Unbranded unit

Unbranded unit

Unbranded unit

The protocol used by this unit is a bit different. At first glance it looks like identical short bursts until one looks at the intervals between the bursts. Short intervals mean 0 and long intervals mean 1. The unit sends 36 bits 7 times. My Google-fu didn’t find a lot of information about this one, but apparently the protocol seems to be very similar to the ones used by other unbranded china-devices. The so-called checksum used by this device is somewhere between useless and batshit insane.. Have a look in the code for the dirty details.

Signal sample

Signal sample

Bonus: Weber Style wireless BBQ thermometer (Model AW129)

Weber AW129

Weber AW129

Interestingly enough, this is just a rebranded Oregon Scientific unit that (unsurprisingly) uses the so-called “Oregon Scientific V2” protocol. To ensure data integrity, the signal is sent twice and each instance includes both a nibble checksum and a byte CRC8.

Signal sample

Signal sample

Having a wireless BBQ thermometer with data logging is actually very useful when doing slow-food like pulled pork where the smoker has to be monitored regularly over a period of several hours. It’s suddenly very easy to pick up on small changes in the rate of temperature increase inside the meat. This enables very fine-grained control of the air vents in the smoker as well as an indication if more coal or water is needed. Finally, it allows me to accurately predict several hours in advance when the meat will be done.

Pulled pork

Pulled pork

I have no idea why a relatively nice wireless thermometer like this one is shipped with such a crappy receiver. Main problems include:

  • There is no way of setting user-defined temperature alarms. The unit is shipped with a small number of factory presets depending on the type of meat and doneness, but the selection is extremely limited.
  • The transmitter sends quite accurate readings with a resolution of 0.1 degrees Celcius, but the receiver unit just rounds this number to the nearest integer. This may be OK for most use-cases, but it’s very annoying for me when I want to keep a close watch on things.
  • Sound alarms cannot be changed/muted.

But at least I’m happy that I can make my own receiver this way. 🙂

Porting to the ATtiny84 and adding 433MHz capability to RPIWeather

I had a few DIP ATtiny84s left over from the prototype phase of my own sensor nodes. Using one of these I was able to make a sufficiently compact module that listens for these known data packets on 433MHz and then forwards them to my Raspberry Pi using its internal UART RX pin. For this to work, I had to stop Linux from using the internal UART pins for a serial console interface. But it was a small price to pay, I think.

433MHz receiver

433MHz receiver

Originally, RPIWeather was designed exclusively with my own sensor nodes in mind. It actually triggered a bit of much needed refactoring to add this new capability to the code. Now the script starts a thread for the InfluxDB sender as well as a thread for each data source. These threads run totally independently and are only communicating through a concurrent queue object. At this point in time, RPIWeather supports three data sources which are connected to the Raspberry Pi in three different ways:

  1. My own 2.4GHz sensor nodes. The receiver is connected to the internal SPI pins.
  2. The above-mentioned 433MHz thermometer sensors. The receiver is connected to the internal UART RX pin.
  3. A Bosch BMP180 barometric sensor for measuring atmospheric pressure. It is connected to the internal I2C pins.

Show me the code!

All code and schematics can, as usual, be found on GitHub.

Happy Hacking! 🙂

Reverse engineering an Ecoteck wood pellet stove remote control

In our living room we have an “Ecoteck Francesca” wood pellet stove that helps us keep a reasonable temperature during winter. The problem is, however, that the remote control is horribly bad (yes, it has a friggin’ remote control). At this point I have already had to replace the buttons in it once, as the old ones were beginning to wear out.

Ecoteck remote control

Ecoteck remote control

There are four buttons. Two for adjusting the target air temperature and two for adjusting the level of flames or something. Pressing the two uppermost buttons at once turns the stove on or off. I haven’t looked at other Ecoteck models, but the codes in this post may also work for other models that has the same control electronics. The front panel looks like this:

Ecoteck Francesca front panel

Ecoteck Francesca front panel

So, for the long run we might have to find some sort of replacement of this remote control. Fortunately, our Samsung tablet has an IR transmitter on-board that would be perfect for this. There’s even an easy to use Android API for accessing it. The problem is then that the tablet has no built-in way of “recording” the IR signal from the old remote. And the protocol is nowhere to be found online (until now, that is). So before we can create an Android app, we need to get the codes and modulation settings from the old remote control.

How to get the codes

One approach would be to get the USB Infrared Toy from Seeed and record the transmitted codes directly, but instead I decided to try out a simple logic analyzer I just received in the post from China. It’s not really a logic analyzer per se, but rather a breakout board for the Cypress CY7C68013A MCU, which is the same chip as the one in the original Saleae Logic. It even enumerates as a Saleae device when I plug it in. So, basically it’s a knockoff. Naughty Chinese!

However, word on the interwebs has it that it won’t work with recent versions of the Saleae Logic software due to some minor hardware differences regarding the onboard EEPROM chip. But all this doesn’t matter, as I’ll be using the open source PulseView tool from the sigrok project instead.

Getting the codes

It’s not necessary to build a fancy IR receiver. Just open the remote control and attach a couple of probes across the IR LED. The voltage drop here is big enough to trigger the logic analyzer. I started the analysis by having a look at the signal itself by sampling at 24 MHz and pressing a button.

The setup

The setup

The signal consists of a series of infrared pulses, which seems to be grouped into blocks. An “on-block” is 30 pulses long. An “off-block” has no pulses, but lasts for the same duration as an “on-block”. Each individual pulse is on for 8.25 μs and off for 19.625 μs except for the last cycle of each block which is only on for 5.25 μs. The interval between the last pulse of a block and the first pulse of the next block is 28.5 μs.

29 pulses, 1 end-of-block pulse, and the beginning of the next block.

29 pulses, 1 end-of-block pulse, and the beginning of the next block.

Thus a normal pulse is 27.875 μs long, which means a modulation frequency of 35874 Hz. I don’t know if the duty-cycle matters at all. Time will tell… The length of a block (incl the inter-block distance) is then: 29 * 27.875 μs + 5.25 μs + 28.5 μs = 842.125 μs.

Now that we have the signal timings we can zoom out a bit. For the rest of the analysis a lower sampling rate is sufficient. In the following 1 means a high block and 0 means a low block.

A single button press

A single button press

Notice how the slight inter-block delay causes the anti-aliasing to color each block a slightly different shade of gray. If we annotate the trace with 1s for on-blocks and 0s for off-blocks, we get something like this:

Annotated button press

Annotated button press

If we do this for all 5 functions, we get these codes:

Ecoteck remote control codes

FunctionCode
Temperature up111111110001111001010011011010100110101011
Temperature down111111110001111001010011110010100111110011
Fire up111111110001111001010011111010100111101011
Fire down111111110001111001010011101010100111001011
On/off111111110001111001010011010010100110110011

Now we have all the necessary data we need to create a compatible remote control.

Implementing an Android app

Based on these codes, I have made a simple Android widget that should work on any phone/tablet that has an IR transmitter and runs Android 4.4.2 (API level 19). It relies on the ConsumerIrManager class that was added in that release.

During normal operation the widget looks like this:

Ecoteck widget

Ecoteck widget

To prevent turning the stove on or off at a bad time, I originally intended the power button to be activated only if the user pressed and held it. However, in Android the long press event is reserved for doing widget management stuff and cannot be used by the widgets themselves. Bummer… Instead the widget presents the user with a confirmation dialog of sorts if the power button is pressed:

Confirm on/off command

Confirm on/off command

I have been using the widget exclusively for a couple of days now and it works like a charm. 🙂

That’s it!

As usual, all code for this project can be found on GitHub. If you have any questions, please comment below.

RPIWeather: My wireless monitoring system

Some of the first posts on this blog were about how to interact with the famous nRF24L01 2.4GHz radio chipset from both an Arduino and a Raspberry Pi. Well.. Much have happened in the mean time, but at least I have managed to put together something using what I learned back then. I decided to make a wireless monitoring system for environmental data in and around our house with at least one sensor node in each room as well as a couple of sensors outside. It is called RPIWeather and you can get all the code and documentation by clicking the name. This post is just meant as a short summary.

RPIWeather consists of a bunch of wireless sensor nodes, a base station that collects the data packets, a database server, and one or more frontends. My goal has been to collect data at 5 minute intervals and keep it indefinitely for analysis, comparison, and visualization. This creates some demands for power efficiency and reliability, which I find interesting.

The sensor nodes

My first prototype was based around an Arduino and some proto-board and is described here, here, and here. It looked like this:

Arduino with nRF24L01 and DHT22

Arduino with nRF24L01 and DHT22

To keep things simple, clean, and small, I decided to ditch the Arduino platform and code in straight avr-libc for the ATtiny84 chip from Atmel. So I made another prototype, but this time with an ATtiny84 instead.

Partial prototype without the DHT22 sensor

Partial prototype without the DHT22 sensor

Little by little a schematic emerged. Besides the radio, the sensor and the MCU, I also needed some sort of power supply. As the sensor nodes are to be distributed throughout the house, this implied battery power, but it couldn’t just be any old battery. The thing is that the radio chip can only tolerate up to 3.6v and the DHT22 sensor can only operate down to ~3v, which leaves a narrow band of usable voltages. A traditional voltage regulator would have burned though the batteries quite quickly, so I had to put in a switching boost converter. This way 2 AA NiMH batteries can deliver a reasonably stable 3.3v supply voltage for the circuit. Pro tip: when buying NiMH batteries, do yourself a favor and use the low self-discharge kind like Eneloop. In this use-case they will go for several months between charges.

Schematic for the sensor nodes

Schematic for the sensor nodes

With the schematic in place, I made a PCB layout and sent it to ITEAD for manufacturing. Here are a couple of pictures showing various stages of assembly. The funny shape of the boards was needed to make them fit snugly into some cool boxes from New Age Enclosures.

Sensor node PCBs

Sensor node PCBs

The first 10 finished boards

The first 10 finished boards

Inside a single sensor node

Inside a single sensor node

A single sensor node

A single sensor node

The back of a sensor node

The back of a sensor node

The 10 first sensor nodes

The 10 first sensor nodes

In addition to the DHT22 sensors, I have also made firmware for collecting data from a wind vane and a rain gauge. But I haven’t deployed any of that yet. Maybe next spring…

All in all the main results for the sensors are:

  • They work! I have tested concurrent operation of 10 units without major problems.
  • Firmware optimized for ATtiny84 @ 1 MHz (8MHz crystal with the CKDV8 fuse set)
  • Temperature and humidity measurement using a DHT22 sensor
  • Wind speed and wind direction measurement using a La Crosse TX23 anemometer
  • Rainfall measurement using a WS-2300-16 rain gauge
  • Wireless operation using the very popular nRF24L01+ 2.4 GHz radio chip
  • Very compact CRC32 implementation
  • Battery powered operation using a very efficient 3.3v DC/DC converter
  • Power management by sleeping the CPU and turning off unneeded hardware
  • Battery voltage measurement included in data packet
  • Typical battery draw while sleeping has been measured to around 17uA
  • Total firmware size from 3.0 kiB to 3.5 kiB (depending on sensor type)

The base station

I use a Raspberry Pi as base station. To make it more appliance-like than a typical Raspbian installation, I have instead installed a variant of Tiny Core Linux called piCore. This is basically a very small Linux distribution that loads all programs into memory on boot and leaves the SD card alone after this. This eliminates the usual risk of corrupting the file system when doing a power-cycle.

On the base station I have installed a small python script that continually polls the nRF24L01 radio using the Raspberry Pi’s built-in SPI interface pins. When a data packet arrives, it is buffered (in case of network problems) and forwarded to the database.

The database

With my limited data requirements, I could probably use any old database out there without issues. However, given the nature of the data, it was natural to select a so-called timeseries database. For this project I chose InfluxDB, which was very, very easy to set up on my Ubuntu-based file server. It automatically exposes a simple HTTP interface for storing and querying data, which is just what I need for this project.

The frontend(s)

Well, I’m not quite there yet… So far the only frontend is the admin interface that is built in to InfluxDB. Not very user friendly (not to mention the Wife Acceptance Factor)! The next step now is to make some sort of nice frontend for this. I have several ideas floating around my head:

  • An intranet website. The easiest way.
  • An Android widget. Both the wife and I have Android smartphones.
  • Dedicated hardware devices. This would be a great use-case for my new ESP8266 wifi modules and some 84×48 Nokia LCDs I have lying around.

Stay tuned…

Making prototype perf board hardware

In my last post, I described the various electronic components in my soon-to-be wireless thermo- and hygrometer. In this post, we’ll look at how to wire up some prototype perf boards.

Connecting an nRF24L01 module and a DHT22 sensor to an Arduino

An nRF24L01 radio module communicates with its host using SPI. Luckily for us, the Arduino (as well as most of the Atmel AVR chips in general) supports SPI directly in the hardware. The hardware SPI pins on the Arduino UNO are digital pins 11 (MOSI), 12 (MISO), and 13 (SCK). Furthermore, we need to wire up the radio module’s pins for CSN (Chip Select), CE (Chip Enable), VCC (3.3V), and GND. There’s also a pin called IRQ, but it seems to be used less commonly. All I/O pins are 5V tolerant, but VCC must not be above 3.6V according to the datasheet. This means that we don’t need to have a level-converter chip in order to use the radio module with an Arduino.

nRF24L01

nRF24L01

I connected the module to my Arduino board like this:

nRF24L01 pin: Arduino pin:
1 (GND) GND
2 (VCC) 3.3V
3 (CE) Digital pin 9
4 (CSN) Digital pin 10
5 (SCK) Digital pin 13
6 (MOSI) Digital pin 11
7 (MISO) Digital pin 12
8 (IRQ) Digital pin 8

Please note that the SPI pins are totally different on Arduino Leonardo boards, where they can only be accessed through the ICSP pin header. Backward compatibility FTW…

The DHT22 sensor is much simpler to hook up. It has four pins, but we only need three of them. I would have liked to use one of the remaining “traditional” digital pins on the Arduino, but due to the infamous pin header alignment bug, it’s much easier to reconfigure one of the analog input pins as a digital pin when using perf board. I have used pin A5, which is also known as digital pin 19.

DHT22 pin: Arduino pin:
1 (VCC) 5V (3.3V would probably also work)
2 (DATA) Digital pin 19
3 (N/C)
4 (GND) GND

According to the datasheet, there’s supposed to be a pull-up resistor from the data pin to VCC. In practice it seems that the weak internal pull-up in the ATMEGA chip is enough. The sensor uses a weird 1-wire protocol on the data-pin, but fortunately we have the library provided by Adafruit.

With this knowledge it is just a matter of finding a suitable piece of perf board and the various needed bits and pieces. I must say that I never thought I would find a purpose for this exact piece of scrap perf board, but in this case it’s perfect.

Arduino shield

Arduino shield

When mounted it looks like this:

Arduino with nRF24L01 and DHT22

Arduino with nRF24L01 and DHT22

Connecting an nRF24L01 module to a Raspberry PI

Now we are ready for part two of this post. Again, we are going to use the hardware SPI port provided by the hardware. All the pins we need are located in the big 26-pin P1 header. There’s a nice write-up about P1 (and the other headers) on eLinux.org. I have connected the nRF24L01 module like this:

nRF24L01 pin: Raspberry PI pin (P1 header):
1 (GND) 20 (GND)
2 (VCC) 17 (3.3V)
3 (CE) 16 (GPIO 23)
4 (CSN) 18 (GPIO 24)
5 (SCK) 23 (SCLK / GPIO 11)
6 (MOSI) 19 (MOSI / GPIO 10)
7 (MISO) 21 (MISO / GPIO 9)
8 (IRQ)

This is mostly based on the documentation for this code I found while researching how to connect the parts. It is a Raspberry Pi port of a Beagleboard port of Maniacbug’s nice RF24 library for Arduino. The author writes that he doesn’t know if it works or not. Well it doesn’t. Not right away at least. It took some work to get running, but I’ll get back to that in the next post.

My adaptor board:

nRF24L01 adaptor board for Raspberry Pi

nRF24L01 adaptor board for Raspberry Pi

And mounted on the Pi with a radio module:

Mounted adaptor board

Mounted nRF24L01 adaptor board on Raspberry Pi

That’s it! Our prototype hardware is finished. In the next post I’ll explain how to get a simple ping/pong test working.