BitBot Programming in Python

BitBot and BitBot XL Programming in Python

Programming in Python

For text-based programming there is micro-python, and I prefer to use this offline using the Mu editor.  It provides a very neat and easy way of interfacing to the micro:bit without all the fuss of dragging and dropping.

Note on examples: We want to show people how the various features can be used. We don’t want to do the coding for you – that is the learning experience you should be taking away from using it. In the following examples, we will give you the tools to use all the features of Bit:Bot but it is up to you to combine them together in your code to make it do something useful. We do give a complete example of line-following – but it is a very basic algorithm and will get confused at T-junctions  and crossings; and it doesn’t use the FireLeds.

Download Python examples at the bottom of this page.

Some great tutorials/examples by Mark Atkinson here

Motors

Each motor has two pins connected to it. If the first pin is High and the second is Low, then the motor will drive Forward. Conversely, if the first is Low and the Second is High then it will drive in Reverse.

For BitBot Classic: Left pins are P0, P8 and Right pins are P1, P12

For BitBot XL: Left pins are P16, P8 and Right pins are P14, P12

The simplest way to make the motors move Forward is to set the First pin to HIGH and the Second pin to LOW. eg for BitBot XL:

Move left motor Forwards:

pin16.write_digital(1)
pin8.write_digital(0)

Move left motor Reverse:

pin16.write_digital(0)
pin8.write_digital(1)

If we want to change the speed of a motor, so that it is not going at full speed all the time, we need to use PWM (Pulse Width Modulation). This is a means of changing the amount of power given to the motor by switching it on and off very fast. The percentage value of PWM determines the amount of each cycle that the output is ON. So a percentage of 100% is the same as being on all the time and thus the same as the examples above. A percentage of 50% would mean that the motor is only energised half the time, so it will go much slower. Note that the actual speed of the motor is not the same as the percentage of PWM – the motor won’t turn at all if the PWM value is too low and you will also get some stuttering at certain values. Nevertheless, being able to change the speed makes for a much better robot. For example, you can make a line follower that smoothly follows the line, rather than the normal shaking left and right.

To change the PWM value of a pin, we must use the analog_write commands. These can be set to a value between 0 (always off = 0%) to 1023 (always on = 100%), so 50% would be 511. Here are the commands to change the speed of the Right motor to approx 75% (value is 770) for the BitBot XL

Move right motor forwards at 75%

pin14.write_analog(770)
pin12.write_analog(0)

To move it in reverse, we simply apply the PWM value to the other pin instead and set the first pin to 0

Move right motor Reverse at 75%

pin14.write_analog(0)
pin12.write_analog(770)

 

FireLeds

The FireLeds smart RGB pixels are able to display any of 16 million colours by selecting a value of 0 to 255 for each of the Red, Green and Blue LEDs on each chip. The whole thing is controlled by a single pin on the BBC micro:bit (pin 13 for all models of Bit:Bot). It is simple to use the included neopixel libraries to control each FireLed individually.

The pixels are labelled on the Bit:Bot. From 0 to 5 on the left arm and from 6 to 11 on the right arm.

Set FireLed 2 to purple (red and blue)

from microbit import *
import neopixel
fireleds = neopixel.NeoPixel(pin13, 12)
fireleds[2] = (40, 0, 40)
fireleds.show( )

The first line is the standard import all from Microbit library.

The second line imports the neopixel library. We only need to do this once, at the very top of your Python program.

The third line creates a Python list with an element for each pixel. As shown, it specifies 12 pixels connected to pin 13.

The fourth line sets the pixel we have selected (number 2 in this case) to the colour which is set by three values in the brackets, each value can be from 0 to 255 and covers Red, Green and Blue. In our example we have set Red and Blue to 40.

The fifth line tells the neopixel library to copy all the data to the neopixels, from the Python list that we have been working with. It is only at this point that the LEDs change. In general, you would make all the changes you want and only at the end would you use a np.show( )

Line Follower Sensors

The pins used for line following are quite different for the BitBot Classic and the BitBot XL. BitBot Classic uses Pin11 (Left sensor) and Pin5 (Right sensor), which are the same pins as used for the Microbit’s two buttons. This can cause all sorts of issues.

The BitBot XL uses an I2C chip for these pins, with bit 0 of the resulting value being the Left sensor and bit 1 being the Right sensor.

The following two programs perform the same operation. They read the state of each line sensor and set the corresponding FireLed on the end of the stalks to either Red or Green.  The BitBot Classic first

from microbit import *
import neopixel
fireleds = neopixel.NeoPixel(pin13, 12)
while True:
    if(pin11.read_digital() == 0):
        fireleds[5]=(40,0,0)
    else:
        fireleds[5]=(0,40,0)
    if(pin5.read_digital() == 0):
        fireleds[11]=(40,0,0)
    else:
        fireleds[11]=(0,40,0)
    fireleds.show()
    sleep(200)

And now the equivalent program for the BitBot XL. You can see that we’ve defined a new function getLine( ) that reads the I2C device and returns the state of bit 0 (Left sensor) or bit 1 (Right sensor)

from microbit import *
import neopixel
I2CADDR = 0x1c # address of PCA9557
fireleds = neopixel.NeoPixel(pin13, 12)

def getLine(bit):
    mask = 1 << bit
    value = 0
    try:
        value = i2c.read(I2CADDR, 1)[0]
    except OSError:
        pass
    if (value & mask) > 0:
        return 1
    else:
        return 0

while True:
    if(getLine(0) == 0):
        fireleds[5]=(40,0,0)
    else:
        fireleds[5]=(0,40,0)
    if(getLine(1) == 0):
        fireleds[11]=(40,0,0)
    else:
        fireleds[11]=(0,40,0)
    fireleds.show()
    sleep(200)

The above programs are complete, with all the imports and defines required. This simple line following algorithm for the BitBot XL uses the getLine( ) function defined above as well as some simple motor functions which aren’t defined here

while True:
    lline = getLine(0)
    rline = getLine(1)
    if (lline == 1):
        spinLeft( )
    elif (rline == 1):
        spinRight( )
    else:
        forward(speed)

Light Sensors

These are analog sensors and will give a value of 0 to 1023, where 0 is fully dark and 1023 is maximum brightness. As there are only 3 analog pins available on the micro:bit (without affecting the LED displays) and we are using 2 of them to control the motors, we only have one left (Pin 2) to read the analog values from 2 line sensors. How can we do this? Well, the Bit:Bot has an analog switch that uses a digital output signal (pin 16) to determine whether the analog input we are reading is for the left sensor or the right sensor.

Therefore, to read the light sensors we need to set the selection output pin first, then read the analog data.

In Python, we can do it like this to read the values into 2 variables called leftVal and rightVal:

Pin16.write_digital(0) # select left sensor
leftVal = Pin2.read_analog()
Pin16.write_digital(1) # select right sensor
rightVal = Pin2.read_analog()

 

Buzzer

The buzzer is a very simply device that outputs a 2.4kHz sound when it is set to ON. It is NOT controlled by the tone signal that can be output by the micro:bit on Pin 0 so you don’t need to install any libraries to operate it.

It is connected to Pin14. Setting this to ON (1) will activate the buzzer and setting to OFF (0) will deactivate it.

In Python, a very simple and annoying beep, beep, beep sound can be made as follows:

while True:
pin14.write_digital(1)
sleep(400)
pin14.write_digital(0)
sleep(400)

Ultrasonic Distance Sensor

This optional HC-SR04 ultrasonic distance sensor addon can be used most easily in Microsoft PXT. In MicroPython we can use the utime module to measure time at microsecond level. Below we have a function called sonar() which returns the number of cm to the nearest object. Then we have a while loop that prints the distance every second:

from microbit import *
from utime import ticks_us, sleep_us

def sonar( ):
SONAR.write_digital(1) # Send 10us Ping pulse
sleep_us(10)
SONAR.write_digital(0)
SONAR.set_pull(SONAR, NO_PULL)
while SONAR.read_digital() == 0: # ensure Ping pulse has cleared
pass
start = ticks_us() # define starting time
while SONAR.read_digital() == 1: # wait for Echo pulse to return
pass
end = ticks_us() # define ending time
echo = end-start
distance = int(0.01715 * echo) # Calculate cm distance
return distance

while True:
display.scroll(sonar())
sleep(1000)

Programming BitBot XL

BitBot and BitBot XL Programming in Makecode

BitBot XL is the latest incarnation of the popular BitBot robot. It has the following features:

  • 2 micro-metal gear motors. Both fully controllable in software, for both speed (0 to 100%) and direction (forward or reverse)
  • Wheels with rubber tyres for maximum grip
  • Front ball caster
  • 12 FireLeds in 2 sets of 6 along the arms either side. Select any colour for any pixel, produce stunning lighting effects as your Bit:Bot XL moves around
  • 2 digital line following sensors with indicator LEDs. Code your own line-following robots and race them to see whose code produces the fastest lap time!
  • 2 analog light sensors (front left and front right) so your Bit:Bot XL can be programmed to follow a light source such as a torch, or you could code it to go and hide in the darkest place it can find
  • Buzzer, so you can make beeping sounds or music whenever you want
  • Powered from integrated 3xAA battery holder with on/off switch and blue indicator LED
  • Easily plug your BBC micro:bit in and out using the vertical edge connector
  • Expansion connections at the front for accessories. Currently available accessories: Ultrasonic, 5×5 FireLed matrix, BitFace and OLED
  • Two GVS connectors with 5V for servos (shared with light sensors)

Programming in Makecode

Python Programming can be found here

Tip: Click on any image to enlarge

Load Makecode for the Microbit from makecode.microbit.org and create a New Project. Then select the Advanced tab and click on Extensions. You should see BitBot on the extensions home page. If not, enter bitbot in the search box and select the extension when it shows up.

Setting the BitBot Model

The BitBot Makecode extension is fully compatible with all models of BitBot, including BitBot XL. The extension will automatically select the correct  version to use when it runs (as long as the BitBot is switched on when the program starts)

There are blocks available, in the “BitBot Model” category, to force a specific model (Classic or XL) as well as giving the ability to check which version the software is running on. This allows you to write programs that will run unchanged on all models of BitBot.

Controlling the Motors

In the motors category, you can select blocks to go forward or reverse, or spin on the spot. Both types of block can optionally be run for a fixed time, then the robot will stop.

In addition you can stop BitBot with the stop block. This can be a fast stop with an electronic brake, or the robot can more slowly come to rest.

You can also drive each motor individually. This allows you, for example, to turn the left wheel slowly and the right wheel fast so that the BitBot curves smoothly to the left.

Small DC Motors as used in the BitBot and other small robots are never fully matched. To take account of this you can bias the motors to move in the opposite direction to their natural curve. For example, if the robot curves to the left when it should be travelling straight, add some right bias. Vice versa, if it curves to the right, then add some left bias.

Controlling the FireLeds

There are 12 FireLeds on the BitBot. Each of which can be individually controlled with 16 million different colours (not that you can distinguish that many).

By default, the FireLeds are updated as soon as you make any change to them. If you are doing more complicated changes, you may want to change to manual updating so that you make all the changes required, then update the FireLeds once at the end. This is more efficient and gives a tidier appearance to animations, but isn’t necessary for the majority of uses.

You can set all of the FireLeds in one go to the same colour, using the “set all LEDs” block. If you click on the Red blob on the end of the block it will allow you to select one of 25 different colours (you can select your own colours as well, see the advanced blocks)

You can also set individual FireLeds (numbered 0 to 11 on the BitBot’s arms) to specific colours and clear all the FireLeds (switch them off). Setting the FireLeds to Rainbow, sets them all to different colours starting at Red and ending at Purple.

Blocks are also available to shift all the FireLeds along one place (with the FireLed 0 being turned off) and to rotate them all by one place (with FireLed 0 becoming the same colour that FireLed 11 was previously)

Advanced FireLed Control

In the advanced block we can set the brightness of all the FireLeds. The default setting is 40, but it can go as high as 255 for maximum brightness. Do not look directly at the FireLeds if they are set to very bright, especially if they are set to White, as it can hurt the eyes.

If you set the update mode to Manual (instead of Automatic) then you must run the “show FireLed changes” block after you make a change, otherwise nothing will change on the FireLeds themselves.

The final 2 blocks return a number representing a colour that you can select from the colour chooser or by setting specific Red, Green and Blue values. This colour number can be put into a variable for testing against other values, or you can use it directly to set the colour of FireLeds

Sensors – Buzzer, Light Sensors, Line Sensors, Talon, Servos

The Buzzer can be On (continuous beep) or Off (silent). On the BitBot XL, this can also be used to play music (badly) as it is connected to Pin 0. Use the standard Music blocks in Makecode to do this – it isn’t supported directly in the BitBot extension.

The optional ultrasonic sensor is used to measure the distance to the nearest sound reflecting object. This may be anything in the area as the focus of the sound beam is not very tight, so it may pick up other objects than the one you want. This block returns a number that can be the number of cm, number of inches, or a raw microseconds figure.

Similarly the light sensors return a number from 0 (totally dark) to 1023 (maximum brightness).

The line follower sensors are slightly different. They return a value of either 0 (no black line) or 1 (black line).

The Servos (BitBot XL only) and the Talon (optional on all models) operate in the same way – as the Talon is just a servo really.

For the Talon you can select the angle of the servo from 0 to 80 (closed to open). On the servos (BitBot XL only) you can select an angle from 0 (fully clockwise) to 180 (fully anti-clockwise)

If you want to release the pin from being a servo (as the servo pins on the BitBot XL are shared with the light sensors), then you can disable the servos.

 

 

Starting with ScratchGPIO on Pi2Go Mk2

Pi2Go Mark 2 with ScratchGPIO

Simon Walters (Cymplecy) has worked on ScratchGPIO for many years and continues to add new products to the supported list. Pi2Go Mk2 is now also supported – here’s a brief introduction on how to get started.

Step 1: Install ScratchGPIO

Visit the ScratchGPIO install page here.

From a command line, first run the wget to download the installer

wget https://git.io/vMS6T -O isgh8.sh

Then run the installer:

sudo bash isgh8.sh

Step 2: Run ScratchGPIO8Plus

Make sure you choose the correct program to run here. Do NOT run ScratchGPIO8, nor Scratch2GPIO…

Step 3: Create an Addon Variable

You need to create a variable and set it to “Pi2Go2” (without the quotes)

Select the Variables tab (top left) and press “Make a variable”

Name the variable “AddOn”

Move the block “set AddOn…” to the programming area and enter Pi2Go2 as the variable name.

While you’re at it, grab a green flag block from the Control tab and lock the 2 blocks together

Click on the green flag and the AddOn variable in the stage will show up as Pi2Go2 as in the image above.

Step 4: Check the Sensors are available

Now, when you look into the Sensing tab, next to the bottom is a block showing “slider sensor value”. If you click on the slider you can see all the other sensors available, including those for the Pi2Go Mk2: battery, frontleftlight, frontrightright, etc. You can now use all these sensors in your program.

Step 5: Drive the Motors

Now you can create two more variables for the motors. MotorL and MotorR for the Left and Right motors respectively.

Setting these to values between 0 and 100 will drive the motors. Note that speeds below 30 or so may not be able to power the motors – it depends what batteries and what voltage is available.

The program below drives the left motor for 1 second at speed 60, then stops

Step 6: Further Programming

Now visit the ScratchGPIO page dedicated to Pi2Go Mk2 for further tips and information.

Servo:Bit Affordable Multi-Servo Driver for Microbit

Servo:Bit Multi-Servo Driver

Purchase Servo:Bit here

Servo:Bit is a little board, exactly the same size as a Raspberry Pi Zero and the 4tronix Drive:Bit, which provides control for up to 16 servos. Access to the useful pins of the Microbit is provided as is a single Smart RGB LED

Power for the servos is provided by one of three options:

  • USB connector
  • 2-pin male header
  • 2-way screw connector

Providing power (5V – 6V) to one of these connectors also provides power for the Microbit.

Connections

NB: Fit the Microbit into the connector with the LEDs on the Microbit facing the switch and indicator LED.

Voltage

Most hobby servos operate within 5V to 6V range. Ensure that the voltage you provide does not exceed the voltage supported by your servo. Unless you have a specialist servo, you should be safe with the 5V USB input

Current Draw

Running 16 servos will consume a fair amount of current. Check the specification of your servos to see how much current they may take and ensure your power supply can provide sufficient. For instance, 16 servos taking 100mA each may require up to 1.6A this may not be available from your USB power supply.

You can connect both USB power and one of 2-pin male header or 2-way screw terminal to power at the same time as there are blocking diodes to prevent back-current. Do NOT connect power to both the 2-pin male header and the 2-way screw terminal as there is no blocking diode between these two. Use one or the other, but not both.

Each servo output is provided with 3 connections using the GVS (Ground, Volts, Signal) layout common to servo cables. Ensure you plug them in the correct way round or your servo may be damaged. Brown or Black is the normal colour for the Ground lead and this should be connected nearest to the pins near the edge of the board labelled ‘G’. The signal wire is likely to be White, Yellow or Orange and this should be on the pins labelled ‘S’

The Microbit can power the Smart RGB LED and the blue LED on the board, but it cannot power and is not connected to the servos. Your servos will not operate unless you connect power into the USB, 2-pin header or 2-way screw terminal.

Programming the ServoBit in Microsoft Makecode

There is a Makecode extension available to control the servos and Smart RGB LED on the ServoBit. Go into the Advanced tab in Makecode (or click on the gear icon in top right) then select Extensions. Enter ServoBit in the search box and select it.

The 4tronix ServoBit uses a PCA9685 to control 16 independent servos.
Helper commands are available to centre all servos, or set individual servos to any angle from -90 to +90 degrees

It is also possible to set the speed at which each servo moves to its new position, which gives a smoother operation

In addition, the 4tronix ServoBit contains a single Smart RGB status LED which can be set to any colour and brightness and a flashing function is also available.

Setting the servos

Set all 16 servos to the centre position

ServoBit.centreServos()

Set a specified servo to an angle, between -90 and +90 degrees

eg. Set Servo 5 to +30 degrees
ServoBit.setServo(5, 30)

Controlling servo movements and speeds

You can control the number of degrees per second that the servo moves. A typical servo would have a maximum speed of around 500 degrees per second.
Reasonable values for slower movements are between 30 and 200 degrees per second, although a range of 1 to 1000 is supported.
Setting the servo position whilst it is still moving, will cancel the movement command.
Creating a new movement command for a servo with an existing movement will cancel the first and then start the second.
You can also check if the servo has reached its target position, or wait until it has completed.

Move specified servo to an angle at a specified speed (speed can be from 1 degree per second to 1000 degrees per second)

eg. Move servo 5 to 30 degrees at 40 degrees per second
ServoBit.moveServo(5, 30, 40)

Check current position of specified servo

eg. Check current actual position of servo 5
let variable = ServoBit.getServoActual (5)

Check target positon for servo

eg. Check target positon for servo 5
let variable = ServoBit.getServoTarget (5)

Wait for specified servo to complete its movement

eg. Wait for servo 5 to complete its movement
ServoBit.waitServo (5)

Smart RGB LED helpers

The 4tronix ServoBit has a single smart RGB LED (aka neopixel) fitted. There are various blocks available to make it easy to control the LED

Clear the LED (turn it Off)

ServoBit.ledClear()

Set LED to selected colour. You can use other blocks to generate your own RGB colours

eg. Set LED to Red
ServoBit.setLedColor(ServoBit.vColours(vColors.Red))

Set brightness of LED from 0 to 255. Default value is 40

ServoBit.ledBrightness(40)

Start Flashing the LED with selected colour and defined speed

eg. Start Flashing the LED with Green at 100ms
ServoBit.startFlash(ServoBit.vColours(vColors.Green), 100)

Stop flashing the LED

ServoBit.stopFlash()

 

Programming M.A.R.S. Rover in Microsoft Makecode

Makecode for 4tronix M.A.R.S. Rover

Installing the Extension

In the Makecode editor, select “Advanced” and then “Extensions”. Alternatively click on the gear icon and select “Extensions” from there

Then enter in the search bar: https://github.com/4tronix/MARS-Rover

Click on the extension and it will be loaded into your Makecode editor. You will now have a rocket ship icon, Rover, with several sub-sections

Calibrating the Servos

Before we start using the Rover we should calibrate the servos so that they run directly.

Load this project into your Makecode editor: https://makecode.microbit.org/_Mpt6xpCRF0EK by selecting “Import”, then “Import URL”

Alternatively, download it from https://4tronix.co.uk/rover/microbit-CalibrateServos.hex

This program goes round all the wheel servos and allows you to use the A and B buttons on the Microbit to set each servo to straight ahead position.

It indicates using the LEDs which servo is being calibrated.

When you are happy with each servo, press the A+B buttons together to store the setting and move onto the next servo. After setting all servos, simply switch off and start coding.

 

 

Drive:Bit Affordable Motor Controller for Microbit

Drive:Bit Motor Controller

Purchase Drive:Bit here

Drive:Bit has been created to provide a really affordable motor and robotics controller board for the BBC micro:bit. Even though we reduced the price as much as we could, we kept some great features which will make it an excellent board to build DIY buggies and the like

Connections

NB: Fit the Microbit into the connector with the LEDs on the Microbit facing the switch and indicator LED.

Connect your batteries to the 2-pin screw terminal, or the 2-pin header pins, on the left. The battery voltage should be in the range 6V to 10V, so use 4 x AA alkaline cells, or a 9V PP3 battery or similar. This input voltage is what is used to drive the motors and generate the 3.3V for the Microbit, so make sure that your motors can cope with the voltage you provide and that the voltage is kept high enough when the motors take a lot of current.

Connect your motors to the 2-pin screw terminals (or 2-pin male headers). Motor 1 is on the left, labelled M1. Motor 2 is on the right, labelled M2. The current to the motors is limited by the circuitry so it won’t damage the DriveBit if you try and take too much current. However, if things aren’t working, switch off and check for short circuits. Better safe than sorry!

In the centre of the DriveBit is a group of pins, 4 x 3. These are GVS (Ground, Voltage, Signal) pins that allow you to connect 3.3V devices (inputs or outputs) directly to the Microbit pins 0, 1, 2 and 8. Small, micro, servos such as SG90 can be plugged in directly – although they are 5V devices they will generally work at 3.3V.

Other pins are available on the top of the board as pads. You will have to solder wires in there, or you could add a (male or female) header yourself.

Programming Drive:Bit with Makecode

There is a Makecode extension available which makes it trivial to control the motors or set the status FireLed to any colour with or without flashing. The 4 GVS pins are general purpose so use other Makecode libraries to drive what you connect to these pins.

In Makecode editor go to Advanced and Extensions, then search for DriveBit

Driving Motors:

Setting the Status LED

 

Using Drive:Bit with MicroPython

For micro Python, you can drive the motors and the onboard status LED very simply. The pins used are:
Motor 1: Pin 12 and Pin 13
Motor 2: Pin 14 and Pin 15
LED: Pin 16

To drive forward, Set Pin 12 and Pin 14 to the speed you want, from 0 to 1023. And set Pin 13 and Pin 15 to 0. Eg. to drive at speed 600

pin12.write_analog (600)
pin13.write_analog (0)
pin14.write_analog (600)
pin15.write_analog (0)

To drive backwards, set Pin 12 and Pin 14 to zero, and set Pin 13 and Pin 15 to the speed you want, from 0 to 1023. eg to reverse at speed 600

pin12.write_analog (0)
pin13.write_analog (600)
pin14.write_analog (0)
pin15.write_analog (600)

To stop the motors, set both pins of each motor to 0. This will coast to a stop

pin12.write_analog (0)
pin13.write_analog (0)
pin14.write_analog (0)
pin15.write_analog (0)

To brake the motors quickly, set both to 1023

pin12.write_analog (1023)
pin13.write_analog (1023)
pin14.write_analog (1023)
pin15.write_analog (1023)

To drive the LED, you will need to import and use the neopixel library. This example sets the LED to Red

import neopixel
np = neopixel.NeoPixel(pin16, 1)
np[0] = (255, 0, 0)
np.show()

  • Line 1 imports the neopixel library
  • Line 2 sets up the array of LEDs that the library will use. We only have 1 LED
  • Line 3 sets element 0 (our only LED) to Red=255, Green=0, Blue=0
  • Line 4 copies the array of LED data to the LED itself

 

M.A.R.S. Rover Assembly

Assembly of 4tronix M.A.R.S. Rover Kit

Click on any photo to enlarge

The 4tronix Mars Rover is loosely based on the Curiosity and Mars 2020 rovers from NASA. It uses the same rocker arm, bogey and differential arm mechanism.

Purchase M.A.R.S. Rover from here

Coding for the M.A.R.S. Rover here

Some stats on the 4tronix Mars Rover

  • 6 Motors. 80 rpm 6V, N20 micro gear motors
  • 4 Servos. MG90S metal gear analog micro servos
  • Total number of special PCBs: 30
  • Number of different PCB designs: 11
  • Length: 200mm
  • Width: 185mm
  • Height without Mast and Microbit: 95mm
  • Height with Mast: 170mm

Kit Contents

The kit is packed in 10 bags, which should be assembled in order as follows

  1. Side pack. PCBs and screws to assemble both side pieces of the main body
  2. Brains (Top) Pack. This PCB houses all the electronics and together with the side pieces (1) forms the structural body of the 4tronix Mars Rover
  3. Rocker Pack. These 2 rocker arms are pivoted on the screws fitted into each side piece. Each rocker arm carries a single servo for a front corner wheel assembly
  4. Bogey Pack. These two rear bogeys carry the centre and rear wheels for each side. The rear corner wheels are steered with a servo
  5. Servo Pack. This contains 4 metal gear micro servos together with screws to fix them into the Rockers and Bogeys
  6. Differential Arm Pack: The differential arm and couplers joins the two Rockers in such a way that it tries to keep the main body level (side to side) as one side or the other traverses uneven terrain. In earlier NASA Mars Rovers, this arm was replaced by a differential gear train, but the arm was found to be simpler and less prone to failures.
  7. Corner Wheels Pack. Each corner wheel is steered by its own servo. This pack contains the PCBs and screws needed to connect all four of the motor mounts to the servos
  8. Motors Pack. This includes the 6 motors, each ready-wired with a JST connector lead which plugs into the underneath of the main brains board. Plastic mounting brackets and associated screws are also included
  9. Wheels Pack: Six wheels. Just push them onto the motors. You must enusre that the D-shaped axle is aligned with the D-shaped hole in the wheel
  10. Mast Pack. Includes another servo, the mast base and a plug-in mast head with an ultrasonic sensor and some LEDs.

Assembly

You should allow 2 hours to build this if you are used to assembling kits of this nature. If it is your first assembly of something like this, then you may have to double the expected timeframe.

Step 0

Check you have all the bags described above. There is also a spares bag, a spare servo, a screwdriver and a wrench. The screwdriver has both a flat blade and a philips blade end. Pull out the metal part and insert it the other way round to change ends.

Step 1: Assemble the Sides

You should have two sides pieces (left and right), four aluminium brackets, eight 8mm M3 screws and two long 16mm M3 screws. Photo above shows 2 brackets fitted and two brackets ready to fit.

Screw the brackets into the side pieces from the inside as shown above. Make sure that the vertical screw holes in each brackets are next to the top surface of each side.

Then screw the long screw from the inside, through the PCB and through the fitted nut. .Make sure all screws are tight as once it is assembled it will be very hard to get at them again

Step 2: Fit the Brains/Top to the Sides

You should have the Brains PCB and eight M3, 6mm screws

The sides should be fitted as shown above with the rocker mounting screw nearest the front (the end with the servo hole in the top/brains PCB)

Step 3: Fit the Rocker Arms

You should have two rocker arms (left and right) with servo mounts fitted, two M3 nyloc nuts and 4 M3 washers

Place a washer onto the rocker pivot screw, then place the rocker arm, then a second washer and finally the M3 nyloc nut. Tighten up the nut as far as it will go, then back it off the tiniest bit until the arm moves freely. If you loosen the nut too much the arm will wobble, so get it as tight as possible without binding.

The servo carrier on each side is at the front of the rover, facing outwards as shown above.

Step 4: Fit the Bogeys

You have two bogeys (left and right) with servo and motor carriers attached, two M3, 10mm screws, 4 washers and two nyloc nuts.

Fit the screw from the inside, through the rocker arm, then a washer, then the bogey, then a second washer and finally the nyloc nut. As with the rocker arms, do the nyloc nut up tightly then back it off slightly so the bogey moves freely.

The bogeys also have the servo carriers facing outwards in each rear corner of the rover.

Step 5: Fit the Steering Servos

You have four servos and eight 6mm, M2.5 screws.

Mount each servo with the output shaft nearest the centre of the rover as shown above. Screw from underneath the servo mounting PCB into the holes on the side of each servo, as shown below. Keep hold of the servo arms and servo shaft screws, ready for Step 7.

Step 6: Fit the Differential Arm

You should have the differential arm PCB, a long screw, 2 washers and a nyloc nut and 2 push-rods with 4 screw on snap links.

Screw the long screw from underneath, through the main board and into the fitted nut. Do up tightly.

Place a washer over the long screw and onto the fitted nut, then the differential arm, then the second washer and finally the nyloc nut. As with the rocker arms and bogeys, do up the nyloc nut tightly then slacken it off slightly

Finally adjust the pushrods and snap links by screwing in and out until the distance between the clip points is about 53mm. Then clip firmly into the top of each rocker arm and the ends of the differential arm.

When you have fitted the wheels (later) you can adjust the length of the pushrods to ensure that the body of the Rover sits level.

Step 7: Fit the Corner Wheel Mountings

You should have four top pieces with 4mm nuts attached and eight 6mm black screws.

Also included is the Zero Servo – a little magic PCB that centres your servos without hassle.

You will also need the four cross-shaped servo arms and servo shaft screws from the servo packs. Do not use the longer screws in the servo packs. If the soldered nuts still have the orange kaptan tape on, you will need to peel it off.

Fit the cross-shaped  servo arms to the top pieces with the nuts attached. The arms fit on the opposite side to the nuts and with the hole that accepts the servo shaft facing outwards. Note that the arms are not symmetrical – so the holes will only line  up properly one way round – the longer end goes towards the straight edge of the mounting PCB. You can use a pair of side-cutters (or nail clips?) to chop off the protruding ends of the servo arms.

IMPORTANT: it is important that the motors are mounted so they are pointing outwards at as close to 90 degrees as possible when the servos are set to 0 degrees. Use a ServoZero (included) connected to power by a USB cable and plug each servo in turn into it to set to the zero position. We can fine tune the position later in software, but it is important to get it close mechanically.

Use the little servo shaft screws from the servo packs to fit each motor mounting securely.

Step 8: Fit the Motors

You should have 6 motors with JST leads attached, 6 mounting brackets, 20 M2 screws and 12 M2 nuts. You will also have the 4 lower motor mount PCBs

Mount the centre motors by fitting the nuts into the plastic brackets, then screwing through from underneath into the nuts. See photo above.

The corner motors are mounted by first fitting them to the lower motor PCBs from Pack 7 using 2 screws and 2 nuts for each.

Then screw the resulting assembly onto the 2 fitted 4mm nuts on the PCBs you assembled in step 7.

With all six motors fitted, attach the JST leads to the connectors underneath the main board. It doesn’t matter which connector you use as long as the left side connects to left motors and the right side connects to right motors.

You can use this opportunity to connect all the servo leads as well. These need to be connected to the servo connector nearest to them. So use 9, 11, 13 and 15.

You can wrap the spare lead around the servos to tidy the cables up a little. An alternative method that I use is to put the cables down the side of the battery holders underneath and hold them in with a peice of foam cut from the packing in the box.

Step 9: Fit the Wheels

The six wheels simply push on, but be careful to line up the D-shaped hole in the wheels with the D-shaped axle. Only push the wheel when holding the motor, not when hold the body.

It looks better (I think) if the wheels are on “backwards” with the spokes showing

Step 10: Fit the Mast

The mast houses an ultrasonic distance sensor and 2 White LEDs (not controllable). It is fitted onto a steerable servo and can be removed simply by unplugging it.

This pack contains the servo, the mast base PCB, the mast head PCB, two M2.5 screws to secure the servo and 4 short self-tapping screws to secure the servo horn to the mast base

Fit the servo by screwing the M2.5 screws through the top PCB into the holes on the side of the servo. Connect the servo lead to position SV0 underneath.

Fit the cross-shaped servo horn from the servo bag to the bottom of the mast base PCB using the 4 small self tapping screws.

Fit it so that the connector is pointing forwards when the servo is at its centre position. Use the small shaft mounting screw in the servo bag to fix it firmly to the top of the servo shaft.

Then plug in the mast head and plug the 3-wire lead from the mast base to position P13 on the top of the main board. Ensure the Brown wire is next to G on both boards.

Complete!

Now for some coding using Microsoft Makecode:

Makecode extension is from https://github.com/4tronix/MARS-Rover

In Makecode, click on Advanced, then Extensions. Enter the URL above into the search bar.

 

Pi2Go Mk2 Programming

Programming the Pi2Go Mk 2

Preparing your Raspberry Pi

Before you can install the Pi2Go Mk 2 software, you will need to ensure that your Raspberry Pi is up and running and connected to the internet. You will need to be able to see the desktop or console (either using direct connections, or SSH or VNS over the network).

Setting up a Raspberry Pi is not covered here. It is best to get the information from the source at Raspberry Pi

You will also need to enable SPI and I2C. Do this from raspi-config

sudo raspi-config

Select interfaces and enable both SPI and I2C. Then reboot.

Using with ScratchGPIO

Simplesi (Simon Walters) has generously included Pi2Go Mk2 in the list of directly supported devices in ScratchGPIO.

Visit this blog post for installation and coding tips

Installing the Pi2Go Mk2 Python Software

NB. Note that this software is still in Python 2. Python 3 will not work due to Print statements. Hopefully this will be resolved shortly

First you will need to prepare your Pi for the Smart RGB LEDs (fully compatible with neopixels). The best way we’ve found to do this is run Pimoroni’s curl script.
With your Pi connected to the internet, run (you don’t need to install the resources and examples):

curl -sS https://get.pimoroni.com/unicornhat | bash

Download the Python library module and example software for Pi2Go Mk2 with

wget https://4tronix.co.uk/pi2go2.sh -O pi2go2.sh

bash pi2go2.sh

This installs the following, which should be run in Python 2 for now (unless otherwise stated)

  • ipd.desktop in home/pi/.config/autostart which will start the IP Display on boot. This will silently fail if the optional IP Display is not plugged into either port.
  • Creates a folder home/pi/pi2go2 for all the example files and library module pi2go2.py (the main library module)
  • motorTest.py to demonstrate driving the motors. Must be run in a terminal, not from an IDE like Idle or Thonny. Use LXTerminal for this
  • stepTest.py to demonstrate running motors controlled by the wheel sensors. Must be run in a terminal, not from an IDE like Idle or Thonny. Use LXTerminal for this
  • adc.py shows the light sensor values and raw battery voltage
  • ledTest.py flashes all LEDs through Red, Green, Blue and White. This must be run using sudo. ie: sudo python3 ledTest.py
  • rainbow.py sets the LEDs to rainbow colours (static, but flashes every 10 seconds). This must be run using sudo in Python 3. ie: sudo python3 rainbow.py
  • lineTest.py shows the value of the line sensors
  • lineFollower.py is very basic line follower program
  • sonarTest.py shows the distance in cm for an obstacle using the optional ultrasonic breakout in either or both expansion slots
  • ipd03.py this is the program run on boot up to display the IP address of the Pi to make it easy to connect to using VNC or SSH

Using the Pi2go2.py Library Module

To use this module, you must first import it into your program using

import pi2go2

Then, before using any other functions you should call the init ( ) function to initialise all the variables used by the library. The init ( ) function has an optional parameter which is the default brightness of the LEDs. If omitted, this defaults to 40. So the following call will initialise the library and set the default brightness to 100:

pi2go2.init (100)

Hot Tip:
As a special case, if you set the brightness to zero, then the LEDs are not initialised. As this would require use of the sudo command, it can be beneficial to call init (0) so that your program can be run without using sudo.

When your program has finished, it is good practice to close down everything tidily by calling:

pi2go2.cleanup ( )

Motor Functions

  • stop ( ): Stops both motors – coast slowly to a halt
  • brake ( ): Stops both motors – brakes quickly
  • forward (speed): Sets both motors to move forward at speed. 0 <= speed <= 100
  • reverse (speed): Sets both motors to reverse at speed. 0 <= speed <= 100
  • spinLeft (speed): Sets motors to turn opposite directions at speed. 0 <= speed <= 100
  • spinRight (speed): Sets motors to turn opposite directions at speed. 0 <= speed <= 100
  • turnForward (leftSpeed, rightSpeed): Moves forwards in an arc by setting different speeds. 0 <= leftSpeed,rightSpeed <= 100
  • turnreverse (leftSpeed, rightSpeed): Moves backwards in an arc by setting different speeds. 0 <= leftSpeed,rightSpeed <= 100

 

Wheel Sensor Functions

  • stepForward (speed, steps): Moves forwards specified number of steps, then stops
  • stepReverse (speed, steps): Reverses specified number of steps, then stops
  • stepSpinL (speed, steps): Spins left specified number of steps, then stops
  • stepSpinR (speed, steps): Spins right specified number of steps, then stops

 

RGB LED Functions

  • setColor (color): Sets all LEDs to color – requires show()
  • setPixel (ID, color): Sets pixel ID to color – requires show()
  • show ( ): Updates the LEDs with state of LED array
  • clear ( ): Clears all LEDs to off – requires show()
  • rainbow ( ): Sets the LEDs to rainbow colors – requires show()
  • fromRGB (red, green, blue): Creates a color value from R, G and B values
  • toRGB (color): Converts a color value to separate R, G and B
  • wheel (pos): Generates rainbow colors across 0-255 positions

IR Sensor Functions

  • irLeft ( ): Returns state of Left IR Obstacle sensor
  • irRight ( ): Returns state of Right IR Obstacle sensor
  • irAll ( ): Returns true if either of the Obstacle sensors are triggered
  • irLeftLine ( ): Returns state of Left IR Line sensor
  • irRightLine ( ): Returns state of Right IR Line sensor

UltraSonic Function

  • getDistance (sonar = 0). Returns the distance in cm to the nearest reflecting object. 0 == no object. Sonar 0 is the front connector, Sonar=1 is the side connector. If you don’t include the parameter it defaults to 0 (front)

    Analog and Light Sensor Functions

  • getLight (Sensor). Returns the value 0..1023 for the selected sensor, 0 <= Sensor <= 3
  • getLightFL ( ). Returns the value 0..1023 for Front-Left light sensor
  • getLightFR ( ). Returns the value 0..1023 for Front-Right light sensor
  • getLightBL ( ). Returns the value 0..1023 for Back-Left light sensor
  • getLightBR ( ). Returns the value 0..1023 for Back-Right light sensor
  • getBattery ( ). Returns the voltage of the battery pack (>7.2V is good, less is bad)

    Switch Function

  • getSwitch ( ). Returns the value of the tact switch: True == pressed

Pi2Go Mk 2 Home Page

Links

Overview

The Pi2Go Mk2 is the evolution of the very popular original Pi2Go, first shipped in April 2015. The major changes are:

  • Improved assembly method, particularly the motor mounts
  • No wires for attaching the battery packs
  • Better quality wheels with high grip tyres
  • Wheel sensors built into both wheels
  • Programmatic access to the raw battery voltage
  • Improved analog light sensors – one in each corner
  • 10 individually addressable Smart RGB LEDs
  • 2 edge connectors compatible with Pimoroni’s Breakout Garden with full access to I2C signals and individual GPIO signals
  • Improved motor controller allowing higher speeds and optional braking on stop
  • Now with 4WD option

 

Specification

  • Requires 6 x AA rechargeable battery cells (not included)
  • Supports all versions of 40-pin Raspberry Pi
    (NB. the Raspberry Pi 4 consumes a lot of power and it is recommended to use one of the optional 7 x AA, or 2 x 18650 battery boards)
  • Motor controller: DRV8833
  • Analog input (light sensors and battery) MCP3008
  • Switching 5V power supply using TPS5430
  • 10 x SK6812-3535 Smart RGB LEDs (compatible with neopixels) – on battery board
  • On/Off switch with Blue indicator LED – on battery board
  • 2 x TCRT5000 infra-red obstacle sensors (front corners)
  • 4 x SFH3710 light sensors (all 4 corners)
  • 2 x TCRT5000 infra-red line follower sensors
  • 6mm tact switch for programmatic use
  • 4 x servo connections – direct from GPIO pins, with 5V and Gnd signals
  • 2 x optical wheel sensors with 20 slot encoder wheels (ie. 20 pulses per revolution)
  • 2 slots for breakout boards, including ultrasonic distance sensor and IP Display. These slots are compatible with Pimoroni’s Breakout Garden range.
  • Overall size with wheels attached: 148 x 118 x 98mm (length x width x height)
  • Weight (excluding Raspberry Pi & batteries): 282g

 

GPIO Connections

(Broadcom numbering)

  • Left Motor: 26, 19
  • Right Motor: 21, 16
  • Smart RGB LEDs: 18
  • Left Obstacle Sensor: 22
  • Right Obstacle Sensor: 17
  • Left Line Sensor: 23
  • Right Line Sensor: 27
  • Front ultrasonic (or general I/O): 20
  • Side ultrasonic (or general I/O): 4
  • Tact switch: 15
  • Left wheel sensor: 5
  • Right wheel sensor: 6
  • Servos: 12, 13, 24, 25

 

MiniBit

MiniBit Entry-Level Robot for Microbit

Purchase here

Overview

MiniBit is a ready-assembled simple and inexpensive robot for the BBC micro:bit.

It has the following features:

  • Ready-assembled. Just push on the wheels
  • Edge connector to easily insert the Microbit
  • Micro metal gear motors with fully-enclosed gearbox (no grit or fluff can enter)
  • Wire-free battery holder for 3 x AA batteries
  • 4 x Smart RGB LEDs (neopixel compatible)
  • Integrated Pen holder for 10mm diameter pens (eg. Sharpie felt tips)
  • Robust On/Off switch with Blue indicator LED
  • Wide chunky wheels with lots of grip
  • Metal ball front caster
  • Connector for optional ultrasonic sensor or I2C breakouts (fully compatible with Pimoroni’s Breakout Garden range)
  • The Microbit pins 0, 1, 2, Gnd and 3V are available for use with croc clips etc.
  • Lots of mounting holes to create your own “body” for the robot or additional sensors etc.
  • Makecode extension and micropython examples available

Batteries

Please use Alkaline batteries. Rechargeable batteries do not provide sufficient voltage once they have started to deplete. This primarily affects the ultrasonic sensor, so you may be okay to use with the other functions even when the batteries get low

Coding Your MiniBit

Microsoft MakeCode

Click any image to enlarge.

To load the extension, select Advanced, then Extensions. Then enter “Minibit” into the search box and press Enter. If that doesn’t find it (there are sometimes earch glitches) you can enter the full URL into the search box: “https://github.com/4tronix/MiniBit”

NB. This post is being updated to relate to the new functions added (Feb 2020). Images may not match the text.

Once loaded, you will have a MiniBit menu item with 4 sub-folders: Motors, FireLeds, Sensors, Addons

Motor Blocks

The “New style block” section contains command for basic movements eg. “Go Forwards/Reverse at speed 60” or “Rotate Left/Right at speed 40 for 700 ms”. All the commands in this section use speeds from 0 to 100 inclusive.

Both the “Go” and the “Rotate” blocks have a paired block that will do the command for a selected amount of time and then stop

There are two ways of stopping. Coasting to a stop or braking. If you set the speed to 0 or use the “stop with no brake” command, then it will stop gently over the coourse of a second or so depending on initial speed). If you use the “stop with brake” block (or the go/rotate for a time block) then it will stop almost immediately.

You can also drive each motor individually using the “Move Left/Right/Both motors…” block. For instance if you set the left motor to drive at 600 and the right motor to drive at 1000, then it will perform an arc towards the left

We have introduced a new command to bias the driving in one direction or the other. This is to counteract any mismatch between the motors. So if your robot drifts over the left when you want it to go straight, then add a bias to the Right. At a speed of 60, a bias of 10% is roughly equal to 10 cms or so.

FireLed Blocks

You can use these blocks to set and clear one or all the FireLeds.

Note that the MiniBit defaults to automatically updating the FireLeds whenever any change is made, but you can change this behaviour by setting the update mode to manual. Then you would have to run the “Show LED changes” block after making any changes to the LED settings.

The LEDs on the MiniBit are labelled from 0 to 3. Use these numbers in the Makecode blocks to change the colour. eg setting LED 1 to Purple could be done like this:

The default brightness level is 40. This is plenty bright enough for most uses, saves damaging eyes, and reduces battery consumption. If required you can change the brightness from 0 up to 255

In the Advanced section of FireLeds :

Set update mode is used to switch between automatic LED updates or manual LED updates. The default is for automatic updates: every change to the LEDs results in all the LEDs being written to with the updated values. This is easy to understand, but it does mean that when making a lot of changes it can slow things down considerably. If doing that, it is best to use Manual update mode, make all the changes required, then use the show LED changes block to make all the updates in one go.

Rotate LEDs block will move the colour in LED 0 to LED 1, LED1 to LED2, LED2 to LED3 and LED3 to LED0. If done repeatedly, with a delay between each one, it will show the LED colours rotating around all the 4 LEDs.

Shift LEDs block will move LED0 to LED1, LED1 to LED2 and LED2 to LED3. It will blank LED0. So all the colours will disappear one at a time from 0 to 3

You can also create your own colours and replace the fixed list of colours in any command using the convert from red, green, blue block. For example, to set LED0 to a blue-green colour:

 

Sensor Blocks

Ultrasonic distance sensor: You can get the values to the nearest object in cm, inches or microseconds. This block returns a number that you can put into a variable or use it directly in a calculation or test

Line sensors: This optional accessory has 3 sensors: left, centre and right. These are connected directly to Pin 0, 1 and 2 of the Microbit. There are two ways of using the sensors: a) read the current value and check it’s state before deciding what to do, or b) use a block that only gets run when the requested event occurs. eg: when the left sensor finds a (black) line

More Blocks

These are the advanced usage blocks. Most students will not need to use them.

  • Set update mode is used to switch between automatic LED updates or manual LED updates. The default is for automatic updates: every change to the LEDs results in all the LEDs being written to with the updated values. This is easy to understand, but it does mean that when making a lot of changes it can slow things down considerably. If doing that, it is best to use Manual update mode, make all the changes required, then use the show LED changes block to make all the updates in one go.
  • Rotate LEDs block will move the colour in LED 0 to LED 1, LED1 to LED2, LED2 to LED3 and LED3 to LED0. If done repeatedly, with a delay between each one, it will show the lED colours rotating around all the 4 LEDs.
  • Shift LEDs block will move LED0 to LED1, LED1 to LED2 and LED2 to LED3. It will blank LED0. So all the colours will disappear one at a time from 0 to 3
  • You can also create your own colours and replace the fixed list of colours in any command using the convert from red, green, blue block. For example, to set LED0 to a blue-green colour:

 

Programming in microPython

Driving Motors

The motors use 2 pins each to determine the speed and direction. In microPython we use write_analog ( ) to set the first pin to a value between 0 and 1023 and the second pin to 0 in order to go forward. To reverse, we swap the pins so that the first pin is set to 0 and the second pin is set to the value.

On the MiniBit the left motor uses pins 12 and 8, and the right motor uses pins 16 and 14.

So to move the left motor forwards at speed 600:

pin12.write_analog(600)
pin8.write_digital(0)

And to move the right motor in reverse at speed 450:

pin16.write_digital(0)
pin14.write_analog(450)

To stop with no brake, use write_digital ( ) to set both pins to 0. To stop with brake, set both pins to 1.
eg. stop left motor with coasting and right motor with brake:

pin12.write_digital(0)
pin8.write_digital(0)

pin16.write_digital(1)
pin14.write_digital(1)

So a complete, but fairly useless, program to drive the motors for 2 seconds and then stop quickly, would look like this:

from microbit import *
pin12.write_analog(600)
pin8.write_digital(0)
pin16.write_analog(600)
pin14.write_digital(0)
sleep(2000)
pin12.write_analog(0) # temporary fix for python bug
pin12.write_digital(1)

pin8.write_digital(1)
pin16.write_analog(0) # temporary fix for python bug
pin16.write_digital(1)

pin14.write_digital(1)

Note the 2 lines that write_analog(0) before swapping a pin from analog to digital. These are required until a fix is obtained for the python PWM driver continually updating the pin type to analog

Lighting the LEDs

This uses the standard neopixel code, with the LEDs connected to Pin 13.

At the top of your program add import neopixel then:

leds = neopixel.NeoPixel(13, 4)

leds is then an array of all 4 LEDs. leds[0] refers to the LED 0 and leds[3] refers to LED3. Each element of the array is a set of 3 numbers representing the Red, Green and Blue values (each 0..255) for that LED. So to set LED2 to Blue:

leds[2] = (0, 0, 255)

All this does is update the array. To show the new value of the array, we need to call the show ( ) function as follows:

leds.show ( )

 

Reading the Ultrasonic Distance Sensor

The ultrasonic sensor breakout is on pin15.

The concept is simple: send an ultrasonic pulse out, then time how long it takes to return. Using the speed of sound and some maths, we can then work out the distance. The following complete program has 2 parts to it: a function sonar ( ) which returns the distance to the object, and the main code in a loop which continually prints the distance. We also need to import the utime library:

from microbit import *
from utime import ticks_us, sleep_us

def sonar():
    pin15.write_digital(1) # Send 10us Ping pulse
    sleep_us(10)
    pin15.write_digital(0)
    pin15.set_pull(pin15, NO_PULL)
while pin15.read_digital() == 0: # ensure Ping pulse has cleared

        pass
    start = ticks_us() # define starting time
    while pin15.read_digital() == 1: # wait for Echo pulse to return
        pass
    end = ticks_us() # define ending time
    echo = end-start
    distance = int(0.01715 * echo) # Calculate cm distance
    return distance

while True:
    display.scroll(sonar())
    sleep(1000)