Authors: Asha Bazil, Jenna Epstein, Kristin Chang, Celine Apollon
INTRODUCTION
Philadelphia residents are experiencing unprecedented levels of food insecurity. 17% of Philly’s population was considered food insecure in 2021,while in 2019 the City generated approximately 240,000 tons of food waste. On top of this, recent escalations in food costs mean that people are relying more on community fridges. The volunteers and mutual aid networks that stock these fridges have limited capacity, and are well aware of the gravity of the situation. The fridges they oversee could be refilled every half hour. They just don’t have the resources to do so.
FreshFridge seeks to inform better allocation of these limited financial and human resources necessary to keep Philly’s community fridge system running. FreshFridge is a monitoring and response system that comes in an easy to install kit that will save time, and optimize the amount of quality, fresh food available for community members around the city. The FreshFridge kit measures the amount of food, the internal conditions, and the frequency of use at each fridge site and sends that information to a realtime database. The information is then layered onto a public online map giving residents real-time information about available food. The map and additional data provided in a supporting dashboard can also be accessed via login by those stocking and maintaining the fridges. Our two main user groups are those who are coordinating the delivery of produce to the fridges, and those who are consuming that produce.
FRESHFRIDGE: THE KIT
Equipment List
- 1 WiFi-enabled Arduino board: ESP8266 NodeMCU
- 1 temperature / humidity sensor: DHT-11
- 1 door magnet sensor: Gikfun MC-38
- 4 Ultrasonic sensors per shelf: HC-SR04
- 1 5V or higher power source with micro-usb adapter: Belker Adapter
- Several M-F, F-F, and M-M wires
- 1 methane sensor (optional): MQ4
Overview Diagram
This diagram shows very generally how the FreshFridge kit is installed, using the Powelton Fridge as the pilot site. The entire FreshFridge kit will be powered by the same power source as the fridge on site. The kit is comprised of several sensors (as noted in the equipment list) and a WiFi-enabled Arduino board which sends sensed information to a realtime database on Google Firebase.
The sensors, and their purposes, include:
- A sensor that detects both temperature and humidity to regulate the internal conditions of the fridge
- A motion sensor placed on the fridge door to document each time the door is opened, and to make sure it’s not left open
- A series of ultrasonic distance sensors on each shelf to estimate the amount of food in the fridge.
- We also have an “add on” option for a methane sensor to detect methane emitted by spoiled produce.
Zooming into one shelf
Looking closer at one shelf, 4 distance sensors are placed at the back of the shelf to detect the presence of food by measuring the distance to the door or any object in front of them. For our prototype, we used a distance of 16 inches based on the total depth of our pilot fridge to define the shelf’s capacity.
- For instance, if all 4 sensors measure 16 inches or greater, then the shelf is empty since that is the absolute distance from the back of the fridge to the door.
- If 1 to 3 of the sensors measure a distance of 16 inches or more, the shelf is partially empty,
- and if none of the sensors measure a distance of 16 inches or more, the shelf is considered full.
These combined measurements provide a rough “snapshot” of the fridge at any given time. and would be placed on each shelf in the fridge and calibrated to the depth of that specific fridge.
The rest of the kit (WiFi arduino, temperature/humidity sensor, and optional methane sensor), can be placed in an unobtrusive location within the fridge on just one of the shelves.
TUTORIAL
High-level: Each sensor is connected to the wifi board, and the sensed data is sent to a Firebase database. You’ll have two power rails on your breadboard– one supplying 3.3V, and one supplying 5V.
Wiring
- Wire the temperature sensor to the D2 pin and the 3.3V power + ground.
- Wire the methane sensor* to the A0 pin and the 3.3V power + ground.
- Wire the door sensor to the D0 pin + ground.
- Wire one** distance sensor to D5 and D6 + the 5V power + ground. Tutorial here.
*Optional add-on sensor
** For the purposes of this tutorial, only one ultrasonic distance sensor is configured. To connect multiple ultrasonic distance sensors, as intended, it is best to use as few pins as possible. We suggest referencing this forum. For wiring multiple ultrasonic distance sensors across multiple shelves, we recommend using the “Octosonar” library and implementation. It allows for connection of up to 16 ultrasonic range sensors to an Arduino using a I2C bus and just one pin. See details here.
These photos show what each of these sensors looks like in our prototype fridge. In this case the distance sensor is at the front of the shelf so we could test it with the door open, but it works best when they’re placed at the back.
Configuration
Follow this tutorial to set up your Firebase account (note that the ESP boards are different but the process is the same).
Code
Below is the code used to collect, analyze, and send sensed data to the database created in the configuration step. If issues arise uploading this code to the ESP8266 NodeMCU, please find troubleshooting tips in the tutorial linked above.
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
/* Title: FreshFridge Arduino Code By: Kristin Chang, Jenna Epstein, Asha Bazil, and Celine Apollon Last Updated: 05/01/2022 Description: This is the code to upload to your ESP8266 board that comes with the FreshFridge kit. The code includes commands to setup and collect data from the DHT temperature and humidity sensor, ultrasonic distance sensor, the door sensor, and the optional add-on methane sensor. The code also includes the setup and commands to send the data using WiFi to a Google Firebase database. Please consult the FreshFridge kit tutorial to set up the wires for your kit and properly install it in your refridgerator. Data collected from the temperature and humidity and methane sensors will help users monitor the internal conditions of the fridge. Data collected from the ultrasonic distance sensor will help estimate shelf capacity by measuring the distance from the back of the shelf to the fridge door or any object placed in front of it (NOTE: this code is currently written for just one ultrasonic sensor). You may edit this section of the code to the specific depth of your fridge (see comments below). Lastly, the magnet sensor placed on the door will estimate overall fridge use as well as serve as a signal that the fridge contents may have changed. As such, the main loop consists of two events. This structure mainly allows us to take readings at independent time scales. Event 1 occurs every 5 seconds and event 2 occurs every 30 seconds(NOTE: these durations are calibrated for testing purposes and you may want to update them based on your own data collection motivation. See comments below for where this should be updated). Event 1 consists of the commands to collect data on how many times the door has been opened, whether it has been left opened, and when it is closed. When it is closed, a new distance measurement for the ultrasonic sensor will be taken. Event 2 contains the commands to collect data from the DHT temperature and humidity sensor as well as the main sensor. Both events also contain the respective code to send this data to Firebase. The string messages sent to Firebase are also completely customizeable -- please see the comments below to edit these messages. Sources: DHT Sensor: ELEGOO Super Starter Kit Lesson 10 Ultrasonic Sensor: ELEGOO Super Starter Kit Lesson 11 Door Sensor: https://arduinogetstarted.com/tutorials/arduino-door-sensor-piezo-buzzer Methane Sensor: https://www.sensingthecity.com/configuring-an-mq-4-sensor-to-detect-methane-gas/ Defining D2 Pin for ESP8266 board: https://github.com/esp8266/Arduino/blob/master/variants/d1_mini/pins_arduino.h Using milis() for multiple events: https://www.programmingelectronics.com/arduino-millis-multiple-things/ */ //Libraries -- Make sure these are installed before proceeding! #include <ESP8266WiFi.h> #include <FirebaseArduino.h> #include <DHT.h> #include "millisDelay.h" //Define global variables to configure Firebase and WiFi network #define FIREBASE_HOST "YOUR FIREBASE HOST NAME HERE" #define FIREBASE_AUTH "YOUR FIREBASE AUTHENTICATION KEY HERE" #define WIFI_SSID "YOUR WIFI NAME HERE" #define WIFI_PASSWORD "YOUR WIFI PASSWORD HERE" //Define global variables for DHT sensor //static const uint8_t D2 = 4; //Uncomment this line if you receive an error stating D2 is undefined #define DHTPIN D2 //DHT pin is connected to D2 on the ESP8266 board #define DHTTYPE DHT11 //Initialize DHT type as DHT 11 DHT dht(DHTPIN, DHTTYPE); #define SOUND_VELOCITY 0.034 //Define sound velocity in cm/uS #define CM_TO_INCH 0.393701 //Define the conversion for cm to inch //Define global variables for ultrasonic distance sensor (you will need more pins for each ultrasonic sensor being used) const int trigPin = 12; //TrigPin is connected to digital pin 12 on the ESP8266 board const int echoPin = 14; //EchoPin is connected to digital pin 14 on the ESP8266 board long duration; //Define a variable for the output of the ultrasonic sensor int distanceCm; //Define a variable for the distance in cm int distanceInch; //Define a variable for the distance in inches //Define global variables for methane sensor const int AO_Pin=0; //AO of MQ-4 sensor is connected to analog pin 0 on the ESP8266 board int threshold; //Define a variable for the digital output of the MQ-4 sensor int AO_Out; //Define a variable for the analog output of the MQ-4 sensor //Define global variables for door sensor const int DOOR_SENSOR_PIN = 16; //Door sensor pin is connected to digital pin 16 on the ESP8266 board int currentState; //Define a variable for the current state of the door (output 1 is open and output 0 is closed) int previousState; //Define a variable for the previous state of the door unsigned long doorCounter; //Define a variable to store the amount of times the door has been opened //Define global time interval variables const long eventTime_1_doorDist = 5000; //Read and display every 5000 ms -- change this to change how often door and distance data is collected const long eventTime_2_dhtMeth = 30000; //Read and display every 30000 ms -- change this to change how often temperature, humidity, and methane data is collected unsigned long previousTime_1 = 0; //Define a variable to store time passed since last reading unsigned long previousTime_2 = 0; //these are unsigned long to make sure we have enough storage for long numbers //Setup loop that runs one time when the sketch is uploaded void setup() { //Door sensor setup pinMode(DOOR_SENSOR_PIN, INPUT_PULLUP); //Set door sensor pin to input pull-up mode //Ultrasonic distance sensor setup pinMode(trigPin, OUTPUT); //Set the trigPin as an Output pinMode(echoPin, INPUT); //Set the echoPin as an Input //DHT setup Serial.begin(115200); //Initialize serial monitor to view outputs and confirm data collection dht.begin(); //Initialize dht sensor //WiFi setup WiFi.begin(WIFI_SSID, WIFI_PASSWORD); //Initialize WiFi connection Serial.print("Connecting to "); //Prints the WiFi connection status to the serial monitor Serial.print(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } //Firebase setup Serial.println(); //Prints the local IP address and connection status to Firebase to the serial monitor Serial.print("Connected"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); } //Main Loop void loop() { //Start the time interval unsigned long currentTime = millis(); //millis() function returns the number of ms passed since the board was connected to power /*EVENT 1: DOOR AND DISTANCE READINGS*/ //Time interval for event 1 if (currentTime - previousTime_1 >= eventTime_1_doorDist){ //Door data collection currentState = digitalRead(DOOR_SENSOR_PIN); //Read pin output, 1 for open or 0 for closed //Detect and record change if (currentState > previousState){ //If currentState > previousState or 1>0, then the door is currently open Serial.print("Door Status: "); Serial.println("Opened"); doorCounter++; //Add 1 to the total number of times the door has been opened } else if (currentState < previousState){ //If currentState < previousState or 0<1, then the door is currently closed Serial.print("Door Status: "); Serial.println("Closed"); } else if (currentState == 1 && previousState == 1){ //If currentState and previousState are both 1, the door has been left open for two duration periods Serial.print("Door Status: "); Serial.println("Left Open!"); } else { //If currentState and previousState are both 0, the door is still closed Serial.print("Door Status: "); Serial.println("Closed"); } Serial.print("Door Counter: "); //Print the number of times the door has been opened to the serial monitor Serial.println(doorCounter); previousState = currentState; //Reset values for next reading //Send to firebase String fireDoor = String(currentState); //Convert door state integer to string String fireDoorCounter = String(doorCounter); //Convert door counter to string Firebase.pushString("/Door/Door", fireDoor); //Setup path to send door readings if (Firebase.failed()){ //Message to print to serial monitor if sending data to Firebase has failed Serial.print("pushing /logs failed:"); Serial.println(Firebase.error()); } //Distance readings digitalWrite(trigPin, LOW); //Start with trigPin low delayMicroseconds(2); digitalWrite(trigPin, HIGH); //Set the trigPin on HIGH state for 10 micro seconds delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); //Read the echoPin -- returns the sound wave travel time in microseconds distanceCm = duration * SOUND_VELOCITY/2; //Calculate the distance distanceInch = distanceCm * CM_TO_INCH; //Convert from cm to inches if (currentState == 0){ //Only print distance readings to the serial monitor and send to Firebase when the door is closed Serial.print("Distance to back of fridge: "); Serial.println(distanceInch); // Print //Send to firebase String fireDist = String(distanceInch); //Convert distance integer to string Firebase.pushString("/HCSR04/Distance", fireDist); //Setup path to send distance readings if (Firebase.failed()){ Serial.print("pushing /logs failed:"); Serial.println(Firebase.error()); } } //Update timing for next event 1 previousTime_1 = currentTime; } /*EVENT 2: DHT AND METHANE READINGS*/ //Time interval for event2 if (currentTime - previousTime_2 >= eventTime_2_dhtMeth){ //DHT readings float h = dht.readHumidity(); //Read humidity float t = dht.readTemperature(); //Read temperature if (isnan(h) || isnan(t)){ //Check DHT sensor working Serial.println(F("Failed to read from DHT sensor!")); //Message to print to serial monitor if DHT sensor fails return; } Serial.print("Humidity: "); Serial.print(h); String fireHumid = String(h) + String("%"); //Convert Humidity integer to string Serial.print("% Temperature: "); Serial.print(t); Serial.println("°C "); String fireTemp = String(t) + String("°C"); //Convert Temperature integer to string /*//Methane readings (OPTIONAL ADD-ON: uncomment this section if you are using a methane sensor) AO_Out = analogRead(AO_Pin); // Read the analog output measurement sample from the MQ4 sensor's AO pin Serial.print("Methane Concentration: "); //Print readings to the serial monitor with this text Serial.println(AO_Out); String fireMeth = String(AO_Out); //Convert Methane integer to string //Send to firebase Firebase.pushString("/DHT11/Humidity", fireHumid); //Setup path to send Humidity readings Firebase.pushString("/DHT11/Temperature", fireTemp); //Setup path to send Temperature readings Firebase.pushString("/MQ4/Methane", fireMeth); //Setup path to send Methane readings if (Firebase.failed()){ Serial.print("pushing /logs failed:"); Serial.println(Firebase.error()); }*/ //update timing from last event previousTime_2 = currentTime; } } |
Now the sensed data will send to your Firebase database. See the details of the data below, as well as a video showing an example of how the distance sensor sends information to Firebase in realtime.
SENSED DATA IN ACTION: THE FRESHFRIDGE WEB APPLICATION
We envision a dashboard-driven web application to make the sensed information accessible and useful to the public as well as community fridge maintainers and stockers. We propose building on top of an existing map maintained by a group of community volunteers. The map is based on a Google Sheets file with information about fridges such as the address, zip code, website, and relevant notes. The data then populates a map instance through Google Maps. We would like to build functionality on top of this existing implementation. Here is a sequence of screens that we envision.
When a user clicks a fridge point, a side panel opens to the right with details about the fridge. The information at the top comes from the Google Sheet owned by the network of volunteers, and the information in the table comes from the Firebase database. There is also an aggregate counter of how many times the fridge door has been opened in the past 24 hours to provide an understanding of general traffic.
For each timestamp, the sensor data is displayed in a user-friendly format. The fridge’s “amount of food” measure – the red, yellow, and green dots for empty, partial, and full – are displayed as visual indicators to the right of each timestamp so that it is immediately clear to the viewers what the status is at each given log. When a user clicks to expand a timestamp, the data from the DHT11 humidity and temperature sensor are displayed.
Maintaining the Dashboard
In this model, we would rely on the current map network maintainers to add or remove fridge points (and their associated data) from the map when a fridge is added or removed, or information is edited.
Using a Google plugin called “geosheets”, the map would update as the Sheet is edited. If a new FreshFridge kit were to be deployed to a fridge in the city, its kit-specific fridgeID will be joined into the same Firebase database, easing the technical lift needed to enable a new kit.
THE FUTURE OF FRESHFRIDGE
FreshFridge App. 2.0
Our vision for the next iteration of the FreshFridge application is a mobile rollout. We would leverage the cloud messaging feature associated with Google Firebase to make this happen.
The push notifications and key information are geared towards maintainers and stockers, and will be customizable based on specific user priorities. Examples of push notifications can be sent when fridges are empty, when the temperature is too high, or when the door has been left open.
Anyone from the public could also download the app and sign up for push notifications. For the future of FreshFridge, we envision creating the capability for members of any neighborhood to check the capacity status of their nearest fridge, and to vouch for where new fridges should be added based on their knowledge.
This can be done by displaying QR codes throughout the city — enabling residents to check fridge statues, provide user input, and/or download the FreshFridge App 2.0. We recommend using QR.io which will collect the count, date, and location of scans to understanding hotspots or gaps in QR participation. Further, places with fewer total scans of QR codes inform managers to rethink their awareness strategy and perhaps evaluate how to better serve the needs of the community.
Add-on Features and Alternatives
There is flexibility to adapt the FreshFridge kit for your specific fridge needs!
Methane Sensors
An MQ-4 sensor can be added to detect methane that may be emitted from spoiling food. For most fridges, currently, this is not a high priority feature because items have not been staying in fridges for long due to rising food sales prices. However, it is available and easy to attach using this tutorial. NOTE: the code to calibrate and collect data using the MQ-4 methane sensor is already included and commented out in the FreshFridge tutorial code above.
Shelf Capacity
Some alternative options to measuring shelf capacity per fridge include load cell weight sensors or tactile buttons. You may consider switching either of these options out for the ultrasonic distance sensors if you are looking to take more precise measurements.
- You may follow this tutorial to calibrate and collect data from the load cell sensor. We recommend starting with two per shelf with the FreshFridge kit.
- Using tactile buttons instead of the ultrasonic distance sensors may provide more precise information about shelf capacity. When an item is placed on top of the button, it is pushed down, and when the item is removed, the button will need to be pressed by a user to reset it. When used perfectly, this could provide more exact readings. To setup and collect data using button sensors, you may follow the Elegoo Super Starter Kit Lesson 5 tutorial on digital inputs found online here.
Recommendations for Scaling
- Enhance the features by researching the for the most economically and sustainably optimal sensors. By incorporating higher quality sensors, the accuracy of the sensed data will improve, thus ensuring that fridges are being communally used and operated in the most efficient way possible.
- Diversify hardware to accommodate for varying neighborhood contexts. For example, this could include offering a cellular as well as a wifi enabled kit option for areas of Philadelphia without access to wifi. The cellular option is a bit more expensive in terms of hardware.
- We propose establishing a city-wide initiative to secure funding and house+aggregate community fridge usage data. The funding would be for supplying food and deployment and maintenance of the kits, perhaps in conjunction with programs such as the Philadelphia Food Waste Business Challenge in the Office of Sustainability. In the long term, the initiative’s funding could also establish a workforce training program to teach members of the community how to use and manage the FreshFridge, which could then lead to full-time paid positions as official community fridge managers.The data managed by the initiative will equip advocates another method of communicating the need for increased funding and prioritization.
Acknowledgments
Thank you to Bunnyhop, a volunteer-led mutual aid group providing free food to neighbors in West Philadelphia. We greatly appreciate the time and insights they shared with us as we developed this project.
Thank you to Allison Lassiter and Logan Weaver for their instruction and guidance.
CITATIONS
- Sending Serial Monitor Data to Google Firebase with an ESP8266-01
- Elegoo Tutorial – Lesson 5 Digital Inputs
- Monitor shelf capacity with Arduino and load cell sensors
- Using an MQ-4 Sensor with Arduino to Detect Methane Gas
- ELEGOO Super Starter Kit Lesson 10
- ELEGOO Super Starter Kit Lesson 11
- Arduino – Door Sensor
- Defining D2 Pin for ESP8266 board
- Using milis() for multiple events
- ESP8266 NodeMCU with HC-SR04 Ultrasonic Sensor with Arduino IDE