There is a bunch of stuff in my closet, so it requires only time and appropriate mood to build some hardware device. And there is a summer around and weather is rather hot, so it’s not a surprising idea to build a thermometer.
DS1820 is a great thermometer and I started with it, but I have a spare HDPM01 barometer module with built-in thermometer, so let’s use it.
There is HP03 library found in Arduino forum. Following sketch used to test this hardware module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <Arduino.h> #include <HP03.h> void showReadings() { Serial.print(" Temp: "); Serial.print(HP03.Temperature / 10.0); Serial.print(" Pressure: "); Serial.print(HP03.Pressure / 100.0); Serial.print(" Altitude: "); Serial.println(HP03.getAltitude(HP03.Pressure) / 10); } void setup(){ Serial.begin(9600); if (HP03.begin()) { Serial.println("HP03 initialization succeed."); HP03.distanceUnits = METERS; } else { Serial.println("Failed to initialize HP03."); } } void loop(){ if (HP03.update()) { showReadings(); } else { Serial.println("Error getting HP03 data, check sensor connection"); } } |
HP03 library was patched to redefine TONE_PIN to 8’th digital pin because 11’th pin will be needed for SPI. There is no HDPM01 model in Fritzing editor but anyway hardware looks like this image:
Data logger functionality
Most convenient way to store megabytes of information on Arduino is to dump it to SD Card. SD Cards uses 3.3V levels and doesn’t claim to be 5V tolerant, so there are resistor based voltage divider for all 3 pins with Arduino -> SD Card data direction. Schematics looks like that:
Sketch to test SD Card connectivity and compatibility:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <SPI.h> #include <SD.h> Sd2Card card; SdVolume volume; const int chipSelect = 4; void setup() { Serial.begin(9600); if (!card.init(SPI_HALF_SPEED, chipSelect)) { Serial.println("SD card initialization succeed."); return; } else { Serial.println("Failed to initialize SD card."); } if (!volume.init(card)) { Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); return; } } void loop(void) { } |
Real time clock
What the point to log the data without timestamps? Good question, I doesn’t know answer either. So we need to attach RTC like DS1307 for example.
Sketch to set time and test RTC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
#include <Arduino.h> #include "Wire.h" #define DS3231_I2C_ADDRESS 0x68 byte decToBcd(byte val) { return ((val / 10 * 16) + (val % 10)); } byte bcdToDec(byte val) { return ((val / 16 * 10) + (val % 16)); } void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes of data from DS3231 starting from register 00h *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } void displayTime() { byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); Serial.print("Date: "); Serial.print(dayOfMonth, DEC); Serial.print('/'); Serial.print(month, DEC); Serial.print('/'); Serial.print(year, DEC); Serial.print(" Time: "); Serial.print(hour, DEC); Serial.print(":"); if (minute < 10) Serial.print("0"); Serial.print(minute, DEC); Serial.print(":"); if (second < 10) Serial.print("0"); Serial.println(second, DEC); } void setup(void) { Serial.begin(9600); Wire.begin(); setDS3231time(00, 22, 2, 1, 18, 07, 16); } void loop(void) { displayTime(); delay(1000); } |
Cut the wires
Besides strange barometer module I have couple of NRF24L01 radio modules.
Fritzing schematics with pin mapping memo:
NRF24L01 module have nice ACK feature that provides possibility to passively listen broadcast and send data only as response to request. Sketch to send some data to receiver in ACK payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#include <Arduino.h> #include "RF24.h" struct response { long temp; //*100 long pressure; //*100 long altitude; //*100 long signalStrength; } sensorReadings; RF24 radio(9, 10); const uint64_t pipe = 0xE8E8F0F0E1LL; void setup(void) { Serial.begin(9600); radio.begin(); radio.enableAckPayload(); radio.openReadingPipe(1, pipe); radio.startListening(); } void loop(void) { if (radio.available()) { bool done = false; while (!done) { byte tmp; done = radio.read(&tmp, sizeof(tmp)); } radio.writeAckPayload(1, &sensorReadings, sizeof(sensorReadings)); } delay(100); } |
Put all pieces together
Full sketch that logs temperature and pressure with timestamps on SD Card and respond with currently measured values on wireless requests can be found on github.