meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
ixc2025:team_2:start [2025/05/14 10:34] – Added title divaixc2025: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 MembersTauri TorpRehan AliHaben YohannesMishqat MaqboolThomas Curtis  
-  * Motion detector can automatically stop tram before collision - activates RGB light in red as brake lightbuzzer as warning sound +Roles utilised throughout: Programmerarchitectelectriciandesigner
-  * Fan control – fan activates at certain temperature (data also from internet?) BUT turns off if doors open​ +
-  * Lights turn on first as dimthen later gradually brighter​ +
-  * Passenger information system via display- cycling through info e.g. tempnext tramp stopalert (if sudden stop) +
-  * Data sent to website e.g. log of actionspassenger numbersalertstemperature 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/concepts ===
 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://utufi-my.sharepoint.com/:p:/g/personal/tjcurt_utu_fi/EajJ4qdvY-tKmBoB6I-NMPcBsNiMwygQtwIO_VnHju2J7w?e=dEHmlX
 +
 +=== 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://utufi-my.sharepoint.com/:p:/g/personal/tautor_utu_fi/ERYLEUsP55xEsYmF-mjSuLYBstzINHCUbmxqcY2E-rxbSw?e=M3qavC
 +
 +=== 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("Starting main loop")
 +    dm.write_message("Tram start!")
 +    detections = 0
 +
 +
 +    while True:
 +        current_time = time.time()
 +        
 +        
 +        if alert_state == False:
 +            print("no alert")
 +            if current_time - rolling_timer > 5:
 +                print("Display: New rolling message")
 +                rolling_timer += 5
 +                dm.rolling_message()
 +                
 +            #check for danger
 +            alert_state, alert_length = bm.detect_alert_state()
 +            alert_timer = current_time
 +            
 +            if alert_state == True:
 +                detections += 1
 +                if detections < 3:
 +                    alert_state = False
 +                else:
 +                    detections = 0
 +
 +        else:
 +            print("alert!")
 +            if current_time - alert_timer < alert_length:
 +                dm.force_message("Emergency stop!")
 +                bm.activate_brake_and_warning()
 +                bm.clear_brake_light()
 +                bm.stop_buzzer()
 +            else:
 +                alert_state = False
 +    wm.force_message("Tram shutdown!")
 +            
 +        
 +
 +#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), sda=Pin(21), freq=400000) 
 +lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16)
 +
 +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,0)
 +    if "\n" in message:
 +        message_sections = message.split("\n")
 +        
 +        lcd.putstr(message_sections[0])
 +        lcd.move_to(0,1)
 +        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('Hello world')
 +# 2. To clear the display:
 +#lcd.clear()
 +# 3. To control the cursor position:
 +# lcd.move_to(2, 1)
 +# 4. To show the cursor:
 +# lcd.show_cursor()
 +# 5. To hide the cursor:
 +#lcd.hide_cursor()
 +# 6. To set the cursor to blink:
 +#lcd.blink_cursor_on()
 +# 7. To stop the cursor on blinking:
 +#lcd.blink_cursor_off()
 +# 8. To hide the currently displayed character:
 +#lcd.display_off()
 +# 9. To show the currently hidden character:
 +#lcd.display_on()
 +# 10. To turn off the backlight:
 +#lcd.backlight_off()
 +# 11. To turn ON the backlight:
 +#lcd.backlight_on()
 +# 12. To print a single character:
 +#lcd.putchar('x')
 +# 13. To print a custom character:
 +#happy_face = bytearray([0x00, 0x0A, 0x00, 0x04, 0x00, 0x11, 0x0E, 0x00])
 +#lcd.custom_char(0, happy_face)
 +#lcd.putchar(chr(0))
 +
 +
 +
 +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, 4)
 +
 +# RGB colors (Red for brake light)
 +brightness = 100
 +colors = [
 +    [brightness, 0, 0],  # Red (Brake light)
 +    [0, brightness, 0],  # Green
 +    [0, 0, brightness],  # Blue
 +    [brightness, brightness, brightness],  # White
 +    [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]  # Set all LEDs to red (brake light)
 +    np.write()
 +    
 +    # Activate buzzer warning sound
 +    buzzer.duty(1000)
 +    buzzer.freq(294)  # Start sound
 +    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)  # Stop sound
 +
 +# Function to clear brake light (turn off LEDs)
 +def clear_brake_light():
 +    for i in range(4):
 +        np[i] = colors[4]  # Turn off all LEDs
 +    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()  # Button press state
 +
 +    # Check for motion detection or button press
 +    if PIR.value() == 1 and last_value == 0:  # Motion detected (new motion event)
 +        print(f"Motion detected! Count: {count + 1}")
 +        count += 1  # Increment people count
 +        
 +        # Activate brake light and buzzer
 +        return true, 5
 +        
 +    elif btnVal1 == 0:  # Emergency stop button pressed (active low)
 +        print("Emergency Stop Activated!")
 +        
 +        # Activate brake light and buzzer
 +        return true, 5
 +
 +    else:
 +        last_value = PIR.value()  # Update PIR last value
 +        clear_brake_light()  # Turn off brake light if no motion and no button press
 +
 +    time.sleep(0.1)  # Small delay for debounce
 +
 +
 +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, Pin.OUT), PWM_FREQ)
 +
 +
 +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, 0.8)
 +        
 +        brightness = int(brightness_factor * MAX_BRIGHTNESS)
 +        return max(MIN_BRIGHTNESS, min(brightness, MAX_BRIGHTNESS))
 +
 +
 +def print_debug_info(irradiance, brightness):
 +    hour = get_current_hour()
 +    print(f"Time: {hour:.2f}h | Irradiance: {irradiance:.2f} | Light brightness: {brightness} ({brightness/MAX_BRIGHTNESS*100:.1f}%)")
 +
 +
 +try:
 +    print("Smart Tram Light Control - Demo Mode")
 +    print("------------------------------------")
 +    print("Light will adjust automatically based on simulated time of day")
 +    print("Press Ctrl+C to exit")
 +    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, brightness)
 +        
 +        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("\nExiting program")
 +finally:
 +    led_pwm.deinit()
 +    print("PWM resource released")
 +
 +
 +
 +fan.py
 +
 +from machine import Pin, PWM
 +import machine
 +import time
 +import dht
 +
 +# Initialize Fan Control Pins
 +INA = PWM(Pin(27, Pin.OUT), 10000)  # INA corresponds to IN+
 +INB = PWM(Pin(18, Pin.OUT), 10000)  # INB corresponds to IN-
 +
 +# Initialize Button for door control
 +button1 = Pin(26, Pin.IN, Pin.PULL_UP)  # Button for opening/closing the door
 +
 +# 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)   # Fan control forward direction
 +    INB.duty(700) # Set duty cycle to rotate the fan
 +
 +def deactivate_fan():
 +    INA.duty(0)   # Stop fan
 +    INB.duty(0)   # Stop fan
 +
 +# Function to simulate door control with PWM (servo motor)
 +def control_door(open_door):
 +    if open_door:
 +        pwm.duty(77)  # Door open (90 degrees)
 +        print("Door opened.")
 +    else:
 +        pwm.duty(25)  # Door closed (0 degrees)
 +        print("Door closed.")
 +
 +# Main loop to toggle door and control fan
 +door_open = False  # Initially, door is closed
 +
 +while True:
 +    btnVal1 = button1.value()  # Read the button value (active low)
 +    DHT.measure()
 +    
 +    if btnVal1 == 0:  # Button pressed (active low)
 +        time.sleep(0.01)  # Delay to debounce the button
 +        while btnVal1 == 0:
 +            btnVal1 = button1.value()  # Wait for button release
 +        door_open = not door_open  # Toggle door state
 +        
 +        # Control the door based on the state
 +        control_door(door_open)
 +        
 +        # Control the fan based on door state
 +        if door_open:
 +            deactivate_fan()  # Turn off fan if door is open
 +        else:
 +            activate_fan()  # Turn on fan if door is closed
 +
 +    time.sleep(0.1)  # Short delay to prevent rapid toggling
  
  
 +testwebsite.html
  
 +  <!DOCTYPE html>
 +  <html>
 +  <head>
 +  </head>
 +  <body>
 +  <h3>Daily passenger count:</h3><!--Motion detector detects how many people used the tram-->
 +  <h3>Tram is moving: [yes/no]</h3> <!--Motion detector can automatically stop tram before collision - activates RGB light in red as brake light, buzzer as warning sound-->
 +  <h3>Button for emergency stop: [on/off]</h3> <!--Button for emergency stop, triggers alert system-->
 +  <h3>Fan: [on/off]</h3> <!--Fan control – fan activates at certain temperature (data also from internet?) BUT turns off if doors open-->
 +  <h3>Lights: [dim/brighter/brightest]</h3> <!--Lights turn on first as dim, then later gradually brighter-->
 +  <h3>Display information: [temperature outside/time until tram arrives at the next stop] </h3> <!--Passenger information system via display- cycling through info e.g. temp, next tramp stop, alert (if sudden stop)-->
 +  <h3></h3> <!--Data sent to website e.g. log of actions, passenger numbers, alerts, temperature on tram-->
 +  <script>
 +    // Refresh the page every 1000 milliseconds (1 second)
 +    setInterval(function () {
 +      location.reload();
 +    }, 1000);
 +  </script>
 +  </body>
 +  </html>