Saturday, November 27, 2010

The DS18B20 Digital Thermometer

Dallas Semiconductor (Maxim) produces a line of "One-Wire" devices, that allow multiple sensors to connect to a single data pin on a microcontroller. GND and +5vdc are also needed. I've put together a single sensor DS18B20 (soon to be expanded to multiple sensors) displaying the temperature on a LCD display. This example is digital, unlike the analog thermistor project from a few days ago. Enjoy, and please comment.

// LCD Thermostat
// www.hacktronics.com

#include <onewire.h>
#include <liquidcrystal.h>

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int backLight = 13; // pin 13 will control the backlight

OneWire ds(8); // ds18b20 pin #2 (middle pin) to Arduino pin 8
// ds18b20 pin #1 GND
// ds18b20 pin #3 +5vdc
// 5k ohm resistor between pins 2 & 3

byte i;
byte present = 0;
byte data[12];
byte addr[8];
 
int HighByte, LowByte, SignBit, Whole, Fract, TReading, Tc_100, FWhole;

void setup(void) {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(2,16);              // rows, columns.  use 2,16 for a 2x16 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0
 
    if ( !ds.search(addr)) {
      lcd.clear(); lcd.print("No more addrs");
      delay(1000);
      ds.reset_search();
      return;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      lcd.clear(); lcd.print("CRC not valid!");
      delay(1000);
      return;
  }
}

void getTemp() {
  int foo, bar;
 
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);

  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
 
  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
 
  if (SignBit) {
    TReading = -TReading;
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
  Whole = Tc_100 / 100;          // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
  if (Fract > 49) {
    if (SignBit) {
      --Whole;
    } else {
      ++Whole;
    }
  }

  if (SignBit) {
    bar = -1;
  } else {
    bar = 1;
  }
  foo = ((Whole * bar) * 18);      // celsius to fahrenheit conversion section
  FWhole = (((Whole * bar) * 18) / 10) + 32;
  if ((foo % 10) > 4) {            // round up if needed
       ++FWhole;
  }
}

void printTemp(void) {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Temp is: ");
  lcd.setCursor(0,1);  
 
  if (SignBit) { 
     lcd.print("-");
  }
  lcd.print(Whole);
  lcd.print(" C / ");
  lcd.print(FWhole);
  lcd.print(" F");
}

void loop(void) {
  getTemp();
  printTemp();
  delay(1000);
}

Friday, November 26, 2010

CdS Light Sensor

I've been playing with my Cadmium Sulfide (CdS) photoresistors, and have put together a basic light sensor. I'm outputting raw values, so there is no correlation with solar insolation. If anyone knows some cool formulas that would convert the output to sun hours, I'd love to play with them. The wiring is documented in the code as follows:




#include <LiquidCrystal.h>

/*
LCD Connections:
rs (LCD pin 4) to Arduino pin 12
rw (LCD pin 5) to Arduino pin 11
enable (LCD pin 6) to Arduino pin 10
LCD pin 15 to Arduino pin 13
LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2

Cds Connections:
CdS Pin 1 to +5v
CdS Pin 2 to Analog Pin 0
10k ohm resistor pin 1 to Analog Pin 0
10k ohm resistor pin 2 to Gnd
*/

LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int backLight = 13;    // pin 13 will control the backlight
int sensorPin = 0;
int val = 0;


void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(20, 4);              // rows, columns.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                   // start with a blank screen
  lcd.setCursor(0,0);            // set cursor to column 0, row 0
  lcd.print("Light level is:");
}



void loop() {
  val = analogRead(sensorPin);
  lcd.setCursor(0,1);
  lcd.print (val);
  delay(100);
   }