Showing posts with label Arduino Nano. Show all posts
Showing posts with label Arduino Nano. Show all posts

Friday, May 15, 2015

Temperature & Humidity monitor using Arduino NANO + DHT11 + 0.96 inch 128X64 I2C OLED

A simple Temperature & Humidity monitor using Arduino NANO + DHT11 + 0.96 inch 128X64 I2C OLED.

Reference:
- Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library
Arduino Nano + DHT11, Temperature & Humidity sensors
- To convert the float returned by dht library to string (cahr array) for u8glib to display, function dtostrf() is used.
  • The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.
    Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.
    The dtostrf() function returns the pointer to the converted string s.
- To display the degree sign (°C or °F) on the mini OLED using u8glib, use te string:
°C : "\260C"
°F : "\260F"



NANO_DHT11_I2C_OLED.ino
// Read DHT11 humidity/temperature sensors
// display on 0.96 inch 128X64 I2C OLED

#include "DHT.h"
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor for normal 16mhz Arduino
//DHT dht(DHTPIN, DHTTYPE);
// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
DHT dht(DHTPIN, DHTTYPE, 6);

char str[10];

void drawTest(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 20, "DHTxx test!");
}

void setup() {
  Serial.begin(9600); 
  Serial.println("DHTxx test!");
 
  dht.begin();
  u8g.firstPage();  
  do {
    drawTest();
  } while( u8g.nextPage() );
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index
  // Must send in temp in Fahrenheit!
  float hi = dht.computeHeatIndex(f, h);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  
  Serial.print("Heat index: ");
  Serial.print(hi);
  Serial.println(" *F");
  
  // picture loop
  u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_helvB08);
    
    u8g.drawStr( 0, 15, "Humidity:");
    u8g.drawStr( 80, 15, dtostrf(h, 5, 2, str));
    u8g.drawStr( 120, 15, "%");
    
    u8g.drawStr( 0, 30, "Temperature:");
    u8g.drawStr( 80, 30, dtostrf(t, 5, 2, str));
    u8g.drawStr( 120, 30, "\260C");
    
    u8g.drawStr( 80, 45, dtostrf(f, 5, 2, str));
    u8g.drawStr( 120, 45, "\260F");
    
    u8g.drawStr( 0, 60, "Heat index:");
    u8g.drawStr( 80, 60, dtostrf(hi, 5, 2, str));
    u8g.drawStr( 120, 60, "\260F");
    
  } while( u8g.nextPage() );
}


Related:
- Arduino Due + ESP8266 + DHT11, to update dweet.io


Monday, May 11, 2015

Arduino Nano + DHT11, Temperature & Humidity sensors

This example run on Arduino Nano, read DHT11 (Temperature & Humidity sensors), send data to PC via serial. The library adafruit/DHT-sensor-library is used to read DHT11.



The library adafruit/DHT-sensor-library is included in Arduino IDE library sources, so it's easy to add it to your project. Read the video to know how to add the library to Arduino IDE.


Once the library added, you can find a example in File -> Examples -> DHT sensor library -> DHTtester.


To make it work on Arduino Nano + DHT11, DHTtester.ino
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor for normal 16mhz Arduino
//DHT dht(DHTPIN, DHTTYPE);
// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
DHT dht(DHTPIN, DHTTYPE, 6);

void setup() {
  Serial.begin(9600); 
  Serial.println("DHTxx test!");
 
  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index
  // Must send in temp in Fahrenheit!
  float hi = dht.computeHeatIndex(f, h);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  Serial.print("Heat index: ");
  Serial.print(hi);
  Serial.println(" *F");
}

Sunday, April 26, 2015

Simple Compass - Arduino Nano + GY-271(HMC5883L) + mini-OLED

Use Arduino Nano + GY-271 Digital Compass Module (with HMC5883L) + 0.96" I2C mini-OLED to implement a simple compass.


For HMC5883L library with calibration, refer LAST POST.
For u8glib library used on 0.96" I2C mini OLED, refer Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library.
Connection between Arduino Nano, GY-271 and the mini OLED via I2C, refer to Arduino Nano + GY-271 (Digital Compass module) + OLED.


Nano_Compass.ino
/*
http://arduino-er.blogspot.com/

For HMC5883L_Header_Arduino_Auto_calibration library
ref: http://hobbylogs.me.pn/?p=17

For u8glib Universal Graphics Library for 8 Bit Embedded Systems
ref: https://code.google.com/p/u8glib/
*/

#include "U8glib.h"
#include <Wire.h>
#include "compass.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#define Task_t 10          // Task Time in milli seconds

int dt=0;
unsigned long t;
// Main code -----------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  // Serial.print("Setting up I2C ........\n");
  Wire.begin();
  compass_x_offset = -48.23;  //122.17;
  compass_y_offset = 284.69;  //230.08;
  compass_z_offset = 59.87;  //389.85;
  compass_x_gainError = 1.07;  //1.12;
  compass_y_gainError = 1.09;  //1.13;
  compass_z_gainError = 1.01;  //1.03;
  
  compass_init(2);
  //compass_debug = 1;
  //compass_offset_calibration(3);

}

void loop(){
  
  t = millis();
 
  float load;
 
  compass_scalled_reading();
  
  Serial.print("x = ");
  Serial.println(compass_x_scalled);
  Serial.print("y = ");
  Serial.println(compass_y_scalled);
  Serial.print("z = ");
  Serial.println(compass_z_scalled);
  
  compass_heading();
  Serial.print ("Heading angle = ");
  Serial.print (bearing);
  Serial.println(" Degree");
  
  dt = millis()-t;
  load = (float)dt/(Task_t/100);
  Serial.print ("Load on processor = ");
  Serial.print(load);
  Serial.println("%");
  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );

  delay(100);
}

void draw(void) {
  static int armLength = 20;
  static int cx = 64;
  static int cy = 20;
  int armX, armY;
  
  //convert degree to radian
  float bearingRad = bearing/57.2957795;
  armX = armLength*cos(bearingRad);
  armY = -armLength*sin(bearingRad);

  u8g.setFont(u8g_font_unifont);
  
  u8g.setPrintPos(0, 60);
  u8g.print("bearing: ");
  u8g.setPrintPos(70, 60);
  u8g.print(bearing);
  
  u8g.drawLine(cx, cy, cx-armX, cy-armY);
  u8g.drawCircle(cx, cy, armLength, U8G_DRAW_ALL);

}

Saturday, April 25, 2015

HMC5883L library with calibration, for Arduino

Last post I read HMC5883L (in GY-271) from Arduino Nano. Then I tried to convert to bearing by calling atan2((double)y, (double)x) * 180/M_PI. The result have very big error without calibration. Finally I found this library HMC5883L Header Arduino With Auto calibration. For detail about the functions read http://hobbylogs.me.pn/?p=17#more-17


Here is modified from Compass_header_example_ver_0_2.ino to display bearing on mini OLED.
/*
For HMC5883L_Header_Arduino_Auto_calibration library
ref: http://hobbylogs.me.pn/?p=17
*/

#include "U8glib.h"
#include <Wire.h>
#include "compass.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#define Task_t 10          // Task Time in milli seconds

int dt=0;
unsigned long t;
// Main code -----------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  // Serial.print("Setting up I2C ........\n");
  Wire.begin();
  compass_x_offset = -48.23;  //122.17;
  compass_y_offset = 284.69;  //230.08;
  compass_z_offset = 59.87;  //389.85;
  compass_x_gainError = 1.07;  //1.12;
  compass_y_gainError = 1.09;  //1.13;
  compass_z_gainError = 1.01;  //1.03;
  
  compass_init(2);
  //compass_debug = 1;
  //compass_offset_calibration(3);

}

// Main loop 
// Main loop -----------------------------------------------------------------
void loop(){
  
  t = millis();
 
  float load;
 
  compass_scalled_reading();
  
  Serial.print("x = ");
  Serial.println(compass_x_scalled);
  Serial.print("y = ");
  Serial.println(compass_y_scalled);
  Serial.print("z = ");
  Serial.println(compass_z_scalled);
  
  compass_heading();
  Serial.print ("Heading angle = ");
  Serial.print (bearing);
  Serial.println(" Degree");
  
  dt = millis()-t;
  load = (float)dt/(Task_t/100);
  Serial.print ("Load on processor = ");
  Serial.print(load);
  Serial.println("%");
  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );

  
  delay(100);
}

void draw(void) {
  u8g.setFont(u8g_font_unifont);

  u8g.setPrintPos(0, 15);
  u8g.print("x: ");
  u8g.setPrintPos(70, 15);
  u8g.print(compass_x_scalled);
  
  u8g.setPrintPos(0, 30);
  u8g.print("y: ");
  u8g.setPrintPos(70, 30);
  u8g.print(compass_y_scalled);
  
  u8g.setPrintPos(0, 45);
  u8g.print("z: ");
  u8g.setPrintPos(70, 45);
  u8g.print(compass_z_scalled);
  
  u8g.setPrintPos(0, 60);
  u8g.print("bearing: ");
  u8g.setPrintPos(70, 60);
  u8g.print(bearing);

}

For compass.cpp and compass.h, refer to https://github.com/helscream/HMC5883L_Header_Arduino_Auto_calibration/tree/master/Core/Compass_header_example_ver_0_2.



Next:
- Simple Compass - Arduino Nano + GY-271(HMC5883L) + mini-OLED

Friday, April 24, 2015

Arduino Nano + GY-271 (Digital Compass module) + OLED

This example show a Arduino Nano, connect with GY-271 Digital Compass module and 0.96" 128x64 OLED via a common I2C bus. GY-271 is a Digital Compass module using HMC5883L, a 3-Axis Digital Compass IC. The reading from GY-271 (x, y, abd z) is display on the OLED. Arduino Nano communicate with GY-271 via I2C bus using Wire library. Arduino Nano communicate with 0.96" 128x64 OLED via the same I2C bus, using u8glib library. I'm not sure is it 100% compatible to use both Wire and u8glib libraries, both share the common I2C bus. Anyway in this example it work.


Connection:
VCC of GY-271, OLED and Arduino Nano connect together.
GND of GY-271, OLED and Arduino Nano connect together.
SCL of GY-271 and OLED connect to A5 of Arduino Nano.
SDA of GY-271 and OLED connect to A4 of Arduino Nano.
DRDY of GY-271 no connection.
(In the following Fritzing drawing, the HMC5883 breakout not exactly my GY-271 module, just to show the connect of SCL and SDA.)


Nano_OLED_Compass.ino
#include "U8glib.h"
#include <Wire.h> //I2C Arduino Library

#define address 0x1E //0011110b, I2C 7bit address of HMC5883

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

int x,y,z; //triple axis data

char bufferX [20];
char bufferY [20];
char bufferZ [20];

void draw(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 20, bufferX);
  u8g.drawStr( 0, 40, bufferY);
  u8g.drawStr( 0, 60, bufferZ);

}

void setup(void) {
  x = 0;
  y = 0;
  z = 0;
  
  Wire.begin();
  
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();

}

void loop(void) {
  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
 
 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  sprintf(bufferX, "x : %d", x);
  sprintf(bufferY, "y : %d", y);
  sprintf(bufferZ, "z : %d", z);

  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  delay(100);
}



Then I tried to find the bearing by calling atan2((double)y, (double)x) * 180/M_PI, but get a very big error without calibration. Finally I found a library with auto calibration, read next: HMC5883L library with calibration, for Arduino.

About 3-Axis Digital Compass IC HMC5883L:



- 3-Axis Digital Compass IC HMC5883L
- Application Note – AN226 Honeywell HMC5883L/HMC5983 3-Axis Digital Compass IC Pin Configuration for I2C Communication

Tuesday, April 21, 2015

Arduino Nano: Capture analog input in Timer Interrupt

Last post show a "oscilloscope-like waveform on 0.96" 128X64 I2C OLED with Arduino Nano". But the analog input is captured inside loop(), it's not in fixed timing, and affected by the slow operation of displaying.

To capture analog input in accurate timing, we are going to implement TIMER1 ISR (Interrupt Service Routine) in this example, and call analogRead() to capture analog input inside ISR.


Connecttion between Arduino Nano and OLED, refer to last post.

To understand Arduino Timer and Interrupt, it have a good tutorial HERE.

I2C_OLED_scope.ino
// Display analog input to mini-OLED I2C,
// capture input inside TIMER1 ISR
// http://arduino-er.blogspot.com/

// OLED display: ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const int WIDTH=128;
const int HEIGHT=64;
const int LENGTH=WIDTH;

const int LED = 13;
boolean LEDst = false;

//true: request capture analog input in ISR
//false: stop capture, draw waveform in loop
boolean capture = false;

const int analogInPin = A0;
int analogInValue = 0;

int x;
int y[LENGTH];

/*
    reference: Arduino Timer and Interrupt Tutorial
    http://blog.oscarliang.net/arduino-timer-and-interrupt-tutorial/
    
    For our TIMER1 Interrupt:
    Clock Freq = 16MHz
    no prescale, 1
    16MHz - 0.0625us/cycle
   
    To calculator preload value to generate 1ms(1KHz) 
    (65536 - t) x 0.0625us = 1000us
    t = 65536 - 1000/0.0625 = 49536
    
    To calculator preload value to generate 0.5ms(2KHz)
    (65536 - t) x 0.0625us = 500us
    t = 65536 - 500/0.0625 = 57536

 */
const int TCNT1_PRELOAD = 57536;

void clearY(){
  for(int i=0; i<LENGTH; i++){
    y[i] = -1;
  }
}

void drawY(){
  u8g.drawPixel(0, y[0]);
  for(int i=1; i<LENGTH; i++){
    u8g.drawLine(i-1, y[i-1], i, y[i]);
  }
}

void setup(void) {
  
  pinMode(LED, OUTPUT);
  
  // initialize Timer1
  noInterrupts(); // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = TCNT1_PRELOAD;
  TCCR1B |= (1 << CS10);   // no prescaler
  TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
    
  x = 0;
  clearY();
  capture = true;

  interrupts(); // enable all interrupts  
}

void loop(void) {
  if(!capture){
    
    u8g.firstPage();  
    do {
      drawY();
    } while( u8g.nextPage() );
    
    //start capture another frame
    x = 0;
    clearY();
    capture = true;
  }

  delay(100);

}

ISR(TIMER1_OVF_vect){
  TCNT1 = TCNT1_PRELOAD; // preload timer
  
  if(capture){
    //toggle LED
    digitalWrite(LED, LEDst=!LEDst);
  
    analogInValue = analogRead(analogInPin);
    y[x] = map(analogInValue, 0, 1023, HEIGHT-1, 0);
    
    x++;
    if(x >= WIDTH){
      capture = false;
    }
  }
}

Monday, April 20, 2015

Display waveform on mini OLED with Arduino Nano

Display oscilloscope-like waveform on 0.96" 128X64 I2C OLED with Arduino Nano. Read analog input (A0) and plot the waveform acordingly.



// ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const int WIDTH=128;
const int HEIGHT=64;
const int LENGTH=WIDTH;

const int analogInPin = A0;
int analogInValue = 0;

int x;
int y[LENGTH];

void clearY(){
  for(int i=0; i<LENGTH; i++){
    y[i] = -1;
  }
}

void drawY(){
  u8g.drawPixel(0, y[0]);
  for(int i=1; i<LENGTH; i++){
    if(y[i]!=-1){
      //u8g.drawPixel(i, y[i]);
      u8g.drawLine(i-1, y[i-1], i, y[i]);
    }else{
      break;
    }
  }
}

void setup(void) {
  x = 0;
  clearY();
}

void loop(void) {
  
  analogInValue = analogRead(analogInPin);
  
  y[x] = map(analogInValue, 0, 1023, HEIGHT-1, 0);;

  u8g.firstPage();  
  do {
    drawY();
  } while( u8g.nextPage() );
  
  //delay(10);

  x++;
  if(x >= WIDTH){
    x = 0;
    clearY();
  }
}


This example read analog input inside loop(), it's not in fixed timing, and affected by the slow operation of displaying. To read input in accurate timing, Refer to next post "Capture analog input in Timer Interrupt".

Walking bitmap on 0.96 inch 128X64 I2C OLED x Arduino Nano

Implement walking bitmap on 0.96 inch 128X64 I2C OLED x Arduino Nano V3.0 (ATmega328 5V), using u8glib library.


(Refer to te post "Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library" to install the library to Arduino IDE)

Connect the 0.96 inch 128X64 I2C OLED to Arduino Nano:

GND - GND on Arduino Uno
VCC - 5V on Arduino Uno
SCL - A5 on Arduino Uno
SDA - A4 on Arduino Uno

I2C_OLED_bitmap.ino
// ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const uint8_t bm[] PROGMEM = {
  0b00011000,
  0b00111100,
  0b01111110,
  0b11111111,
  0b11111111,
  0b01111110,
  0b00111100,
  0b00011000
};

static int WIDTH=128;
static int HEIGHT=64;

int x, y;

void setup(void) {
  x = 0;
  y = 0;
}

void loop(void) {

  u8g.firstPage();  
  do {
    u8g.drawBitmapP( x, y, 1, 8, bm);
  } while( u8g.nextPage() );
  
  delay(100);

  x += 8;
  if( x >= WIDTH){
    x = 0;
    y += 8;
    if( y >= HEIGHT){
      y = 0;
    }
  }
}