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