feat: implement handler for distance and led
This commit is contained in:
parent
16ca573610
commit
ae9b468be7
2 changed files with 120 additions and 0 deletions
84
distance.py
Normal file
84
distance.py
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import machine
|
||||||
|
import time
|
||||||
|
from i2c_handler import I2CSlaveHandler, Packet
|
||||||
|
|
||||||
|
class DistanceHandler(I2CSlaveHandler):
|
||||||
|
"""
|
||||||
|
I2C handler that responds to master requests by sending distance values
|
||||||
|
from an HC-SR04 ultrasonic sensor.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, i2c_id, sda, scl, slave_addr, trig_pin, echo_pin):
|
||||||
|
super().__init__(i2c_id, sda, scl, slave_addr)
|
||||||
|
self.trig = machine.Pin(trig_pin, machine.Pin.OUT)
|
||||||
|
self.echo = machine.Pin(echo_pin, machine.Pin.IN)
|
||||||
|
|
||||||
|
def read_distance_mm(self):
|
||||||
|
"""
|
||||||
|
Measure distance using the HC-SR04 sensor.
|
||||||
|
Returns distance in millimeters as an integer.
|
||||||
|
"""
|
||||||
|
# Send a 10us pulse to trigger
|
||||||
|
self.trig.low()
|
||||||
|
time.sleep_us(2)
|
||||||
|
self.trig.high()
|
||||||
|
time.sleep_us(10)
|
||||||
|
self.trig.low()
|
||||||
|
|
||||||
|
# Wait for echo high (timeout after 25ms)
|
||||||
|
timeout = 25000
|
||||||
|
start = time.ticks_us()
|
||||||
|
while not self.echo.value():
|
||||||
|
if time.ticks_diff(time.ticks_us(), start) > timeout:
|
||||||
|
return 0 # sensor error
|
||||||
|
t1 = time.ticks_us()
|
||||||
|
while self.echo.value():
|
||||||
|
if time.ticks_diff(time.ticks_us(), t1) > timeout:
|
||||||
|
return 0 # sensor error
|
||||||
|
t2 = time.ticks_us()
|
||||||
|
|
||||||
|
# Calculate duration and distance
|
||||||
|
duration = time.ticks_diff(t2, t1)
|
||||||
|
distance_mm = (duration * 100) // 582
|
||||||
|
# HC-SR04: distance (mm) = duration (us) / 5.82
|
||||||
|
|
||||||
|
# Clamp to 0..65535
|
||||||
|
return max(0, min(distance_mm, 65535))
|
||||||
|
|
||||||
|
def process_request(self):
|
||||||
|
"""
|
||||||
|
Called when master requests data. Responds with a packet containing distance.
|
||||||
|
Packet format:
|
||||||
|
Byte 0: 0x01 (distance command)
|
||||||
|
Byte 1: reserved
|
||||||
|
Byte 2-3: distance (uint16, mm, little-endian)
|
||||||
|
Byte 4-6: reserved
|
||||||
|
Byte 7: checksum (xor of bytes 0-6)
|
||||||
|
"""
|
||||||
|
#dist = self.read_distance_mm()
|
||||||
|
dist = 155
|
||||||
|
data = [0] * Packet.LENGTH
|
||||||
|
data[0] = 0x01 # Command: distance
|
||||||
|
data[2] = dist & 0xFF # Low byte
|
||||||
|
data[3] = (dist >> 8) & 0xFF # High byte
|
||||||
|
|
||||||
|
# Checksum: XOR of bytes 0-6
|
||||||
|
cs = 0
|
||||||
|
for b in data[:-1]:
|
||||||
|
cs ^= b
|
||||||
|
data[7] = cs
|
||||||
|
|
||||||
|
print(Packet.from_bytes(data))
|
||||||
|
return Packet.from_bytes(data)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
handler = DistanceHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41, trig_pin=3, echo_pin=2)
|
||||||
|
print("Distance handler I2C slave started")
|
||||||
|
try:
|
||||||
|
handler.handle()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
handler.deinit()
|
||||||
|
print("I2C slave stopped")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
36
led.py
Normal file
36
led.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from i2c_handler import I2CSlaveHandler, Packet
|
||||||
|
import neopixel
|
||||||
|
|
||||||
|
class LedDistanceHandler(I2CSlaveHandler):
|
||||||
|
def __init__(self, i2c_id, sda, scl, slave_addr):
|
||||||
|
super().__init__(i2c_id, sda, scl, slave_addr)
|
||||||
|
self.last_led_color = (0, 0, 0) # RGB tuple
|
||||||
|
self.np = neopixel.NeoPixel(machine.Pin(23), 1)
|
||||||
|
|
||||||
|
def process_packet(self, packet: Packet):
|
||||||
|
cmd = packet[0]
|
||||||
|
# Assume LED color command is 0x10, RGB in bytes 2,3,4
|
||||||
|
if cmd == 0x10: # Set LED Color
|
||||||
|
r = packet[2]
|
||||||
|
g = packet[3]
|
||||||
|
b = packet[4]
|
||||||
|
self.last_led_color = (r, g, b)
|
||||||
|
print(f"Set LED color to RGB({r},{g},{b})")
|
||||||
|
# TODO: Set the hardware LED to this color
|
||||||
|
self.np[0] = self.last_led_color
|
||||||
|
self.np.write()
|
||||||
|
else:
|
||||||
|
print(f"Unknown command 0x{cmd:02X}")
|
||||||
|
self.response_packet = None
|
||||||
|
|
||||||
|
def main():
|
||||||
|
handler = LedDistanceHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41)
|
||||||
|
print("LED/Distance handler I2C slave started")
|
||||||
|
try:
|
||||||
|
handler.handle()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
handler.deinit()
|
||||||
|
print("I2C slave stopped")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Add table
Add a link
Reference in a new issue