diff --git a/images/thonny_code.png b/images/thonny_code.png new file mode 100644 index 0000000..e0a0579 Binary files /dev/null and b/images/thonny_code.png differ diff --git a/images/thonny_firmware.png b/images/thonny_firmware.png new file mode 100644 index 0000000..033c484 Binary files /dev/null and b/images/thonny_firmware.png differ diff --git a/index.html b/index.html index 1918c4b..357040b 100644 --- a/index.html +++ b/index.html @@ -41,26 +41,23 @@
-

Setting up our Circuitpython toolchain

+

Setting up our MicroPython toolchain

Step 1: Setting up the IDE

-

There are many IDEs that we can use to program CircuitPython robot, we can even just use a text - editor.

-

However we'll be using one called "Mu Editor". So let's begin by downloading it.

+

There are many IDEs that we can use to program MicroPython robot, we'll be using one called "Thonny". So let's begin by downloading it.

Download

-

You can also get it from the Mu website, https://codewith.mu/en/

+

You can also get it from the Thonny website, https://thonny.org/

@@ -68,21 +65,23 @@
-

Step 2: Install Circuitpython on board

+

Step 2: Install MicroPython firmware on board

    -
  1. Download the CircuitPython firmware UF2 file for the RP2040 Zero here.
  2. -
  3. Connect your RP2040 Zero to your computer using a USB cable.
  4. -
  5. Hold down the BOOT button, press and release the RST button.
  6. -
  7. A new USB drive appears in your file explorer called RPI-RP2.
  8. -
  9. Drag the downloaded CircuitPython firmware file into the RPI-RP2 drive.
  10. -
  11. The firmware will install, and after a moment, the drive should be called CIRCUITPY. -
  12. -
  13. Open the drive and examine the different files in there. The "code.py" file is our main - file, but we won't open it here.
  14. -
  15. Open the MU Editor, and we can start coding!
  16. +
  17. In Thonny, click on the Run->Configure Interpreter buttons at the top of the window.
  18. +
  19. Choose "MicroPython (Raspberry Pi Pico) from the first dropdown menu.
  20. +
  21. Click the "Install or update MicroPython" button down the bottom-right of the window.
  22. +
  23. You need to put your device in FLASH mode, hold down the BOOT button, press and release the RESET button.
  24. +
  25. You should now find a drive called "RPI-RP2". in the Target volume dropdown, shoose it.
  26. +
  27. Choose the variant "Raspberry Pi Pico - Pico / Pico H"
  28. +
  29. Press Install button to install the firmware.
  30. +
  31. Reset the device again with the RESET button.
  32. +
  33. Press the cancel button to close the firmware update panel, then press OK to officially begin coding.
+
+ Robot moving further +
Robot moving further @@ -94,15 +93,15 @@ @@ -196,27 +184,25 @@

-import board
-import pwmio
+from machine import Pin, PWM
 import time
 
-motorIN1 = pwmio.PWMOut(board.GP8, frequency=1000, duty_cycle=0)
-motorIN2 = pwmio.PWMOut(board.GP9, frequency=1000, duty_cycle=0) 
-
+motorIN1 = PWM(Pin(8))
+motorIN2 = PWM(Pin(9))
 
 # DRIVE FORWARD
-motorIN1.duty_cycle = 65535 # This is the maximum value
-motorIN2.duty_cycle = 0     # This is the minimum value
+motorIN1.duty_u16(65535) # This is the maximum value
+motorIN2.duty_u16(0)     # This is the minimum value
 time.sleep(1)
 
 # DRIVE BACKWARD
-motorIN1.duty_cycle = 0
-motorIN2.duty_cycle = 65535
+motorIN1.duty_u16(0)
+motorIN2.duty_u16(65535)
 time.sleep(1)
 
 # STOP
-motorIN1.duty_cycle = 0
-motorIN2.duty_cycle = 0 
+motorIN1.duty_u16(0) +motorIN2.duty_u16(0)
@@ -228,13 +214,11 @@ motorIN2.duty_cycle = 0

-import board
-import pwmio
-import time
+from machine import Pin, PWM
 
 # Initialize motor PWM pins
-motorIN1 = pwmio.PWMOut(board.GP8, frequency=1000, duty_cycle=0)
-motorIN2 = pwmio.PWMOut(board.GP9, frequency=1000, duty_cycle=0) 
+motorIN1 = PWM(Pin(8))
+motorIN2 = PWM(Pin(9))
 
 def motor(power):
     # Make sure power is never greater than 100 or less than -100
@@ -248,14 +232,14 @@ def motor(power):
 
     # Apply power to the correct motor pin
     if power > 0:
-        motorIN1.duty_cycle = duty
-        motorIN2.duty_cycle = 0   
+        motorIN1.duty_u16(duty)
+        motorIN2.duty_u16(0)
     elif power < 0:
-        motorIN1.duty_cycle = 0
-        motorIN2.duty_cycle = duty
+        motorIN1.duty_u16(0)
+        motorIN2.duty_u16(duty)
     else:
-        motorIN1.duty_cycle = 0
-        motorIN2.duty_cycle = 0
+        motorIN1.duty_u16(0)
+        motorIN2.duty_u16(0)
 
 # TESTS
 motor(100) # FULL FORWARD
@@ -283,27 +267,26 @@ for i in range(-100, 100):
                     

Now all we need to do from the main code is:


Import the module

-

import motors

+

from motor import Motor


Initialize a motor object

-

left_motor = motor.Motor(board.GP8, board.GP9)

+

left_motor = Motor(8, 9)


Set the power

left_motor.move(100)


You can also add a second, third, or 20th motor at any time just by initializing another - motor.Motor object.

-

right_motor = motor.Motor(board.GP10, board.GP11)

+ Motor object.

+

right_motor = Motor(10, 11)

 
 # code.py
-import board
 import time
 import motor
 
-left_motor = motor.Motor(board.GP8, board.GP9)
+left_motor = motor.Motor(9,8)  
 
 # TESTS
 left_motor.move(100)   # FULL FORWARD
@@ -321,15 +304,20 @@ for i in range(-100, 100):
 

-
+
 # motor.py
-import pwmio
+from machine import Pin, PWM
 
 class Motor:
     def __init__(self, in1, in2, frequency=1000):
         # Set up PWM outputs on the specified pins
-        self.in1 = pwmio.PWMOut(in1, frequency=frequency, duty_cycle=0)
-        self.in2 = pwmio.PWMOut(in2, frequency=frequency, duty_cycle=0)
+        self.in1 = PWM(Pin(in1))
+        self.in2 = PWM(Pin(in2))
+        self.in1.freq(frequency)
+        self.in2.freq(frequency)
+        # Initialize duty to 0
+        self.in1.duty_u16(0)
+        self.in2.duty_u16(0)
 
     def move(self, power):
         # Constrain power to -100 to 100
@@ -338,18 +326,18 @@ class Motor:
         elif power < -100:
             power = -100
 
-        # Scale to duty cycle
+        # Scale to duty cycle (0–65535 for RP2040)
         duty = abs(power) * 65535 // 100
 
         if power > 0:
-            self.in1.duty_cycle = duty
-            self.in2.duty_cycle = 0
+            self.in1.duty_u16(duty)
+            self.in2.duty_u16(0)
         elif power < 0:
-            self.in1.duty_cycle = 0
-            self.in2.duty_cycle = duty
+            self.in1.duty_u16(0)
+            self.in2.duty_u16(duty)
         else:
-            self.in1.duty_cycle = 0
-            self.in2.duty_cycle = 0
+            self.in1.duty_u16(0)
+            self.in2.duty_u16(0)
 
 
@@ -920,75 +908,68 @@ while True:

Step 2: Coding

-

We'll use a library to handle sending and listening for the pulses. Put this module in your - CIRCUITPY/lib folder.

+

We'll use a library to handle sending and listening for the pulses. Put this module on your device.


-

adafruit_hcsr04.py

-
-

Note the timeout=0.005, this is important as it tells the code how long to wait for - an ECHO. If we don't have that, our code could be blocked for quite a lot of time if the only - obstacles are a long way away.

- -
-

Even though all we really need is to get the distance with sonar.distance, when no - echo is received in time an error will occur that will stop your code from running.

-
-

With our try-except block, any errors will just run whatever is in the - except part. In this case, nothing. -

+

When the "distance()" function is called, it sends a short pulse on the trigger pin, then waits for a response on the echo pin. The time it takes for the echo to return is used to calculate the distance.

+

-import board
-import adafruit_hcsr04
+# sonar.py
+import machine
+import time
 
-# Initialize the sonar device
-sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.GP26, echo_pin=board.GP28, timeout=0.005)
+class Sonar:
+    def __init__(self, trigger_pin, echo_pin):
+        self.trigger = machine.Pin(trigger_pin, machine.Pin.OUT)
+        self.echo = machine.Pin(echo_pin, machine.Pin.IN)
 
-while True:
-    distance = 99
-    
-    # The try-except block catches errors that
-    # occur when no signal returns in time
-    try:
-        distance = sonar.distance
-        print(distance)
-    except RuntimeError as e:
-        pass
+    def distance(self):
+        # Send a 10µs pulse to trigger
+        self.trigger.off()
+        time.sleep_us(2)
+        self.trigger.on()
+        time.sleep_us(10)
+        self.trigger.off()
+
+        # Wait for echo start
+        while self.echo.value() == 0:
+            pass
+        start = time.ticks_us()
+
+        # Wait for echo end
+        while self.echo.value() == 1:
+            pass
+        end = time.ticks_us()
+
+        # Calculate duration
+        duration = time.ticks_diff(end, start)
+
+        # Convert to distance (speed of sound ~343 m/s)
+        distance = (duration / 2) * 0.0343
+        return int(distance)
 
 
-

Step 3: Clean it up a bit

-

To tidy up our main loop, we can move all that to a function so the main loop just needs - get_distance(). -

-
-

If your code is getting quite long, you might even take functions like this and put them in your - own module to keep your main code easy to read.

+

Step 3: Call it in the main.py

+

Now all we need to do is create the object and call the distance function in the main.py file.


-import board
+# main.py
 import time
-import adafruit_hcsr04
+import sonar
 
-# Initialize the sonar device
-sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.GP26, echo_pin=board.GP28, timeout=0.005)
+# Create sonar object with trigger on GP3 and echo on GP2
+sonar = sonar.Sonar(trigger_pin=26, echo_pin=28)
 
-def get_distance():
-    distance = 99
-    try:
-        distance = sonar.distance
-    except RuntimeError as e:
-        pass
-    return distance
-    
 while True:
-    print(get_distance())
-    time.sleep(0.1)
+    dist = sonar.distance()
+    print("Distance:", dist, "cm")
+    time.sleep(1)