feat: add servo handling
This commit is contained in:
		
							parent
							
								
									f2863ee798
								
							
						
					
					
						commit
						3aecfd6187
					
				
					 2 changed files with 120 additions and 0 deletions
				
			
		
							
								
								
									
										68
									
								
								servo.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								servo.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					from machine import Pin, PWM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Servo:
 | 
				
			||||||
 | 
					    """ A simple class for controlling a 9g servo with the Raspberry Pi Pico.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    Attributes:
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        minVal: An integer denoting the minimum duty value for the servo motor.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        maxVal: An integer denoting the maximum duty value for the servo motor.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    def __init__(self, pin: int or Pin or PWM, minVal=2500, maxVal=7500):
 | 
				
			||||||
 | 
					        """ Creates a new Servo Object.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        args:
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					            pin (int or machine.Pin or machine.PWM): Either an integer denoting the number of the GPIO pin or an already constructed Pin or PWM object that is connected to the servo.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					            minVal (int): Optional, denotes the minimum duty value to be used for this servo.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					            maxVal (int): Optional, denotes the maximum duty value to be used for this servo.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        if isinstance(pin, int):
 | 
				
			||||||
 | 
					            pin = Pin(pin, Pin.OUT)
 | 
				
			||||||
 | 
					        if isinstance(pin, Pin):
 | 
				
			||||||
 | 
					            self.__pwm = PWM(pin)
 | 
				
			||||||
 | 
					        if isinstance(pin, PWM):
 | 
				
			||||||
 | 
					            self.__pwm = pin
 | 
				
			||||||
 | 
					        self.__pwm.freq(50)
 | 
				
			||||||
 | 
					        self.minVal = minVal
 | 
				
			||||||
 | 
					        self.maxVal = maxVal
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    def deinit(self):
 | 
				
			||||||
 | 
					        """ Deinitializes the underlying PWM object.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.__pwm.deinit()
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    def goto(self, value: int):
 | 
				
			||||||
 | 
					        """ Moves the servo to the specified position.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        args:
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					            value (int): The position to move to, represented by a value from 0 to 1024 (inclusive).
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if value < 0:
 | 
				
			||||||
 | 
					            value = 0
 | 
				
			||||||
 | 
					        if value > 1024:
 | 
				
			||||||
 | 
					            value = 1024
 | 
				
			||||||
 | 
					        delta = self.maxVal-self.minVal
 | 
				
			||||||
 | 
					        target = int(self.minVal + ((value / 1024) * delta))
 | 
				
			||||||
 | 
					        self.__pwm.duty_u16(target)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    def middle(self):
 | 
				
			||||||
 | 
					        """ Moves the servo to the middle.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.goto(512)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    def free(self):
 | 
				
			||||||
 | 
					        """ Allows the servo to be moved freely.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.__pwm.duty_u16(0)
 | 
				
			||||||
							
								
								
									
										52
									
								
								servo_handler.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								servo_handler.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					from i2c_handler import I2CSlaveHandler, Packet
 | 
				
			||||||
 | 
					from servo import Servo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					s1 = Servo(0)
 | 
				
			||||||
 | 
					s1.middle()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def servo_Map(x, in_min, in_max, out_min, out_max):
 | 
				
			||||||
 | 
					    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					def servo_Angle(angle, servo):
 | 
				
			||||||
 | 
					    if angle < 0:
 | 
				
			||||||
 | 
					        angle = 0
 | 
				
			||||||
 | 
					    if angle > 180:
 | 
				
			||||||
 | 
					        angle = 180
 | 
				
			||||||
 | 
					    servo.goto(round(servo_Map(angle,0,180,0,1024))) # Convert range value to angle value
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					def move_body_parts(angle, servo):
 | 
				
			||||||
 | 
					    for i in range(90, 90 + angle, 5):
 | 
				
			||||||
 | 
					        servo_Angle(i, servo)
 | 
				
			||||||
 | 
					        utime.sleep(0.05)
 | 
				
			||||||
 | 
					    for i in range(90 + angle, 90 - angle, -5):
 | 
				
			||||||
 | 
					        servo_Angle(i, servo)
 | 
				
			||||||
 | 
					        utime.sleep(0.05)
 | 
				
			||||||
 | 
					    for i in range(90 - angle, 90, 5):
 | 
				
			||||||
 | 
					        servo_Angle(i, servo)
 | 
				
			||||||
 | 
					        utime.sleep(0.05)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServoHandler(I2CSlaveHandler):
 | 
				
			||||||
 | 
					    def process_packet(self, packet: Packet):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Example: Override process_packet to perform actions based on packet command/type.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if packet[0] == 0x01:
 | 
				
			||||||
 | 
					            if packet[2] == 0x00:
 | 
				
			||||||
 | 
					                s1.middle()
 | 
				
			||||||
 | 
					            if packet[2] == 0x01:
 | 
				
			||||||
 | 
					                s1.move_body_parts(15, s1)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print('Unknown command')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Usage example
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    handler = ServoHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41)
 | 
				
			||||||
 | 
					    print("ServoHandler 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