Measure some environmental values in my parents' heating unit

Aus DL8RDS Wiki
Wechseln zu: Navigation, Suche

1 Project

This little project has a manifold background:

  • My parents have a heating room in their house which holds an oil heater.
  • My parents recently had a solar water heater installed on their roof.
  • My mother usually dries the washed clothes in that room, which results in some higher air moisture, which can be measured.

So I decided to build a networked arduino that does all these measurements. The temperature measuring facility should be extensible in order to cover some more measuring points.

2 Hardware

3 Sketch

I tried a number of libraries over some time. Particularly the SHT1x library didn't seem to work. Then I discovered another sketch by somebody on the internet which eventually worked. Another sketch that

So I integrated the two sketches with the standard Webserver example and this was the result. I know that the following code block is crappy, but please click in "edit" / view source to see the original code:

 //Based of the wiring code at http://wiring.org.co/learning/basics/humiditytemperaturesht15.html
 
 #include <SPI.h>
 #include <Ethernet.h>
 #include <OneWire.h>
 
 byte mac[] = { 0xAE, 0xAD, 0xAE, 0xAF, 0xAE, 0xAD };
 IPAddress gateway(192, 168, 1, 1);
 IPAddress ip(192, 168, 1, 175);
 IPAddress dns(192, 168, 1, 1);
 IPAddress subnet(255, 255, 255, 0);
 
 int SHT_clockPin = 4;  // pin used for clock
 int SHT_dataPin  = 6;  // pin used for data
 
 OneWire  ds(9);  // on pin 9
 
 // Initialize the Ethernet server library
 // with the IP address and port you want to use 
 // (port 80 is default for HTTP):
 EthernetServer server(80);
 
 void setup(){
   Serial.begin(9600); // open serial at 9600 bps
   Ethernet.begin(mac, ip, dns, gateway, subnet);
 }
 
 void loop(){
   byte i;
   byte present = 0;
   byte type_s;
   byte data[12];
   byte addr[8];
   float celsius, fahrenheit;
   
   // listen for incoming clients
   EthernetClient client = server.available();
   if (client) {
     // an http request ends with a blank line
     boolean currentLineIsBlank = true;
     while (client.connected()) {
       if (client.available()) {
         char c = client.read();
         // if you've gotten to the end of the line (received a newline
         // character) and the line is blank, the http request has ended,
         // so you can send a reply
         if (c == '\n' && currentLineIsBlank) {
           // send a standard http response header
           client.println("HTTP/1.1 200 OK");
           client.println("Content-Type: text/html");
           client.println();
 
           //these can take a bit to get the values (100ms or so)
           float temperature = getTemperature();
           float humidity = getHumidity();
  
           client.print("<html><head><title>Temperaturen und Feuchtigkeit im Heizungsraum</title></head>\n");
           client.print("<body>\n");
           
           client.print("<h3>Temperaturen und Feuchtigkeit im Heizungsraum</h3>\n<hr/>\n");
           client.print("<table>\n");
            
           client.print("<tr><td>Lufttemperatur: </td><td><temp>");
           client.print(temperature);
           client.print("</temp></td></tr>");
           client.print("<tr><td>Luftfeuchtigkeit: </td><td><humidity>");
           client.print(humidity);
           client.print("</humidity></td></tr>");
                 
           while ( ds.search(addr)) {
  
               if (OneWire::crc8(addr, 7) != addr[7]) {
                   Serial.println("CRC is not valid!");
                   continue;
               }
               Serial.println();
  
                // the first ROM byte indicates which chip
               switch (addr[0]) {
                 case 0x10:
                   Serial.println("  Chip = DS18S20");  // or old DS1820
                   type_s = 1;
                   break;
                 case 0x28:
                   Serial.println("  Chip = DS18B20");
                   type_s = 0;
                   break;
                 case 0x22:
                   Serial.println("  Chip = DS1822");
                   type_s = 0;
                   break;
                 default:
                   Serial.println("Device is not a DS18x20 family device.");
                   continue;
               } 
         
               ds.reset();
               ds.select(addr);
               ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
               delay(1000);     // maybe 750ms is enough, maybe not
               // we might do a ds.depower() here, but the reset will take care of it.
 
               present = ds.reset();
               ds.select(addr);    
               ds.write(0xBE);         // Read Scratchpad
  
               for ( i = 0; i < 9; i++) {           // we need 9 bytes
                   data[i] = ds.read(); 
               }
             
               unsigned int raw = (data[1] << 8) | data[0];
               if (type_s) {
                 raw = raw << 3; // 9 bit resolution default
                 if (data[7] == 0x10) {
                   // count remain gives full 12 bit resolution
                   raw = (raw & 0xFFF0) + 12 - data[6];
                 }
               } else {
                 byte cfg = (data[4] & 0x60);
                 if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
                 else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
                 else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
                 // default is 12 bit resolution, 750 ms conversion time
               }
               celsius = (float)raw / 16.0;
               fahrenheit = celsius * 1.8 + 32.0;
             
               client.print("<tr><td>Sensor: ");
               for( i = 0; i < 8; i++) {
                   client.print(" ");
                   client.print(addr[i], HEX);
               }
               client.print("</td><td><temp>");
               client.print(celsius);
               client.print("</temp></td></tr>");
             
           }
                    
 
           client.print("</table>\n</body>\n</html>\n");
 
           break;
         }
         if (c == '\n') {
           // you're starting a new line
           currentLineIsBlank = true;
         } 
         else if (c != '\r') {
           // you've gotten a character on the current line
           currentLineIsBlank = false;
         }
       }
     }
     // give the web browser time to receive the data
     delay(1);
     // close the connection:
     client.stop();
     ds.reset_search();
   }  
 }
 
 float getTemperature(){
   //Return Temperature in Celsius
   SHT_sendCommand(B00000011, SHT_dataPin, SHT_clockPin);
   SHT_waitForResult(SHT_dataPin);
 
   int val = SHT_getData(SHT_dataPin, SHT_clockPin);
   SHT_skipCrc(SHT_dataPin, SHT_clockPin);
   return (float)val * 0.01 - 40; //convert to celsius
 }
 
 float getHumidity(){
   //Return  Relative Humidity
   SHT_sendCommand(B00000101, SHT_dataPin, SHT_clockPin);
   SHT_waitForResult(SHT_dataPin);
   int val = SHT_getData(SHT_dataPin, SHT_clockPin);
   SHT_skipCrc(SHT_dataPin, SHT_clockPin);
   return -4.0 + 0.0405 * val + -0.0000028 * val * val; 
 }
 
 
 void SHT_sendCommand(int command, int dataPin, int clockPin){
   // send a command to the SHTx sensor
   // 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);
 
   // shift out the command (the 3 MSB are address and must be 000, the last 5 bits are the command)
   shiftOut(dataPin, clockPin, MSBFIRST, command);
 
   // verify we get the right ACK
   digitalWrite(clockPin, HIGH);
   pinMode(dataPin, INPUT);
 
   if (digitalRead(dataPin)) Serial.println("ACK error 0");
   digitalWrite(clockPin, LOW);
   if (!digitalRead(dataPin)) Serial.println("ACK error 1");
 }
 
 
 void SHT_waitForResult(int dataPin){
   // wait for the SHTx answer
   pinMode(dataPin, INPUT);
 
   int ack; //acknowledgement
 
   //need to wait up to 2 seconds for the value
   for (int i = 0; i < 1000; ++i){
     delay(2);
     ack = digitalRead(dataPin);
     if (ack == LOW) break;
   }
 
   if (ack == HIGH) Serial.println("ACK error 2");
 }
 
 int SHT_getData(int dataPin, int clockPin){
   // get data from the SHTx sensor
 
   // get the MSB (most significant bits)
   pinMode(dataPin, INPUT);
   pinMode(clockPin, OUTPUT);
   byte MSB = shiftIn(dataPin, clockPin, MSBFIRST);
 
   // send the required ACK
   pinMode(dataPin, OUTPUT);
   digitalWrite(dataPin, HIGH);
   digitalWrite(dataPin, LOW);
   digitalWrite(clockPin, HIGH);
   digitalWrite(clockPin, LOW);
 
   // get the LSB (less significant bits)
   pinMode(dataPin, INPUT);
   byte LSB = shiftIn(dataPin, clockPin, MSBFIRST);
   return ((MSB << 8) | LSB); //combine bits
 }
 
 void SHT_skipCrc(int dataPin, int clockPin){
   // skip CRC data from the SHTx sensor
   pinMode(dataPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
   digitalWrite(dataPin, HIGH);
   digitalWrite(clockPin, HIGH);
   digitalWrite(clockPin, LOW);
 }

4 Pictures

HeizungController1.jpg HeizungController2.jpg HeizungController3.jpg

HeizungController4.jpg HeizungController5.jpg HeizungController6.jpg