Wednesday, January 12, 2011

Temperature and Humidity Sensor on Arduino

I already posted about connecting a temperature sensor to the Arduino, but I wanted to use the opportunity to introduce a small combo board. The SHT15 mini board from sparkfun. They made a convenient mini board to easily access the SHT15 sensor from sensirion, which is well documented. After soldering on a connector for the breadboard, I found a blog post which provided a good working source code to access the data. I changed it only slightly because it already provided the access methods to get the data from the sensor.

The setup is trivial but here it is anyway:



All of the credits for the source go to Maurice Ribble:
int gTempCmd  = 0b00000011;
int gHumidCmd = 0b00000101;
int theDataPin  = 10;
int theClockPin = 11;
int temperatureVal;
int currentTemperatureInF;
int currentTemperatureInC;
int humidityVal;
int currentHumidityInPercent;
int ack;
 
int shiftIn(int dataPin, int clockPin, int numBits)
{
   int ret = 0;
   int i;

   for (i=0; i<numBits; ++i)
   {
      digitalWrite(clockPin, HIGH);
      delay(10);  // I don't know why I need this, but without it I don't get my 8 lsb of temp
      ret = ret*2 + digitalRead(dataPin);
      digitalWrite(clockPin, LOW);
   }

   return(ret);
}

void sendCommandSHT(int command, int dataPin, int clockPin)
{
  // Transmission Start
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, LOW);
          
  // The command (3 msb are address and must be 000, and last 5 bits are command)
  shiftOut(dataPin, clockPin, MSBFIRST, command);

  // Verify we get the correct ack
  digitalWrite(clockPin, HIGH);
  pinMode(dataPin, INPUT);
  ack = digitalRead(dataPin);
  if (ack != LOW)
    Serial.println("Ack Error 0");
  digitalWrite(clockPin, LOW);
  ack = digitalRead(dataPin);
  if (ack != HIGH)
     Serial.println("Ack Error 1");
}

void waitForResultSHT(int dataPin)
{
  int i;
 
  pinMode(dataPin, INPUT);
 
  for(i= 0; i < 100; ++i)
  {
    delay(10);
    ack = digitalRead(dataPin);

    if (ack == LOW)
      break;
  }
 
  if (ack == HIGH)
    Serial.println("Ack Error 2");
}

int getData16SHT(int dataPin, int clockPin)
{
  int val;
 
  // Get the most significant bits
  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  val = shiftIn(dataPin, clockPin, 8);
  val *= 256;

  // Send the required ack
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
          
  // Get the least significant bits
  pinMode(dataPin, INPUT);
  val |= shiftIn(dataPin, clockPin, 8);

  return val;
}

void skipCrcSHT(int dataPin, int clockPin)
{
  // Skip acknowledge to end trans (no CRC)
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
}

void setup()
{
   Serial.begin(9600); // open serial
}

void loop()
{
  sendCommandSHT(gTempCmd, theDataPin, theClockPin);
  waitForResultSHT(theDataPin);
  temperatureVal = getData16SHT(theDataPin, theClockPin);
  skipCrcSHT(theDataPin, theClockPin);
  Serial.print("Temperature in F:");
  currentTemperatureInF = -40.2 + 0.018 * (float)temperatureVal;
  Serial.println(currentTemperatureInF, DEC);
  Serial.print("Temperature in C:");
  currentTemperatureInC = -40.1 + 0.01 * (float)temperatureVal;
  Serial.println(currentTemperatureInC, DEC); 
 
  sendCommandSHT(gHumidCmd, theDataPin, theClockPin);
  waitForResultSHT(theDataPin);
  humidityVal = getData16SHT(theDataPin, theClockPin);
  skipCrcSHT(theDataPin, theClockPin);
  Serial.print("Humidity in percent:");
  currentHumidityInPercent = -4.0 + 0.0405 * humidityVal + -0.0000028 * humidityVal * humidityVal;
  Serial.println(currentHumidityInPercent, DEC);
  Serial.println("");
}
Here is a small demonstration:

LCD Display on Arduino

Let's hook up a LCD display to our Arduino. It is actually pretty easy to do that because there are already pre assembled boards, which can be soldered to adapter boards if you want to use a bus system for example, like I did. However, you could just connect the display board itself directly to the Arduino. Here is a simple schematic of how to do that. You can find plenty of information about LCD displays on the web. Here is a good introduction of the Hitachi HD44780, if you're interested.

To interface the LCD display with an Arduino is also made pretty easy. There already is the LiquidCrystal library which can be used with the Hitachi HD44780 or any compatible chipset. The Arduino IDE comes with an example on how to use it. I share my modified code anyway, so you can have a look at how easy it is.

Souce code:
#include <LiquidCrystal.h> // include a library headfile
// LiquidCrystal display with:
// rs on pin 10
// rw on pin 11
// enable on pin 12
// d4, d5, d6, d7 on pins 13, 14, 15, 16
LiquidCrystal lcd(10, 11, 12, 13, 14, 15, 16);

void setup() {
  lcd.begin(16, 2);
}

void loop() {
  lcd.clear(); //clears the LCD and positions the cursor in the upper-left corner
  lcd.setCursor(3,0); //move cursor to column 4 row 1
  lcd.print("Hi there!"); //print a message to the LCD
  delay(2000);
  lcd.setCursor(3,1); //move cursor to column 4 row 2
  lcd.print("Check out");
  delay(2000);
  lcd.clear();
  lcd.print("marioboehmer.");
  lcd.setCursor(3,1);
  lcd.print("blogspot.com");
  delay(2000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("for more");
  delay(2000);
  lcd.setCursor(1,1);
  lcd.print("experiments!");
  delay(2000);
}
Here it is in action:

Tilt Switch on Arduino

Another simple component is a tilt switch. This simple tilt switch has a mercury ball inside which closes the circuit and sends a high to the input if it is tilted. As an indicator I chose a LED mini board. Both boards can be found in the starter kit from seeedstudio.

This is the souce code. Plain and simple.
int tiltSwitch = 9;
int led = 8;

void setup() {
  pinMode(led,OUTPUT);
  pinMode(tiltSwitch,INPUT);
}

void loop() {
  if(digitalRead(tiltSwitch))
    digitalWrite(led,HIGH);
  else
    digitalWrite(led,LOW);
}

Here is a small demonstration: