PIK-PIK RTU1

introduction

this is a tiny project i've been working for some time.

the purpose is to gather temperature information from two sources: inside my room and outside. the information is stored in a log file every minute and then make a plot of that information.

equipment

testing the concept

using a breadboard and single sensor i've managed to test it. there's a lot of tutorial in the internet about connecting DS18B20 to an arduino.

pik-pik_rtu1_sch.png

arduino connected to ds18b20

these tutorials are usually for arduinos without wifi, so i had to modify it slightly:

  1. /*
  2.   WiFi Web Server
  3.  
  4.  A simple web server that shows the value of the analog input pins.
  5.  
  6.  This example is written for a network using WPA encryption. For
  7.  WEP or WPA, change the Wifi.begin() call accordingly.
  8.  
  9.  Circuit:
  10.  * Analog inputs attached to pins A0 through A5 (optional)
  11.  
  12.  created 13 July 2010
  13.  by dlf (Metodo2 srl)
  14.  modified 31 May 2012
  15.  by Tom Igoe
  16.  
  17.  */
  18.  
  19. #include
  20. #include
  21.  
  22.  
  23. #include "arduino_secrets.h"
  24. ///////please enter your sensitive data in the Secret tab/arduino_secrets.h
  25. char ssid[] = SECRET_SSID; // your network SSID (name)
  26. char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
  27. int keyIndex = 0; // your network key Index number (needed only for WEP)
  28.  
  29. int status = WL_IDLE_STATUS;
  30.  
  31. WiFiServer server(80);
  32.  
  33. #include
  34. #include
  35.  
  36. // Data wire is plugged into pin 2 on the Arduino
  37. #define ONE_WIRE_BUS1 5
  38. #define ONE_WIRE_BUS2 10
  39.  
  40. // Setup a oneWire instance to communicate with any OneWire devices
  41. // (not just Maxim/Dallas temperature ICs)
  42. OneWire oneWire1(ONE_WIRE_BUS1);
  43. OneWire oneWire2(ONE_WIRE_BUS2);
  44.  
  45. // Pass our oneWire reference to Dallas Temperature.
  46. DallasTemperature sensor1(&oneWire1);
  47. DallasTemperature sensor2(&oneWire2);
  48.  
  49. void setup() {
  50. //Initialize serial and wait for port to open:
  51. Serial.begin(9600);
  52. while (!Serial) {
  53. ; // wait for serial port to connect. Needed for native USB port only
  54. }
  55.  
  56. Serial.println("Initialization...");
  57.  
  58. // Power for the second sensor
  59. pinMode(2, OUTPUT);
  60. digitalWrite(2, HIGH);
  61.  
  62. // check for the WiFi module:
  63. if (WiFi.status() == WL_NO_MODULE) {
  64. Serial.println("Communication with WiFi module failed!");
  65. // don't continue
  66. while (true);
  67. }
  68.  
  69. String fv = WiFi.firmwareVersion();
  70. if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
  71. Serial.println("Please upgrade the firmware");
  72. }
  73.  
  74. // Start up the library
  75. delay(500);
  76. sensor1.begin();
  77. sensor2.begin();
  78.  
  79. // attempt to connect to Wifi network:
  80. while (status != WL_CONNECTED) {
  81. Serial.print("Attempting to connect to SSID: ");
  82. Serial.println(ssid);
  83. // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
  84. status = WiFi.begin(ssid, pass);
  85.  
  86. // wait 10 seconds for connection:
  87. delay(10000);
  88. }
  89. server.begin();
  90. // you're connected now, so print out the status:
  91. printWifiStatus();
  92. }
  93.  
  94.  
  95. void loop() {
  96. // listen for incoming clients
  97. WiFiClient client = server.available();
  98.  
  99. if (client) { // if you get a client,
  100. Serial.println("new client"); // print a message out the serial port
  101. String currentLine = ""; // make a String to hold incoming data from the client
  102. String getLine = "";
  103. while (client.connected()) { // loop while the client's connected
  104. if (client.available()) { // if there's bytes to read from the client,
  105. char c = client.read(); // read a byte, then
  106. //Serial.write(c); // print it out the serial monitor
  107. if (c == '\n') { // if the byte is a newline character
  108.  
  109. // if the current line is blank, you got two newline characters in a row.
  110. // that's the end of the client HTTP request, so send a response:
  111. if (currentLine.length() == 0) {
  112. // Check to see if the client request was "GET /H" or "GET /L":
  113. if (getLine.startsWith("GET /H")) {
  114. digitalWrite(LED_BUILTIN, HIGH); // GET /H turns the LED on
  115. goto default_page;
  116. }
  117. else if (getLine.startsWith("GET /L")) {
  118. digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off
  119. goto default_page;
  120. }
  121. else if (getLine.startsWith("GET /ds18b20")) {
  122. // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
  123. // and a content-type so the client knows what's coming, then a blank line:
  124. client.println("HTTP/1.1 200 OK");
  125. client.println("Content-type: text/html");
  126. client.println();
  127.  
  128. // call sensors.requestTemperatures() to issue a global temperature
  129. // request to all devices on the bus
  130. sensor1.requestTemperatures(); // Send the command to get temperatures
  131. client.print(sensor1.getTempCByIndex(0)); // Why "byIndex"?
  132. client.print(" ");
  133. sensor2.requestTemperatures(); // Send the command to get temperatures
  134. client.print(sensor2.getTempCByIndex(0)); // Why "byIndex"?
  135. // You can have more than one IC on the same bus.
  136. // 0 refers to the first IC on the wire
  137.  
  138. // The HTTP response ends with another blank line:
  139. client.println();
  140. }
  141. else {
  142. default_page:
  143. // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
  144. // and a content-type so the client knows what's coming, then a blank line:
  145. client.println("HTTP/1.1 200 OK");
  146. client.println("Content-type: text/html");
  147. client.println();
  148.  
  149. // the content of the HTTP response follows the header:
  150. client.print("Status of the LED: ");
  151. client.print( digitalRead(LED_BUILTIN) ? "ON" : "OFF" );
  152. client.print( " " );
  153. client.print("Click <a>here</a> turn the LED on pin 9 on");
  154. client.print("Click <a>here</a> turn the LED on pin 9 off");
  155.  
  156. // output the value of each analog input pin
  157. for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
  158. int sensorReading = analogRead(analogChannel);
  159. client.print("analog input ");
  160. client.print(analogChannel);
  161. client.print(" is ");
  162. client.print(sensorReading);
  163. client.println(" ");
  164. }
  165.  
  166. client.println(" ");
  167.  
  168. // call sensors.requestTemperatures() to issue a global temperature
  169. // request to all devices on the bus
  170. sensor1.requestTemperatures(); // Send the command to get temperatures
  171. sensor2.requestTemperatures(); // Send the command to get temperatures
  172. client.print("Temperature1 is: ");
  173. client.print(sensor1.getTempCByIndex(0)); // Why "byIndex"?
  174. client.println(" ");
  175. client.print("Temperature2 is: ");
  176. client.print(sensor2.getTempCByIndex(0)); // Why "byIndex"?
  177. // You can have more than one IC on the same bus.
  178. // 0 refers to the first IC on the wire
  179. client.print("° C.");
  180.  
  181. // The HTTP response ends with another blank line:
  182. client.println();
  183. }
  184. // break out of the while loop:
  185. break;
  186. } else { // if you got a newline, then clear currentLine:
  187. if (currentLine.startsWith("GET /")) {
  188. getLine = currentLine;
  189. }
  190.  
  191. Serial.println( currentLine );
  192. currentLine = "";
  193. }
  194. } else if (c != '\r') { // if you got anything else but a carriage return character,
  195. currentLine += c; // add it to the end of the currentLine
  196. }
  197. }
  198. }
  199.  
  200. // give the web browser time to receive the data
  201. delay(1);
  202.  
  203. // close the connection:
  204. client.stop();
  205. Serial.println("client disonnected");
  206. }
  207. }
  208.  
  209.  
  210. void printWifiStatus() {
  211. // print the SSID of the network you're attached to:
  212. Serial.print("SSID: ");
  213. Serial.println(WiFi.SSID());
  214.  
  215. // print your board's IP address:
  216. IPAddress ip = WiFi.localIP();
  217. Serial.print("IP Address: ");
  218. Serial.println(ip);
  219.  
  220. // print the received signal strength:
  221. long rssi = WiFi.RSSI();
  222. Serial.print("signal strength (RSSI):");
  223. Serial.print(rssi);
  224. Serial.println(" dBm");
  225. }

i used gnuplot to draw plot of the data:

 

  1. set xdata time
  2. set format x "%d.%m.%Y\ %H:%M"
  3. set timefmt "%d.%m.%Y\ %H:%M:%S"
  4. set xtics 7200 rotate by 90 textcolor rgb "#000000" right
  5.  
  6. set ytics 1 nomirror
  7. set yrange [15:30]
  8.  
  9. set grid xtics ytics
  10. show grid
  11.  
  12. plot ARG1.".log"  using 1:3 with lines
  13.  
  14. pause -1

here's what i get:

data_2020_10_30.png

 it is possible to combine data for several days and get this:

data_special.png

enclosure

i'm only familiar with Blender. it is not a convenient tool to make such enclosures, because it is not parametric. should try to learning using FreeCAD instead.

the first try failed. hole for power supply is misaligned, cover didn't had sides - it was completely flat, and holes for sensor sockets were wrong, so i will show you the second version:

enclosure in blender

download the blender source file: https://pik-pik.ee/nextcloud/index.php/s/dFDGrY5QcKsBHe8.

putting it all together

after several days of 3d printing, i put all the parts inside the box and they all fit perfectly.

PIK-PIK RTU1

now i need to modify scripts slightly to display second data line on the plot:

  1. #set term qt enhanced font "Latin Modern Roman, 12"
  2. set term pngcairo enhanced color font "Latin Modern Roman, 12" size 1024,768
  3. set output ARG1.".png"
  4.  
  5. set xdata time
  6. set x2data time
  7. set format x "%d.%m.%Y\ %H:%M"
  8. set timefmt "%d.%m.%Y\ %H:%M:%S"
  9. set xtics 3600 rotate by 90 textcolor rgb "#000000" right
  10. set x2tics 3600 format ""
  11.  
  12. set ytics 1 nomirror
  13. set y2tics 2
  14. set yrange [15:30]
  15. set y2range [-20:30]
  16.  
  17. set grid xtics ytics
  18. show grid
  19.  
  20. plot ARG1.".log" using 1:3 axis x1y1 with lines title "Inside", ARG1.".log" using 1:4 axis x2y2 with lines title "Outside"
  21.  
  22. pause -1

waiting several day to gather some data and get the picture:

data_2021_03_10_0.png

i also made a multiple day version:

data_special2.png

 

when the sun is shining the signal is a bit noisy. the problem is that my sensor on sunny side of the house. i need a longer cable to hide the sensor in a shadow.

all gathered data are available on following webpage: https://pik-pik.ee/temp/ .