PiWeather part 4 : first PCBs

Hello again, dear readers!

I don't have so much time to give to this project, but PiWeather is still moving forward!

The first prototype only had a DS18B20 temperature sensor, and was working on a breadboard, so the next logical step was to design and realize a first PCB for the project. I also moved from the DS18B20 to the DHT22 sensor because it gives both temperature and humidity, and is pretty accurate. I added to that a pressure sensor : the BMP085, sometimes referred to as GY 65 on eBay! This would give my sensor unit the ability to read pressure, temperature and humidity.  That's a good start !

I used EAGLE to design the schematics and the PCB :


PiWeather 0.1 schematics under EAGLE.
PiWeather 0.1 schematics under EAGLE.
The first PCB design.
The first PCB design.

We made the PCB ourselves like we did for our old quadcopter flight controller shield. It is pretty hard to get good results with homemade PCBs, and the tracks have to be very big if you want to be sure there won't be any problems. We got a working PCB on which we soldered the components, and it succesfully worked, powered by two AA cells!

Yep. It is definitely homemade.
Yep. It is definitely homemade.
Isn't it beautiful ? ;)
Isn't it beautiful ? 😉
On this top view, you can see we accidently took a 2 layer plate for our PCB. So we had to remove the copper with a sander :D
On this top view, you can see we accidently took a 2 layer plate for our PCB. So we had to remove the copper with a sander 😀

 

I am pretty happy with this PCB as it works great, but it obviously has drawbacks:

  • PCB making is the worst. It never works as you want, there always is a problem, some tracks are too thin, some are too thick, you have to carefully check for possible shorts...
  • There is no protection against oxydation. Of course you can by some sprays for that, but I don't know if that would work great for an outdoor sensor.
  • The minimum track width is too big to make something small and reliable
  • It's very, very ugly 😀

So I started to look for inexpensive solutions for my PCB to get produced in a "professional" way. And I found exactly what I wanted on Seeedstudio.com .They offer a very cheap PCB service starting at 9.99$ for 5 PCBs of max 5cm x 5cm. Perfect!

Seeedstudio provides you design rule files for EAGLE, so you can see directly if your design will respect their process. I designed a new 2 layer PCB that Seedstudio produced and sent to me in a few days.

The 2 layer PCB for PiWeather v0.2
The 2 layer PCB for PiWeather v0.2

 

I was blown away by the quality of the boards 😀

Here are the two sides of the v0.2
Here are the two sides of the v0.2
It just looks perfect. Nothing more to say.
It just looks perfect. Nothing more to say.
A board ready to be soldered :)
A board ready to be soldered 🙂

 

The v0.2 finally took life and is ready for duty !

In red: the NCP1402 regulator In blue : GY65 barometer White: DHT22 Black: nrf24L01+ The Atmega328p proudly stands in the middle :)
In red: the NCP1402 regulator
In blue : GY65 barometer
White: DHT22
Black: nrf24L01+
The Atmega328p proudly stands in the middle 🙂

v0.2

 

In the next weeks we'll try to build the first outdoor sensor, which will be solar powered. Then we'll probably deploy the website hosting the data gathered by the numerous PiWeather stations 😀

Cheers 🙂

 

Update 25/10/14 : The schematics are on github : https://github.com/psykhi/PiWeatherEAGLE

I also created a Raspberry Pi shield in order to plug the nRF24L01+ 🙂

I will write an article about it!

PiWeather : How to communicate wirelessly between an Arduino and a Raspberry Pi

If you wonder what PiWeather is, check out the first article I wrote !

Raspberry Pi FTW !
Raspberry Pi FTW !

One of the key part of this project is to first determinate what technology to use to transmit the data and second how to encode the data to send. What I wanted was:

  • Reliability
  • Low power design
  • Good range (enough to cover a small house)
  • Ease of use
  • Something cheap
  • Something that could work simply on the Arduino and Raspberry Pi side

RF chip

A standard 433 MHz RX/TX couple

My first choice was spontaneously to pick 433MHz RX and TX as they are incredibly cheap and can reach a pretty long range if you associate them with the right antennas. The problem with these is that the very low-level side of the transmission. If you put the TX pin high, the RX pin will go high too, and that's it. You really have to do all the encoding by yourself, and if you want it to be really reliable, you must provide a way to ensure all your data were transmitted correctly (like a CRC).  I first thought I would have to cope with this and handle all this low-level part by myself on both the Pi and Arduino's sides, when I stumbled upon the one RF chip I needed: the 2.4GHz nRFL24L01+.

nRF24L01+
The nRF24L01+ used on my first prototype.

The nRF24L01+ was exactly what I needed: cheap, low power, easily connected to a Pi or an Arduino through SPI, built-in CRC, both RX and TX at the same time, multi pipe, and more!

It also is really easy to use through SPI: just give it the bytes you want to send (up to 32), and send it to the address of your choice. The same thing goes for the RX mode, it can even generate an IRQ when a message has come!

I used the library from Stanly Seow on both Arduino and Raspberry's side, and it works pretty good! One flaw of the Pi's implementation is that it doesn't use interrupts generated by the nRFL2401+, so it kind of stalls the Pi polling the chip. I modified it a bit to use interrupts from the great WiringPi library, allowing my program to sleep 99.9% of the time. I will get into these details in an other post, stay tuned 😉

Okay, so I know how data will go from my sensor units to the Pi. But what am I going to send?

Messages

So far, I've thought about sending the following data to the Pi from the sensor units:

  • Temperature
  • Pressure
  • Humidity
  • Wind speed
  • Wind direction
  • Rain metrics
  • Unit battery level, to detect low voltage

Also, my units needed some kind of address or unique ID so the Pi could easily recognize them, so I added an ID in the list of things I could possibly send. I could have decided of my own encoding format, but what if I change in the future the things I send and in which order, etc? You can see now that encoding the data in a forward compatible way is really not that simple!

I actually never thought about encoding myself the data 😀 It was just to show you that it is definitely not a piece of cake. I knew exactly what I needed to use : Google Protocol Buffers

From the Google website , "Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler". You can find libraries to use them in almost any available language, from a micro controller with 2kB of RAM running C code, to a server running PHP or Python.

So how does it work?

You first describe the messages you want to send in a file having the .proto extension:

message SensorData{
 required int32 id=1;
 optional bool binding= 2;
 optional float temperature = 3;
 optional int32 battery_level = 4;
 optional float pressure = 5;
 optional float humidity = 6;
 optional int32 type = 7;
 }

message is the keyword required to start defining a message. Then it looks a bit like a mix of a C structure and enum declaration. You define your fields and attribute them a unique ID (ex : the field temperature has the ID 3), and then add if your field is optional or required in the message. In this case, each of my sensor units will have to send its ID to the Pi during a transaction so the Pi know who it is talking to, but some sensors will retrieve temperatures, some wind speed, some pressure, so I made all the other fields optionals.
If I want in the future, to add a new data to my message SensorData, such as windspeed, I can just modify my the proto file like so:

message SensorData{
 required int32 id=1;
 optional bool binding= 2;
 optional float temperature = 3;
 optional int32 battery_level = 4;
 optional float pressure = 5;
 optional float humidity = 6;
 optional int32 type = 7;
 optional float wind_speed = 8;
 }

And you know what the great part about this is? It will be backward compatible with the existing sensor units using the "old" messages! So no need to re-flash the existing sensor units if I had optional fields in my messages, which is a very, very nice thing 🙂 I won't get more into details for GPB here, their website has tons of examples of how to use them!

To actually use these messages, you need to translate them into the language you are using. I chose to use NanoPb, which is a very good implementation of protocol buffers for embedded systems. It has a tiny footprint (less than 2kB!) and generates all the code you need to include in your project, so no need to link against a lib, which is always good news 😉

NanoPb takes the proto file and creates the associated C structures, encoding/decoding functions for my messages. The generated structure looks like this:


typedef struct _SensorData {
 int32_t id;
 bool has_binding;
 bool binding;
 bool has_temperature;
 float temperature;
 bool has_battery_level;
 int32_t battery_level;
 bool has_pressure;
 float pressure;
 bool has_humidity;
 float humidity;
 bool has_type;
 int32_t type;
} SensorData;

Let's say my sensor unit has both a temperature sensor, and a humidity sensor. If I want to send the data to the Pi, I can do like so:

 SensorData message;
 uint8_t sensorDataBuffer[32];/*Maximum size you can send with the nRF24L01*/
 pb_ostream_t stream;

 message->has_temperature=true;
 message->temperature=sensor.temp();
 message->has_humidity=true;
 message->humidity=sensor.humidity();
 message->id=42; /*The unit ID*/

/*Let's encode this with nanopb*/

 stream = pb_ostream_from_buffer(sensorDataBuffer, sizeof(sensorDataBuffer));
 pb_encode(&stream, SensorData_fields, message);

/*Now our encoded data is in the sensorDataBuffer, ready to be sent ! */
 nRF24.send(sensorDataBuffer);

It's as simple as that, and very powerful. I think protocol buffers are really the right way to go for size constrained embedded applications such as this one. But don't think they are only used for small applications, they can be so powerful that they are wildly used in different industries to send big loads of data, through nested messages for example 😉

So that's it, I introduced you the chip I use to make the communications, and the format I adopted for the messages my sensors send wirelessly. I think I will go back on this in a coming article where I will define exactly how the software I developed works.

Cheers 🙂

PiWeather weather station : introduction

The weather station project (codename : PiWeather)

It's been quite a while we haven't posted anything here, but it doesn't mean we're not working on cool things !

A few months ago, I thought it would be cool and useful if I could monitor temperatures inside and outside of my apartment. This way I could know when to open the windows or close them in summer when it gets warmer outside than inside, and the other way around. Then I figured that I might as well add other data, such as pressure, humidity, maybe wind speed and others if I gather the time and the energy to go through with my project, which I admit, rarely happens 😀

Anyway, things are now moving with the project so now is the time to write here. The idea for this first article is to introduce briefly what I will do and how I am planning to do it. I will update this article in the future with links to the latest articles I post about the PiWeather project.

Architecture

The PiWeather main architecture
The PiWeather main architecture

As you probably guessed from the project's codename, the central unit is a Raspberry Pi. The Pi itself does not host any sensor. It will instead be connected wirelessly to them, or more precisely, to what I will call from now on “sensor units”. These sensor units will be Arduino based (what a surprise!) sensor platforms. I mean by this that a sensor unit can host more than one sensor on board, like both a pressure sensor and a temperature sensor for example.

Goals

My goals are :

  • No wires : While the Pi will be connected both to a power source and through Ethernet, the sensor units must be wireless.
  • Plug and play sensors. Just put a battery inside a sensor unit, and you're done. No complicated setup on the computer, through switches, nor command lines.
  •  Longest possible battery life for the sensor units. If you have to change batteries every other week, then being wireless has in fact no point.
  •  Web interface to monitor and access all the logged data
  •  Use cheap parts

There are probably tons and tons of similar projects on the Internet, and I don't really care. The point is as always to have fun, learn, design, and do something useful...Okay, it's not always useful 🙂

Technical topics

On a technical side, the topics I will try to approach during this long journey are:

  • The sensors I used or plan to use
  • Low power Arduino design
  • Arduino development in Eclipse
  • Raspberry Pi program cross compilation
  • Communicate wirelessly between an Arduino and a raspberry Pi
  • Google protocol buffers
  • Symfony 2 PHP framework
  • Create a daemon for Linux
  • Interrupts on Raspberry Pi
  • PCB design
  • Case design (if I make to this stage obviously :D)
  • Twitter Bootstrap
  • Javascript
  • jQuery
  • mySQL
  • phpmyadmin

This list is not exhaustive, but it shows that this project approaches a very broad range of domains and languages .

The articles won't be a series of tutorials. Nothing I will do is new, I will instead focus more on how  all of these things work together, and how the design evolves through time.

And this ends this introduction post 🙂

Follow our RSS feed if you want to hear more about the PiWeather project !