<?xml version="1.0" encoding="UTF-8"?>        <rss version="2.0"
             xmlns:atom="http://www.w3.org/2005/Atom"
             xmlns:dc="http://purl.org/dc/elements/1.1/"
             xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
             xmlns:admin="http://webns.net/mvcb/"
             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
             xmlns:content="http://purl.org/rss/1.0/modules/content/">
        <channel>
            <title>
									Median filter with DHT22, etc. - Show &amp; Tell				            </title>
            <link>https://forum.dronebotworkshop.com/show-tell/median-filter-with-dht22-etc/</link>
            <description>Discussion board for Robotics, Arduino, Raspberry Pi and other DIY electronics and modules. Join us today!</description>
            <language>en-US</language>
            <lastBuildDate>Thu, 16 Apr 2026 18:09:38 +0000</lastBuildDate>
            <generator>wpForo</generator>
            <ttl>60</ttl>
							                    <item>
                        <title>Median filter with DHT22, etc.</title>
                        <link>https://forum.dronebotworkshop.com/show-tell/median-filter-with-dht22-etc/#post-8358</link>
                        <pubDate>Sat, 08 Feb 2020 14:20:57 +0000</pubDate>
                        <description><![CDATA[Here are a circuit and sketch I put together roughly based on Bill&#039;s video on OLEDs, with a DHT22 sensor and an RTC using an Arduino Nano. I added a median filter to the temperature and humi...]]></description>
                        <content:encoded><![CDATA[<p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"><span style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt" data-preserver-spaces="true">Here are a circuit and sketch I put together roughly based on Bill's video on OLEDs, with a DHT22 sensor and an RTC using an Arduino Nano. I added a median filter to the temperature and humidity data to smooth out any spikes of odd data points. The DHT22 is stable for the most part, but everything can generate oddball readings occasionally. It takes a little longer to reflect on temperature and humidity changes, but all and all, it works well. I could have used moving averages, etc., but experience writing data loggers suggests median filters work well. Data changes have to be persistent and exceed 1/2 the filter size to ever show up. I'm using 7 points, although this can be any odd number within reason.</span></p><p> </p><p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"><span style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt" data-preserver-spaces="true">The U8glib library is great for the display as it has a lot of flexibility to allow manipulation of the OLED fonts, etc.:</span></p><p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"> </p><p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"><a class="_e75a791d-denali-editor-page-rtfLink" style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt;;color: #4a6ee0" href="https://github.com/olikraus/u8glib" target="_blank" rel="noopener"><span style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt;;color: #4a6ee0" data-preserver-spaces="true">https://github.com/olikraus/u8glib</span></a></p><p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"> </p><p style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt"><span style="color: #0e101a;background: transparent;margin-top: 0pt;margin-bottom: 0pt" data-preserver-spaces="true">Paul VE1DX</span></p><p> </p><pre><br /> 1323 <br /><br /><br /><br /> /*<br /> <br />  Use an Arduino Nano to display temp/humidity on 0.96 inch Yellow/Blue IIC OLED I2c <br />  serial 128x64 LCD Display<br />  <br />  Use an Adafruit DHT22 Temperature and Humidity Sensor (accuracy ±2%)<br /><br />  These data might bounce around somewhat because the sensor can be a little noisy<br />  at times.  We use a simple median filter to smooth out the noise<br />  <br />  Arduino Nano &lt;--&gt; OLED = pin A4 to SDA and pin A5 to SLC <br /><br />  February 2020<br /><br />  Paul M Dunphy<br />  <br />*/<br /><br /><br />// This library allows you to communicate with I2C devices, in this<br />// case the RTC and OLED display<br />#include &lt;Wire.h&gt; <br /><br />// For the DS3231 Real time Clock Module (AT24C32 Module)<br />#include &lt;DS1307RTC.h&gt;<br /><br />// Include DHT Library from Adafruit<br /><br />#include "DHT.h";<br />/* DHT22 pin-out:<br />   Pin 1 VCC <br />   Pin 2 Data out<br />   Pin 3 Not connected<br />   Pin 4 Ground<br />*/<br /><br />#include "U8glib.h"  // For the OLED - Obtain from: https://github.com/olikraus/u8glib<br /><br />// Define Constants<br /> <br />#define dhtPin 7        // DHT-22 Output Pin connection<br />#define dhtType DHT22   // DHT Type is a DHT 22 (AM2302)<br /><br />// Initialize OLED<br />U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);<br /><br />// Initialize DHT sensor<br /> <br />DHT dht(dhtPin, dhtType); <br /><br />tmElements_t tm;  // For the RTC<br /><br />#define buff_size 7  // Must be an odd number.  Should be greater than 5.  7 works well.<br /><br />unsigned long a_second = 1000;<br />float h = 0.0;  //Stores humidity value<br />float t = 0.0;  //Stores temperature value<br />float h_array = {0.0};<br />float t_array = {0.0};<br />float h_array_sort = {0.0};<br />float t_array_sort = {0.0};<br />String string_Temp, string_Humid, temporary_string, tick_string;<br /><br /> <br />char OLED_string_1; // Need a couple of character buffers to hold the two OLED lines<br />char OLED_string_2;<br /><br /><br />String str_day, str_month, str_year, str_time; // Lot of conversion to strings required because the<br />                                               // DSD Tech display doesn't like integers and floats<br /><br /><br />void clearOLED()<br />  {<br />    u8g.firstPage(); <br />    do {<br />    } while( u8g.nextPage() );<br />  }<br /><br /><br />void Initialize()<br />{<br />  float startup_delay;<br />  int i;<br />  <br />  clearOLED();<br />  startup_delay = buff_size * (a_second * 5.0 / 1000.0);<br />  temporary_string  = String(startup_delay,0);<br />  temporary_string = " (" + temporary_string + " seconds)";<br /><br />  tick_string = "Initializing "; <br />  strcpy(OLED_string_1, tick_string.c_str());<br />  strcpy(OLED_string_2, temporary_string.c_str());<br />  <br />  // Take "buff_size" readings of each parameter, one every 5 seconds,<br />  // to get initial arrays of data.  Print "status" dots across display.<br />  for (i = 0 ; i &lt; buff_size ; i++)<br />    {    <br />       tick_string = tick_string + ". ";<br />       strcpy(OLED_string_1, tick_string.c_str());<br />       sendstringstoDisplay();<br />       delay(a_second * 5);<br />       h_array = dht.readHumidity();       // Get Humidity value<br />       t_array = dht.readTemperature();    // Get Temperature value<br />    }    <br />  }<br /><br /><br /><br /><br />void bubble_sort(float sort_array[], int n)<br />  {<br />  int i, j;<br />  float  temp;<br /> <br />  for (i = 0 ; i &lt; n - 1; i++)<br />    {<br />      for (j = 0 ; j &lt; n - i - 1; j++)<br />        {<br />          if (sort_array &gt; sort_array)<br />            {<br />            // Swap values <br />            temp            = sort_array;<br />            sort_array   = sort_array;<br />            sort_array = temp;<br />            }<br />          }<br />      }<br />  }<br /><br /><br /><br /><br /><br />void sendstringstoDisplay()<br />  {<br />    u8g.firstPage();  // Send them to the dispaly<br />      do {<br /><br />        u8g.setFont(u8g_font_5x7);  // This can be adjusted to various fonts.  See:  https://github.com/olikraus/u8glib/wiki/fontsize<br />        u8g.setPrintPos(0,7);       // Position of first line<br />        u8g.print(OLED_string_1);<br />        u8g.setFont(u8g_font_helvB14); // Little biger and bolder font as this is the temperature and humidy<br />        u8g.setPrintPos(0, 25);        // Position of second line<br />        u8g.print(OLED_string_2);<br /><br />         } while (u8g.nextPage() );<br />  }<br /><br /><br /><br /><br /><br />void monthStr(tmElements_t tm)<br />{<br /><br />   int int_month;<br />   <br />   str_month = tm.Month;<br />   int_month = str_month.toInt();<br /><br />   switch(int_month)<br />   {<br />   case 1:<br />         str_month =("JAN");<br />         break;<br />   case 2:<br />         str_month =("FEB");<br />         break;<br />   case 3:<br />         str_month =("MAR");<br />         break;<br />   case 4:<br />         str_month =("APR");<br />         break;<br />   case 5:<br />         str_month =("MAY");<br />         break;<br />   case 6:<br />         str_month =("JUN");<br />         break;<br />   case 7:<br />         str_month =("JUL");<br />         break;<br />   case 8:<br />         str_month =("AUG");<br />         break;<br />   case 9:<br />         str_month =("SEP");<br />         break;<br />   case 10:<br />         str_month =("OCT");<br />         break;<br />   case 11:<br />         str_month =("NOV");<br />         break;<br />   case 12:<br />         str_month =("DEC");<br />         break;<br />   default:<br />         str_month =("ERR");<br />         break;<br />      }<br />      <br />}<br /><br /><br /><br /><br />void timeStr(tmElements_t tm)<br />{<br /><br />  // Add a leading zero when needed so all numbers are two characters<br />   <br />  String hours,seconds,minutes;<br /><br />  if(tm.Hour&lt;10)<br />  {<br />    hours = "0"+String(tm.Hour);<br />  }<br />  else<br />  { <br />    hours = String(tm.Hour); <br />   }<br />  <br />  if(tm.Minute&lt;10)<br />  {<br />    minutes = "0"+String(tm.Minute);<br />  }<br />  else<br />  { <br />    minutes = String(tm.Minute); <br />   }<br /><br />  // We're processing seconds "just in case", but not adding them to the small display <br />  <br />  if(tm.Second&lt;10)<br />  {<br />    seconds = "0"+String(tm.Second);<br />  }<br />  else<br />  { <br />    seconds = String(tm.Second); <br />   }<br />   <br />  str_time = hours + ":" + minutes;<br />}<br />  <br /><br /><br /><br /><br />void setup() <br />  { <br />   // Start Wire library for I2C<br />   Wire.begin();  <br />   clearOLED();  <br />   dht.begin();<br />   // initialize digital pin LED_BUILTIN as an output.<br />   pinMode(LED_BUILTIN, OUTPUT); <br />   Initialize();<br />  } <br /><br /><br /><br /><br /><br />void loop()<br />  { <br />    int i, median_index;<br />    <br />    RTC.read(tm);  // Get the date and time<br />    monthStr(tm);  // Convert the month from a number to Jan, Feb, Mar, etc<br />    timeStr(tm);   // Convert the time to strings<br /><br />    h = dht.readHumidity();         // Get Humidity value<br />    t = dht.readTemperature();      // Get Temperature value<br /><br />    // Replace the oldest value with the newest just read by moving every element in <br />    // the arrays up one and sticking this new value in the bottom.<br />    for (i = 0 ; i &lt; buff_size - 1 ; i++)<br />      {   <br />        h_array = h_array;<br />        t_array = t_array;<br />      }<br />    h_array = h;<br />    t_array = t;<br /><br />    // Move them into the sort arrays<br />    for (i = 0 ; i &lt; buff_size ; i++)<br />      {    <br />        h_array_sort = h_array;<br />        t_array_sort = t_array;<br />      }<br /><br />    // Sort them. Use quick and dirty bubble sort because it's a small number of data points<br />    bubble_sort(h_array_sort, buff_size);<br />    bubble_sort(t_array_sort, buff_size);<br /><br />    // Use the median of the last "buff_zize" readings for the display<br />    median_index = buff_size / 2;<br />    h = h_array_sort; <br />    t = t_array_sort;<br />    string_Temp  = String(t,1);     // Make temp a character string<br />    string_Humid = String(h,1);     // Make humid a character string<br />    <br />    //  Build first OLED line<br />    str_year = tmYearToCalendar(tm.Year);<br />    str_day = tm.Day;<br />    str_day = str_day + "-";<br />    str_month = str_month + "-";<br />    temporary_string = "    " + str_day + str_month + str_year + " " + str_time;<br />    strcpy(OLED_string_1, temporary_string.c_str());      // Put date/time string in the first character array<br />    <br />    //  Build second OLED line<br />    temporary_string = "";<br />    temporary_string = temporary_string + string_Temp + char(176) + "C   ";  // char(176) is the degree symbol<br />    temporary_string = temporary_string + string_Humid + " %";    <br />    strcpy(OLED_string_2, temporary_string.c_str());      // Put temperature/humidity string in the second character array<br />    <br />    <br />    sendstringstoDisplay();             // Display the median temperature and humidity<br />    delay(5000);                        // Updates every 5 seconds<br />  <br />  }</pre>]]></content:encoded>
						                            <category domain="https://forum.dronebotworkshop.com/show-tell/">Show &amp; Tell</category>                        <dc:creator>VE1DX</dc:creator>
                        <guid isPermaLink="true">https://forum.dronebotworkshop.com/show-tell/median-filter-with-dht22-etc/#post-8358</guid>
                    </item>
							        </channel>
        </rss>
		