meta data for this page
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
ixc2025:team_2:start [2025/05/14 10:34] – Added title diva | ixc2025:team_2:start [2025/05/15 16:29] (current) – completing sections 1 and 6 tomc1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
====Thunder Bolts==== | ====Thunder Bolts==== | ||
- | Current solutions being developed: | + | === 1. Group Introduction === |
- | * Motion detector detects how many people used the tram | + | Team Members: Tauri Torp, Rehan Ali, Haben Yohannes, Mishqat Maqbool, Thomas Curtis |
- | * Motion detector can automatically stop tram before collision - activates RGB light in red as brake light, buzzer as warning sound | + | Roles utilised throughout: Programmer, architect, electrician, designer |
- | * Fan control – fan activates at certain temperature (data also from internet?) BUT turns off if doors open | + | |
- | * Lights turn on first as dim, then later gradually brighter | + | |
- | * Passenger information system via display- cycling through info e.g. temp, next tramp stop, alert (if sudden stop) | + | |
- | * Data sent to website e.g. log of actions, passenger numbers, alerts, temperature on tram | + | |
- | + | ||
- | + | ||
- | Possible additional solutions: | + | |
- | * Button for emergency stop, triggers alert system | + | |
- | * Unordered List ItemSmoking detector warns if any smoke or toxic gas is detected | + | |
- | + | ||
+ | === 2. Initial brainstorming ideas/ | ||
Problem: Energy waste with lights being on all the time. | Problem: Energy waste with lights being on all the time. | ||
Line 56: | Line 46: | ||
2. Peace of Mind: Homeowners can monitor their homes remotely. | 2. Peace of Mind: Homeowners can monitor their homes remotely. | ||
3. Prevention: Automated safety measures reduce risk. | 3. Prevention: Automated safety measures reduce risk. | ||
+ | |||
+ | === 3. Day 2 Presentation slides === | ||
+ | https:// | ||
+ | |||
+ | === 3. Finalised Idea, description & Functions === | ||
+ | Solutions completed | ||
+ | * Motion detector can automatically stop tram before collision - activates RGB light in red as brake light, buzzer as warning sound | ||
+ | * Button for emergency stop, triggers alert system | ||
+ | * Passenger information system via display- cycling through info e.g. temp, next tramp stop, alert (if sudden stop) | ||
+ | |||
+ | |||
+ | Current solutions being developed: | ||
+ | * Fan control – fan activates at certain temperature BUT turns off if doors open | ||
+ | * * Mostly implemented | ||
+ | * Lights turn on first as dim, then later gradually brighter | ||
+ | * * Unimplemented | ||
+ | * Data sent to website e.g. log of actions, passenger numbers, alerts, temperature on tram | ||
+ | * * Implementation started | ||
+ | |||
+ | |||
+ | Possible additional solutions: | ||
+ | * Smoking detector warns if any smoke or toxic gas is detected | ||
+ | * Motion detector detects how many people used the tram | ||
+ | |||
+ | === 4. SUSAF Analysis === | ||
+ | See final powerpoint slide on susaf | ||
+ | |||
+ | === 5. Power meter measurements === | ||
+ | Attempted but incomplete due to time constraints. Did achieve some results | ||
+ | |||
+ | === 6. Future Improvements === | ||
+ | See final powerpoint slide on future improvements and reflection | ||
+ | |||
+ | === 7. Final Day Presentation Slides === | ||
+ | https:// | ||
+ | |||
+ | === 8. Final Code === | ||
+ | |||
+ | main.py | ||
+ | |||
+ | import time | ||
+ | |||
+ | import website_manager as wm | ||
+ | import display_manager as dm | ||
+ | import combine_btn_motion as bm | ||
+ | |||
+ | def test_func(): | ||
+ | pass | ||
+ | |||
+ | |||
+ | def main(): | ||
+ | alert_state = False | ||
+ | alert_length = 0 | ||
+ | | ||
+ | rolling_timer = time.time() | ||
+ | alert_timer = time.time() | ||
+ | print(" | ||
+ | dm.write_message(" | ||
+ | detections = 0 | ||
+ | |||
+ | |||
+ | while True: | ||
+ | current_time = time.time() | ||
+ | | ||
+ | | ||
+ | if alert_state == False: | ||
+ | print(" | ||
+ | if current_time - rolling_timer > 5: | ||
+ | print(" | ||
+ | rolling_timer += 5 | ||
+ | dm.rolling_message() | ||
+ | | ||
+ | #check for danger | ||
+ | alert_state, | ||
+ | alert_timer = current_time | ||
+ | | ||
+ | if alert_state == True: | ||
+ | detections += 1 | ||
+ | if detections < 3: | ||
+ | alert_state = False | ||
+ | else: | ||
+ | detections = 0 | ||
+ | |||
+ | else: | ||
+ | print(" | ||
+ | if current_time - alert_timer < alert_length: | ||
+ | dm.force_message(" | ||
+ | bm.activate_brake_and_warning() | ||
+ | bm.clear_brake_light() | ||
+ | bm.stop_buzzer() | ||
+ | else: | ||
+ | alert_state = False | ||
+ | wm.force_message(" | ||
+ | | ||
+ | | ||
+ | |||
+ | #trigger buzzer | ||
+ | #write message on lcd | ||
+ | #send message to website | ||
+ | def trigger_alert(alert_message : str): | ||
+ | wm.alert_website(alert_message) | ||
+ | dm.force_message(alert_message) | ||
+ | | ||
+ | | ||
+ | |||
+ | test_func() | ||
+ | print() | ||
+ | main() | ||
+ | |||
+ | |||
+ | |||
+ | display_manager.py | ||
+ | |||
+ | from time import sleep_ms, ticks_ms | ||
+ | from machine import I2C, Pin | ||
+ | from i2c_lcd import I2cLcd | ||
+ | |||
+ | DEFAULT_I2C_ADDR = 0x27 | ||
+ | |||
+ | i2c = I2C(scl=Pin(22), | ||
+ | lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, | ||
+ | |||
+ | messages = ["Out temp: 22C\nIn temp: 20C", "Next Stop: Kauppatori C"] | ||
+ | message_counter = 0 | ||
+ | |||
+ | # Max characters around 40 | ||
+ | # Message can be split using \n | ||
+ | def write_message(message : str): | ||
+ | lcd.clear() | ||
+ | lcd.move_to(0, | ||
+ | if " | ||
+ | message_sections = message.split(" | ||
+ | | ||
+ | lcd.putstr(message_sections[0]) | ||
+ | lcd.move_to(0, | ||
+ | lcd.putstr(message_sections[1]) | ||
+ | else: | ||
+ | lcd.putstr(message) | ||
+ | |||
+ | |||
+ | def force_message(message : str): | ||
+ | write_message(message) | ||
+ | | ||
+ | |||
+ | def rolling_message(): | ||
+ | global message_counter | ||
+ | write_message(messages[message_counter]) | ||
+ | | ||
+ | message_counter += 1 | ||
+ | if message_counter >= len(messages): | ||
+ | message_counter = 0 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | # The following line of code should be tested | ||
+ | # using the REPL: | ||
+ | |||
+ | # 1. To print a string to the LCD: | ||
+ | # lcd.putstr(' | ||
+ | # 2. To clear the display: | ||
+ | # | ||
+ | # 3. To control the cursor position: | ||
+ | # lcd.move_to(2, | ||
+ | # 4. To show the cursor: | ||
+ | # lcd.show_cursor() | ||
+ | # 5. To hide the cursor: | ||
+ | # | ||
+ | # 6. To set the cursor to blink: | ||
+ | # | ||
+ | # 7. To stop the cursor on blinking: | ||
+ | # | ||
+ | # 8. To hide the currently displayed character: | ||
+ | # | ||
+ | # 9. To show the currently hidden character: | ||
+ | # | ||
+ | # 10. To turn off the backlight: | ||
+ | # | ||
+ | # 11. To turn ON the backlight: | ||
+ | # | ||
+ | # 12. To print a single character: | ||
+ | # | ||
+ | # 13. To print a custom character: | ||
+ | #happy_face = bytearray([0x00, | ||
+ | # | ||
+ | # | ||
+ | |||
+ | |||
+ | |||
+ | combine_btn_motion.py | ||
+ | |||
+ | from time import sleep_ms, ticks_ms | ||
+ | from machine import Pin, PWM | ||
+ | import neopixel | ||
+ | import time | ||
+ | |||
+ | # Initialize PIR sensor (motion detector) | ||
+ | PIR = Pin(19, Pin.IN) | ||
+ | |||
+ | # Initialize Button (Emergency Stop) on Pin 16 | ||
+ | button1 = Pin(16, Pin.IN, Pin.PULL_UP) | ||
+ | |||
+ | # Initialize RGB LED (Brake light) | ||
+ | pin = Pin(14, Pin.OUT) | ||
+ | np = neopixel.NeoPixel(pin, | ||
+ | |||
+ | # RGB colors (Red for brake light) | ||
+ | brightness = 100 | ||
+ | colors = [ | ||
+ | [brightness, | ||
+ | [0, brightness, 0], # Green | ||
+ | [0, 0, brightness], | ||
+ | [brightness, | ||
+ | [0, 0, 0] # Off | ||
+ | ] | ||
+ | |||
+ | # Initialize Buzzer | ||
+ | buzzer = PWM(Pin(25)) | ||
+ | |||
+ | # Function to activate brake light (Red) and buzzer | ||
+ | def activate_brake_and_warning(): | ||
+ | # Turn on red brake light | ||
+ | for i in range(4): | ||
+ | np[i] = colors[0] | ||
+ | np.write() | ||
+ | | ||
+ | # Activate buzzer warning sound | ||
+ | buzzer.duty(1000) | ||
+ | buzzer.freq(294) | ||
+ | time.sleep(0.25) | ||
+ | buzzer.freq(440) | ||
+ | time.sleep(0.25) | ||
+ | buzzer.freq(392) | ||
+ | time.sleep(0.25) | ||
+ | buzzer.freq(532) | ||
+ | time.sleep(0.25) | ||
+ | buzzer.duty(0) | ||
+ | |||
+ | # Function to clear brake light (turn off LEDs) | ||
+ | def clear_brake_light(): | ||
+ | for i in range(4): | ||
+ | np[i] = colors[4] | ||
+ | np.write() | ||
+ | |||
+ | # Initialize counter and last PIR value | ||
+ | count = 0 | ||
+ | last_value = 0 | ||
+ | |||
+ | # Main loop to detect motion or button press and activate brake and buzzer | ||
+ | def detect_alert_state(): | ||
+ | # Read button state (Emergency Stop) | ||
+ | btnVal1 = button1.value() | ||
+ | |||
+ | # Check for motion detection or button press | ||
+ | if PIR.value() == 1 and last_value == 0: # Motion detected (new motion event) | ||
+ | print(f" | ||
+ | count += 1 # Increment people count | ||
+ | | ||
+ | # Activate brake light and buzzer | ||
+ | return true, 5 | ||
+ | | ||
+ | elif btnVal1 == 0: # Emergency stop button pressed (active low) | ||
+ | print(" | ||
+ | | ||
+ | # Activate brake light and buzzer | ||
+ | return true, 5 | ||
+ | |||
+ | else: | ||
+ | last_value = PIR.value() | ||
+ | clear_brake_light() | ||
+ | |||
+ | time.sleep(0.1) | ||
+ | |||
+ | |||
+ | light_control.py | ||
+ | |||
+ | mport time | ||
+ | import math | ||
+ | from machine import Pin, PWM | ||
+ | |||
+ | PWM_PIN = 12 | ||
+ | PWM_FREQ = 10000 # PWM frequency in Hz | ||
+ | MIN_BRIGHTNESS = 0 | ||
+ | MAX_BRIGHTNESS = 1023 | ||
+ | |||
+ | # Time-based irradiance simulation parameters | ||
+ | DAWN_HOUR = 6 | ||
+ | SUNRISE_HOUR = 7 | ||
+ | NOON_HOUR = 12 | ||
+ | SUNSET_HOUR = 19 | ||
+ | DUSK_HOUR = 20 | ||
+ | |||
+ | led_pwm = PWM(Pin(PWM_PIN, | ||
+ | |||
+ | |||
+ | def get_current_hour(): | ||
+ | cycle_minutes = (time.time() % (24 * 60)) | ||
+ | current_hour = (cycle_minutes / 60) % 24 | ||
+ | return current_hour | ||
+ | |||
+ | |||
+ | def simulate_irradiance(): | ||
+ | hour = get_current_hour() | ||
+ | | ||
+ | # Night (before dawn or after dusk) | ||
+ | if hour < DAWN_HOUR or hour > DUSK_HOUR: | ||
+ | return 0.0 | ||
+ | | ||
+ | # Dawn (gradual increase from dark to daylight) | ||
+ | elif DAWN_HOUR <= hour < SUNRISE_HOUR: | ||
+ | dawn_progress = (hour - DAWN_HOUR) / (SUNRISE_HOUR - DAWN_HOUR) | ||
+ | return dawn_progress * 0.5 | ||
+ | | ||
+ | # Morning (increasing to noon) | ||
+ | elif SUNRISE_HOUR <= hour < NOON_HOUR: | ||
+ | morning_progress = (hour - SUNRISE_HOUR) / (NOON_HOUR - SUNRISE_HOUR) | ||
+ | return 0.5 + (morning_progress * 0.5) | ||
+ | | ||
+ | # Afternoon (decreasing from noon) | ||
+ | elif NOON_HOUR <= hour < SUNSET_HOUR: | ||
+ | afternoon_progress = (hour - NOON_HOUR) / (SUNSET_HOUR - NOON_HOUR) | ||
+ | return 1.0 - (afternoon_progress * 0.5) | ||
+ | | ||
+ | # Dusk (gradual decrease from daylight to dark) | ||
+ | else: | ||
+ | dusk_progress = (hour - SUNSET_HOUR) / (DUSK_HOUR - SUNSET_HOUR) | ||
+ | return 0.5 - (dusk_progress * 0.5) | ||
+ | |||
+ | |||
+ | def calculate_light_brightness(irradiance): | ||
+ | # Threshold above which no artificial light is needed | ||
+ | DAY_THRESHOLD = 0.7 | ||
+ | | ||
+ | if irradiance >= DAY_THRESHOLD: | ||
+ | return 0 | ||
+ | else: | ||
+ | brightness_factor = 1.0 - (irradiance / DAY_THRESHOLD) | ||
+ | | ||
+ | brightness_factor = math.pow(brightness_factor, | ||
+ | | ||
+ | brightness = int(brightness_factor * MAX_BRIGHTNESS) | ||
+ | return max(MIN_BRIGHTNESS, | ||
+ | |||
+ | |||
+ | def print_debug_info(irradiance, | ||
+ | hour = get_current_hour() | ||
+ | print(f" | ||
+ | |||
+ | |||
+ | try: | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | print(" | ||
+ | print() | ||
+ | | ||
+ | # For demo purposes, we'll speed up time | ||
+ | demo_time_factor = 60 # 1 minute = 1 hour | ||
+ | last_time = time.time() | ||
+ | | ||
+ | while True: | ||
+ | irradiance = simulate_irradiance() | ||
+ | | ||
+ | brightness = calculate_light_brightness(irradiance) | ||
+ | | ||
+ | led_pwm.duty(brightness) | ||
+ | | ||
+ | print_debug_info(irradiance, | ||
+ | | ||
+ | time.sleep(1) | ||
+ | | ||
+ | current_time = time.time() | ||
+ | time_diff = current_time - last_time | ||
+ | last_time = current_time | ||
+ | time.sleep_ms(int(time_diff * demo_time_factor * 1000)) | ||
+ | | ||
+ | except KeyboardInterrupt: | ||
+ | print(" | ||
+ | finally: | ||
+ | led_pwm.deinit() | ||
+ | print(" | ||
+ | |||
+ | |||
+ | |||
+ | fan.py | ||
+ | |||
+ | from machine import Pin, PWM | ||
+ | import machine | ||
+ | import time | ||
+ | import dht | ||
+ | |||
+ | # Initialize Fan Control Pins | ||
+ | INA = PWM(Pin(27, Pin.OUT), 10000) | ||
+ | INB = PWM(Pin(18, Pin.OUT), 10000) | ||
+ | |||
+ | # Initialize Button for door control | ||
+ | button1 = Pin(26, Pin.IN, Pin.PULL_UP) | ||
+ | |||
+ | # Initialize PWM for Servo (Door control) | ||
+ | pwm = PWM(Pin(5)) | ||
+ | pwm.freq(50) | ||
+ | |||
+ | #Associate DHT11 with Pin(17). | ||
+ | DHT = dht.DHT11(machine.Pin(17)) | ||
+ | |||
+ | |||
+ | # RGB colors (Red for brake light, for indication when door is open) | ||
+ | |||
+ | |||
+ | # Fan control functions | ||
+ | def activate_fan(): | ||
+ | INA.duty(0) | ||
+ | INB.duty(700) # Set duty cycle to rotate the fan | ||
+ | |||
+ | def deactivate_fan(): | ||
+ | INA.duty(0) | ||
+ | INB.duty(0) | ||
+ | |||
+ | # Function to simulate door control with PWM (servo motor) | ||
+ | def control_door(open_door): | ||
+ | if open_door: | ||
+ | pwm.duty(77) | ||
+ | print(" | ||
+ | else: | ||
+ | pwm.duty(25) | ||
+ | print(" | ||
+ | |||
+ | # Main loop to toggle door and control fan | ||
+ | door_open = False # Initially, door is closed | ||
+ | |||
+ | while True: | ||
+ | btnVal1 = button1.value() | ||
+ | DHT.measure() | ||
+ | | ||
+ | if btnVal1 == 0: # Button pressed (active low) | ||
+ | time.sleep(0.01) | ||
+ | while btnVal1 == 0: | ||
+ | btnVal1 = button1.value() | ||
+ | door_open = not door_open | ||
+ | | ||
+ | # Control the door based on the state | ||
+ | control_door(door_open) | ||
+ | | ||
+ | # Control the fan based on door state | ||
+ | if door_open: | ||
+ | deactivate_fan() | ||
+ | else: | ||
+ | activate_fan() | ||
+ | |||
+ | time.sleep(0.1) | ||
+ | testwebsite.html | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | // Refresh the page every 1000 milliseconds (1 second) | ||
+ | setInterval(function () { | ||
+ | location.reload(); | ||
+ | }, 1000); | ||
+ | </ | ||
+ | </ | ||
+ | </ |