├── AllMotorTest.py ├── AllServoTest.py ├── LICENSE ├── PicoRobotics.py ├── README.md ├── README_FR.md ├── SingleMotorTest.py ├── SingleServoTest.py ├── StepperTest.py └── docs └── _static └── pico-robotics-board.jpg /AllMotorTest.py: -------------------------------------------------------------------------------- 1 | #AllMotorTest.py 2 | # test code that ramps each motor 0-100-0 then changes direction and does it again. 3 | #all motors run at once, but with staggered timings 4 | 5 | import PicoRobotics 6 | import utime 7 | 8 | 9 | board = PicoRobotics.KitronikPicoRobotics() 10 | directions = ["f","r"] 11 | 12 | while True: 13 | for direction in directions: 14 | for speed in range(0,25): 15 | board.motorOn(1, direction, speed) 16 | board.motorOn(2, direction, 25-speed) 17 | board.motorOn(3, direction, 50-speed) 18 | board.motorOn(4, direction, 75-speed) 19 | utime.sleep_ms(100) #ramp speed over 25x100ms => approx 2.5 second. 20 | for speed in range(0,25): 21 | board.motorOn(1, direction, 25+speed) 22 | board.motorOn(2, direction, speed) 23 | board.motorOn(3, direction, 25-speed) 24 | board.motorOn(4, direction, 50-speed) 25 | utime.sleep_ms(100) 26 | for speed in range(0,25): 27 | board.motorOn(1, direction, 50+speed) 28 | board.motorOn(2, direction, 25+speed) 29 | board.motorOn(3, direction, speed) 30 | board.motorOn(4, direction, 25-speed) 31 | utime.sleep_ms(100) 32 | for speed in range(0,25): 33 | board.motorOn(1, direction, 75+speed) 34 | board.motorOn(2, direction, 50+speed) 35 | board.motorOn(3, direction, 25+speed) 36 | board.motorOn(4, direction, speed) 37 | utime.sleep_ms(100) 38 | for speed in range(0,25): 39 | board.motorOn(1, direction, 100-speed) 40 | board.motorOn(2, direction, 75+speed) 41 | board.motorOn(3, direction, 50+speed) 42 | board.motorOn(4, direction, 25+speed) 43 | utime.sleep_ms(100) 44 | for speed in range(0,25): 45 | board.motorOn(1, direction, 75-speed) 46 | board.motorOn(2, direction, 100-speed) 47 | board.motorOn(3, direction, 75+speed) 48 | board.motorOn(4, direction, 50+speed) 49 | utime.sleep_ms(100) 50 | for speed in range(0,25): 51 | board.motorOn(1, direction, 50-speed) 52 | board.motorOn(2, direction, 75-speed) 53 | board.motorOn(3, direction, 100-speed) 54 | board.motorOn(4, direction, 75+speed) 55 | utime.sleep_ms(100) 56 | for speed in range(0,25): 57 | board.motorOn(1, direction, 25-speed) 58 | board.motorOn(2, direction, 50-speed) 59 | board.motorOn(3, direction, 75-speed) 60 | board.motorOn(4, direction, 100-speed) 61 | utime.sleep_ms(100) 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /AllServoTest.py: -------------------------------------------------------------------------------- 1 | #AllServoTest.py 2 | # test code that ramps each servo from 0-180-0 3 | import PicoRobotics 4 | import utime 5 | 6 | 7 | board = PicoRobotics.KitronikPicoRobotics() 8 | while True: 9 | for degrees in range(180): 10 | for servo in range(1,9): 11 | board.servoWrite(servo, degrees) 12 | utime.sleep_ms(10) #ramp speed over 10x180ms => approx 2 seconds. 13 | for degrees in range(180): 14 | for servo in range(1,9): 15 | board.servoWrite(servo, 180-degrees) 16 | utime.sleep_ms(10) #ramp speed over 10x180ms => approx 2 seconds. 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kitronik Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PicoRobotics.py: -------------------------------------------------------------------------------- 1 | import machine 2 | import utime 3 | 4 | class KitronikPicoRobotics: 5 | #Class variables - these should be the same for all instances of the class. 6 | # If you wanted to write some code that stepped through 7 | # the servos or motors then this is the Base and size to do that 8 | SRV_REG_BASE = 0x08 9 | MOT_REG_BASE = 0x28 10 | REG_OFFSET = 4 11 | PRESCALE_VAL = b'\x79' 12 | PI_ESTIMATE = 3.1416 13 | 14 | #setup the PCA chip for 50Hz and zero out registers. 15 | def initPCA(self): 16 | # Make sure we are in a known position 17 | # Soft reset of the I2C chip 18 | self.i2c.writeto(0,"\x06") 19 | 20 | # setup the prescale to have 20mS pulse repetition - this is dictated by the servos. 21 | # set PWM Frequency Pre Scale. The prescale value is determined with the formunla: 22 | # presscale value = round(osc clock / (4096 * update rate)) 23 | # Where update rate is the output modulation frequency required. 24 | # For example, the output frequency of 50Hz (20ms) for the servo, with the internal oscillator 25 | # clock frequency of 25 Mhz is as follows: 26 | # prescale value = round( 25MHZ / (4096 * 50Hz) ) - 1 27 | # prescale value = round (25000000 / (4096 * 50)) - 1 28 | # presscale value = 121 = 79h = 0x79 29 | self.i2c.writeto_mem(108,0xfe,self.PRESCALE_VAL) 30 | 31 | #block write outputs to off 32 | self.i2c.writeto_mem(108,0xfa,"\x00") 33 | self.i2c.writeto_mem(108,0xfb,"\x00") 34 | self.i2c.writeto_mem(108,0xfc,"\x00") 35 | self.i2c.writeto_mem(108,0xfd,"\x00") 36 | 37 | # come out of sleep 38 | self.i2c.writeto_mem(108,0x00,"\x01") 39 | 40 | # It takes 500uS max for the oscillator to be up and running once the SLEEP bit (bit 4) has 41 | # been set to logic 0. Timings on outputs are not guranteed if the PWM control registers are 42 | # accessed within the 500uS window. 43 | utime.sleep_us(500) 44 | 45 | # Adjusts the servos. 46 | # This block should be used if the connected servo does not respond correctly to the 'servoWrite' command. 47 | # Try changing the value by small amounts and testing the servo until it correctly sets to the angle. 48 | def adjustServos(self, change): 49 | if change < -25: 50 | change = -25 51 | if change > 25: 52 | change = 25 53 | self.PRESCALE_VAL = (121 + change).to_bytes(1,"big") 54 | self.initPCA() 55 | 56 | # To get the PWM pulses to the correct size and zero 57 | # offset these are the default numbers. 58 | #Servo multiplier is calcualted as follows: 59 | # 4096 pulses ->20mS 1mS-> count of 204.8 60 | # 1mS is 90 degrees of travel, so each degree is a count of 204.8/90->2.2755 61 | # servo pulses always have aminimum value - so there is guarentees to be a pulse. 62 | # in the servos Ive examined this is 0.5ms or a count of 102 63 | #to clauclate the count for the corect pulse is simply: 64 | # (degrees x count per degree )+ offset 65 | def servoWrite(self,servo, degrees): 66 | #check the degrees is a reasonable number. we expect 0-180, so cap at those values. 67 | if(degrees>180): 68 | degrees = 180 69 | elif (degrees<0): 70 | degrees = 0 71 | #check the servo number 72 | if((servo<1) or (servo>8)): 73 | raise Exception("INVALID SERVO NUMBER") #harsh, but at least you'll know 74 | calcServo = self.SRV_REG_BASE + ((servo - 1) * self.REG_OFFSET) 75 | PWMVal = int((degrees*2.2755)+102) # see comment above for maths 76 | lowByte = PWMVal & 0xFF 77 | highByte = (PWMVal>>8)&0x01 #cap high byte at 1 - shoud never be more than 2.5mS. 78 | self.i2c.writeto_mem(self.CHIP_ADDRESS, calcServo,bytes([lowByte])) 79 | self.i2c.writeto_mem(self.CHIP_ADDRESS, calcServo+1,bytes([highByte])) 80 | 81 | # Takes the servo to change and the angle in radians to move to. 82 | # 0 radians to 3.1416 83 | def servoWriteRadians(self, servo, radians): 84 | if servo < 1: 85 | servo = 1 86 | if servo > 8: 87 | servo = 8 88 | if radians < 0: 89 | radians = 0 90 | if radians > self.PI_ESTIMATE: 91 | radians = self.PI_ESTIMATE 92 | 93 | calcServo = self.SRV_REG_BASE + ((servo - 1) * self.REG_OFFSET) 94 | PWMVal = int((radians / self.PI_ESTIMATE) * 408) + 102 # See comment above for maths 95 | lowByte = PWMVal & 0xFF 96 | highByte = (PWMVal >> 8) & 0x01 # Cap high byte at 1 - shoud never be more than 2.5mS 97 | self.i2c.writeto_mem(self.CHIP_ADDRESS, calcServo, bytes([lowByte])) 98 | self.i2c.writeto_mem(self.CHIP_ADDRESS, calcServo + 1, bytes([highByte])) 99 | 100 | #Driving the motor is simpler than the servo - just convert 0-100% to 0-4095 and push it to the correct registers. 101 | #each motor has 4 writes - low and high bytes for a pair of registers. 102 | def motorOn(self,motor, direction, speed): 103 | #cap speed to 0-100% 104 | if (speed<0): 105 | speed = 0 106 | elif (speed>100): 107 | speed=100 108 | 109 | if((motor<1) or (motor>4)): 110 | raise Exception("INVALID MOTOR NUMBER") # harsh, but at least you'll know 111 | 112 | motorReg = self.MOT_REG_BASE + (2 * (motor - 1) * self.REG_OFFSET) 113 | PWMVal = int(speed * 40.95) 114 | lowByte = PWMVal & 0xFF 115 | highByte = (PWMVal>>8) & 0xFF #motors can use all 0-4096 116 | #print (motor, direction, "LB ",lowByte," HB ",highByte) 117 | if direction == "f": 118 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg,bytes([lowByte])) 119 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+1,bytes([highByte])) 120 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+4,bytes([0])) 121 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+5,bytes([0])) 122 | elif direction == "r": 123 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+4,bytes([lowByte])) 124 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+5,bytes([highByte])) 125 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg,bytes([0])) 126 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+1,bytes([0])) 127 | else: 128 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+4,bytes([0])) 129 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+5,bytes([0])) 130 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg,bytes([0])) 131 | self.i2c.writeto_mem(self.CHIP_ADDRESS, motorReg+1,bytes([0])) 132 | raise Exception("INVALID DIRECTION") 133 | #To turn off set the speed to 0... 134 | def motorOff(self,motor): 135 | self.motorOn(motor,"f",0) 136 | 137 | ################# 138 | #Stepper Motors 139 | ################# 140 | #this is only a basic full stepping. 141 | #speed sets the length of the pulses (and hence the speed...) 142 | #so is 'backwards' - the fastest that works reliably with the motors I have to hand is 20mS, but slower than that is good. tested to 2000 (2 seconds per step). 143 | # motor should be 1 or 2 - 1 is terminals for motor 1 and 2 on PCB, 2 is terminals for motor 3 and 4 on PCB 144 | 145 | def step(self,motor, direction, steps, speed =20, holdPosition=False): 146 | 147 | if((motor<1) or (motor>2)): 148 | raise Exception("INVALID MOTOR NUMBER") # harsh, but at least you'll know 149 | 150 | if(direction =="f"): 151 | directions = ["f", "r"] 152 | coils = [((motor*2)-1),(motor*2)] 153 | elif (direction == "r"): 154 | directions = ["r", "f"] 155 | coils = [(motor*2),((motor*2)-1)] 156 | else: 157 | raise Exception("INVALID DIRECTION") #harsh, but at least you'll know 158 | while steps > 0: 159 | for direction in directions: 160 | if(steps == 0): 161 | break 162 | for coil in coils: 163 | self.motorOn(coil,direction,100) 164 | utime.sleep_ms(speed) 165 | steps -=1 166 | if(steps == 0): 167 | break 168 | #to save power turn off the coils once we have finished. 169 | #this means the motor wont hold position. 170 | if(holdPosition == False): 171 | for coil in coils: 172 | self.motorOff(coil) 173 | 174 | #Step an angle. this is limited by the step resolution - so 200 steps is 1.8 degrees per step for instance. 175 | # a request for 20 degrees with 200 steps/rev will result in 11 steps - or 19.8 rather than 20. 176 | def stepAngle(self,motor, direction, angle, speed =20, holdPosition=False, stepsPerRev=200): 177 | steps = int(angle/(360/stepsPerRev)) 178 | print (steps) 179 | self.step(motor, direction, steps, speed, holdPosition) 180 | 181 | 182 | # initialaisation code for using: 183 | #defaults to the standard pins and address for the kitronik board, but could be overridden 184 | def __init__(self, I2CAddress=108,sda=8,scl=9): 185 | self.CHIP_ADDRESS = 108 186 | sda=machine.Pin(sda) 187 | scl=machine.Pin(scl) 188 | self.i2c=machine.I2C(0,sda=sda, scl=scl, freq=100000) 189 | self.initPCA() 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Other Languages: [FRANCAIS](README_FR.md) 2 | 3 | # Kitronik-Pico-Robotics-Board-MicroPython 4 | 5 | ![Pico Robotics Board de KitroniK](docs/_static/pico-robotics-board.jpg) 6 | 7 | A class and sample code to use the Kitronik Robotics board for Raspberry Pi Pico. (www.kitronik.co.uk/5329) 8 | 9 | This is the microPython version. For CircuitPython see: https://github.com/KitronikLtd/Kitronik-Pico-Robotics-Board-CircuitPython 10 | 11 | To use this library, save the file `PicoRobotics.py` file onto the Pico so Python can import it. 12 | 13 | ## Import the library and construct an instance: 14 | ``` python 15 | import PicoRobotics 16 | board = PicoRobotics.KitronikPicoRobotics() 17 | ``` 18 | This will initialise the PCA to default values. 19 | 20 | ## Drive a motor: 21 | ``` python 22 | board.motorOn(motor, direction, speed) 23 | ``` 24 | where: 25 | * __motor__ => 1 to 4 26 | * __direction__ => "f" or "r" (in quotes) 27 | * __speed__ => 0 to 100 28 | 29 | ## Stop a motor: 30 | ``` python 31 | board.motorOff(motor) 32 | ``` 33 | where: 34 | * __motor__ => 1 to 4 35 | 36 | ## Drive a Servo: 37 | ``` python 38 | board.servoWrite(servo, degrees) 39 | ``` 40 | where: 41 | * __servo__ => 1 to 8 42 | * __degrees__ => 0-180 43 | 44 | ``` python 45 | board.servoWriteRadians(servo, radians) 46 | ``` 47 | where: 48 | * __servo__ => 1 to 8 49 | * __radians__ => 0 to 3.1416 (Pi to four digits) 50 | 51 | ## Drive a Stepper: 52 | ``` python 53 | board.step(stepperMotor,direction,steps) 54 | ``` 55 | where: 56 | * __stepperMotor__ => 1 or 2 (stepper 1 is DC motors 1 and 2, stepper 2 is DC motors 3 and 4) 57 | * __direction__ => "f" or "r" (in quotes) 58 | * __steps__ => how many steps to make 59 | 60 | ### To step an angle: 61 | ``` python 62 | board.stepAngle(stepperMotor, direction, angle) 63 | ``` 64 | where 65 | * __stepperMotor__ => 1 or 2 (stepper 1 is DC motors 1 and 2, stepper 2 is DC motors 3 and 4) 66 | * __direction__ => "f" or "r" (in quotes) 67 | * __angle__ => how many degrees to move 68 | 69 | The stepper code assumes 200 steps per rev (1.8 degrees resolution) and only does full steps. 70 | There are defaulted parameters for stepper speeds (default 20mS pause between steps), hold position when finished stepping (off - saves energy) and how many steps per rev (200). Look at the function headers and function comments in [PicoRobotics.py](PicoRobotics.py) for more detail if you need to change them. 71 | 72 | # Troubleshooting 73 | 74 | If the code is run without the Pico Robotics board connected, or if the board is not powered up it is likely that it will throw an OS Error (usually OS Error 5). 75 | This is because it tries to communicate with an I2C device which is not responding. 76 | 77 | This code is designed to be used as a module. See: https://kitronik.co.uk/blogs/resources/modules-micro-python-and-the-raspberry-pi-pico for more information 78 | -------------------------------------------------------------------------------- /README_FR.md: -------------------------------------------------------------------------------- 1 | # Kitronik-Pico-Robotics-Board-MicroPython 2 | __Crédit:__ le fichier [README](README.md) est traduit par [MCHobby](https://shop.mchobby.be) - the [README](README.md) file is translated by [MCHobby](https://shop.mchobby.be) 3 | 4 | ![Pico Robotics Board de KitroniK](docs/_static/pico-robotics-board.jpg) 5 | 6 | Une classe et code d'exemple de la carte Robotics de Kitronik pour Raspberry Pi Pico (www.kitronik.co.uk/5329) . 7 | 8 | Ce README concerne la __version MicroPython__, pour CircuitPython [voir ici](https://github.com/KitronikLtd/Kitronik-Pico-Robotics-Board-CircuitPython) . 9 | 10 | Avant usage, copiez le fichier `PicoRobotics.py` sur votre Pico pour qu'il puisse être importé. 11 | 12 | ## Importer la bibliothèque et créer une instance 13 | ``` python 14 | import PicoRobotics 15 | board = PicoRobotics.KitronikPicoRobotics() 16 | ``` 17 | Cela initialise le circuit PCA avec les valeurs par défaut. 18 | 19 | ## Piloter un moteur 20 | ``` python 21 | board.motorOn(motor, direction, speed) 22 | ``` 23 | Où: 24 | * __motor__ => 1 à 4. Le moteur à commander. 25 | * __direction__ => f ou r. Sens de rotation, "f" pour sens horlogique/avant (_forward_) et "r" pour sens anti-horlogique/arrière (_reverse_). 26 | * __speed__ => 0 à 100. Fixe la vitesse de rotation (entre 0 et 100%). 27 | 28 | ## Arrêter un moteur 29 | ``` python 30 | board.motorOff(motor) 31 | ``` 32 | Où: 33 | * __motor__ => 1 à 4. Le moteur à arrêter. 34 | 35 | ## Piloter un Servo: 36 | ``` python 37 | board.servoWrite(servo, degrees) 38 | ``` 39 | Où: 40 | * __servo__ => 1 à 8. Numéro de sortie sur lequel est branché le servo-moteur. 41 | * __degrees__ => 0-180. Angle en degrés. 42 | 43 | ## Piloter un moteur pas-à-pas 44 | ``` python 45 | board.step(stepperMotor,direction,steps) 46 | ``` 47 | Où: 48 | * __stepperMotor__ => 1 ou 2. Le moteur pas-à-pas 1 est branché sur les sorties moteurs 1 et 2, moteur pas-à-pas 2 est branché sur les sorties moteurs 3 et 4 49 | * __direction__ => f ou r. Utiliser "f" pour sens horlogique/avant (_forward_) et "r" pour le sens anti-horlogique/arrière (_reverse_) 50 | * __steps__ => Le nombre de pas à avancer. Pour un moteur avec 200 pas/rotation, 50 pas équivaut a un angle de 90°. 51 | 52 | ### Rotation angulaire 53 | ``` python 54 | board.stepAngle(stepperMotor, direction, angle) 55 | ``` 56 | Où 57 | * __stepperMotor__ => 1 ou 2. Le moteur pas-à-pas 1 est branché sur les sorties moteurs 1 et 2, moteur pas-à-pas 2 est branché sur les sorties moteurs 3 et 4. 58 | * __direction__ => f ou r. Utiliser "f" pour sens horlogique/avant (_forward_) et "r" pour le sens anti-horlogique/arrière (_reverse_) 59 | * __angle__ => Angle de rotation à ajouter (en degrés). 60 | 61 | Le code part du principe qu'il s'agit d'un moteur ayant 200 pas par révolution (résolution de 1.8 degrés/pas) et qu'il fonctionne en pas complet (_full step_). 62 | Il y a des paramètres par défaut pour le moteur pas-à-pas: 63 | * 20mS de pause entre les pas, 64 | * Tenue de la position après chaque rotation (_off_ pour économiser de l'énergie), 65 | * 200 pas par révolution. 66 | 67 | Inspectez l'entête et commentaires des méthodes de [PicoRobotics.py](PicoRobotics.py) pour plus d'information (si vous désirez modifier ces valeurs). 68 | 69 | # Dépannage 70 | 71 | Si le code est exécuté sans avoir connecté la carte Robotique ou si la carte n'est pas alimentée alors la bibliothèques produira une erreur système (habituellement _OS Error 5_). 72 | Cette erreur est provoquée lors que la bibliothèque essaye de communiquer avec le périphérique I2C (mais qu'il ne répond pas). 73 | 74 | Le code est conçu pour être utilisé comme un module. Voir [modules micropython and the raspberry-pi pico](https://kitronik.co.uk/blogs/resources/modules-micro-python-and-the-raspberry-pi-pico) (_Blog KitroniK, Anglais_) pour plus d'information 75 | -------------------------------------------------------------------------------- /SingleMotorTest.py: -------------------------------------------------------------------------------- 1 | #SingleMotorTest.py 2 | # test code that ramps each motor individually form 0-100-0 then changes direction and does it again then steps onto next motor. 3 | import PicoRobotics 4 | import utime 5 | 6 | 7 | board = PicoRobotics.KitronikPicoRobotics() 8 | directions = ["f","r"] 9 | 10 | while True: 11 | 12 | for motor in range(4): 13 | for direction in directions: 14 | for speed in range(100): 15 | board.motorOn(motor+1, direction, speed) 16 | utime.sleep_ms(10) #ramp speed over 10x100ms => approx 1 second. 17 | for speed in range(100): 18 | board.motorOn(motor+1, direction, 100-speed) #ramp down 19 | utime.sleep_ms(10) #ramp speed over 10x100ms => approx 1 second. 20 | utime.sleep_ms(500)#pause between motors 21 | 22 | -------------------------------------------------------------------------------- /SingleServoTest.py: -------------------------------------------------------------------------------- 1 | #SingleServoTest.py 2 | # test code that ramps each servo individually from 0-180-0 3 | import PicoRobotics 4 | import utime 5 | 6 | 7 | board = PicoRobotics.KitronikPicoRobotics() 8 | while True: 9 | 10 | for servo in range(8): 11 | for degrees in range(180): 12 | board.servoWrite(servo+1, degrees) 13 | utime.sleep_ms(10) #ramp speed over 10x180ms => approx 2 seconds. 14 | for degrees in range(180): 15 | board.servoWrite(servo+1, 180-degrees) 16 | utime.sleep_ms(10) #ramp speed over 10x180ms => approx 2 seconds. 17 | board.servoWrite(servo+1, 90) 18 | utime.sleep_ms(50)#pause between servos 19 | -------------------------------------------------------------------------------- /StepperTest.py: -------------------------------------------------------------------------------- 1 | import PicoRobotics 2 | import utime 3 | 4 | board = PicoRobotics.KitronikPicoRobotics() 5 | directions = ["f","r"] 6 | 7 | while True: 8 | for direction in directions: 9 | for stepcount in range(200): 10 | board.step(1,direction,8) 11 | board.step(2,direction,8) 12 | utime.sleep_ms(500)#pause between motors 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/_static/pico-robotics-board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitronikLtd/Kitronik-Pico-Robotics-Board-MicroPython/66c7a6ef8ed40b888df83a1ce928e82ac7afdbf1/docs/_static/pico-robotics-board.jpg --------------------------------------------------------------------------------