Moisture is a problem for most things in storage. How do you know that your storage bin is air tight? How do you know if your desiccant is still working? You could get a hygrometer but that would require your bin to be transparent enough for you to read the device.
This project is perfect for bins that are opaque or too cloudy to read a meter from the outside. I store 3d printer filament in a Pelican case that is solid black. I needed a way to make sure the case was air tight and that the desiccant still worked. This project is also great for when you need to monitor out of sight storages.
This project uses the ESP8266 Wi-Fi module and Cayenne by myDevices. The ESP8266 is inexpensive and easy to use. Cayenne is an IOT service that provides a very nice, intuitive drag and drop dashboard to display data from the ESP8266. Cayenne also monitors your data and provides custom alerts sent via text message to your phone or email.
Monitor Features- Start-Up Test Routine
- Battery Powered
- Monitor Humidity
- Monitor Battery Voltage
- Monitor Temperature
- Monitor Wi-Fi Signal Strength
AA Batteries vs LiPo Pack
I chose rechargeable AA batteries because they are easier and cheaper to get (for me). I live in Hawaii and companies will only deliver LiPo batteries via 2-day (or faster) air shipping. Shipping raises the overall costs of LiPo batteries substantially that using a LiPo is not worth buying.
ESP8266 Development Module
I chose to go with a WEMOS D1 Mini development board for ease of use. Development boards have a voltage regulator and USB to serial converter (which is also a drawback, see Future Considerations section). The WEMOS D1 Mini's voltage regulator has a low voltage drop out of 120mv-260mv and fairly low quiescent current 55uA as compared to other development boards. This should make the board a slightly better candidate for using batteries among other development boards.
If you use another development board make sure to check the datasheet of the voltage regulator as other boards use an AMS1117 regulator that has a dropout of 1.1V-1.3V and stand-by current of 5-10mA. The stand-by current will drain a battery pack fairly quickly. My first prototype was a NodeMCU LoLin V3 board and the batteries lasted for about 6 days.
No On-Board Display
The purpose of this project is to monitor humidity from within a storage bin that you can't see through or somewhere that is out of sight. An on-board display would be useless if you cannot see it. Instead of an on-board display, you can view all data on the Cayenne dashboard from a browser or the Cayenne phone app.
Optional Start-Up Test Routine
The monitor has been coded to send information to the Cayenne server every 20 minutes (update code if you want more or less frequent updates). The start-up test routine will send information every 15 seconds for one and a half minutes to aid in setup. The start-up routine should give enough time to place the monitor in a bin and move the bin to its location. Within that time you can check to make sure the ESP8266 contacts your Wi-Fi router by checking that your Cayenne dashboard is updating every 15 seconds instead of waiting 20 minutes.
No Enclosure USB Port
The enclosure I modeled does not have easy access to the USB port of the ESP8266 module. The reason for this is that the D0 and RST pins are connected together which prevents the module from being flashed. Did not make sense for me to expose the USB port if I could not flash the board. I opted instead for headers to easily remove the module should it need flashing.
Project Steps In A Nutshell- Sign up for a Cayenne account.
- Add a device to your Cayenne dashboard to get the login information and client ID to use in the code files.
- Download the project files.
- Open the project in the Arduino IDE.
- Transfer the bread boarded module and components to a PCB prototype board.ne.
- Compile and upload the program to your ESP8266 module.
- Breadboard the ESP8266 module and components.
- Power the breadboard module and ensure that your module talks to Cayenne.
- Transfer the breadboard module and components to a PCB prototype board.
- Print the enclosure and pretty it up if you want.
- Put the PCB module in the enclosure.
- Turn on the unit and place in a storage bin or anywhere else that needs humidity monitoring.
- Relax knowing that your precious items are monitored.
The code for the project is an Arduino project. The project consists of two files:
- DebugUtil.h - Utility file to toggle debugging statements to serial output when the symbol DEBUG is defined.
- ESP8266CayenneHumidityMonitor.ino - Main program file.
The next section describes areas in the code that you need to change or change to suit your tastes.
Code ConfigurationsSerial Output Debugging
Uncomment the first line #define DEBUG in ESP8266CayenneHumidityMonitor.ino to print to serial output.
#define DEBUG // uncomment to print to Serial output
Comment the first line before you finalize your project because the monitor will not attach to anything serially when in a storage bin or wherever.
Credentials
I define my Wi-Fi password and Cayenne login information in a separate header file placed in my Arduino library path. That way, I don't accidently upload my username and password to GitHub for this project.
#include <MyCredentials.h> // contains my credential information, outside of
You can either create your own MyCredentials.h file and define the following (change client ID for your purposes):
- HOME_WIFI_SSID
- HOME_WIFI_PASSWORD
- CAYENNE_USERNAME
- CAYENNE_PASSWORD
- CAYENNE_CLIENT_ID_HATCHBOX_ABS
Or directly update parts of the main program file replacing the symbols mentioned above with your information.
char ssid[] = HOME_WIFI_SSID;
char wifiPassword[] = HOME_WIFI_PASSWORD;
// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = CAYENNE_USERNAME;
char password[] = CAYENNE_PASSWORD;
char clientID[] = CAYENNE_CLIENT_ID_HATCHBOX_ABS;
DHT Sensor
I use Adafruit's DHT libraries to read the DHT sensor. A quick Google search will return many ways to get the library installed into your Arduino environment. Choose the one that works for you.
Update the definitions for the DHT sensor if needed.
#define DHTTYPE DHT22
#define DHT_RETRY_COUNT 10
#define DHT_RETRY_DELAY 2000 // internet said wait 2 seconds to give the DHT time to get ready
Sometimes the sensor will not be ready when you read it. Retry as many times as specified by DHT_RETRY_COUNT. You can increase if you find that the sensor is not reading by the 10th try, but you should get a reading by the 2nd or 3rd try.
Start-Up Test Routine
You can change how many times and how far apart the monitor will send data to Cayenne during the test routine. Delay is in milliseconds.
#define STARTUP_TEST_RETRY_COUNT 5
#define STARTUP_TEST_RETRY_DELAY 15000
Deep Sleep Delay
The monitor goes into deep sleep to save on battery life. Default is 20 minutes. Change to a longer time to prolong batter life or shorten if you want more frequent updates.
#define DEEP_SLEEP_TIME 1200000000 // 20minutes = 1200000000us
Battery Voltage Reading
Sometimes I read either a randomly high or low value from the ADC. To combat this, I use the average of 10 readings 50 milliseconds apart. Change count if you want the average or more or less readings. I found that I could not consistently go lower than 50 milliseconds between reads. Sometimes I would get a value and other times, the ESP8266 would throw exceptions.
#define ADC_SAMPLE_COUNT 10
#define ADC_SAMPLE_DELAY 50
The WEMOS D1 Mini has a 220k/100k ohm voltage divider before ESP8266 ADC input. This allows you to connect up to 3.3V instead of the 1V maximum of the ESP8266. I wanted to measure just under 6V so I add a 270k ohm resistor before A0 which makes a 490k/100k ohm voltage divider before the ADC. 6V input would yield just slightly over 1V.
#define RESISTOR1 490000 // 270k added to R1 (220k) of the voltage divider of the Wemos D1 Mini before the ADC
#define RESISTOR2 100000 // R2 from the Wemos D1 Mini divider before ADC
Update VOLTAGE_ERROR_CORRECTION if you find your readings are consistently off by a small percentage. My readings were consistently 2% off when on the breadboard but pretty much spot on when the project was finalized on a PCB prototype board.
#define VOLTAGE_ERROR_CORRECTION 1.000 // set to 1 with debug on, find percentage voltage is off and update
Static IP Setup
Update the code in setup() for your preferred IP address. Consult your Wi-Fi router documentation on which IP addresses are statically assignable. In my case, anything over 100 is reserved for DHCP so I need to pick something under 100.
// setup static IP as this cuts down on time trying to obtain an IP through DHCP
IPAddress espIP(192, 168, 1, 80);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
Use a static IP as that will cut down a significant chunk of time the ESP8266 is on to save on battery life.
Main Programvoid setup()
The setup() function is where we setup the module for IP address and initialize the GPIO pins.
Setup for static IP since that is way faster than waiting for DHCP.
// setup static IP as this cuts down on time trying to obtain an IP through DHCP
IPAddress espIP(192, 168, 1, 80);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.config(espIP, gateway, subnet);
Setup GPIO pins for the push button and LED. Enable the internal pull-up resistor for use with the push button. Set the LED pin as output and initially set the pin low so that the LED is off.
pinMode(BUTTON_GPIO, INPUT_PULLUP);
pinMode(LED_GPIO, OUTPUT);
digitalWrite(LED_GPIO, LOW);
I could be mistaken or just had errors, but I had to run Cayenne.begin() from the setup() function. I tried to run it right before sending data but I was not able to connect to Cayenne.
Cayenne.begin(username, password, clientID, ssid, wifiPassword);
void loop()
The loop function() is where code is repeatedly executed. For this monitor, that doesn't really happen since we utilize the deep sleep function of the ESP8266 which does a hard reset on wake up.
The first thing to do is call Cayenne.loop().
Cayenne.loop();
The next set of statements check to see if the push button was held down. If the button was held down, turn on the LED and perform syncData() a few times so many seconds apart. The function syncData() is where we read data and send the data to Cayenne.
int performTest = !digitalRead(BUTTON_GPIO);
if(performTest) {
DEBUG_UTIL_PRINTLN("Perform test routine");
digitalWrite(LED_GPIO, HIGH);
for(int count = 0; count < STARTUP_TEST_RETRY_COUNT; count++){
syncData();
delay(STARTUP_TEST_RETRY_DELAY);
}
}
If the button was not held, call syncData() to send data to Cayenne.
After that, go into deep sleep to save on power. The delay after the call to deepSleep() is to give the module time to enter the sleep state. That's what I read on a bunch of blog posts so I'm gonna put that delay in.
syncData();
DEBUG_UTIL_PRINTLN("Entering deep sleeeeeeep...........");
ESP.deepSleep(DEEP_SLEEP_TIME, WAKE_RF_DEFAULT);
delay(500);
syncData()
The function syncData() is where the monitor reads data and sends data to Cayenne.
Humidity is read first. Looping up to the specified amount of retries till a valid value is read. Usually will get a good reading by the 2nd or 3rd try.
// retry a few times for a good reading
int retries = 0;
while(isnan(humidity = dht.readHumidity()) && (retries++ < DHT_RETRY_COUNT)){
delay(DHT_RETRY_DELAY);
}
Temperature is read next and done the same way as humidity to get a valid value.
retries = 0;
while(isnan(temperature = dht.readTemperature()) && (retries++ < DHT_RETRY_COUNT)){
delay(DHT_RETRY_DELAY);
}
Next up is reading the battery pack voltage. I went with an average of readings because there would be random high or low readings. I included voltage correction because my breadboard prototype was consistently off by 2%. That went away though when I finalized the project onto a PCB prototype board. The calculation for voltage is just the voltage divider formula solved for source voltage times the percent of 1V the ADC reads.
// get average of analog reads, I would get weird really off values from time to time, probably better algorithms out there but this is good enough for me
voltage = 0;
for(int i = 0; i < ADC_SAMPLE_COUNT; i++){
voltage += analogRead(A0) / 1023.0 * (RESISTOR1 + RESISTOR2) / RESISTOR2 * VOLTAGE_ERROR_CORRECTION;
delay(ADC_SAMPLE_DELAY);
}
voltage /= ADC_SAMPLE_COUNT;
Then read the signal strength of the Wi-Fi connection.
int rssi = WiFi.RSSI();
Finally, send all the data to Cayenne to display on the dashboard.
Cayenne.virtualWrite(0, humidity, TYPE_RELATIVE_HUMIDITY, UNIT_PERCENT);
Cayenne.celsiusWrite(1, temperature);
Cayenne.virtualWrite(2, voltage, TYPE_BATTERY, UNIT_VOLTS);
Cayenne.virtualWrite(3, rssi);
BreadboardUse the Fritzing file to first breadboard the project to make sure things are working the way they should when you first connect to Cayenne.
Power Supply Capacitors
The values for the two capacitors are 100uF and 10uF. The 10uF is probably good enough. I had a 100uF within arms reach so I used it. The reason for the capacitors even though there is already a 1uF cap before the regulator on the WEMOS D1 Mini is that I would get wild low voltage readings after the monitor had been on for a day or two. I guess the batteries couldn't provide enough current at times.
Power Switch
I used a DPDT slide switch that I got super cheap from a closing sale at Radio Shack. You can just use a SPST switch instead. Just connect the positive wire to the switch and directly connect the negative wire to the circuit.
Battery Holder
I couldn't find a nice 2x2 AA battery holder for Fritzing. I know the picture shows a single row 4xAA holder with switch but that's not what I used in the final project. If you want to use the enclosure I modeled, you will need a 2x2 AA battery holder.
Schematic:The schematic to help wire up the module on the breadboard if the breadboard view is not easier to understand.
Cayenne SetupSign up for a Cayenne account if you have not done so yet. The registration process is quick and easy.
After you completed your registration, you will see a blank dashboard.
Click the "Add new" in the left plane, then select Generic ESP8266.
The next screen has instructions and information you will use to connect to Cayenne. This screen has the username, password, and client ID that you will use in the project code. The symbol mapping as follows:
- MQTT Username = CAYENNE_USERNAME
- MQTT Password = CAYENNE_PASSWORD
- Client ID = CAYENNE_CLIENT_ID_xxx (where xxx should be something descriptive, in my case, the monitor is for my Hatchbox ABS filament)
Name your device now or later, I'd rather just name it now. I renamed this example as Test.
Keep the screen open as it waits for your device to connect. When you power on the ESP8266 board, the screen will automatically redirect to the dashboard. The dashboard will automatically create a temporary widget for each channel that received data.
You will need to setup how you want to display the data from the ESP8266. Click on the '+' sign to permanently add the widget. Add all the widgets at once because they are temporary. They go away if you navigate somewhere else. To get them back you'll have to restart the module to resend data.
Click on the little gear in the upper right corner of the widget after you have added it. You will get to customize how you want to display your data. Customize to your hearts content.
Repeat for the rest of the widgets.
The following is what I settled on in terms of icons, units, and decimals. Shown is an extra widget added on to display Fahrenheit. The widget reads the same channel as Celsius temperature (Channel 1) but is set to display Fahrenheit instead.
Next, setup a trigger to alert if humidity is too high. I'm taking a guess under 40% humidity is considered acceptable for filament storage according to reading a bunch of forums and blog posts. Don't take my word for it, as your mileage may vary. Click the little gear in any widget and select Trigger. This will bring you to the trigger settings page that you can choose which device and channel to monitor.
The interface is very intuitive and tells you what to do. I setup my trigger as follows to send me an email when the humidity level goes above 40%.
Click save and you should see your trigger in the Triggers dashboard.
You should also make an alert when your battery reaches a low level. That level is determined by the type of batteries you use. I would go for 4V for NiMH batteries as a good time to get a notification.
That is all that is necessary to setup Cayenne. I suggest you click around Cayenne to familiarize yourself with the features Cayenne has to offer.
Now that you have a working prototype, time to finalize your project onto a PCB board and into an enclosure.
PCBI don't etch my own custom PCB boards (I wish I could). I use regular PCB prototype boards that you can get cheaply. I'm still new to Fritzing so I am unsure how to show wires connecting to the PCB board. I tried to layout the components and space them apart as if they were on a prototype board. Traces that go off the rectangle PCB board shape were meant to be wires connecting to the board.
Use female socket headers on the PCB prototype board so that you can easily take the ESP8266 module on and off. To re-flash, you need to disconnect D0 from RST, not something easily done when you solder a trace connecting the two pins. The headers will all you to easily remove the module to re-flash.
The ground wires for the LED and switch connect back to the ground trace on the prototype board. Not as pictured in the Fritzing where they connect to the ground pin of the DHT22 module. Hopefully the following picture will clarify wire hookup a bit. See the three black wires between the blue and yellow wire (well, one is hiding under the yellow wire, you can see it peeking a bit if you look carefully).
Usually I would trim down PCB boards to the smallest possible size but didn't for this project. The battery holder pretty much determined the width of the enclosure so I didn't need to trim the PCB.
EnclosureI made an enclosure using FreeCAD. The model has all its dimensions defined in the spreadsheet. Update the spreadsheet if you need to change the diameter size or hole sizes for your components. All screw holes are sized for 4-40 screws (except slide switch of course). Tap the mounting holes to prevent from applying too much pressure on the printed plastic that can crack and separate layers.
The following pictures show how the components are placed.
Slide the On/Off switch to Off.
Insert batteries into the battery holder.
Screw the cover onto the enclosure.
To start the test routine, as you slide the On/Off switch to On, press and hold the push button till the LED lights up. Check your that your Cayenne dashboard updates every 15 seconds. You can skip the test routine by not pressing the push button as you turn on the module.
Place the humidity monitor in your bin and take solace that your filament or whatever is monitored.
Future ConsiderationsMost ESP8266 development boards are not ideal for a battery powered project. My LoLin board ran out of batteries around 6 days. As of writing this, the WEMOS D1 Mini is still running after a week. I'm hoping to get at least 3 weeks. If not, then I'll have to switch to the suggestions below. But for now, the WEMOS should be good enough.
To ensure long battery life, the ESP8266 must run with minimal components. The big power consumers on development boards are the USB to Serial chip and voltage regulator.
Make the project with a bare ESP8266 module by programming with an external FTDI serial adapter. That way there is no onboard CH340G or CP2102 that will draw power when the ESP8266 is in deep sleep.
Pick a low quiescent voltage regulator so that not a lot of power is wasted while in deep sleep. The MCP1700 is a good choice as it has a quiescent current of 4uA.
Since a bare ESP8266 module does not have a voltage divider before the ADC, use a 2.7M/3.3M ohm voltage divider. This will cut power loss from 60uW that was on a development board down to 6uW using the 2.7M/3.3M ohm voltage divider. Just need to remember to update the code for these resistor values.
Thank YouLeave a comment if you have questions and I'll do my best to answer.
Thank you for reading.
Update 9/20/2017 - The Wemos D1 mini is still going strong after 3 weeks on 4AA NiMh batteries. Battery voltage dropped from 5.40V to 5.10V over that time. I am hoping to get at least 5 weeks now.
Update 12/18/2017 - I'm amazed how long the batteries lasted (just under 16 weeks). Batteries hit 4V yesterday which I will take as low and needs to be recharged. I could probably go as low as 3.6V but don't want to take the chance that I forget and over drain the batteries. I think the Wemos D1 mini is a good choice for this project without having to piece together components with bare ESP8266 modules.
Comments