Components and supplies
DHT22 Temperature Sensor
Robojax DS3231 IIC Precision Real time Clock Module
Kuman 0.96 Inch Yellow Blue IIC OLED Module I2c
Arduino Nano R3
Project description
Code
DHT Median filter with RTC
arduino
Simply upload to your Nano with the Arduini IDE
1/* 2 3 Use an Arduino Nano to display temp/humidy on 0.96 inch Yellow/Blue IIC OLED I2c 4 serial 128x64 Display 5 6 Use an Adafruit DHT22 Temperature and Humidity Sensor (accuracy ±2%) 7 8 These data might bounce around somewhat because the sensor can be a little noisy 9 at times. We use a simple median filter to smooth out the noise 10 11 Arduino Nano <--> OLED = pin A4 to SDA and pin A5 to SLC 12 13 February 2020 14 15 Paul M Dunphy, VE1DX 16 17*/ 18 19 20// This library allows you to communicate with I2C devices, in this 21// case the RTC and OLED display 22#include <Wire.h> 23 24// For the DS3231 Real time Clock Module (AT24C32 Module) 25#include <DS1307RTC.h> 26 27// Include DHT Library from Adafruit 28 29#include "DHT.h"; 30/* DHT22 pin-out: 31 Pin 1 VCC 32 Pin 2 Data out 33 Pin 3 Not connected 34 Pin 4 Ground 35*/ 36 37#include "U8glib.h" // For the OLED - Obtain from: https://github.com/olikraus/u8glib 38 39// Define Constants 40 41#define dhtPin 7 // DHT-22 Output Pin connection 42#define dhtType DHT22 // DHT Type is a DHT 22 (AM2302) 43 44// Initialize OLED 45U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); 46 47// Initialize DHT sensor 48 49DHT dht(dhtPin, dhtType); 50 51tmElements_t tm; // For the RTC 52 53#define buff_size 7 // Must be an odd number. Should be greater than 5. 7 works well. 54 55unsigned long a_second = 1000; 56float h = 0.0; //Stores humidity value 57float t = 0.0; //Stores temperature value 58float h_array[buff_size] = {0.0}; 59float t_array[buff_size] = {0.0}; 60float h_array_sort[buff_size] = {0.0}; 61float t_array_sort[buff_size] = {0.0}; 62String string_Temp, string_Humid, temporary_string, tick_string; 63 64 65char OLED_string_1[50]; // Need a couple of character buffers to hold the two OLED lines 66char OLED_string_2[50]; 67 68 69String str_day, str_month, str_year, str_time; // Lot of conversion to strings required because the 70 // DSD Tech display doesn't like integers and floats 71 72 73void clearOLED() 74 { 75 u8g.firstPage(); 76 do { 77 } while( u8g.nextPage() ); 78 } 79 80 81void Initialize() 82{ 83 float startup_delay; 84 int i; 85 86 clearOLED(); 87 startup_delay = buff_size * (a_second * 5.0 / 1000.0); 88 temporary_string = String(startup_delay,0); 89 temporary_string = " (" + temporary_string + " seconds)"; 90 91 tick_string = "Initializing "; 92 strcpy(OLED_string_1, tick_string.c_str()); 93 strcpy(OLED_string_2, temporary_string.c_str()); 94 95 // Take "buff_size" readings of each parameter, one every 5 seconds, 96 // to get initial arrays of data. Print "status" dots across display. 97 for (i = 0 ; i < buff_size ; i++) 98 { 99 tick_string = tick_string + ". "; 100 strcpy(OLED_string_1, tick_string.c_str()); 101 sendstringstoDisplay(); 102 delay(a_second * 5); 103 h_array[i] = dht.readHumidity(); // Get Humidity value 104 t_array[i] = dht.readTemperature(); // Get Temperature value 105 } 106 } 107 108 109 110void bubble_sort(float sort_array[], int n) 111 { 112 int i, j; 113 float temp; 114 115 for (i = 0 ; i < n - 1; i++) 116 { 117 for (j = 0 ; j < n - i - 1; j++) 118 { 119 if (sort_array[j] > sort_array[j+1]) 120 { 121 // Swap values 122 temp = sort_array[j]; 123 sort_array[j] = sort_array[j+1]; 124 sort_array[j+1] = temp; 125 } 126 } 127 } 128 } 129 130 131 132 133void sendstringstoDisplay() 134 { 135 u8g.firstPage(); // Send them to the dispaly 136 do { 137 138 u8g.setFont(u8g_font_5x7); // This can be adjusted to various fonts. See: https://github.com/olikraus/u8glib/wiki/fontsize 139 u8g.setPrintPos(0,7); // Position of first line 140 u8g.print(OLED_string_1); 141 u8g.setFont(u8g_font_helvB14); // Little biger and bolder font as this is the temperature and humidy 142 u8g.setPrintPos(0, 25); // Position of second line 143 u8g.print(OLED_string_2); 144 145 } while (u8g.nextPage() ); 146 } 147 148 149 150 151void monthStr(tmElements_t tm) 152{ 153 154 int int_month; 155 156 str_month = tm.Month; 157 int_month = str_month.toInt(); 158 159 switch(int_month) 160 { 161 case 1: 162 str_month =("JAN"); 163 break; 164 case 2: 165 str_month =("FEB"); 166 break; 167 case 3: 168 str_month =("MAR"); 169 break; 170 case 4: 171 str_month =("APR"); 172 break; 173 case 5: 174 str_month =("MAY"); 175 break; 176 case 6: 177 str_month =("JUN"); 178 break; 179 case 7: 180 str_month =("JUL"); 181 break; 182 case 8: 183 str_month =("AUG"); 184 break; 185 case 9: 186 str_month =("SEP"); 187 break; 188 case 10: 189 str_month =("OCT"); 190 break; 191 case 11: 192 str_month =("NOV"); 193 break; 194 case 12: 195 str_month =("DEC"); 196 break; 197 default: 198 str_month =("ERR"); 199 break; 200 } 201 202} 203 204 205 206void timeStr(tmElements_t tm) 207{ 208 209 // Add a leading zero when needed so all numbers are two characters 210 211 String hours,seconds,minutes; 212 213 if(tm.Hour<10) 214 { 215 hours = "0"+String(tm.Hour); 216 } 217 else 218 { 219 hours = String(tm.Hour); 220 } 221 222 if(tm.Minute<10) 223 { 224 minutes = "0"+String(tm.Minute); 225 } 226 else 227 { 228 minutes = String(tm.Minute); 229 } 230 231 // We're processing seconds "just in case", but not adding them to the small display 232 233 if(tm.Second<10) 234 { 235 seconds = "0"+String(tm.Second); 236 } 237 else 238 { 239 seconds = String(tm.Second); 240 } 241 242 str_time = hours + ":" + minutes; 243} 244 245 246 247 248void setup() 249 { 250 // Start Wire library for I2C 251 Wire.begin(); 252 clearOLED(); 253 dht.begin(); 254 // initialize digital pin LED_BUILTIN as an output. 255 pinMode(LED_BUILTIN, OUTPUT); 256 Initialize(); 257 } 258 259 260 261 262void loop() 263 { 264 int i, median_index; 265 266 RTC.read(tm); // Get the date and time 267 monthStr(tm); // Convert the month from a number to Jan, Feb, Mar, etc 268 timeStr(tm); // Convert the time to strings 269 270 h = dht.readHumidity(); // Get Humidity value 271 t = dht.readTemperature(); // Get Temperature value 272 273 // Replace the oldest value with the newest just read by moving every element in 274 // the arrays up one and sticking this new value in the bottom. 275 for (i = 0 ; i < buff_size - 1 ; i++) 276 { 277 h_array[i] = h_array[i + 1]; 278 t_array[i] = t_array[i + 1]; 279 } 280 h_array[buff_size-1] = h; 281 t_array[buff_size-1] = t; 282 283 // Move them into the sort arrays 284 for (i = 0 ; i < buff_size ; i++) 285 { 286 h_array_sort[i] = h_array[i]; 287 t_array_sort[i] = t_array[i]; 288 } 289 290 // Sort them. Use quick and dirty bubble sort because it's a small number of data points 291 bubble_sort(h_array_sort, buff_size); 292 bubble_sort(t_array_sort, buff_size); 293 294 // Use the median of the last "buff_zize" readings for the display 295 median_index = buff_size / 2; 296 h = h_array_sort[median_index]; 297 t = t_array_sort[median_index]; 298 string_Temp = String(t,1); // Make temp a character string 299 string_Humid = String(h,1); // Make humid a character string 300 301 // Build first OLED line 302 str_year = tmYearToCalendar(tm.Year); 303 str_day = tm.Day; 304 str_day = str_day + "-"; 305 str_month = str_month + "-"; 306 temporary_string = " " + str_day + str_month + str_year + " " + str_time; 307 strcpy(OLED_string_1, temporary_string.c_str()); // Put date/time string in the first character array 308 309 // Build second OLED line 310 temporary_string = ""; 311 temporary_string = temporary_string + string_Temp + char(176) + "C "; // char(176) is the degree symbol 312 temporary_string = temporary_string + string_Humid + " %"; 313 strcpy(OLED_string_2, temporary_string.c_str()); // Put temperature/humidity string in the second character array 314 315 316 sendstringstoDisplay(); // Display the median temperature and humidity 317 delay(5000); // Updates every 5 seconds 318 319 }
DHT Median filter with RTC
arduino
Simply upload to your Nano with the Arduini IDE
1/* 2 3 Use an Arduino Nano to display temp/humidy on 0.96 inch Yellow/Blue 4 IIC OLED I2c 5 serial 128x64 Display 6 7 Use an Adafruit DHT22 Temperature 8 and Humidity Sensor (accuracy ±2%) 9 10 These data might bounce around somewhat 11 because the sensor can be a little noisy 12 at times. We use a simple median 13 filter to smooth out the noise 14 15 Arduino Nano <--> OLED = pin A4 to SDA 16 and pin A5 to SLC 17 18 February 2020 19 20 Paul M Dunphy, VE1DX 21 22*/ 23 24 25// 26 This library allows you to communicate with I2C devices, in this 27// case the 28 RTC and OLED display 29#include <Wire.h> 30 31// For the DS3231 Real time Clock 32 Module (AT24C32 Module) 33#include <DS1307RTC.h> 34 35// Include DHT Library 36 from Adafruit 37 38#include "DHT.h"; 39/* DHT22 pin-out: 40 Pin 1 VCC 41 42 Pin 2 Data out 43 Pin 3 Not connected 44 Pin 4 Ground 45*/ 46 47#include 48 "U8glib.h" // For the OLED - Obtain from: https://github.com/olikraus/u8glib 49 50// 51 Define Constants 52 53#define dhtPin 7 // DHT-22 Output Pin connection 54#define 55 dhtType DHT22 // DHT Type is a DHT 22 (AM2302) 56 57// Initialize OLED 58U8GLIB_SSD1306_128X32 59 u8g(U8G_I2C_OPT_NONE); 60 61// Initialize DHT sensor 62 63DHT dht(dhtPin, dhtType); 64 65 66tmElements_t tm; // For the RTC 67 68#define buff_size 7 // Must be 69 an odd number. Should be greater than 5. 7 works well. 70 71unsigned long a_second 72 = 1000; 73float h = 0.0; //Stores humidity value 74float t = 0.0; //Stores temperature 75 value 76float h_array[buff_size] = {0.0}; 77float t_array[buff_size] = {0.0}; 78float 79 h_array_sort[buff_size] = {0.0}; 80float t_array_sort[buff_size] = {0.0}; 81String 82 string_Temp, string_Humid, temporary_string, tick_string; 83 84 85char OLED_string_1[50]; 86 // Need a couple of character buffers to hold the two OLED lines 87char OLED_string_2[50]; 88 89 90String 91 str_day, str_month, str_year, str_time; // Lot of conversion to strings required 92 because the 93 // DSD Tech display 94 doesn't like integers and floats 95 96 97void clearOLED() 98 { 99 u8g.firstPage(); 100 101 do { 102 } while( u8g.nextPage() ); 103 } 104 105 106void Initialize() 107{ 108 109 float startup_delay; 110 int i; 111 112 clearOLED(); 113 startup_delay = 114 buff_size * (a_second * 5.0 / 1000.0); 115 temporary_string = String(startup_delay,0); 116 117 temporary_string = " (" + temporary_string + " seconds)"; 118 119 tick_string 120 = "Initializing "; 121 strcpy(OLED_string_1, tick_string.c_str()); 122 strcpy(OLED_string_2, 123 temporary_string.c_str()); 124 125 // Take "buff_size" readings of each parameter, 126 one every 5 seconds, 127 // to get initial arrays of data. Print "status" dots 128 across display. 129 for (i = 0 ; i < buff_size ; i++) 130 { 131 tick_string 132 = tick_string + ". "; 133 strcpy(OLED_string_1, tick_string.c_str()); 134 135 sendstringstoDisplay(); 136 delay(a_second * 5); 137 h_array[i] 138 = dht.readHumidity(); // Get Humidity value 139 t_array[i] = dht.readTemperature(); 140 // Get Temperature value 141 } 142 } 143 144 145 146void bubble_sort(float 147 sort_array[], int n) 148 { 149 int i, j; 150 float temp; 151 152 for (i = 153 0 ; i < n - 1; i++) 154 { 155 for (j = 0 ; j < n - i - 1; j++) 156 { 157 158 if (sort_array[j] > sort_array[j+1]) 159 { 160 // 161 Swap values 162 temp = sort_array[j]; 163 sort_array[j] 164 = sort_array[j+1]; 165 sort_array[j+1] = temp; 166 } 167 168 } 169 } 170 } 171 172 173 174 175void sendstringstoDisplay() 176 177 { 178 u8g.firstPage(); // Send them to the dispaly 179 do { 180 181 u8g.setFont(u8g_font_5x7); 182 // This can be adjusted to various fonts. See: https://github.com/olikraus/u8glib/wiki/fontsize 183 184 u8g.setPrintPos(0,7); // Position of first line 185 u8g.print(OLED_string_1); 186 187 u8g.setFont(u8g_font_helvB14); // Little biger and bolder font as this is 188 the temperature and humidy 189 u8g.setPrintPos(0, 25); // Position 190 of second line 191 u8g.print(OLED_string_2); 192 193 } while (u8g.nextPage() 194 ); 195 } 196 197 198 199 200void monthStr(tmElements_t tm) 201{ 202 203 int int_month; 204 205 206 str_month = tm.Month; 207 int_month = str_month.toInt(); 208 209 switch(int_month) 210 211 { 212 case 1: 213 str_month =("JAN"); 214 break; 215 case 216 2: 217 str_month =("FEB"); 218 break; 219 case 3: 220 str_month 221 =("MAR"); 222 break; 223 case 4: 224 str_month =("APR"); 225 226 break; 227 case 5: 228 str_month =("MAY"); 229 break; 230 231 case 6: 232 str_month =("JUN"); 233 break; 234 case 7: 235 236 str_month =("JUL"); 237 break; 238 case 8: 239 str_month 240 =("AUG"); 241 break; 242 case 9: 243 str_month =("SEP"); 244 245 break; 246 case 10: 247 str_month =("OCT"); 248 break; 249 250 case 11: 251 str_month =("NOV"); 252 break; 253 case 12: 254 255 str_month =("DEC"); 256 break; 257 default: 258 str_month 259 =("ERR"); 260 break; 261 } 262 263} 264 265 266 267void timeStr(tmElements_t 268 tm) 269{ 270 271 // Add a leading zero when needed so all numbers are two characters 272 273 274 String hours,seconds,minutes; 275 276 if(tm.Hour<10) 277 { 278 hours 279 = "0"+String(tm.Hour); 280 } 281 else 282 { 283 hours = String(tm.Hour); 284 285 } 286 287 if(tm.Minute<10) 288 { 289 minutes = "0"+String(tm.Minute); 290 291 } 292 else 293 { 294 minutes = String(tm.Minute); 295 } 296 297 // We're 298 processing seconds "just in case", but not adding them to the small display 299 300 301 if(tm.Second<10) 302 { 303 seconds = "0"+String(tm.Second); 304 } 305 306 else 307 { 308 seconds = String(tm.Second); 309 } 310 311 str_time 312 = hours + ":" + minutes; 313} 314 315 316 317 318void setup() 319 { 320 // 321 Start Wire library for I2C 322 Wire.begin(); 323 clearOLED(); 324 dht.begin(); 325 326 // initialize digital pin LED_BUILTIN as an output. 327 pinMode(LED_BUILTIN, 328 OUTPUT); 329 Initialize(); 330 } 331 332 333 334 335void loop() 336 { 337 338 int i, median_index; 339 340 RTC.read(tm); // Get the date and time 341 342 monthStr(tm); // Convert the month from a number to Jan, Feb, Mar, etc 343 344 timeStr(tm); // Convert the time to strings 345 346 h = dht.readHumidity(); 347 // Get Humidity value 348 t = dht.readTemperature(); // Get Temperature 349 value 350 351 // Replace the oldest value with the newest just read by moving 352 every element in 353 // the arrays up one and sticking this new value in the 354 bottom. 355 for (i = 0 ; i < buff_size - 1 ; i++) 356 { 357 h_array[i] 358 = h_array[i + 1]; 359 t_array[i] = t_array[i + 1]; 360 } 361 h_array[buff_size-1] 362 = h; 363 t_array[buff_size-1] = t; 364 365 // Move them into the sort arrays 366 367 for (i = 0 ; i < buff_size ; i++) 368 { 369 h_array_sort[i] 370 = h_array[i]; 371 t_array_sort[i] = t_array[i]; 372 } 373 374 // 375 Sort them. Use quick and dirty bubble sort because it's a small number of data points 376 377 bubble_sort(h_array_sort, buff_size); 378 bubble_sort(t_array_sort, buff_size); 379 380 381 // Use the median of the last "buff_zize" readings for the display 382 median_index 383 = buff_size / 2; 384 h = h_array_sort[median_index]; 385 t = t_array_sort[median_index]; 386 387 string_Temp = String(t,1); // Make temp a character string 388 string_Humid 389 = String(h,1); // Make humid a character string 390 391 // Build first 392 OLED line 393 str_year = tmYearToCalendar(tm.Year); 394 str_day = tm.Day; 395 396 str_day = str_day + "-"; 397 str_month = str_month + "-"; 398 temporary_string 399 = " " + str_day + str_month + str_year + " " + str_time; 400 strcpy(OLED_string_1, 401 temporary_string.c_str()); // Put date/time string in the first character array 402 403 404 // Build second OLED line 405 temporary_string = ""; 406 temporary_string 407 = temporary_string + string_Temp + char(176) + "C "; // char(176) is the degree 408 symbol 409 temporary_string = temporary_string + string_Humid + " %"; 410 411 strcpy(OLED_string_2, temporary_string.c_str()); // Put temperature/humidity 412 string in the second character array 413 414 415 sendstringstoDisplay(); 416 // Display the median temperature and humidity 417 delay(5000); 418 // Updates every 5 seconds 419 420 }
Downloadable files
Breadboard layout
Breadboard layout
Comments
Only logged in users can leave comments