Components and supplies
TP4056 5V 1A TYPE C Micro USB Board Module for 18650 Lithium Battery Charger
Hook Up wire
DHT11 Temperature Humidity Sensor Module
Arduino Pro Mini 328 - 3.3V/8MHz
1M ohm Resistor
3.7V 1000mAh Lithium Rechargable Battery Lipo Batteries
AZDelivery I2C 0.96-inch OLED Display SSD1306 128x64 Pixels IIC 3.3V 5V White Character Display
Tactile Switch, Top Actuated
330k ohm Resistor
Apps and platforms
Arduino IDE
Project description
Code
Temp/Humid monitor with graphs and battery monitor
arduino
1/* Paul Brace April 2021 2 Temperature and humidity monitor with minimum and maximum monitoring, 3 graph and battery monitor 4 Board - Arduino Pro Mini/Nano or Uno r3 tested 5 Display - OLED 128x64 IC2 6 A screensaver kicks in after the period set in keepDisplayFor. 7 Screensaver is a bitmap that represents the state of the battery charge 8 and is respositioned after the period set in moveEvery. 9 The mode button is used to activate the diplsya and show the readings 10 and to circulate from the temperature, to temperature graph, humidity and humidity graph. 11 The reset button is used to reset the minimum and maximum values. 12 The graph displays show the temperature and humidity recording for the last 24 hour period 13 14 Note on using the 3.7v rechargeable battery. 15 The Nano specification is that it requires a 5v supply, however 16 for this project it runs perfectly well on a 3.7v rechargeable battery 17 with the supply connected to the 5v pin. 18 It is also safe to recharge when in use as the voltage will only increase to 4.2v 19*/ 20 21// Include drivers 22// DHT_sensor_library 23#include <DHT.h> // This is the DHT sensor library by Adafruit 24 // required for the OLED display 25#include <SPI.h> // Synchronous serial data protocol library 26#include <Wire.h> // IC2 communications library 27#include <Adafruit_GFX.h> // Adafruit Graphics Core Library 28#include <Adafruit_SSD1306.h> // SSD1306 library for Monochrome 128x64 and 128x32 OLEDs 29#include <Fonts/FreeMonoBold9pt7b.h> // Include fonts to be used 30#include <Fonts/FreeSans9pt7b.h> 31#include <EEPROM.h> // Library to support writing to and reading from EPROM 32 33 34#define DATA_PIN 4 // Pin used to collect data from the DHT 35#define DHTTYPE DHT11 // DHT Type 36//#define DHTTYPE DHT22 // If you have a DHT22 comment the DHT11 and 37 // uncomment DHT22 38// Create the sensor object and assign pin 39DHT dht(DATA_PIN, DHTTYPE); 40 41 42#define SCREEN_WIDTH 128 // OLED display width, in pixels 43#define SCREEN_HEIGHT 64 // OLED display height, in pixels 44 45// The pins for I2C are defined by the Wire-library. 46// On an arduino UNO/Nano and Pro Mini: A4(SDA), A5(SCL) 47// On an arduino MEGA 2560: 20(SDA), 21(SCL) 48// On an arduino LEONARDO: 2(SDA), 3(SCL), ... 49#define OLED_RESET -1 // Reset pin # (or -1 if no reset on display) 50#define SCREEN_ADDRESS 0x3C // See datasheet for Address (Yours could be 0x3D) 51 52// Create object for the SSD1306 display connected to I2C (SDA, SCL pins) 53Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 54 55#define MODE_BUTTON 2 // Activate display and switched between temperature, graph and humidity 56#define RESET_BUTTON 3 // If pressed when data displayed resets min and max settings 57 58float temp; //Current temperature 59float humid; //Current humidity 60float minTemp; //The minimum temperature recorded 61float maxTemp; //The maximum temperature recorded 62float minHumid; //The minimum humidity recorded 63float maxHumid; //The maximum humidity recorded 64 65unsigned long lastReadingUpdate; // Time readings last updated 66 67// Battery Monitor 68#define MONITOR_PIN A0 // Pin used to monitor supply voltage 69const float voltageDivider = 4.0; // Used to calculate the actual voltage fRom the monitor pin reading 70 // Using 1m and 330k ohm resistors dividS the voltage by approx 4 71 // You may wany to substitute actual values of resistors in an equation (R1 + R2)/R2 72 // E.g. (1000 + 330)/330 = 4.03 73 // Alternatively take the voltage reading across the battery and from the joint between 74 // the 2 resistors to ground and divide one by the other to get the value. 75 76 77// Variables for History stored in EPROM 78// First version stored history in arrays but program would not run as may have 79// run out of memory even though there appeared to be memory to spare 80// 1 day's history is stored 96 readings at 15 minute intervals so each 81// EPROM position is written once per day. 82// EPROM has a limited life of approx 100,000 writes per postion so as we 83// are writin to each postion once a day the EPROM should last 100,000 days (274 years!) 84const int intSize = sizeof(int); // Size of int to calculate storage location 85const int tempStart = 0; // Start postion of temperature history - length = 96 * intSize 86const int humidStart = 100 * intSize; // Start postion of humidity 87int histPointer = - 1; // Last last postion updated (-1 means no history yet stored) 88unsigned long histUpdated; // time last updated 89unsigned long interval = 900000ul; //(15 * 60 * 1000); 15 minutes in milliseconds 90 91 92enum mode { 93 dispTemp, // Temperature currently displayed 94 dispTempGraph, // Temperature history graph displayed 95 dispHumid, // Humidity currently displayed 96 dispHumidGraph // Humidity history graph displayed 97}; 98 99mode currentMode; // Current display setting 100 101bool displaying; // True if currently displaying data 102unsigned long timeDisplay; // Time started to display, or last button pressed 103unsigned long keepDisplayFor = 15000; // Number of milliseconds before enter screensave mode 104 105unsigned long lastMoved; // Time last moved screensave bitmap 106 // The battery indicator is displayed as the screensaver 107unsigned long moveEvery = 10000; // Number of milliseconds between moves 108 109// Arrows used to indicate maximum and minimum 110static const unsigned char PROGMEM upArrow[] { 111 B00000000, 112 B00011000, 113 B00111100, 114 B01111110, 115 B11111111, 116 B00011000, 117 B00011000, 118 B00011000 119}; 120 121static const unsigned char PROGMEM downArrow[] { 122 B00011000, 123 B00011000, 124 B00011000, 125 B11111111, 126 B01111110, 127 B00111100, 128 B00011000, 129 B00000000 130}; 131 132// Battery indicator bitmaps 133static const unsigned char PROGMEM full[] { 134 B00001110,B00000000, 135 B00001110,B00000000, 136 B11111111,B11100000, 137 B11111111,B11100000, 138 B11111111,B11100000, 139 B11111111,B11100000, 140 B11111111,B11100000, 141 B11111111,B11100000, 142 B11111111,B11100000, 143 B11111111,B11100000, 144 B11111111,B11100000, 145 B11111111,B11100000, 146 B11111111,B11100000, 147 B11111111,B11100000, 148 B11111111,B11100000, 149 B11111111,B11100000 150}; 151 152static const unsigned char PROGMEM three4[] { 153 B00001110,B00000000, 154 B00001110,B00000000, 155 B11111111,B11100000, 156 B10000000,B00100000, 157 B10000000,B00100000, 158 B10000000,B00100000, 159 B11111111,B11100000, 160 B11111111,B11100000, 161 B11111111,B11100000, 162 B11111111,B11100000, 163 B11111111,B11100000, 164 B11111111,B11100000, 165 B11111111,B11100000, 166 B11111111,B11100000, 167 B11111111,B11100000, 168 B11111111,B11100000 169}; 170 171static const unsigned char PROGMEM half[] { 172 B00001110,B00000000, 173 B00001110,B00000000, 174 B11111111,B11100000, 175 B10000000,B00100000, 176 B10000000,B00100000, 177 B10000000,B00100000, 178 B10000000,B00100000, 179 B10000000,B00100000, 180 B10000000,B00100000, 181 B11111111,B11100000, 182 B11111111,B11100000, 183 B11111111,B11100000, 184 B11111111,B11100000, 185 B11111111,B11100000, 186 B11111111,B11100000, 187 B11111111,B11100000 188}; 189 190static const unsigned char PROGMEM one4[] { 191 B00001110,B00000000, 192 B00001110,B00000000, 193 B11111111,B11100000, 194 B10000000,B00100000, 195 B10000000,B00100000, 196 B10000000,B00100000, 197 B10000000,B00100000, 198 B10000000,B00100000, 199 B10000000,B00100000, 200 B10000000,B00100000, 201 B10000000,B00100000, 202 B10000000,B00100000, 203 B11111111,B11100000, 204 B11111111,B11100000, 205 B11111111,B11100000, 206 B11111111,B11100000 207}; 208 209static const unsigned char PROGMEM empty[] { 210 B00001110,B00000000, 211 B00001110,B00000000, 212 B11111111,B11100000, 213 B10000000,B00100000, 214 B10000000,B00100000, 215 B10000000,B00100000, 216 B10000000,B00100000, 217 B10000000,B00100000, 218 B10000000,B00100000, 219 B10000000,B00100000, 220 B10000000,B00100000, 221 B10000000,B00100000, 222 B10000000,B00100000, 223 B10000000,B00100000, 224 B10000000,B00100000, 225 B11111111,B11100000 226}; 227 228void setup() { 229 minTemp = 99; //Set to a figure that is going to be too high 230 maxTemp = -9; //Set to a figure that is going to be too low 231 minHumid = 99; //Set to a figure that is going to be too high 232 maxHumid = -9; //Set to a figure that is going to be too low 233 pinMode(MODE_BUTTON, INPUT_PULLUP); // Use INPUT_PULLUP - will go LOW when button pressed 234 pinMode(RESET_BUTTON, INPUT_PULLUP); 235 analogReference(INTERNAL); // Sets the reference voltage for the analog pins to 1.1v 236 pinMode(MONITOR_PIN, INPUT); // Set input on pin used to monitor the voltage 237 // Start sensor 238 dht.begin(); 239 // Initialise display 240 display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); 241 display.setTextColor(WHITE); 242 currentMode = dispTemp; 243 displaying = true; 244 timeDisplay = millis(); // Set so initially displays for set period 245 histUpdated = millis(); // First update will be interval after startup 246 lastMoved = millis(); // Time bitmap last moved 247 clearEEPROM(); // Clear EPROM ready to start storing history 248} 249 250void loop() { 251 // Check if the time since last display of data started is greater than 252 // the time set to keeo the display showing 253 if ((millis() - timeDisplay) > keepDisplayFor) { 254 // If so in screen save mode 255 displaying = false; // Flag to indicate data not being displayed 256 // Check if we need to move the bitmap 257 if ((millis() - lastMoved) > moveEvery) { 258 // Update time last moved 259 lastMoved = millis(); 260 // Dislpay battery bitmap in random position 261 DrawScreenSave(random(10, 110), random(10, 45)); 262 } 263 } 264 // Update the readings every 2 seconds 265 if ((millis() - lastReadingUpdate) > 2000ul) { 266 // Get readings, update minimum and maximum values 267 lastReadingUpdate = millis(); 268 humid = dht.readHumidity(); // read humidity 269 temp = dht.readTemperature(); // read temperature 270 if (temp < minTemp) 271 minTemp = temp; 272 if (temp > maxTemp) 273 maxTemp = temp; 274 if (humid < minHumid) 275 minHumid = humid; 276 if (humid > maxHumid) 277 maxHumid = humid; 278 if (displaying) { 279 // Update display if data being displayed 280 switch (currentMode) { 281 case dispTemp: 282 ShowTemperature(); 283 break; 284 case dispTempGraph: 285 ShowGraph(); 286 break; 287 case dispHumid: 288 ShowHumidity(); 289 break; 290 case dispHumidGraph: 291 ShowGraph(); 292 break; 293 } 294 } 295 } 296 // Check if any buttons have been pressed 297 CheckButtons(); 298 // If history update interval has passed, update history 299 if ((millis() - histUpdated) >= interval) 300 UpdateHistory(); 301 delay(150); // Short pause before continuing 302} 303 304// Read the monitor pin and calculate the voltage 305float BatteryVoltage(){ 306 float reading = analogRead(MONITOR_PIN); 307 // Calculate voltage - reference voltage is 1.1v 308 return 1.1 * (reading/1023) * voltageDivider; 309} 310 311void DrawScreenSave(int x, int y){ 312 // Get battery voltage and display approprate bitmap 313 display.clearDisplay(); 314 float voltage = BatteryVoltage(); 315 if (voltage > 3.6) 316 display.drawBitmap(x, y, full, 16, 16, WHITE); 317 else 318 if (voltage > 3.5) 319 display.drawBitmap(x, y, three4, 16, 16, WHITE); 320 else 321 if (voltage > 3.4) 322 display.drawBitmap(x, y, half, 16, 16, WHITE); 323 else 324 if (voltage > 3.3) 325 display.drawBitmap(x, y, one4, 16, 16, WHITE); 326 else 327 display.drawBitmap(x, y, empty, 16, 16, WHITE); 328 /* Debug code to display reading and voltage for checking 329 display.setCursor(random(0,96), random(15,35)); 330 display.print(voltage); 331 float reading = analogRead(MONITOR_PIN); 332 display.setCursor(random(0,75), random(45,60)); 333 display.print(reading);*/ 334 display.display(); 335} 336 337void UpdateHistory() { 338 histUpdated += interval; 339 // Use a circular list 340 // Increment to next element in EPROM and circulate back to 0 if end 341 // of list reached 342 histPointer++; 343 if (histPointer > 95) 344 histPointer = 0; 345 saveTemperature(histPointer, int(temp)); 346 saveHumidity(histPointer, int(humid)); 347} 348 349// Clear area we are using for storage 350void clearEEPROM() 351{ 352 for (int i = 0 ; i < 200 * intSize ; i++) { 353 if(EEPROM.read(i) != 0) //skip already "empty" addresses 354 { 355 EEPROM.write(i, 0); //write 0 to address i 356 } 357 } 358} 359 360void saveTemperature(int postion, int value){ 361 EEPROM.put(tempStart + postion * intSize, value); 362} 363 364void saveHumidity(int postion, int value){ 365 EEPROM.put(humidStart + postion * intSize, value); 366} 367 368int getTemperature(int postion){ 369 int value = 0; 370 EEPROM.get(tempStart + postion * intSize, value); 371 return value; 372} 373 374int getHumidity(int postion){ 375 int value = 0; 376 EEPROM.get(humidStart + postion * intSize, value); 377 return value; 378} 379 380// Routine to display numbers aligned and with sign 381void dispNumber(int y, float value, bool tDisp) { 382 if (value < 10.0 && value > 0.0) 383 display.setCursor(72, y); 384 else 385 display.setCursor(60, y); 386 display.print(value); 387 if (tDisp) 388 display.print("c"); 389 else 390 display.print("%"); 391} 392 393// Routine to display graph 394void ShowGraph() { 395 // Calculate scale 396 int histValue; 397 int minimum = 99; 398 int maximum = -9; 399 float yScale; 400 for (int i = 0; i < 96; i++) { 401 if (currentMode == dispTempGraph) 402 histValue = getTemperature(i); 403 else 404 histValue = getHumidity(i); 405 if (histValue < minimum) 406 minimum = histValue; 407 if (histValue > maximum) 408 maximum = histValue; 409 } 410 if ((maximum - minimum) != 0) 411 yScale = 63.0 / (maximum - minimum); 412 else 413 yScale = 1; 414 // Display axis data 415 display.clearDisplay(); 416 display.setFont(); 417 display.setTextSize(1); 418 display.setCursor(0, 54); 419 display.print(minimum); 420 if (currentMode == dispTempGraph) 421 display.print("c"); 422 else 423 display.print("%"); 424 display.setCursor(0, 0); 425 display.print(maximum); 426 if (currentMode == dispTempGraph) 427 display.print("c"); 428 else 429 display.print("%"); 430 display.setCursor(0, 25); 431 if (currentMode == dispTempGraph) 432 display.print("Temp."); 433 else 434 display.print("Humid."); 435 // Graph list from histPointer + 1 circulating to histPointer 436 int pos = histPointer + 1; 437 int priorPos; 438 int histValuePrior; 439 // Count 1 less than list as stating at point 2 440 for (int i = 1; i < 96; i++) { 441 pos++; 442 if (pos > 95) 443 pos = 0; 444 if (pos > 0) 445 priorPos = pos - 1; 446 else 447 priorPos = 95; 448 if (currentMode == dispTempGraph) { 449 histValuePrior = getTemperature(priorPos); 450 histValue = getTemperature(pos); 451 } 452 else { 453 histValuePrior = getHumidity(priorPos); 454 histValue = getHumidity(pos); 455 } 456 display.drawLine(32 + i - 1, 63 - (histValuePrior - minimum) * yScale, 457 32 + i, 63 - (histValue - minimum) * yScale, SSD1306_WHITE); 458 } 459 display.display(); 460} 461 462void ShowTemperature() { 463 display.clearDisplay(); 464 display.setTextSize(1); 465 display.setFont(&FreeSans9pt7b); // Font used for text 466 display.setCursor(0, 15); 467 display.print("Temp:"); 468 display.drawBitmap(20, 35 - 9, upArrow, 8, 8, WHITE); 469 display.drawBitmap(20, 55 - 9, downArrow, 8, 8, WHITE); 470 display.setFont(&FreeMonoBold9pt7b); // Font used for numbers 471 dispNumber(15, temp, true); 472 dispNumber(35, maxTemp, true); 473 dispNumber(55, minTemp, true); 474 display.display(); 475} 476 477void ShowHumidity() { 478 display.clearDisplay(); 479 display.setTextSize(1); 480 display.setFont(&FreeSans9pt7b); // Font used for text 481 display.setCursor(0, 15); 482 display.print("Humid:"); 483 display.drawBitmap(20, 35 - 9, upArrow, 8, 8, WHITE); 484 display.drawBitmap(20, 55 - 9, downArrow, 8, 8, WHITE); 485 display.setFont(&FreeMonoBold9pt7b); // Font used for numbers 486 dispNumber(15, humid, false); 487 dispNumber(35, maxHumid, false); 488 dispNumber(55, minHumid, false); 489 display.display(); 490} 491 492void DisplayLowBattery(){ 493 display.clearDisplay(); 494 display.setTextSize(1); 495 display.setFont(&FreeSans9pt7b); // Font used for text 496 display.setCursor(48, 20); 497 display.print("Low"); 498 display.setCursor(35, 40); 499 display.print("Battery"); 500 display.display(); 501 delay(2000); 502} 503 504void CheckButtons() { 505 // If the mode or reset button has been pressed pin will go LOW 506 // Check if mode button pressed if so show data or switch mode between displays 507 if (digitalRead(MODE_BUTTON) == LOW) { 508 timeDisplay = millis(); // Reset so remains display for reset period after switching mode 509 if (!displaying) { 510 displaying = true; // Set so displays data 511 // Check level of battery 512 float voltage = BatteryVoltage(); 513 if (voltage < 3.3) 514 DisplayLowBattery(); 515 currentMode = dispTemp; 516 ShowTemperature(); 517 delay(1000); 518 return; 519 } 520 // If already displaying move to next display 521 switch (currentMode) { 522 case dispTemp: 523 currentMode = dispTempGraph; 524 ShowGraph(); 525 break; 526 case dispTempGraph: 527 currentMode = dispHumid; 528 ShowHumidity(); 529 break; 530 case dispHumid: 531 currentMode = dispHumidGraph; 532 ShowGraph(); 533 break; 534 case dispHumidGraph: 535 currentMode = dispTemp; 536 ShowTemperature(); 537 break; 538 } 539 delay(1000); // Give time to release button 540 } 541 542 // Check if reset button pressed 543 // Is the system displaying? 544 // If so the reset min and max values 545 if (displaying) { 546 if (digitalRead(RESET_BUTTON) == LOW) { 547 maxTemp = -9; 548 minTemp = 99; 549 maxHumid = -9; 550 minHumid = 99; 551 delay(1000); // Give time to release button 552 } 553 } 554}
Temp/Humid monitor with graphs and battery monitor
arduino
1/* Paul Brace April 2021 2 Temperature and humidity monitor with 3 minimum and maximum monitoring, 4 graph and battery monitor 5 Board 6 - Arduino Pro Mini/Nano or Uno r3 tested 7 Display - OLED 128x64 IC2 8 A 9 screensaver kicks in after the period set in keepDisplayFor. 10 Screensaver 11 is a bitmap that represents the state of the battery charge 12 and is respositioned 13 after the period set in moveEvery. 14 The mode button is used to activate the 15 diplsya and show the readings 16 and to circulate from the temperature, 17 to temperature graph, humidity and humidity graph. 18 The reset button is used 19 to reset the minimum and maximum values. 20 The graph displays show the temperature 21 and humidity recording for the last 24 hour period 22 23 Note on using 24 the 3.7v rechargeable battery. 25 The Nano specification is that it requires 26 a 5v supply, however 27 for this project it runs perfectly well on a 3.7v 28 rechargeable battery 29 with the supply connected to the 5v pin. 30 It 31 is also safe to recharge when in use as the voltage will only increase to 4.2v 32*/ 33 34// 35 Include drivers 36// DHT_sensor_library 37#include <DHT.h> // This 38 is the DHT sensor library by Adafruit 39 // required 40 for the OLED display 41#include <SPI.h> // Synchronous serial data protocol 42 library 43#include <Wire.h> // IC2 communications library 44#include 45 <Adafruit_GFX.h> // Adafruit Graphics Core Library 46#include <Adafruit_SSD1306.h> 47 // SSD1306 library for Monochrome 128x64 and 128x32 OLEDs 48#include <Fonts/FreeMonoBold9pt7b.h> 49 // Include fonts to be used 50#include <Fonts/FreeSans9pt7b.h> 51#include <EEPROM.h> 52 // Library to support writing to and reading from EPROM 53 54 55#define 56 DATA_PIN 4 // Pin used to collect data from the DHT 57#define 58 DHTTYPE DHT11 // DHT Type 59//#define DHTTYPE DHT22 // 60 If you have a DHT22 comment the DHT11 and 61 // 62 uncomment DHT22 63// Create the sensor object and assign pin 64DHT dht(DATA_PIN, 65 DHTTYPE); 66 67 68#define SCREEN_WIDTH 128 // OLED display width, in pixels 69#define 70 SCREEN_HEIGHT 64 // OLED display height, in pixels 71 72// The pins for I2C are 73 defined by the Wire-library. 74// On an arduino UNO/Nano and Pro Mini: A4(SDA), 75 A5(SCL) 76// On an arduino MEGA 2560: 20(SDA), 21(SCL) 77// On an 78 arduino LEONARDO: 2(SDA), 3(SCL), ... 79#define OLED_RESET -1 // 80 Reset pin # (or -1 if no reset on display) 81#define SCREEN_ADDRESS 0x3C // See 82 datasheet for Address (Yours could be 0x3D) 83 84// Create object for the SSD1306 85 display connected to I2C (SDA, SCL pins) 86Adafruit_SSD1306 display(SCREEN_WIDTH, 87 SCREEN_HEIGHT, &Wire, OLED_RESET); 88 89#define MODE_BUTTON 2 // Activate 90 display and switched between temperature, graph and humidity 91#define RESET_BUTTON 92 3 // If pressed when data displayed resets min and max settings 93 94float 95 temp; //Current temperature 96float humid; //Current humidity 97float 98 minTemp; //The minimum temperature recorded 99float maxTemp; //The maximum 100 temperature recorded 101float minHumid; //The minimum humidity recorded 102float 103 maxHumid; //The maximum humidity recorded 104 105unsigned long lastReadingUpdate; 106 // Time readings last updated 107 108// Battery Monitor 109#define MONITOR_PIN 110 A0 // Pin used to monitor supply voltage 111const float voltageDivider 112 = 4.0; // Used to calculate the actual voltage fRom the monitor pin reading 113 114 // Using 1m and 330k ohm resistors dividS the 115 voltage by approx 4 116 // You may wany to substitute 117 actual values of resistors in an equation (R1 + R2)/R2 118 // 119 E.g. (1000 + 330)/330 = 4.03 120 // Alternatively 121 take the voltage reading across the battery and from the joint between 122 // 123 the 2 resistors to ground and divide one by the other to get the value. 124 125 126// 127 Variables for History stored in EPROM 128// First version stored history in arrays 129 but program would not run as may have 130// run out of memory even though there 131 appeared to be memory to spare 132// 1 day's history is stored 96 readings at 15 133 minute intervals so each 134// EPROM position is written once per day. 135// 136 EPROM has a limited life of approx 100,000 writes per postion so as we 137// are 138 writin to each postion once a day the EPROM should last 100,000 days (274 years!) 139const 140 int intSize = sizeof(int); // Size of int to calculate storage location 141const 142 int tempStart = 0; // Start postion of temperature history - length 143 = 96 * intSize 144const int humidStart = 100 * intSize; // Start postion of humidity 145int 146 histPointer = - 1; // Last last postion updated (-1 means no history 147 yet stored) 148unsigned long histUpdated; // time last updated 149unsigned 150 long interval = 900000ul; //(15 * 60 * 1000); 15 minutes in milliseconds 151 152 153enum 154 mode { 155 dispTemp, // Temperature currently displayed 156 dispTempGraph, 157 // Temperature history graph displayed 158 dispHumid, // Humidity currently 159 displayed 160 dispHumidGraph // Humidity history graph displayed 161}; 162 163mode 164 currentMode; // Current display setting 165 166bool displaying; // 167 True if currently displaying data 168unsigned long timeDisplay; // 169 Time started to display, or last button pressed 170unsigned long keepDisplayFor 171 = 15000; // Number of milliseconds before enter screensave mode 172 173unsigned 174 long lastMoved; // Time last moved screensave bitmap 175 // 176 The battery indicator is displayed as the screensaver 177unsigned long moveEvery 178 = 10000; // Number of milliseconds between moves 179 180// Arrows used to 181 indicate maximum and minimum 182static const unsigned char PROGMEM upArrow[] { 183 184 B00000000, 185 B00011000, 186 B00111100, 187 B01111110, 188 B11111111, 189 190 B00011000, 191 B00011000, 192 B00011000 193}; 194 195static const unsigned char 196 PROGMEM downArrow[] { 197 B00011000, 198 B00011000, 199 B00011000, 200 B11111111, 201 202 B01111110, 203 B00111100, 204 B00011000, 205 B00000000 206}; 207 208// Battery 209 indicator bitmaps 210static const unsigned char PROGMEM full[] { 211 B00001110,B00000000, 212 213 B00001110,B00000000, 214 B11111111,B11100000, 215 B11111111,B11100000, 216 B11111111,B11100000, 217 218 B11111111,B11100000, 219 B11111111,B11100000, 220 B11111111,B11100000, 221 B11111111,B11100000, 222 223 B11111111,B11100000, 224 B11111111,B11100000, 225 B11111111,B11100000, 226 B11111111,B11100000, 227 228 B11111111,B11100000, 229 B11111111,B11100000, 230 B11111111,B11100000 231}; 232 233static 234 const unsigned char PROGMEM three4[] { 235 B00001110,B00000000, 236 B00001110,B00000000, 237 238 B11111111,B11100000, 239 B10000000,B00100000, 240 B10000000,B00100000, 241 B10000000,B00100000, 242 243 B11111111,B11100000, 244 B11111111,B11100000, 245 B11111111,B11100000, 246 B11111111,B11100000, 247 248 B11111111,B11100000, 249 B11111111,B11100000, 250 B11111111,B11100000, 251 B11111111,B11100000, 252 253 B11111111,B11100000, 254 B11111111,B11100000 255}; 256 257static const unsigned 258 char PROGMEM half[] { 259 B00001110,B00000000, 260 B00001110,B00000000, 261 B11111111,B11100000, 262 263 B10000000,B00100000, 264 B10000000,B00100000, 265 B10000000,B00100000, 266 B10000000,B00100000, 267 268 B10000000,B00100000, 269 B10000000,B00100000, 270 B11111111,B11100000, 271 B11111111,B11100000, 272 273 B11111111,B11100000, 274 B11111111,B11100000, 275 B11111111,B11100000, 276 B11111111,B11100000, 277 278 B11111111,B11100000 279}; 280 281static const unsigned char PROGMEM one4[] { 282 283 B00001110,B00000000, 284 B00001110,B00000000, 285 B11111111,B11100000, 286 B10000000,B00100000, 287 288 B10000000,B00100000, 289 B10000000,B00100000, 290 B10000000,B00100000, 291 B10000000,B00100000, 292 293 B10000000,B00100000, 294 B10000000,B00100000, 295 B10000000,B00100000, 296 B10000000,B00100000, 297 298 B11111111,B11100000, 299 B11111111,B11100000, 300 B11111111,B11100000, 301 B11111111,B11100000 302}; 303 304static 305 const unsigned char PROGMEM empty[] { 306 B00001110,B00000000, 307 B00001110,B00000000, 308 309 B11111111,B11100000, 310 B10000000,B00100000, 311 B10000000,B00100000, 312 B10000000,B00100000, 313 314 B10000000,B00100000, 315 B10000000,B00100000, 316 B10000000,B00100000, 317 B10000000,B00100000, 318 319 B10000000,B00100000, 320 B10000000,B00100000, 321 B10000000,B00100000, 322 B10000000,B00100000, 323 324 B10000000,B00100000, 325 B11111111,B11100000 326}; 327 328void setup() { 329 330 minTemp = 99; //Set to a figure that is going to be too high 331 maxTemp = 332 -9; //Set to a figure that is going to be too low 333 minHumid = 99; //Set 334 to a figure that is going to be too high 335 maxHumid = -9; //Set to a figure 336 that is going to be too low 337 pinMode(MODE_BUTTON, INPUT_PULLUP); // Use INPUT_PULLUP 338 - will go LOW when button pressed 339 pinMode(RESET_BUTTON, INPUT_PULLUP); 340 341 analogReference(INTERNAL); // Sets the reference voltage for the analog pins 342 to 1.1v 343 pinMode(MONITOR_PIN, INPUT); // Set input on pin used to monitor 344 the voltage 345 // Start sensor 346 dht.begin(); 347 // Initialise display 348 349 display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); 350 display.setTextColor(WHITE); 351 352 currentMode = dispTemp; 353 displaying = true; 354 timeDisplay = millis(); // 355 Set so initially displays for set period 356 histUpdated = millis(); // First 357 update will be interval after startup 358 lastMoved = millis(); // Time bitmap 359 last moved 360 clearEEPROM(); // Clear EPROM ready to start storing 361 history 362} 363 364void loop() { 365 // Check if the time since last display of 366 data started is greater than 367 // the time set to keeo the display showing 368 369 if ((millis() - timeDisplay) > keepDisplayFor) { 370 // If so in screen save 371 mode 372 displaying = false; // Flag to indicate data not being 373 displayed 374 // Check if we need to move the bitmap 375 if ((millis() - lastMoved) 376 > moveEvery) { 377 // Update time last moved 378 lastMoved = millis(); 379 380 // Dislpay battery bitmap in random position 381 DrawScreenSave(random(10, 382 110), random(10, 45)); 383 } 384 } 385 // Update the readings every 2 seconds 386 387 if ((millis() - lastReadingUpdate) > 2000ul) { 388 // Get readings, update 389 minimum and maximum values 390 lastReadingUpdate = millis(); 391 humid = dht.readHumidity(); 392 // read humidity 393 temp = dht.readTemperature(); // 394 read temperature 395 if (temp < minTemp) 396 minTemp = temp; 397 if (temp 398 > maxTemp) 399 maxTemp = temp; 400 if (humid < minHumid) 401 minHumid 402 = humid; 403 if (humid > maxHumid) 404 maxHumid = humid; 405 if (displaying) 406 { 407 // Update display if data being displayed 408 switch (currentMode) 409 { 410 case dispTemp: 411 ShowTemperature(); 412 break; 413 414 case dispTempGraph: 415 ShowGraph(); 416 break; 417 case 418 dispHumid: 419 ShowHumidity(); 420 break; 421 case dispHumidGraph: 422 423 ShowGraph(); 424 break; 425 } 426 } 427 } 428 // Check 429 if any buttons have been pressed 430 CheckButtons(); 431 // If history update 432 interval has passed, update history 433 if ((millis() - histUpdated) >= interval) 434 435 UpdateHistory(); 436 delay(150); // Short pause before continuing 437} 438 439// 440 Read the monitor pin and calculate the voltage 441float BatteryVoltage(){ 442 float 443 reading = analogRead(MONITOR_PIN); 444 // Calculate voltage - reference voltage 445 is 1.1v 446 return 1.1 * (reading/1023) * voltageDivider; 447} 448 449void DrawScreenSave(int 450 x, int y){ 451 // Get battery voltage and display approprate bitmap 452 display.clearDisplay(); 453 454 float voltage = BatteryVoltage(); 455 if (voltage > 3.6) 456 display.drawBitmap(x, 457 y, full, 16, 16, WHITE); 458 else 459 if (voltage > 3.5) 460 display.drawBitmap(x, 461 y, three4, 16, 16, WHITE); 462 else 463 if (voltage > 3.4) 464 display.drawBitmap(x, 465 y, half, 16, 16, WHITE); 466 else 467 if (voltage > 3.3) 468 display.drawBitmap(x, 469 y, one4, 16, 16, WHITE); 470 else 471 display.drawBitmap(x, 472 y, empty, 16, 16, WHITE); 473 /* Debug code to display reading and voltage 474 for checking 475 display.setCursor(random(0,96), random(15,35)); 476 display.print(voltage); 477 478 float reading = analogRead(MONITOR_PIN); 479 display.setCursor(random(0,75), 480 random(45,60)); 481 display.print(reading);*/ 482 display.display(); 483} 484 485void 486 UpdateHistory() { 487 histUpdated += interval; 488 // Use a circular list 489 490 // Increment to next element in EPROM and circulate back to 0 if end 491 // of 492 list reached 493 histPointer++; 494 if (histPointer > 95) 495 histPointer = 496 0; 497 saveTemperature(histPointer, int(temp)); 498 saveHumidity(histPointer, 499 int(humid)); 500} 501 502// Clear area we are using for storage 503void clearEEPROM() 504{ 505 506 for (int i = 0 ; i < 200 * intSize ; i++) { 507 if(EEPROM.read(i) != 0) //skip 508 already "empty" addresses 509 { 510 EEPROM.write(i, 0); //write 511 0 to address i 512 } 513 } 514} 515 516void saveTemperature(int postion, int 517 value){ 518 EEPROM.put(tempStart + postion * intSize, value); 519} 520 521void 522 saveHumidity(int postion, int value){ 523 EEPROM.put(humidStart + postion * intSize, 524 value); 525} 526 527int getTemperature(int postion){ 528 int value = 0; 529 EEPROM.get(tempStart 530 + postion * intSize, value); 531 return value; 532} 533 534int getHumidity(int 535 postion){ 536 int value = 0; 537 EEPROM.get(humidStart + postion * intSize, value); 538 539 return value; 540} 541 542// Routine to display numbers aligned and with sign 543void 544 dispNumber(int y, float value, bool tDisp) { 545 if (value < 10.0 && value > 0.0) 546 547 display.setCursor(72, y); 548 else 549 display.setCursor(60, y); 550 display.print(value); 551 552 if (tDisp) 553 display.print("c"); 554 else 555 display.print("%"); 556} 557 558// 559 Routine to display graph 560void ShowGraph() { 561 // Calculate scale 562 int 563 histValue; 564 int minimum = 99; 565 int maximum = -9; 566 float yScale; 567 568 for (int i = 0; i < 96; i++) { 569 if (currentMode == dispTempGraph) 570 histValue 571 = getTemperature(i); 572 else 573 histValue = getHumidity(i); 574 if 575 (histValue < minimum) 576 minimum = histValue; 577 if (histValue > maximum) 578 579 maximum = histValue; 580 } 581 if ((maximum - minimum) != 0) 582 yScale 583 = 63.0 / (maximum - minimum); 584 else 585 yScale = 1; 586 // Display axis 587 data 588 display.clearDisplay(); 589 display.setFont(); 590 display.setTextSize(1); 591 592 display.setCursor(0, 54); 593 display.print(minimum); 594 if (currentMode == 595 dispTempGraph) 596 display.print("c"); 597 else 598 display.print("%"); 599 600 display.setCursor(0, 0); 601 display.print(maximum); 602 if (currentMode == 603 dispTempGraph) 604 display.print("c"); 605 else 606 display.print("%"); 607 608 display.setCursor(0, 25); 609 if (currentMode == dispTempGraph) 610 display.print("Temp."); 611 612 else 613 display.print("Humid."); 614 // Graph list from histPointer + 1 615 circulating to histPointer 616 int pos = histPointer + 1; 617 int priorPos; 618 619 int histValuePrior; 620 // Count 1 less than list as stating at point 2 621 for 622 (int i = 1; i < 96; i++) { 623 pos++; 624 if (pos > 95) 625 pos = 0; 626 627 if (pos > 0) 628 priorPos = pos - 1; 629 else 630 priorPos = 95; 631 632 if (currentMode == dispTempGraph) { 633 histValuePrior = getTemperature(priorPos); 634 635 histValue = getTemperature(pos); 636 } 637 else { 638 histValuePrior 639 = getHumidity(priorPos); 640 histValue = getHumidity(pos); 641 } 642 643 display.drawLine(32 + i - 1, 63 - (histValuePrior - minimum) * yScale, 644 32 645 + i, 63 - (histValue - minimum) * yScale, SSD1306_WHITE); 646 } 647 display.display(); 648} 649 650void 651 ShowTemperature() { 652 display.clearDisplay(); 653 display.setTextSize(1); 654 655 display.setFont(&FreeSans9pt7b); // Font used for text 656 display.setCursor(0, 657 15); 658 display.print("Temp:"); 659 display.drawBitmap(20, 35 - 9, upArrow, 660 8, 8, WHITE); 661 display.drawBitmap(20, 55 - 9, downArrow, 8, 8, WHITE); 662 display.setFont(&FreeMonoBold9pt7b); 663 // Font used for numbers 664 dispNumber(15, temp, true); 665 dispNumber(35, 666 maxTemp, true); 667 dispNumber(55, minTemp, true); 668 display.display(); 669} 670 671void 672 ShowHumidity() { 673 display.clearDisplay(); 674 display.setTextSize(1); 675 display.setFont(&FreeSans9pt7b); 676 // Font used for text 677 display.setCursor(0, 15); 678 display.print("Humid:"); 679 680 display.drawBitmap(20, 35 - 9, upArrow, 8, 8, WHITE); 681 display.drawBitmap(20, 682 55 - 9, downArrow, 8, 8, WHITE); 683 display.setFont(&FreeMonoBold9pt7b); // 684 Font used for numbers 685 dispNumber(15, humid, false); 686 dispNumber(35, maxHumid, 687 false); 688 dispNumber(55, minHumid, false); 689 display.display(); 690} 691 692void 693 DisplayLowBattery(){ 694 display.clearDisplay(); 695 display.setTextSize(1); 696 697 display.setFont(&FreeSans9pt7b); // Font used for text 698 display.setCursor(48, 699 20); 700 display.print("Low"); 701 display.setCursor(35, 40); 702 display.print("Battery"); 703 704 display.display(); 705 delay(2000); 706} 707 708void CheckButtons() { 709 // 710 If the mode or reset button has been pressed pin will go LOW 711 // Check if mode 712 button pressed if so show data or switch mode between displays 713 if (digitalRead(MODE_BUTTON) 714 == LOW) { 715 timeDisplay = millis(); // Reset so remains display for 716 reset period after switching mode 717 if (!displaying) { 718 displaying 719 = true; // Set so displays data 720 // Check level of battery 721 722 float voltage = BatteryVoltage(); 723 if (voltage < 3.3) 724 DisplayLowBattery(); 725 726 currentMode = dispTemp; 727 ShowTemperature(); 728 delay(1000); 729 730 return; 731 } 732 // If already displaying move to next display 733 734 switch (currentMode) { 735 case dispTemp: 736 currentMode = dispTempGraph; 737 738 ShowGraph(); 739 break; 740 case dispTempGraph: 741 currentMode 742 = dispHumid; 743 ShowHumidity(); 744 break; 745 case dispHumid: 746 747 currentMode = dispHumidGraph; 748 ShowGraph(); 749 break; 750 751 case dispHumidGraph: 752 currentMode = dispTemp; 753 ShowTemperature(); 754 755 break; 756 } 757 delay(1000); // Give time to 758 release button 759 } 760 761 // Check if reset button pressed 762 // Is the system 763 displaying? 764 // If so the reset min and max values 765 if (displaying) { 766 767 if (digitalRead(RESET_BUTTON) == LOW) { 768 maxTemp = -9; 769 minTemp 770 = 99; 771 maxHumid = -9; 772 minHumid = 99; 773 delay(1000); // 774 Give time to release button 775 } 776 } 777}
Downloadable files
Monitor Schematic
Monitor Schematic
Monitor Schematic
Monitor Schematic
Monitor Breadboard
Monitor Breadboard
Comments
Only logged in users can leave comments
paulsb
0 Followers
•0 Projects
Table of contents
Intro
18
0