zaterdag 11 mei 2013

arduino based thermometer with lcd display and logging

How to make a Deluxe thermometer with an LCD display (who know's when someone is close) and logging to a webserver.
some images

Things it should do

measures the temperature (obvious)
sends data to a webserver (and a database)
show the temperature on a display
tell's if the temperature is rising of dropping over the last
10 minutes.
Display should only work if there's somebody close to the display. This is done by using de arduino's pins to power the LCD backlight.
The backlight controlling pin goes high (backlight on) when another pin goes hight. This other pin is connect to a digital motion sensor.

materials used:

1 arduino with built in ethernet
http://arduino.cc/en/Main/ArduinoBoardEthernet
library
http://arduino.cc/en/Reference/Ethernet

1 digital motion sensor
http://www.ladyada.net/learn/sensors/pir.html
http://iprototype.be/search?search_string=pir

1 lcd 2 x 16 characters based on a Hitachi HD44780 chipset
http://iprototype.be/products/components/led-lcd/lcd16x2-BL
library:
http://arduino.cc/en/Reference/LiquidCrystal

1 NTC (temperature sensitive resistor)
http://iprototype.be/products/components/sensors/ntc

little extra: measuring light
1 ldr (light sensitive resistor)

1 breadboard and a lot of wire

steps

connect the display to the arduino
VSS connects to ground
VDD connects to +5 v
v0 connect to the slider of a 10K potentiometer (one side on the 5V, the other on the ground) RS connects to arduino D7
R/W connects to ground
E connects to arduino D6
D4-D8 connects to arduino D2-D5 (data)
K of backlight connects to ground
A of backlight connects to arduino D9

Digital Motion Sensor (pir)
connect the Red and black wires to the 5v and ground, connect the data wire to the arduino D8.

NTC
NTC is a negative temperature controller, a resistor whose value changes with the temperature. A 10K resitor is used as a pullup resistor. The analoge input (A0) is connected between the NTC and the 10 K resistor
5V --[10K]-- A0 --[NTC]-- ground.

logging the webserver.


On the webserver a cgi script for the arduino.
The script is written in python. This script passed the values on to a database.

how the breadboard was setup




Fritzing schema :  Fritzing

the code

you can download the code here: temp4.ino


/*
Andre Peeters
2013-05-11
Deluxe thermometer v0.2
measures the temperature
sends this to a webserver (and a database)
also shows the temperature on a display
tell's if the temperature is rising of dropping over the last
10 minutes.
Only shows its value if there's somebody close to the display.
(digital motion sensor)

materials used:
1 arduino with built in ethernet
http://arduino.cc/en/Main/ArduinoBoardEthernet
library
http://arduino.cc/en/Reference/Ethernet

1 digital motion sensor
http://www.ladyada.net/learn/sensors/pir.html

1 lcd 2 x 16 characters based on a Hitachi HD44780 chipset
http://iprototype.be/products/components/led-lcd/lcd16x2-BL
library:
http://arduino.cc/en/Reference/LiquidCrystal

1 NTC (temperature sensitive resistor)
http://iprototype.be/products/components/sensors/ntc

1 ldr (light sensitive resistor)

1 breadboard and a lot of wire

*/



/*
ethernet setup
*/
#include
#include
#include

// my mac address
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x8E, 0x23 };

//medion =  my server's dns name
//byte medion[] = { 192, 168, 128, 17 };
char medion[] = "medion";
EthernetClient client; //(medion, 80);
// msg to send to server
String msg;

/*
display setup
*/
// include the library code:
#include

// celsius character
byte celcius[8] = {
  B00110,
  B01001,
  B01001,
  B00110,
  B00000,
  B00000,
  B00000,
};

// arrow up character
byte up[8] = {
  B00000,
  B00100,
  B01110,
  B10101,
  B00100,
  B00100,
  B00000,
};

// arrow down character
byte down[8] = {
  B00000,
  B00100,
  B00100,
  B10101,
  B01110,
  B00100,
  B00000,
};

// line character
byte equal[8] = {
  B00000,
  B00000,
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
};

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

//pir (digital movement sensor)
#define pirIn 8
// lcd backlight control
#define backLight 9

// temperature
float temp;
int light;
int tempArray[] = {0,0,0,0,0,0,0,0,0,0};
int tempAverage;
int t;

//Temp and light sensor
#define InputTemp 0
#define InputLight 1

/*
convert the value messured on the NTR resistor
to celsius degree temperature
*/
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 4100
// the value of the 'other' resistor
#define SERIESRESISTOR 10000

double Thermister(int RawADC) {
  float average;
  average = 1023.0 / RawADC - 1;
  average = SERIESRESISTOR / average;
  float steinhart;
  steinhart = average / THERMISTORNOMINAL; // (R/Ro)
  steinhart = log(steinhart); // ln(R/Ro)
  steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart; // Invert
  steinhart -= 273.15; // convert to C
  return steinhart;
}


void setup() {
    // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("initial setup");
  lcd.setCursor(0,1);
  lcd.print("please wait");
  // create the special chars
  lcd.createChar(0,celcius);
  lcd.createChar(1,up);
  lcd.createChar(2,down);
  lcd.createChar(3,equal);

  // set the digital pins
  pinMode(pirIn,INPUT);
  pinMode(backLight,OUTPUT);
  digitalWrite(backLight,HIGH);

  Serial.begin(9600);
  // init temp
  temp = 0.0;
  light = 0;

  // ethernet setup
  // configure dhcp
  if ( Ethernet.begin(mac) == 0 ) {
    Serial.println("failed to configure dhcp");
    for ( ;; )
      ;
  }
  else {
    // this is my IP address
    Serial.println( Ethernet.localIP() );
  }
  // clear the lcd when setup is done
  lcd.clear();
}

void loop() {
  // get the temperature
  temp = Thermister(analogRead(InputTemp));
 
  // keep the last 10 mesure values as an int
  int tt = temp * 100;
  // shift the values in the array to the front and add the actual
  // temperatur at the back
  for(int x = 1; x < 10; x++) {
    // replace a zero value in the array with the actual temperatur
    if(tempArray[x] == 0) {
      tempArray[x] = tt;
    }
    tempArray[x-1] = tempArray[x];
  }
  tempArray[9] = tt;
 
  // calculate the average temperature over the last 10 mesurements
  tempAverage = 0;
  for(int x = 0; x < 10; x++) {
    tempAverage = tempAverage + tempArray[x] ;
  }
  tempAverage = tempAverage / 10;

  // create a string with the temperature with 2 numbers after the
  // decimal point
  t = temp * 100;
  int t1 = t / 100;
  int t2 = t % 100;
  String ts = "";
  if(t2 < 10) {
    ts = "0";
  }
  String t0 = "";
  t0 = t0 + t1 + "." + ts + t2;

  // convert the light to a number
  light = constrain(map(analogRead(InputLight),0,250,0,100),0,100);
  int l = light;

  // get things on the display
  lcd.setCursor(5,0);
  lcd.print(t0);
  lcd.write(byte(0));
  lcd.setCursor(15,0);
  if ( tempAverage == tt) {
    lcd.write(byte(3));
    lcd.setCursor(0,1);
    lcd.print("     gelijk     ");
  //lcd.print("     equal      ");
  }
  if ( tempAverage < tt) {
    lcd.write(byte(1));
    lcd.setCursor(0,1);
    lcd.print("    stijgend    ");
  //lcd.print("     rising     ");
  }
  if ( tempAverage > tt) {
    lcd.write(byte(2));
    lcd.setCursor(0,1);
    lcd.print("     dalend     ");
  //lcd.print("    dropping    ");
  }

/* 
  lcd.setCursor(0,1);
  lcd.print("light = ");
  lcd.print(l,DEC);
*/
 
  //send the temperature messured to the webserver and database
  String msg  = "GET /cgi-bin/t2.py?t=";
  String msg2 = "&l=";
  String msg3 = " HTTP/1.0";
  msg = msg + t0 + msg2 + l + msg3;
  client.connect(medion,80);
  if (client.connected()){
    Serial.println("connected");
    client.println(msg);
    client.println();
    client.stop();
  } else {
    Serial.println("error");
  }
  client.stop();

  /*
  wait a second an check the motion sensor
  if there is motion, turn on the display and the backlight
  repeat this for a minute, then measure the temperature again.
  */
  for(int x = 0; x < 60; x++) {
    //read pir and turn on the backlight if ok√©
    if(digitalRead(pirIn)) {
      lcd.display();
      digitalWrite(backLight,HIGH);
    } else {
      lcd.noDisplay();
      digitalWrite(backLight,LOW);
    }
   
    // blink a dot
    lcd.setCursor(15,1);
    if(x % 2) {
      lcd.print(".");
    } else {
      lcd.print(" ");
    }
    // wait a second
    delay(1000);
  }
}