Tag Archives: DHT22

Rentalito goes Spark Core

The Rentalito is a never ending project. It began as a funny project at work using an Arduino UNO and an Ethernet Shield, then it got rid of some cables by using a Roving Networks RN-XV WIFI module, after that it supported MQTT by implementing Nick O’Leary’s PubSubClient library and now it leaves the well known Arduino hardware to embrace the powerful Spark Core board.

Spark Core powered Rentalito

Spark Core powered Rentalito – prototype

Spark Core

The Spark Core is a development board based on the STM32F103CB, an ARM 32-bit Cortex M3 microcontroller by ST Microelectronics, that integrates Texas Instruments CC3000 WIFI module. It makes creating WIFI-enabled devices extremely easy.

The main benefits of migrating from the Arduino+RN-XV bundle to Spark Core are:

  • Powerful 32 bit microcontroller
  • Reliable WIFI connection (auto-reset on failure)
  • Smaller foot print
  • OTA programming (even over the Internet)

And of course it’s a good opportunity to add a couple of features: temperature and humidity sensor and IR remote control to switch the display on and off or fast forward messages.

MQTT support

Spark forum user Kittard ported Nick’s MQTT library to the Spark Core. Since the Spark team implemented the Wiring library for the Spark Core it normally takes very little effort to port Arduino code to the Core.

The library supports both subscribing and publishing. You can subscribe to as many topic as you wish and you get the messages in a callback function with the following prototype:


void (*callback)(char*,uint8_t*,unsigned int);

From here it’s very easy to just store the last value for every topic we are subscribed to, along with some metadata like the precision or the units.

Publishing is even easier. A simple call to publish method is all it takes:


bool PubSubClient::publish(char* topic, char* payload);

DHT22 support

DHT22 support is provided by another port, in this case from Adafruit’s DHT library for Arduino. Forum user wgbartley (this guy is from the Spark Elite, people that basically live on the Spark forums) published the ported DHT library for the Spark Core in github.

Recently another user (peekay123, also from the Elite) has published a non-blocking version of the DHT22 library. It uses interrupts to trap transitions on the data line and calculate timings and a state machine to track message structure. The previous one performs all the calculations in a single method call and disables interrupts to keep control over the timing.

HT1632C dot matrix display support

This one I ported it myself from my previous fork of the original HT1632C library for Arduino by an anonymous user. You can checkout the code at bitbucket (Holtek’s HT1632C library for the Spark Core). The library supports:

  • 32×16 displays
  • drawing graphic primitives (points, lines, circles,…)
  • drawing single colour bitmaps
  • printing chars and texts in fixed positions or aligned to the display boundaries
  • red, green and orange colours
  • 23 different fonts
  • 16 levels of brightness
  • horizontal and vertical scroll

It’s still a work in progress but it’s almost in beta stage.

IR remote support

I had an old-verison Sparkfun IR Control Kit (check it here) laying around and I thought it was a good idea to have a way to switch the LED display on and off. I struggled for a couple of days with the IRRemote library for Arduino (like some others) but finally I quit and I decided to implement my own simpler version.

The approach is very much the same as for the DHT22 non-blocking library before: an interrupt-driven routine that calculates and stores pulse lengths and a state machine to know where in the decoding process we are.

void ir_int() {

    if (ir_status == STATUS_READY) return;

    unsigned long now = micros();
    unsigned long width = now - ir_previous;

    if (width > BIT_1) {
        ir_pulses = 0;
        ir_status = STATUS_IDLE;
    } else {
        ir_data[ir_pulses++] = width;
        ir_status = (ir_pulses == 16) ? STATUS_READY : STATUS_DECODING;
    }

    ir_previous = now;

}

Then in the main loop we check if the message is ready, perform the corresponding action and reset the state:

if (ir_status == STATUS_READY) {

    if (millis() > ir_timer) {

        int key = ir_decode();

        switch(key)  {
            case 10: next(); break;
            case 18: previous(); break;
            case 34: brightness(1); break;
            case 42: brightness(-1); break;
            case 2: toggle(); break;
            default: break;
        }

    }

    ir_status = STATUS_IDLE;
    ir_timer = millis() + IR_DEBOUNCE;

}

The decoding is a matter of translating pulse lengths to bits.

int ir_decode() {
    unsigned int result = 0;
    for (byte i = 0 ; i < 16 ; i++)
        if (ir_data[i] > BIT_0) result |= (1<<i);
    if (REMOTE_CHECK != (result & REMOTE_CHECK)) return 0;
    return result >> 8;
}

It’s very important to add some noise reduction components around the IR receiver, otherwise you will only get streams of semi-random numbers every time you press a key in the remote. You can check the datasheet for the specific model you are using (for instance, check the “application circuit” in the first page of the TSOP382 IR receiver Sparkfun sells) or check the schematic in the next section.

Schematic and layout

The project is mostly a software Frankenstein (well, not quite so, you can check the code in bitbucket). The hardware part is pretty simple. You can get all the information you need from tutorials and datasheets. My only advice is to add noise suppression circuitry around the IR receiver.

Schematic

Schematic

Next steps

I’m ready to try to do my first home etching experiment and this project looks like a good candidate. The first step was to create a board layout using Eagle. The board should be one-layered and the form factor the same as the Arduino, so it could use the same holes the Arduino did in the display frame.

And this is the result:

Board layout

Board layout

As you can see it’s mostly one-layered, I will have to use one wire to connect the DHT22 sensor VCC pin. The layout looks promising and I’m eager to see the final result. Hopefully I will post it here soon.

Thanks for reading!

Weather Station

Keeping on registering data from different sensors my next project has been the all-time favourite weather station. This time I wanted to build an 100% autonomous outdoor sensor.

To achieve this goal I started playing with a LiPo battery and a solar panel. The Arduino Fio looked like the perfect out-of-the-box platform to be the center of the project. It’s a ATmega328P (the same micro as the UNO), has a connection for a LiPo battery, a charge circuit based on the MAX1555 (with an USB connector) and a socket for an XBee radio module. So I just really had to wire things up and work on the code to reduce the power consumption to its minimum.

Hardware

This first version of the weather station uses two sensors: a DHT22 and a BMP085. The former is a temperature and humidity sensor that uses a custom one wire digital protocol. The later is a barometric pressure sensor with I2C protocol. Both sensors are 3V3 compatible (like the Fio) and very easy to set up. Adafruit has tutorials and libraries for the two of them here and here.

Weather Station Schema

The schema is so simple I thought it could be a good opportunity to give Fritzing a try. The result could be better. You have to imagine that the CHG and ON holes are connected to the input of the two voltage dividers on the right to check the voltage from the solar panel and the LiPo battery. The other connector by the on/off switch is there to provide an external on/off switch in the future.

Here you have a picture of the sensor. I think I haven’t said this before: I prefer stripboards (veroboards) over perfboards because they are very suitable for rapid development and the final layout is cleaner.

Weather Station sensor

Power management

The main issue with this sensor is power management. The goal was to have an autonomous sensor that will not require battery replacements. Given that Sun is a natural resource freely available most days here in Barcelona that shouldn’t be a problem.

To provide power I chose the Medium 6V 2W solar panel from Adafruit. The Fio charging voltage requirement goes from 3.7V to 7V and this panel fits quite well in that range. The only drawback is the 3.5×1.3 jack connector – a mini USB would have been a perfect match. No worries, the Fio provides a place holder to connect a custom charging source.

And to store energy I’m using a Lithium-Polymer battery rated 3.7V 850mAh. That’s enough power to make it last for weeks applying simple sleeping strategies. When in power down mode the circuitry consumes a negligible amount of energy (not measurable by my instruments, something around 10 uA?). The problem arises when it wakes up.

The DHT22 sensor is a little picky. It requires a warm-up lapse before reading anything and you cannot perform two readings in a row without another delay in between. After some testing I found out that a 2 seconds warm-up time after wake-up produced constant reliable results. Besides, the reading itself is also time (and power) consuming. At the end every time the Arduino wakes up it waits 2 seconds for the DHT22 to warm-up and 2 more seconds to get the reading from it. The reading from the BMP085 is fast (in comparison) and then sending the data by radio produces a burst of ~55mA for 10 millisecs.

State mA ms/event events/h ms/h mA (avg)
Arduino (and XBee) sleeping ~0 - - 3474488 ~0
Warm-up 10 2000 60 120000 0.333
DHT22 reading 12.5 2000 60 120000 0.417
BMP085 reading 10 10 60 600 0.002
XBee awake 25 80 60 4800 0.033
XBee transmitting 54 10 12 120 0.002

The average is ~0.8mA which means around 44 days for a 850mAh battery. Note than 93% of the power consumption is due to the DHT22 reading process. So here there is a big source for power management improvement, but… don’t optimize until you need it.

Since I still had to buy the solar panel and while I was waiting for it to arrive, I powered the sensor and it started transmitting data. I carried the experiment for some weeks until the voltage from the battery fell below 3300mV and the Fio stopped working. It lasted for 37 days, quite accurate.

Then I plugged the solar panel and (after some trouble shooting) it has never gone below 4200mV except twice where it fell well below 3700mV for a short time. So apparently the current set up is more than good enough. I’m even slightly concerned about continuously charging the LiPo battery but the MAX1555 in the Fio should take care of that.

Software

The software is pretty straight forward. I’m using Ben Adams’ DHT22 library and Adafruit’s BMP085 library to interface the sensors. Like in the Smartmeter Pulse Counter project, I’m using Rocket Scream’s Low Power library to put the Fio to sleep. It’s a very useful one-liner to turn ADC and BOD off and put the Arduino to sleep for two seconds (SLEEP_INTERVAL constant). The every 28 (MEASURE_EVERY constant) intervals it gets a reading from the sensors. Since the reading takes 4 seconds that’s roughly one reading per minute. Every 5 (SEND_EVERY constant) measures it awakes the Xbee and sends the average for all the magnitudes.

void loop() {
    ++interval;
    if (interval % MEASURE_EVERY == 0) {
        readAll();
        interval = 0;
        ++measures;
        if (measures % SEND_EVERY == 0) {
            sendAll();
            resetAll();
            measures = 0;
        }
    }
    LowPower.powerDown(SLEEP_INTERVAL, ADC_OFF, BOD_OFF);
}

The data for each magnitude is stored in a structure with 4 values: maximum and minimum values, sum of all values and number of readings so far. Then, when the code is ready to send the data it subtracts the maximum and minimum values from the sum and averages over the rest of values. This way it gets rid of inconsistent readings and the final value is smoother.

The voltage readings for the solar panel and the battery al calculated based on the actual value of the resistors in each voltage divider and they are expressed as constants in the code (BATT_VOLTAGE_FACTOR and PANEL_VOLTAGE_FACTOR).

Finally, I’ve added some code from Tinker London to get the values from the interval thermometer and voltmeter of the ATmega328.

All the code, along with the Fritzing schema and the XBee configuration file is available in Github.

Boxing it

The sensor is housed in a box to prevent direct Sun exposure. It’s common to use a Stevenson Screen as a shelter for a weather station. The “professional” screens are waaaay too expensive (in the 400€ and above range). There are kits online (most notably this one) to build your own shelter or you can always build one buying the parts from the carpenter or repurposing other items. A good source to get ideas and instructions is this site aimed to schools.

I built mine from scratch. It has slats on three sides (the other is attached to the building facade) and holes on the bottom to ease the air flow inside the box. It doesn’t have double roof or chimney since I have glued the solar panel to the top with a methacrylate stand to make it perpendicular to the winter sun. The solar panel angle was a hard decision but since there is a maximum of power I can store I decided it made more sense to get the maximum from the Sun in that not-so-bright days of winter. The perpendicular of the solar panel points SSW, almost 30 degrees above the horizon, to the winter afternoon Sun…

You will have to let me not showing you any pictures of the final box… it fulfils the requirements but it’s ugly as slapping a father with a wet sock (local quote). Definitely  carpentry is not for me.

To do

It would be interesting to add some sort of power monitoring to the solar panel. Right now I only get voltage readings but most of the time the panel is in nearly open circuit mode. Being able of actually get readings for the power it is providing to the charging circuit (in mW) will provide a more accurate view of the and maybe increase the performance or under-scale the solution (maybe a smaller battery or solar panel would do the job).

I’m also planning to add an anemometer to measure wind speed and a rain gauge. The readings from these two sensors will not be very significant, since the whole building could block the rain or the wind or even create twisted flows of wind around it that will fool the sensor but it will be fun nonetheless. If the battery, backed by the solar panel, has enough juice to permanently power the Arduino (that is, not in sleep mode) I could even get readings for maximum speed of wind gusts, if not I might use a binary counter IC or two (74HC590 will be perfect) to store the counts from the anemometer and get the readings from the Arduino once a minute, avoiding the use of interrupts in the code.

Finally, the data from the sensor is public and available in Cosm.com.