from machine import Pin, I2C, WDT
import time
# Konfiguracja przycisków i diod LED
buttons = [Pin(i, Pin.IN, Pin.PULL_UP) for i in range(8)] # Konfiguracja przycisków od 0 do 7
leds = [Pin(i, Pin.OUT) for i in range(8, 16)] # Konfiguracja diod LED od 8 do 15
# Konfiguracja I2C
i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=400000) # Inicjalizacja magistrali I2C
# Adresy I2C slave'ów
i2c_address = 0x40 # Adres I2C slave'ów do sterowania przez klawiaturę
input_slave_address = 0x41 # Adres slave'a monitorującego napięcie (miganie kierunkowskazu)
output_slave_addresses = [0x42, 0x43, 0x44] # Adresy slave'ów wykonujących komendy
# Skanowanie magistrali I2C
devices = i2c.scan()
if len(devices) == 0:
print("No I2C devices found")
else:
print("I2C devices found:", [hex(device) for device in devices])
# Inicjalizacja Watchdog (timeout 8 sekund)
wdt = WDT(timeout=8000)
# Główna pętla programu
button_states = [-1] * len(buttons) # Zmieniamy False na -1 dla prawidłowego indeksowania
debounce_time = 10
long_press_time = 2000
button_pressed_time = [0] * len(buttons)
long_press_detected = [False] * len(buttons)
output_sequences = [
[[1, 2], [4, 6, 34, 60], [3, 6], [4, 6, 34, 60]], # Przycisk 1
[[1, 35, 40, 55], [4, 6, 34, 60]], # Przycisk 2
[[9, 10, 11], [17]], # Przycisk 3
[[13, 14, 15, 16], [18]], # Przycisk 4
[[17]], # Przycisk 5
[[18]], # Przycisk 6
[[19]], # Przycisk 7
[[20]] # Przycisk 8
]
# Funkcja do zapisywania stanu wyjścia do urządzenia podłączonego przez I2C
def i2c_write_output(outputs, state):
try:
if isinstance(outputs, int): # Sprawdź, czy outputs jest liczbą całkowitą
outputs = [outputs] # Jeśli tak, zamień ją na listę jednoelementową
for output in outputs:
data = bytearray([output, state])
i2c.writeto(i2c_address, data)
print(f"I2C Write: Output {output} set to {state}")
except OSError as e:
print(f"I2C Error: {e}")
# Obsługa wyłączenia wszystkich wyjść
def wyłącz_wszystko():
for led in leds:
led.off() # Wyłączenie wszystkich diod
for seq in output_sequences:
for outputs in seq:
for output in outputs:
i2c_write_output(output, 0) # Wyłączenie wszystkich wyjść
button_states[:] = [-1] * len(buttons) # Zresetowanie stanów przycisków
long_press_detected[:] = [True] * len(buttons) # Zresetowanie wykrytych długich naciśnieć
time.sleep(0.5) # Krótkie opóźnienie po zresetowaniu
print("All outputs turned off")
# Funkcja do odczytu stanu napięcia z input slave'a
def read_voltage_state(address):
try:
data = i2c.readfrom_mem(address, 0x00, 2)
return data[0], data[1] # Zwraca bieżący stan i informację o zmianie stanu
except OSError as e:
print(f"I2C Error: {e}")
return None, None
# Funkcja do wysyłania komendy I2C
def send_i2c_command(address, command):
try:
data = bytearray([command])
i2c.writeto(address, data)
print(f"I2C Write: Sent command {command} to address {hex(address)}")
except OSError as e:
print(f"I2C Error: {e}")
last_voltage_check = 0
voltage_check_interval = 2000 # Czas w milisekundach (2 sekundy)
while True:
current_time = time.ticks_ms()
wdt.feed() # Reset watchdoga na początku pętli
for i, button in enumerate(buttons):
if not button.value():
if button_pressed_time[i] == 0:
button_pressed_time[i] = current_time
if time.ticks_diff(current_time, button_pressed_time[i]) > long_press_time:
if not long_press_detected[i]:
print(f"Long press detected on button {i + 1}")
wyłącz_wszystko() # Wywołanie funkcji wyłącz_wszystko()
long_press_detected[i] = True
else:
if button_pressed_time[i] != 0:
press_duration = time.ticks_diff(current_time, button_pressed_time[i])
if press_duration > debounce_time and not long_press_detected[i]:
seq_index = i
current_output_index = button_states[i]
next_output_index = (current_output_index + 1) % (len(output_sequences[seq_index]) + 1) # Poprawienie indeksowania
if next_output_index == len(output_sequences[seq_index]):
next_output_index = -1 # Ustawienie na -1 oznacza wyłączenie wszystkich wyjść
if current_output_index != -1:
i2c_write_output(output_sequences[seq_index][current_output_index], 0) # Wyłączenie poprzedniego wyjścia
if next_output_index != -1:
i2c_write_output(output_sequences[seq_index][next_output_index], 1) # Włączenie następnego wyjścia
button_states[i] = next_output_index # Zapisanie nowego stanu przycisku
if next_output_index != -1:
leds[i].on() # Włączenie diody odpowiadającej przyciskowi
else:
leds[i].off() # Wyłączenie diody odpowiadającej przyciskowi
button_pressed_time[i] = 0
long_press_detected[i] = False
# Nowa funkcjonalność: odpytywanie slave'a wejściowego co 2 sekundy
if time.ticks_diff(current_time, last_voltage_check) > voltage_check_interval:
voltage_state, state_changed = read_voltage_state(input_slave_address)
if state_changed is not None and state_changed == 1: # Sprawdzenie czy stan się zmienił
if voltage_state == 1:
print(f"Voltage detected on input slave {hex(input_slave_address)}")
command = 1 # Komenda włączenia
else:
print(f"Voltage off on input slave {hex(input_slave_address)}")
command = 0 # Komenda wyłączenia
for address in output_slave_addresses:
send_i2c_command(address, command) # Wysłanie komendy do output slave'ów
last_voltage_check = current_time
time.sleep(0.1) # Odpytuj co 0.1 sekundy (10 razy na sekundę)