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