craftwa.re

A walk outside the sandbox

Home Blog Cheat Sheets MacOS Tips Area 51 About

Building A Humidity Temperature Rig With Arduino

|

Logo

Motivation

I’m always very interested in finding out how things work on a lower level and since I had a few spare days I’ve decided to play around with some sensors and an Arduino board I’ve been using for random projects. After all, there are many mechatronics tutorials online, so how hard can it be?

It turned out that a lot of tutorials implicitely assume many prerequisites. Also they didn’t match exactly the electronic pieces I had already ordered (and waited for almost a month to be shipped from overseas!). But overall it was a good learning experience. So in this post I’ll go through all the steps and include fixes for some issues I’ve encountered along the way. Hopefully this will be useful for somebody in a same position as I was a few days ago. Let’s begin!

Hardware components

I’ve experimented with a bunch of different components and in the end stuck with the ones below (click on the images below to expand). I got most of them from DealExtreme but you can probably find them in many other online shops.

  • Arduino Uno R3 Rev3 ATMEGA328P Board:

Arduino Uno R3

  • SYB-120 Breadboard with Jump Wires:

SYB-120

  • DHT22 2302 Digital Temperature and Humidity Sensor Module:

DHT22

  • 0.96 128x64 I2C Blue Color OLED Display Module:

OLED Front

OLED Back

Issue #1 - Cables

My work machine is an Ubuntu 16.04 box. After having no luck to automatically detect the Arduino board, I found the following solution: unplug the arduino, unload the cdc_acm module and reload it.

$ sudo rmmod cdc_acm
$ sudo modprobe cdc_acm

Still not detected. Then I realised the problem was much simpler. The USB printer cable that came with the board was faulty. Not a very common thing but something to be aware of.

After replacing the cable, the board was detected on ttyUSB0 (ch341-uart is the Serial-to-USB converter on the board):

$ dmesg
[23461.758957] usb 1-1.1: new full-speed USB device number 24 using ehci-pci
[23461.852789] usb 1-1.1: New USB device found, idVendor=1a86, idProduct=7523
[23461.852799] usb 1-1.1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[23461.852804] usb 1-1.1: Product: USB2.0-Serial
[23461.854322] ch341 1-1.1:1.0: ch341-uart converter detected
[23461.858347] usb 1-1.1: ch341-uart converter now attached to ttyUSB0

Issue #2 - Breadboard

Something I didn’t notice from the start which was confusing is that the SYB-120 Breadboard has two gaps in each distribution strip: the distribution strips are split into three pieces, instead of running along the board from one end to another, as you would expect from other boards. You can easily notice this if you remove the back cover of the board:

Breadboard back

Software

I’ve used the following software and libraries:

Issue #3 - Arduino IDE upload error

When trying to upload the compiled hex file to the board I got the following pemission error:

avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied
ioctl("TIOCMGET"): Inappropriate ioctl for device

If you read the whole guide above, the fix is already discussed there:

$ sudo usermod -a -G dialout `whoami`
$ sudo chmod a+rw /dev/ttyACM0

Wiring

Humidity/Temperature sensor

To connect and play with the humidity/tempratature sensor, I’ve found an awesome blog that explained everything:

screenshots

Two things were different in my setup:

  • First, my sensor came out mounted on a breakout board, so it didn’t require the 10K pull up resistor.
  • The pins for my mounted sensor were different than the ones in the image above. The mapping is as follows: + → VCC, - → GND, OUT → DATA.

I2C OLED Display

I’ve found the instructions to hook the OLED display here. The PIN from the OLED maps to the Arduino Uno as follows:

  • OLED GND – Arduino GND
  • OLED VCC – Arduino 5V
  • OLED SCL – Arduino Uno A5
  • OLED SDA – Arduino Uno A4

screenshots

If you’re going through the article, one important section is Modifying the SSD1306 Driver. Don’t skip it! After connecting everything, my board looks like this (all connections are visible, click to expand):

Final board

Coding

Finally, let’s do some coding. After putting the board together, I’ve tested separately the OLED and the DHT22 sensor. All good. The ssd1306_128x64_i2c sketch example (File → Examples → Adafruit SSD1306) demoes all the functionality of the GFX library and is a good starting point for working with the OLED.

Issues #4 - Generate a custom PROGMEM bitmap

The example from the Adafruit GFX Graphics Library draws the Adafruit logo using a 16x16 bitmap. I wanted to replace the logo with something else. Although this can be done manually as well, this site converts an image into a PROGMEM bitmap and has a lot of options as well.

The final code:

#include <cactus_io_DHT22.h>

// what pin on the arduino is the DHT22 data line connected to
#define DHT22_PIN 2     

// Initialize DHT sensor for normal 16mhz Arduino. 
DHT22 dht(DHT22_PIN);

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

// 64x64px Apple logo
const unsigned char PROGMEM logo[]  = {  
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 
  0xff, 0xff, 0xe0, 0x7f, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xf8, 0x00, 0x1f, 0xff, 
  0xff, 0xfc, 0x00, 0x01, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 
  0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
  0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 
  0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 
  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 
  0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 
  0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 
  0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 
  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 
  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
  0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 
  0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
  0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 
  0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 
  0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 
  0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xff, 
  0xff, 0xff, 0xc0, 0x03, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xfe, 0x01, 0xff, 0xff, 
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
};

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {
  // Initialise serial (print stats and debug info)           
  Serial.begin(9600);

  // Initialise DHT library
  dht.begin();
  
  // initialize with the I2C addr 0x3C (Hint: Use I2C Scanner)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // Clear the buffer containing defualt Ada splashscreen
  display.clearDisplay();

  // Display logo
  display.drawBitmap(30, 0,  logo, 64, 64, 1);
  display.display();
  delay(3000);
}


void loop() {
  static char buf[15];
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  dht.readHumidity();
  dht.readTemperature();
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(dht.humidity) || isnan(dht.temperature_C)) {
    Serial.println("DHT sensor read failure!");
    return;
  }
 
  Serial.print(dht.humidity); Serial.print(" %\t\t");
  Serial.print(dht.temperature_C); Serial.print(" *C\n");

  // Print relative humidity and temperature
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.clearDisplay();
  display.println("RH - Temp");
 
  display.setCursor(0,25);
  dtostrf(dht.humidity,5, 2, buf);
  display.print(buf);
  display.println(" %");
  
  display.setCursor(0, 50);
  dtostrf(dht.temperature_C,5, 2, buf);
  display.print(buf);
  display.println(" *C");

  // Actually print stuff!
  display.display();
  
  // Wait a few seconds between measurements. The DHT22 should not be read at a higher frequency of
  // about once every 2 seconds. So we add a 3 second delay to cover this.
  delay(3000);
}

Demo

References