1-Wire Testsoftware für Arduino

Nachdem ja nun schon einige 1-Wire Sensoren fertig sind brauchte ich eine Möglichkeit diese unabhängig von der zentralen Steuerung zu testen. Herausgekommen ist ein kleines, quick and dirty, Programm. Programmiert in der Arduino IDE.

// Testprogramm für 1-Wire Sensoren DS1820, DS18S20, DS18B20, DS1822, DS2438 (mit HIH-5030/HIH-5031 und/oder SFH203P), DS2401 und DS2411
// printFloat Funktion von http://playground.arduino.cc/Code/PrintFloats

#include <OneWire.h> // Einbinden der 1-Wire Library

OneWire  ds(7); // DQ ist an PIN 7 angeschlossen
 
boolean HIH=1; // 0 = Kein HIH-5030/HIH-5031 Sensor angeschlossen, 1 = HIH-5030/HIH-5031 Sensor angeschlossen
boolean SFH=1; // 0 = Kein SFH203P angeschlossen, 1 = SFH203P angeschlossen

int Nachkommastellen=1; // Anzahl der Nachkommastellen auf die Temperatur und ggf. Luftfeuchtewerte gerundet werden

// printFloat prints out the float 'value' rounded to 'places' places after the decimal point
void printFloat(float value, int places) {
  // this is used to cast digits
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;

  // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
  // if this rounding step isn't here, the value  54.321 prints as 54.3209

  // calculate rounding term d:   0.5/pow(10,places)  
  float d = 0.5;
  if (value < 0)
    d *= -1.0;
  // divide by ten for each decimal place
  for (i = 0; i < places; i++)
    d/= 10.0;    
  // this small addition, combined with truncation will round our values properly
  tempfloat +=  d;

  // first get value tens to be the large power of ten less than value
  // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take

  if (value < 0)
    tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) {
    tens *= 10.0;
    tenscount += 1;
  }


  // write out the negative if needed
  if (value < 0)
    Serial.print('-');

  if (tenscount == 0)
    Serial.print(0, DEC);

  for (i=0; i< tenscount; i++) {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }

  // if no places after decimal, stop now and return
  if (places <= 0)
    return;

  // otherwise, write the point and continue on
  Serial.print('.');  

  // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
  for (i = 0; i < places; i++) {
    tempfloat *= 10.0;
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    // once written, subtract off that digit
    tempfloat = tempfloat - (float) digit;
  }
}

void discoverOneWireDevices(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, vdd, vad, vse, hum, lux;
  String add;
  int16_t raw=0;
       
  if ( !ds.search(addr)) {
    ds.reset_search();
    return;
  }
   
  Serial.println("");
 
  Serial.print("ROM =");
 
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
 
    if (addr[i] < 16) {
      Serial.print("0");
    }
     
    Serial.print(addr[i], HEX);
     
    add=add + (int)addr[i];
  }
   
  Serial.println();
  Serial.print("INT = ");
  Serial.println(add);
   
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC nicht korrekt!");
      return;
  }
   
  // Feststellen welcher Chip gefunden wurde
  switch (addr[0]) {
    case 0x01:
      Serial.println("Chip = DS2401 oder DS2411");
      Serial.println("Typ = Seriennummer");
      type_s = 3;
      break;
    case 0x10:
      Serial.println("Chip = DS1820 oder DS18S20");
      Serial.println("Typ = Temperatursensor");
      type_s = 1;
      break;
    case 0x26:
      Serial.println("Chip = DS2438");
      Serial.println("Typ = Batterie Monitor");
      type_s = 2;
      break;
    case 0x28:
      Serial.println("Chip = DS18B20");
      Serial.println("Typ = Temperatursensor");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("Chip = DS1822");
      Serial.println("Typ = Temperatursensor");
      type_s = 0;
      break;
    default:
      Serial.println("Chip = unbekannt");
      return;
  } 
 
  //Wenn ein korrekter Chip erkannt wurde...
  if (type_s < 3){
    long lastMillis;
       
    if (type_s == 2) {
      ds.reset();
      ds.select(addr);
     
      ds.write(0x4E, 1);         // Konfiguration in Scratchpad schreiben
      ds.write(0x00, 1);
      ds.write(0x08, 1);
       
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0x44, 1);        // Wandlung mit aktivierter parasitärer Versorgung starten
   
      lastMillis=millis();
       
      while (millis() - lastMillis < 50) {
          ;
      }
       
      present = ds.reset();
      ds.select(addr);    
   
      ds.write(0xB4, 1);        // Wandlung mit aktivierter parasitärer Versorgung starten
     
      lastMillis=millis();
       
      while (millis() - lastMillis < 50) {
          ;
      }
   
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0xB8, 1);         // Speicherseite 0 auswählen
      ds.write(0x00, 1);
   
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0xBE, 1);         // Scratchpad auslesen
      ds.write(0x00, 1);
   
      Serial.print("Data = ");
      Serial.print(present, HEX);
      Serial.print(" ");
       
      for ( i = 0; i < 9; i++) {           // Wir brauchen 9 Byte
        data[i] = ds.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
      }

      Serial.println();
      Serial.print("CRC = ");
      Serial.print(OneWire::crc8(data, 8), HEX);
      Serial.println();
   
      raw = (data[4] << 8 | data[3]);
       
      vdd=(float)raw / 100;
   
      present=ds.reset();
      ds.select(addr);
     
      ds.write(0x4E, 1);         // Konfiguration in Scratchpad schreiben
      ds.write(0x00, 1);
      ds.write(0x00, 1);
       
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0x44, 1);        // Wandlung mit aktivierter parasitärer Versorgung starten
   
      lastMillis=millis();
       
      while (millis() - lastMillis < 15) {
          ;
      }
       
      present = ds.reset();
      ds.select(addr);    
   
      ds.write(0xB4, 1);        // Wandlung mit aktivierter parasitärer Versorgung starten
     
      lastMillis=millis();
       
      while (millis() - lastMillis < 10) {
          ;
      }
   
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0xB8, 1);         // Speicherseite 0 auswählen
      ds.write(0x00, 1);
   
      present=ds.reset();
      ds.select(addr);    
   
      ds.write(0xBE, 1);         // Scratchpad auslesen
      ds.write(0x00, 1);
   
      Serial.print("Data = ");
      Serial.print(present, HEX);
      Serial.print(" ");
       
      for ( i = 0; i < 9; i++) {           // Wir brauchen 9 Byte
        data[i] = ds.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
      }

      Serial.println();
      Serial.print("CRC = ");
      Serial.print(OneWire::crc8(data, 8), HEX);
      Serial.println();
    } else {
      ds.write(0x44, 1);        // Wandlung mit aktivierter parasitärer Versorgung starten
   
      lastMillis=millis();
       
      while (millis() - lastMillis < 750) {
          ;
      }
          
      present = ds.reset();
      ds.select(addr);    
   
      ds.write(0xBE);         // Scratchpad auslesen
     
      Serial.print("Data = ");
      Serial.print(present, HEX);
      Serial.print(" ");
       
      for ( i = 0; i < 9; i++) {           // Wir brauchen 9 Byte
        data[i] = ds.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
      }

      Serial.println();
      Serial.print("CRC = ");
      Serial.print(OneWire::crc8(data, 8), HEX);
      Serial.println();
    }
   
    if (type_s < 3) {
      if(type_s == 0) {
        byte cfg = (data[4] & 0x60);
        raw = (data[1] << 8) | data[0];
     
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
   
        celsius = (float)raw / 16.0;
      } else if (type_s == 1) {
        raw = (data[1] << 8) | data[0];
        raw = raw << 3; // 9 bit resolution default
         
        if (data[7] == 0x10) {
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
         
        celsius = (float)raw / 16.0;
      } else if(type_s ==2) {
        raw = ((data[2] << 5) | (data[1] >> 3));
         
        celsius = (float)raw * 0.03125;
     
        raw = (data[4] << 8 | data[3]);
         
        vad=(float)raw / 100;
     
        raw = (data[6] << 8 | data[5]);
     
        vse=(float)raw * 0.2441;
 
        Serial.print("VDD = ");
        Serial.print(vdd);
        Serial.print(" V");
   
        Serial.println();
 
        Serial.print("V-ADC = ");
        Serial.print(vad);
        Serial.print(" V");
 
        Serial.println();
 
        Serial.print("V-Sense = ");
        Serial.print(vse);
        Serial.print(" mV");

        if (SFH == 1) {
          Serial.println();
        
          lux = vse * 0.2441 * (1000000.0 / 390.0);
  
          Serial.print("Lichtstaerke = ");
          printFloat(lux, 0);
          Serial.print(" lx");
        }
        
        if (HIH == 1) {
          Serial.println();
        
          hum=(157.233 * (vad / vdd) - 23.2808) / (1.0546 - 0.00216 * celsius);
  
          Serial.print("Luftfeuchte = ");
          printFloat(hum, Nachkommastellen);
          Serial.print(" % rel.");
        }
        
        Serial.println();
      }
 
      Serial.print("Temperatur = ");
      printFloat(celsius, Nachkommastellen);
      Serial.println(" Celsius");

    }
  }
   
  return;
}
 
void setup() {
  Serial.begin(115200);
   
  while (!Serial) {
    ;
  }
 
  Serial.println("Starte System...");
  Serial.println();
}
 
void loop() {
 discoverOneWireDevices();

 delay(500);
}

Es gibt über die serielle Verbindung bei 115200 Baud (8,n,1) alle am Bus gefundenen Sensoren (1-Wire Bausteine) mit deren wichtigsten Werten aus. Bisher werden Temperatursensoren wie DS18B20, Seriennummern Chips wie der DS2401 o. DS2411 und der Batterie Monitor DS2438 erkannt.

Zum testen von Sensoren diese einfach mit 5V, GND und (im obigen Code) PIN 7 (DQ) eines Aruino Boards verbinden, bitte den PullUp-Widerstand zwischen 5V und DQ (PIN 7) nicht vergessen.

So könnte eine Ausgabe aussehen…

1-Wire-Testprogramm-Ausgabe 1-Wire Testsoftware für ArduinoAm Bus hängen zum testen ein DS18B20 Temperatur-Sensor, eine PullUp-Platine sowie der PIR Adapter mit angeschlossenem HC-SR501 PIR Modul. Das PIR Modul erscheint oben als Seriennummer da ja ein DS2411 auf den Bus geschaltet wird sobald eine Bewegung erkannt wird. Alle Platinen zusammen hängen über die Abzweig-Platine an einem Arduino™ Uno.

Verlinke diesen Beitrag:

<a href="http://blog.thomasheldt.de/1-wire-testsoftware-fuer-arduino/">1-Wire Testsoftware für Arduino</a>

The following two tabs change content below.
c7282393508c6050f22643a7feb8fec6?s=80&r=g 1-Wire Testsoftware für Arduino

Thomas H.

Als Betreiber dieses Blog versuche ich hier interessante Projekte und Tipps rund um die Elektronik zu bieten.
c7282393508c6050f22643a7feb8fec6?s=80&r=g 1-Wire Testsoftware für Arduino

Neueste Artikel von Thomas H. (alle ansehen)

Aktualisiert am: 11. Juni 2016

Programm aufgeräumt und Kommentare eingedeutscht ;)

Aktualisiert am: 24. Juni 2016

Programm erweitert.

2 Gedanken zu „1-Wire Testsoftware für Arduino

  1. Chris

    Hallo,
    tolles umfängliches Beispiel. Der Helligkeitssensor ist über ein 1 MOhm angeschlossen oder ?

    Viele Grüße,
    Chris

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Chris,

      aktuell ist der Sensor über 10K angeschlossen, aber ich werde 1M mal testen,

      In Kürze wird es auch einen neuen Light Sensor geben der dann 0 – 5V am AD2 des
      DS2438 liefern wird.

      Gruß
      Thomas

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.