Benutzer-Werkzeuge

Webseiten-Werkzeuge


Übersetzungen dieser Seite:
de:i2c_arduino

I2C Sensoren mittels USB auslesen

Mit der Arduino Plattform lassen sich allerhand Dinge anstellen. So auch Daten vom I2C Bus lesen und LCDs ansteuern. Und ganz nebenbei kann man per USB mit einem PC kommunizieren.

Grundlage ist ein Atmel Microcontroller mit etlichen I/O Anschlüssen und ein Serial/USB Adapter (auch mit einem Atmel realisiert) zum Anschluss an PCs und zur einfachen Programmierung.

Warum das Ganze?

Temperaturen mit DS1621 messen

Ursprünglich habe ich vor Jahren nach einem billigen Thermometer gesucht, das man an einen Server anschließen kann. Damit wollte ich damals einen improvisierten Serverraum überwachen.

Dabei bin ich auf das Webtherm Projekt gestoßen, bei dem ein DS1621 Temperatursensor mit etwas Beschaltung an den seriellen Port angeschlossen wird. Ein kleines Programm spielt dann I2C auf der RS232 und liest den Sensor, bzw. die Sensoren aus. Man kann bis zu acht DS1621 an einem I2C Bus betreiben.

Das Programm hatte seine Macken, so musste man ein paar mal lesen um einen verlässlichen Wert zu bekommen, aber es hat funktioniert. Leider werden Rechner mit RS232 immer seltener …

Integration in Nagios

Von Anfang an war die Integration in Nagios ein wesentliches Ziel. Aber wenn man schon Hardware an den Server anschließt, kann man dann nicht auch mehr machen?

Wäre eine Ausgabe des aktuellen Status nicht auch nett? Zum Beispiel in Form einer Ampel? Dazu habe ich auch schon einmal einen Hack mit legacy Schnittstellen gebaut. Fein wäre noch eine Textausgabe …

LCD Ansteuerung

Mit einem zweizeiligen LCD könnte man schon mehr Informationen transportieren als mit drei LEDs. Und hier kommen die Microcontroller ins Spiel.

Mit dem Arduino lässt sich das alles ganz einfach bewerkstelligen.

Testaufbau

Um einmal zu sehen, ob das überhaupt funktionieren kann, habe ich einen Testaufbau mittels Breadboard erstellt.

I2C Ansteuerung

Der IC auf dem Schema ist besagter DS1621. Der Anschluss an den Arduino ist simpel:

PIN (DS) Name Arduino Kabelfarbe Bemerkung
1 SDA A4 braun I2C Datenleitung
2 SCL A5 weiss I2C Clock
3 Tout - - unbenutzt (hier könnte man bei Schwellwerten ein Signal ausgeben → Thermostat)
4 GND GND schwarz Masse
5 A2 - schwarz Bit 2 der Sensoradresse
6 A1 - schwarz Bit 1 der Sensoradresse
7 A0 - schwarz Bit 0 der Sensoradresse
8 VDD +3.3V orange Betriebsspannung, 2,7 ~ 5,5V

Über die Pins A0..A2 stellt man die Sensoradresse ein … jetzt ist wohl auch klar warum man nur acht DS1621 an einem I2C betreiben kann, obwohl der Bus 112 Devices adressieren könnte. ;-)

LCD

Als Display habe ich ein zweizeiliges LCD mit LED Hintergrundbeleuchtung gewählt (weil es der Hädler im Sortiment hatte). Was man wissen muss steht im Datenblatt, den Rest beschreibe ich:

PIN (LCD) Name Arduino Kabelfarbe Bemerkung
1 VSS GND schwarz Masse
2 VDD +5V rot Betriebsspannung
3 V0 - gelb Displaykontrast - durch einen Spannungsteiler realisiert
4 RS D12 grau Register select
5 R/W D11 grau Read/write select
6 E D10 grau Operation enable
7~10 DB0~DB3 - - siehe Datenblatt
11~14 DB4~DB7 D5~D2 grau High order Data Bus
15 A D9 gelb LED Hintergrundbeleuchtung - Anode
16 K GND schwarz LED Hintergrundbeleuchtung - Kathode

Zu meiner großen Freude benötigt man ausser dem Spannungsteiler keine analogen Bauteile.

In der realen Welt sieht das dann so aus:

Halogen-Schreibtischlampen erzeugen ganz schön viel Strahlungswärme! :-)

Da mir die Teststrippen recht bald zu wenig waren, habe ich den Datenbus mit Flachbandkabeln realsisert. Auch für den DS1621 hatte ich zu wenig Kabel und habe daher auf die Anordnung vom alten Projekt zurückgegriffen. Der Kondensator kommt auch daher, er soll bei längeren Leitungen helfen …

Software

Das Ganze soll ja jetzt auch untereinander und später mit der Aussenwelt kommunizieren. Dazu muss ein bischen programmiert werden.

Firmware für Arduino

Dank der umfangreichen Bibliotheken ist das Programm erstaunlich knapp und recht gut lesbar:

//
// ds1621_lcd.pde
//
// This simple Arduino project reads temerature from DS1621 via I2C
// and outputs to LCD and USB
//
// v0.3 2011-03-25 GS <goesta@smekal.at>
//
/*
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   http://www.gnu.org/licenses
*/
 
#include <LiquidCrystal.h>	// LCD interface library
#include <Wire.h>		// I2C library
#define DEV_ID 0x90 >> 1
#define NAME "DS1621-Therm 0.3"
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int backLight = 9;		// use digital pin 9 to control LCD backlight
int dataRead = 13;		// show I2C activity with on board LED
 
void setup()
{
  Serial.begin(9600);
  Serial.println(NAME);
  pinMode(dataRead, OUTPUT);
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); 
  lcd.begin(16,2);             
  lcd.clear();                  
  lcd.setCursor(0,0);          
  lcd.print(NAME);  
  lcd.setCursor(0,1);          
  lcd.print("initializing ...");
 
  i2cInit();    // call device to attention
}
 
 
void loop()
{
  int temp;
  int decimal;
  i2cInit();    // call device to attention
  delay(1000);  // wait for sensor to convert data
 
  digitalWrite(dataRead, HIGH);    // show I2C activity
  Wire.beginTransmission(DEV_ID);
  Wire.send(0xAA);
  Wire.endTransmission();
  Wire.requestFrom(DEV_ID, 2);     // request two bytes of data
  temp = Wire.receive();           // integer value comes first
  decimal = Wire.receive();        // decimal/negative info
  digitalWrite(dataRead, LOW);
 
  lcd.clear();                  
  lcd.setCursor(0,0);          
  lcd.print(NAME);  
  lcd.setCursor(0,1);          
  lcd.print("Sensor0:");
  lcd.setCursor(9,1);
  lcd.print(temp);
  lcd.setCursor(11,1);
  if ( decimal == 0 ) {
    // no decimal
    lcd.print(".0");
    Serial.print(temp);
    Serial.println(".0 C");
  }
  else {
    //.5 degrees
    lcd.print(".5");
    Serial.print(temp);
    Serial.println(".5 C");
  }
  lcd.setCursor(13,1);
  lcd.print(" C");
}
 
void i2cInit() {
  digitalWrite(dataRead, HIGH);		// show activity on LED
  Wire.begin();
  Wire.beginTransmission(DEV_ID);           // connect to DS1621 (#0)
  Wire.send(0xAC);                          // Access Config
  Wire.send(0x02);                          // set for continuous conversion
  Wire.beginTransmission(DEV_ID);           // restart
  Wire.send(0xEE);                          // start conversions
  Wire.endTransmission();
  digitalWrite(dataRead, LOW);
}

To do

Weil das mit dem I2C Bus keine so gute Idee ist (die Leitunslängen sind für rund einen Meter ausgelegt) werde ich das Ganze auf 1-Wire Bus umstellen. Dafür gibt es auch billige Sensoren und die Kabel können bis zu 100 Meter lang sein.

Vorher muss ich aber einkaufen gehen ;-)

Hardware

Software

  • Scan über alle Sensoren
  • polling einzelner Sensoren über USB → Nagios Plugin

Quellen

Hardware

Software

de/i2c_arduino.txt · Zuletzt geändert: 2011/04/01 11:03 von goesta