Use this template to document your progress! (Add notes anywhere you deem necessary)
We are DAMP+J, a team formed during the hackathon to explore how IoT can be used to influence individual behavior for sustainability and well-being. Our group brings together complementary skills in embedded systems, software engineering, UX design, and environmental awareness.
Our approach prioritizes simplicity, functionality, and measurable impact. Rather than building complex systems for their own sake, we focused on applying accessible technologies to address everyday habits that have long-term environmental consequences.
Our final project, FRoast, reflects this mindset—a behavior-aware smart fridge prototype designed to promote conscious food habits, reduce waste, and make sustainability both personal and actionable.
- Jorge Leon - Marcia Rodrigues - Daniella Fajardo - Prachi Singhal - Abdulkadir Abubakar
We began the ideation process by exploring IoT-based solutions that focus on changing individual behavior to promote sustainability, accessibility, and well-being. We explored several IoT-based concepts that aim to nudge individuals toward sustainable, healthy, and inclusive behaviors, using a combination of sensors, actuators, for IoT tools. Below are the documented ideas from our brainstorming process:
The project is a smart fridge system designed to monitor and influence users’ eating habits through real-time feedback and personalized behavior tracking. It uses RFID identification, sensors, and actuators to encourage healthier and more sustainable routines such as avoiding late-night snacking, reducing energy waste, and improving food management.
Each time a user approaches the fridge, they are identified using an RFID tag. The system monitors fridge access patterns — how often, when, and for how long the fridge is used — and cross-references this with sensor data (e.g., steam, gas, temperature, motion) to detect potential habits like:
Real-time nudges are provided through LEDs, buzzer sounds, and messages on an LCD display, mimicking the role of a digital “fridge coach.”
While the current prototype of FRoast successfully demonstrates real-time behavior tracking and feedback mechanisms, several enhancements could significantly broaden its impact, adaptability, and long-term user engagement. The following proposals aim to transform the system from a fixed, rule-based framework into a dynamic, user-centered behavioral assistant.
Integrating basic food identification features—such as barcode scanning, NFC tags, or weight sensors—could enable FRoast to provide context-specific feedback based on the type of food being stored. This would allow the system to:
By associating RFID tags with specific food items or enabling manual item logging, FRoast could offer inventory tracking capabilities. This would support:
To enhance accessibility, especially for users with visual impairments or limited literacy, the system could include auditory feedback through basic speech synthesis. Voice guidance could supplement or replace LCD text, making the system more inclusive for children, elderly users, or individuals with disabilities.
Incorporating ambient temperature sensing would enable FRoast to adjust its behavioral prompts based on seasonal energy considerations. For example:
Introducing a lightweight machine learning layer could allow the system to evolve beyond fixed thresholds. Using historical behavior data, the model could:
FRoast is designed as more than a sensor-based monitoring system—it is a behavior-oriented intervention tool focused on reducing food and energy waste in domestic environments. Through RFID-linked user profiles, sensor feedback, and context-aware prompts, the system promotes conscious engagement with everyday habits related to food storage and refrigerator use.
Refrigerators contribute significantly to household energy consumption and are often involved in avoidable food waste due to poor usage habits. Traditional tracking alone provides data but fails to initiate meaningful change. FRoast addresses this gap by integrating real-time interventions—turning passive monitoring into active behavioral guidance.
The premise is simple but effective: raising user awareness through timely, personalized prompts can influence decision-making at the moment it matters most. By embedding behavioral nudges into daily routines, the system seeks to support more sustainable and health-conscious food practices over time.
Each user is identified via RFID, enabling individualized tracking and tailored feedback. The following behaviors are monitored:
To assess the effectiveness of FRoast in modifying behavior, both quantitative and qualitative metrics are collected:
Quantitative Indicators
Qualitative Indicators
The long-term objective of FRoast is to instill sustainable behavior without requiring significant user effort or intrusive systems. By embedding behaviorally-informed micro-interventions into an everyday appliance, the system can contribute to:
Through repeated exposure to feedback and subtle reinforcement, FRoast supports gradual habit reformation, enhancing both environmental outcomes and personal well-being.
import uasyncio as asyncio from machine import Pin, PWM, SoftI2C, ADC, DAC from i2c_lcd import I2cLcd import time import dht from mfrc522_i2c import mfrc522 import collections class MessageQueue: def __init__(self): self.queue = [] async def put(self, item): self.queue.append(item) async def get(self): while not self.queue: await asyncio.sleep(0.1) # Non-blocking wait return self.queue.pop(0) message_queue = MessageQueue() # Constants SERVO_PIN = 5 BUZZER_PIN = 25 I2C_SCL = 22 I2C_SDA = 21 I2C_ADDR = 0x27 RFID_ADDR = 0x28 AUTHORIZED_ID = 547 SERVO_OPEN = 125 SERVO_CLOSE = 28 BUZZER_FREQ1 = 1000 BUZZER_FREQ2 = 1500 ALARM_DURATION = 0.5 HUMIDITY_THRESHOLD = 30 TEMP_THRESHOLD = 27 GAS_PIN = 23 GAS_SENSOR = Pin(GAS_PIN, Pin.IN, Pin.PULL_UP) GAS_THRESHOLD = 70 # Adjust based on sensor calibration # State door_opened = False open_time = 0 # I2C + LCD setup i2c = SoftI2C(scl=Pin(I2C_SCL, Pin.OUT, pull=Pin.PULL_UP), sda=Pin(I2C_SDA, Pin.OUT, pull=Pin.PULL_UP), freq=100000) lcd = I2cLcd(i2c, I2C_ADDR, 2, 16) # Buzzer setup buzzer = PWM(Pin(BUZZER_PIN)) buzzer.duty(0) # RFID setup rc522 = mfrc522(I2C_SCL, I2C_SDA, RFID_ADDR) rc522.PCD_Init() rc522.ShowReaderDetails() # DHT Sensor setup DHT_SENSOR = dht.DHT11(Pin(17)) # === STEAM SETUP === STEAM_SENSOR = ADC(Pin(34)) # Analog pin (VP/A2) STEAM_SENSOR.atten(ADC.ATTN_11DB) # Full voltage range (0-3.3V) STEAM_THRESHOLD = 800 # Analog value above this = steam detected current_user = "Unknown" async def move_servo(position): servo = PWM(Pin(SERVO_PIN)) servo.freq(50) servo.duty(position) await asyncio.sleep(0.5) servo.deinit() async def open_door(): global door_opened, open_time print("Opening door") await move_servo(SERVO_OPEN) open_time = time.time() door_opened = True async def close_door(): global door_opened print("Closing door") await move_servo(SERVO_CLOSE) door_opened = False async def play_alarm(): print("Playing alarm") buzzer.duty(512) end_time = time.ticks_ms() + 2000 while time.ticks_ms() < end_time: buzzer.freq(BUZZER_FREQ1) await asyncio.sleep(ALARM_DURATION) buzzer.freq(BUZZER_FREQ2) await asyncio.sleep(ALARM_DURATION) buzzer.duty(0) async def scroll_text(text, row, delay=0.5): if len(text) <= 16: lcd.move_to(0, row) lcd.putstr(text + ' ' * (16 - len(text))) return for i in range(len(text) - 15): lcd.move_to(0, row) lcd.putstr(text[i:i + 16]) await asyncio.sleep(delay) async def message_handler(): while True: upper, lower = await message_queue.get() lcd.clear() await scroll_text(upper, 0) await scroll_text(lower, 1) # --- ASYNC TASKS --- async def monitor_rfid(): global door_opened, open_time while True: buzzer.duty(0) if rc522.PICC_IsNewCardPresent(): if rc522.PICC_ReadCardSerial(): data = sum(rc522.uid.uidByte[0:rc522.uid.size]) print("Card UID:", data) current_user = data print("USER,TYPE={}, TIMESTAMP={}".format(current_user, time.time())) if data == AUTHORIZED_ID: if door_opened: print("LOG,TYPE=OPEN_DOOR, TIMESTAMP={}".format(time.time())) duration = time.time() - open_time print("Duration:", duration) await close_door() if duration > 15: await play_alarm() await message_queue.put(("Your indecision is heating the planet.", "")) print("WARNING,TYPE=OPEN_DOOR, TIMESTAMP={}".format(time.time())) else: await message_queue.put(("Thanks", "For closing me")) else: await open_door() # Time-based snacking roast current_hour = time.localtime()[3] if current_hour >= 23 or current_hour < 5: await message_queue.put(("You hungry or just emotionally empty again?", "Go to sleep, goblin.")) print("WARNING,TYPE=LATE_NIGHT, TIMESTAMP={}".format(time.time())) else: await message_queue.put(("Welcome!", "Door is open")) else: print("Not authorized") await message_queue.put(("Access Denied", "Invalid Card")) await asyncio.sleep(1) def monitor_steam_sensor(): print("🔍 Steam sensor activated...") while True: try: analog_value = STEAM_SENSOR.read() print("Steam sensor value:", analog_value) if analog_value > STEAM_THRESHOLD: await message_queue.put(("The fridge is not your sauna, pal.", "")) print("WARNING,TYPE=HOT_FOOD, TIMESTAMP={}".format(time.time())) await asyncio.sleep(2) except Exception as e: print("DHT read error:", e) await asyncio.sleep(2) async def monitor_humidity(): while True: try: DHT_SENSOR.measure() # Start DHT11 to measure data once. # Call the built-in function of DHT to obtain temperature # and humidity data and print them in “Shell”. temperature_value = DHT_SENSOR.temperature() humidity_value = DHT_SENSOR.humidity() print('temperature:', temperature_value,'℃','humidity:', humidity_value,'%') if temperature_value > TEMP_THRESHOLD: await message_queue.put(("Want to cool the Sahara too?", "")) print("WARNING,TYPE=HOT_FOOD, TIMESTAMP={}".format(time.time())) elif humidity_value > HUMIDITY_THRESHOLD: await message_queue.put(("Too hot in here!", "Not a sauna, pal.")) print("WARNING,TYPE=HOT_FOOD, TIMESTAMP={}".format(time.time())) except Exception as e: print("DHT read error:", e) await asyncio.sleep(2) async def monitor_compartments(): button1 = Pin(16, Pin.IN, Pin.PULL_UP) button2 = Pin(27, Pin.IN, Pin.PULL_UP) #close #Nest two for loops to make the module repeatedly display five states of red, green, blue, white and OFF. while True: try: btnVal1 = button1.value() # Reads the value of button 1 #print("button1 =",btnVal1) #Print it out in the shell if(btnVal1 == 0): await message_queue.put(("Those vitamins won’t drink themselves.", "")) print("LOG,TYPE=VITAMIN, TIMESTAMP={}".format(time.time())) btnVal2 = button2.value() if(btnVal2 == 0): await message_queue.put(("Food compartment opened.", "")) print("LOG,TYPE=FOOD, TIMESTAMP={}".format(time.time())) except Exception as e: print("Compartments read error:", e) await asyncio.sleep(0.5) async def monitor_gas(): while True: try: gas_level = GAS_SENSOR.value() print("Gas Level:", gas_level) if not gas_level: await message_queue.put(("You really like cultivating diseases, huh?", "Did your fruit die?")) print("WARNING,TYPE=FOOD_SPOILAGE, TIMESTAMP={}".format(time.time())) except Exception as e: print("Gas sensor error:", e) await asyncio.sleep(3) # --- MAIN --- async def main(): await asyncio.gather( monitor_rfid(), monitor_humidity(), monitor_compartments(), monitor_steam_sensor(), monitor_gas(), message_handler() ) asyncio.run(main())