Motors

Now let's start with the motors that provide the propulsion for the Joy-Car. You can use the motors to move the Joy-Car both forwards and backwards. You can also adjust the speed individually, steer the vehicle in different directions and stop it if necessary. The motors therefore give you full control over the movements of your Joy-Car, allowing you to perform both precise maneuvers and dynamic driving.

You can find more information about the motors here.

The following code example shows the possible movements of the Joy-Car in detail. The Joy-Car can not only move in the basic directions forwards, backwards, to the right and to the left, but can also drive in a defined radius. This enables the Joy-Car to perform more complex maneuvers by making smooth turns and twists. The movement is controlled via specific commands that define the desired direction and, if necessary, the radius of the curve. This allows the Joy-Car to navigate flexibly and precisely through different environments.

Driving

Drive forwards or backwards. You can also select the speed as a percentage between 0 (no drive) and 100 (maximum drive).

Braking

Brake the Joy-Car to a standstill. You can also choose between hard emergency braking or gentle braking, during which the Joy-Car slowly coasts to a stop.

Curves

Drive a left or right turn. You can also set the speed as a percentage here. You can also specify the radius level of the curve from 0 - 5 (0 = tight curve, 5 = wide curve).

PWM signal

The motors can also be controlled directly via PWM signals. For this purpose, a PWM value between 0 and 255 can be sent to each channel.

Code example

JoyCar.initJoyCar(RevisionMainboard.OnepThree)
basic.forever(function () {
    JoyCar.drive(FRLRDirection.Forward, 100)
    basic.pause(2000)
    JoyCar.drive(FRLRDirection.Reverse, 100)
    basic.pause(2000)
    JoyCar.turn(
    FRDirection.Forward,
    LRDirection.Left,
    100,
    0
    )
    basic.pause(2000)
    JoyCar.turn(
    FRDirection.Forward,
    LRDirection.Right,
    100,
    0
    )
    basic.pause(2000)
    JoyCar.stop(StopIntensity.Intense)
    basic.pause(2000)
    JoyCar.turn(
    FRDirection.Forward,
    LRDirection.Left,
    50,
    4
    )
    basic.pause(1000)
    JoyCar.turn(
    FRDirection.Reverse,
    LRDirection.Right,
    50,
    2
    )
    basic.pause(1000)
})
JavaScript

Preparation for motors

First, we activate the motor control by sending the corresponding commands via the I2C interface.

This enables communication between the microcontroller and the motors. In order to control the motors precisely and efficiently, we use the variables biasL and biasR. These variables are used to adjust the rotational speeds of the left and right motors as a percentage. This is particularly important to compensate for deviations that can occur due to wear, manufacturing tolerances or other influences, and ensures that the Joy-Car drives in a straight line or can perform precise maneuvers.

# Initialize PWM controller
i2c.write(0x70, b'\x00\x01')
i2c.write(0x70, b'\xE8\xAA')

# the delay of a motor deceleration can be used to compensate for different motor speeds
biasR = 0  # Deceleration of the right motor in percent
biasL = 0  # Deceleration of the left motor in percent
Python

Motor control

The drive method enables the two motors of the Joy-Car to be controlled. The PWM signals PWM0 and PWM1 control the left motor, while PWM2 and PWM3 are responsible for the right motor. Within the method, the input values are first scaled in order to adapt the motors to each other if there are differences in the rotational speeds. This scaling takes into account the previously defined correction factors such as biasL and biasR.

At the end of the method, the calculated motor speed is sent via the I2C interface to the motor controller, which uses the address 0x70. This ensures that the control commands are implemented precisely and the motors operate at the desired speed.

# Control motors with the PWM controller
# PWM0 and PWM1 for the left motor and PWM2 and PWM3 for the right motor
def drive(PWM0, PWM1, PWM2, PWM3):
    # The scaling function is used to scale the bias variables 
    # for the calculation of the motor speed
    def scale(num, in_min, in_max, out_min, out_max):
        return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

    # Scaling of the delay value to the value in percent
    PWM0 = int(PWM0 * (scale(biasR, 0, 100, 100, 0) / 100))
    PWM1 = int(PWM1 * (scale(biasR, 0, 100, 100, 0) / 100))
    PWM2 = int(PWM2 * (scale(biasL, 0, 100, 100, 0) / 100))
    PWM3 = int(PWM3 * (scale(biasL, 0, 100, 100, 0) / 100))

    # Transmit value for PWM channel (0-255) to PWM controller
    # 0x70 is the I2C address of the controller
    # the byte with the PWM value is added to the byte for the channel
    i2c.write(0x70, b'\x02' + bytes([PWM0]))
    i2c.write(0x70, b'\x03' + bytes([PWM1]))
    i2c.write(0x70, b'\x04' + bytes([PWM2]))
    i2c.write(0x70, b'\x05' + bytes([PWM3]))
Python

Driving curves

 

The turn method allows the joy car to take precise turns. Four parameters are used for this:

  • orientation: Specifies the direction of travel, e.g. forwards or backwards
  • direction: Specifies the direction of the curve, e.g. left or right
  • speed: Determines the speed of the vehicle on a scale from 0 to 255
  • radius: Specifies the radius of the curve, with smaller values meaning tighter curves.

 

The method first checks whether the specified radius is greater than zero. The speed of the inner wheel (innerWheelSpeed) is then calculated in order to adjust the curve according to the radius. This is achieved by scaling the speed, whereby the outer wheel travels at full speed and the inner wheel is slowed down accordingly.

 

Finally, the drive method is called with the calculated speed values for the two motors. This ensures that the Joy-Car travels the desired curve in the specified direction and speed.

# Method for turning with orientation, direction, speed and radius
def turn(orientation, direction, speed, radius):
    # radius: 0-5
    if radius > 0:
        # Calculation of the inner wheel speed
        innerWheelSpeed = (speed * 0.7) * (radius / 5)
    else:
        return

    # adjust the motors accordingly
    if orientation == "forward":
        if direction == "left":
            drive(0, speed, 0, innerWheelSpeed)
        elif direction == "right":
            drive(0, innerWheelSpeed, 0, speed)
    elif orientation == "backwards":
        if direction == "left":
            drive(speed, 0, innerWheelSpeed, 0)
        elif direction == "right":
            drive(innerWheelSpeed, 0, speed, 0)
Python

Code example

# Import necessary libraries
from microbit import *

# Define your Joy-Car mainboard revision
joycar_rev = 1.3

# Initialization of the I2C interface for the Joy-Car mainboard
i2c.init(freq=400000, sda=pin20, scl=pin19)

# Initialize PWM controller
i2c.write(0x70, b'\x00\x01')
i2c.write(0x70, b'\xE8\xAA')

# the delay of a motor deceleration can be used to compensate for different motor speeds
biasR = 0  # Deceleration of the right motor in percent
biasL = 0  # Deceleration of the left motor in percent

# Control motors with the PWM controller
# PWM0 and PWM1 for the left motor and PWM2 and PWM3 for the right motor
def drive(PWM0, PWM1, PWM2, PWM3):
    # The scaling function is used to scale the bias variables 
    # for the calculation of the motor speed
    def scale(num, in_min, in_max, out_min, out_max):
        return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

    # Scaling of the delay value to the value in percent
    PWM0 = int(PWM0 * (scale(biasR, 0, 100, 100, 0) / 100))
    PWM1 = int(PWM1 * (scale(biasR, 0, 100, 100, 0) / 100))
    PWM2 = int(PWM2 * (scale(biasL, 0, 100, 100, 0) / 100))
    PWM3 = int(PWM3 * (scale(biasL, 0, 100, 100, 0) / 100))

    # Transmit value for PWM channel (0-255) to PWM controller
    # 0x70 is the I2C address of the controller
    # the byte with the PWM value is added to the byte for the channel
    i2c.write(0x70, b'\x02' + bytes([PWM0]))
    i2c.write(0x70, b'\x03' + bytes([PWM1]))
    i2c.write(0x70, b'\x04' + bytes([PWM2]))
    i2c.write(0x70, b'\x05' + bytes([PWM3]))
    
# Method for turning with orientation, direction, speed and radius
def turn(orientation, direction, speed, radius):
    # radius: 0-5
    if radius > 0:
        # Calculation of the inner wheel speed
        innerWheelSpeed = (speed * 0.7) * (radius / 5)
    else:
        return

    # adjust the motors accordingly
    if orientation == "forward":
        if direction == "left":
            drive(0, speed, 0, innerWheelSpeed)
        elif direction == "right":
            drive(0, innerWheelSpeed, 0, speed)
    elif orientation == "backwards":
        if direction == "left":
            drive(speed, 0, innerWheelSpeed, 0)
        elif direction == "right":
            drive(innerWheelSpeed, 0, speed, 0)

while True:
    # drive forward at full power
    drive(0, 255, 0, 255)
    sleep(2000)

    # Reverse at full power
    drive(255, 0, 255, 0)
    sleep(2000)

    # Drive to the left at full power
    drive(0, 255, 255, 0)
    sleep(2000)

    # Drive to the right at full power
    drive(255, 0, 0, 255)
    sleep(2000)

    # stop
    drive(0, 0 , 0, 0)
    sleep(2000)

    # make a left turn forward at 50% speed and radius 4
    turn("forward", "left", 128, 4)
    sleep(1000)

    # make a right turn backwards at 50% speed and radius 2
    turn("backwards", "right", 128, 2)
    sleep(1000)
Python