Amine Amri
Created November 10, 2019 © MIT

Voice Controlled Robot for kids

A small robot for kids to learn, play and discover the world of robotics.

IntermediateFull instructions provided20 hours72
Voice Controlled Robot for kids

Things used in this project

Story

Read more

Schematics

RIght view

Back view

View on the external battery powering Matrix Creator and Raspberry

Side View

Connection between Raspberry and Micro:bit

Front view

With front leds to drive in the dark

Left view

Code

Micro:bit code to control the robot

JavaScript
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () {
    command = serial.readLine()
    distance = parseFloat(command.substr(7, command.length))
    direction = command.substr(0, 4)
    Speed_Char = command.substr(5, 1)
    if (Speed_Char == "S") {
        Speed = Slow_Speed
        Coeff = Slow_Speed_Coeff
    } else if (Speed_Char == "M") {
        Speed = Medium_Speed
        Coeff = Medium_Speed_Coeff
    } else {
        Speed = Fast_Speed
        Coeff = Fast_Speed_Coeff
    }
    if (direction == "LEFT") {
        left(distance * Angle_Duration_Left_90 / 90)
        stop(1)
    } else if (direction == "RGHT") {
        right(distance * Angle_Duration_Right_90 / 90)
        stop(1)
    } else if (direction == "FRWD") {
        forward(distance * Coeff, Speed)
        stop(1)
    } else if (direction == "BKWD") {
        backward(distance * Coeff, Speed)
        stop(1)
    } else {
        stop(1)
    }
})
function forward(distance: number, speed: number) {
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED1, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED2, speed, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED3, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED4, speed, 67)
    basic.pause(distance)
}
function backward(distance: number, speed: number) {
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED1, 100, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED2, speed, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED3, 100, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED4, speed, 67)
    basic.pause(distance)
}
maqueen.IR_callbackUser(function ({ myparam: message }) {
    val = message
    if (val == 70) {
        forward(2, Fast_Speed)
    }
    if (val == 68) {
        left(90)
    }
    if (val == 67) {
        right(90)
    }
    if (val == 21) {
        backward(2, Fast_Speed)
    }
    if (val == 64) {
        stop(1)
    }
})
function left(angle: number) {
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED1, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED2, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED3, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED4, 60, 67)
    basic.pause(angle)
}
function right(angle: number) {
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED1, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED2, 60, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED3, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED4, 0, 67)
    basic.pause(angle)
}
function stop(duration: number) {
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED1, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED2, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED3, 0, 67)
    PCA9685.setLedDutyCycle(PCA9685.LEDNum.LED4, 0, 67)
    basic.pause(duration)
}
let direction = ""
let distance = 0
let command = ""
let Coeff = 0
let Speed = 0
let Speed_Char = ""
let Slow_Speed_Coeff = 0
let Slow_Speed = 0
let Medium_Speed_Coeff = 0
let Medium_Speed = 0
let Fast_Speed_Coeff = 0
let Fast_Speed = 0
let Angle_Duration_Right_90 = 0
let Angle_Duration_Left_90 = 0
let val = 0
val = 0
Angle_Duration_Left_90 = 400
Angle_Duration_Right_90 = 520
Fast_Speed = 100
Fast_Speed_Coeff = 13.5
Medium_Speed = 75
Medium_Speed_Coeff = 20
Slow_Speed = 50
Slow_Speed_Coeff = 27
Speed_Char = "S"
Speed = Slow_Speed
Coeff = Slow_Speed_Coeff
serial.redirectToUSB()
PCA9685.init(67, 0)
basic.forever(function () {

})

Code for playing Color Mix Game (RFID based controls)

Python
from matrix_lite import led
from time import sleep
from math import pi, sin
from random import randint
import matrix_lite_nfc as nfc


everloop = ['black'] * led.length
counter = 0.0
tick = len(everloop) - 1
isChanged = False
nextPosCounterClockWise = 34
nextPosClockWise = 1
debug = False
direction = 0


def gameOver():
    everloop = ['black'] * led.length

    ledAdjust = 0.0
    if len(everloop) == 35:
        ledAdjust = 0.51 # MATRIX Creator
    else:
        ledAdjust = 1.01 # MATRIX Voice

    frequency = 0.375
    counter = 0.0
    tick = len(everloop) - 1
    
    count = 0
    while count < 70:
        # Create rainbow
        for i in range(len(everloop)):
            r = round(max(0, (sin(frequency*counter+(pi/180*240))*155+100)/10))
            g = round(max(0, (sin(frequency*counter+(pi/180*120))*155+100)/10))
            b = round(max(0, (sin(frequency*counter)*155+100)/10))

            counter += ledAdjust

            everloop[i] = {'r':r, 'g':g, 'b':b}

        # Slowly show rainbow
        if tick != 0:
            for i in reversed(range(tick)):
                everloop[i] = {}
            tick -= 1

        led.set(everloop)
        sleep(.035)
        count += 1
        
        
        
def colorPick():
    # Pick a random number representing one of four colors (yellow, blue, red and white) and there is a 1/40 chance to pick a golden ball
    x =  randint(0,40)

    # Return the color matching that random number
    if x <= 10:
        color = 'yellow'
    elif x <= 20:
        color = 'blue'
    elif x <= 30:
        color = 'red'
    elif x <= 39:
        color = 'white'
    else:
        color = 'darkgoldenrod'
    return color

	
def debugEverloop(): #a debug function to print all the leds color's
    if (not debug):
        return
    message=''
    if direction == 1:
        for i in range(0,35):
            if everloop[i] == 'red':
   	           message += 'Red-'
            elif everloop[i] == 'blue':
               message += 'Blue-'
            elif everloop[i] == 'green':
               message += 'Green-'   
            elif everloop[i] == 'white':
               message += 'White-'
            elif everloop[i] == 'black':
               message += 'Empty-'
            elif everloop[i] == 'orange':
               message += 'Orange-'
            elif everloop[i] == 'purple':
               message += 'Purple-'
            elif everloop[i] == 'darkgoldenrod':
               message += 'Golden-'
            elif everloop[i] == 'yellow':
               message += 'Yellow-'
        print(message + '\n')
        print('NextPosClockwise = ' , nextPosClockWise,'\n')
    elif direction == -1:
        for i in reversed(range(0,35)):
            if everloop[i] == 'red':
   	           message += 'Red-'
            elif everloop[i] == 'blue':
               message += 'Blue-'
            elif everloop[i] == 'green':
               message += 'Green-'   
            elif everloop[i] == 'white':
               message += 'White-'
            elif everloop[i] == 'black':
               message += 'Empty-'
            elif everloop[i] == 'orange':
               message += 'Orange-'
            elif everloop[i] == 'purple':
               message += 'Purple-'
            elif everloop[i] == 'darkgoldenrod':
               message += 'Golden-'
            elif everloop[i] == 'yellow':
               message += 'Yellow-'
        print(message + '\n')
        print('NextPosCounterClockWise = ' , nextPosCounterClockWise,'\n')
		
        
def RecursiveMixClockWise():
    global isChanged, nextPosClockWise, debug
    if not isChanged:
        return
    isChanged = False
    for i in reversed(range (2, nextPosClockWise)):
        if everloop[i-1] == everloop[i]:
            if debug:
                print('Mergin two balles ', i, i-1, '\n')
            everloop[nextPosClockWise] = 'black'
            for j in range (i,nextPosClockWise):
                everloop[j] = everloop[j+1]
            nextPosClockWise -= 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    if everloop[2] == 'white':
        if debug:
            print('White Ball ahead')
        for i in range(2,nextPosClockWise):
            everloop[i] = everloop[i+1]
        everloop[nextPosClockWise] = 'black'
        nextPosClockWise -= 1
        debugEverloop()
        isChanged=True
        renderSlow()
    for i in reversed(range(2,nextPosClockWise + 1)):
        if {everloop[i],everloop[i-1]} == {'yellow','blue'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosClockWise] = 'black'
            everloop[i-1] = 'green'
            for j in range(i,nextPosClockWise):
                everloop[j] = everloop[j+1]
            nextPosClockWise -= 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    for i in reversed(range(2,nextPosClockWise + 1)):
        if {everloop[i],everloop[i-1]} == {'red','blue'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosClockWise] = 'black'
            everloop[i-1] = 'purple'
            for j in range(i,nextPosClockWise):
                everloop[j] = everloop[j+1]
            nextPosClockWise -= 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    for i in reversed(range(2,nextPosClockWise + 1)):
        if {everloop[i],everloop[i-1]} == {'red','yellow'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosClockWise] = 'black'
            everloop[i-1] = 'orange'
            for j in range(i,nextPosClockWise):
                everloop[j] = everloop[j+1]
            nextPosClockWise -= 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    RecursiveMixClockWise()



def RecursiveMixCounterClockWise():
    global isChanged, nextPosCounterClockWise, debug
    if not isChanged:
        return
    isChanged = False
    for i in reversed(range (nextPosCounterClockWise + 1,35)):
        if everloop[i] == everloop[i-1]:
            if debug:
                print('Mergin two balles ', i, i-1, '\n')
            everloop[nextPosCounterClockWise] = 'black'
            for j in reversed(range (nextPosCounterClockWise + 1,i+1)):
                everloop[j] = everloop[j-1]
            nextPosCounterClockWise += 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    if everloop[33] == 'white':
        if debug:
            print('White Ball ahead')
        for i in reversed(range(nextPosCounterClockWise + 1,34)):
            everloop[i] = everloop[i-1]
        everloop[nextPosCounterClockWise] = 'black'
        nextPosCounterClockWise += 1
        debugEverloop()
        isChanged=True
        renderSlow()
    for i in reversed(range (nextPosCounterClockWise + 1,35)):
        if {everloop[i],everloop[i-1]} == {'yellow','blue'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosCounterClockWise] = 'black'
            everloop[i] = 'green'
            for j in reversed(range (nextPosCounterClockWise + 1,i)):
                everloop[j] = everloop[j-1]
            nextPosCounterClockWise += 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    for i in reversed(range (nextPosCounterClockWise + 1,35)):
        if {everloop[i],everloop[i-1]}=={'red','blue'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosCounterClockWise] = 'black'
            everloop[i] = 'purple'
            for j in reversed(range (nextPosCounterClockWise+1,i)):
                everloop[j] = everloop[j-1]
            nextPosCounterClockWise += 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break
    for i in reversed(range (nextPosCounterClockWise + 1,35)):
        if {everloop[i],everloop[i-1]} == {'red','yellow'}:
            if debug:
                print('Mixing two colors ', i,' and ',i-1, '\n')
            everloop[nextPosCounterClockWise] = 'black'
            everloop[i] = 'orange'
            for j in reversed(range (nextPosCounterClockWise + 1,i)):
                everloop[j] = everloop[j-1]
            nextPosCounterClockWise += 1
            debugEverloop()
            isChanged = True
            renderSlow()
            break

    RecursiveMixCounterClockWise()

	
def renderSlow():
	led.set(everloop)
	sleep(0.3)
def renderFast():
	led.set(everloop)
	sleep(.15)

	


		
while True:

    everloop[0] = colorPick()
    led0 = everloop[0]
    #make a blink animation of led 0 and wait for a direction
    while direction == 0:
        everloop[0] = led0
        renderFast()
        everloop[0] = 'black'
        renderFast()
        tag = nfc.read.scan({"info": True, "pages": False, "ndef": False,"page": 0})
        if(tag.status == 256):
            if tag.info.UID == '0A24E83C': #Clockwise direction	Change the ID with your RFID Tag ID	
                direction = 1
            elif tag.info.UID != '':
                direction = -1
    everloop[0] = led0
    renderSlow()
    if debug:
        print('Next Ball :' , everloop[0])
    debugEverloop()
    foundplace = False
    isChanged = False
    if direction == 1: #clockwise
        if everloop[0] == 'darkgoldenrod': # lucky man
            for i in range (1,nextPosClockWise):
                everloop[i] = 'black'
                renderFast()
            everloop[0] = 'black'			
            nextPosClockWise = 1
		#find place for the new ball
        for i in range(1,nextPosClockWise+1):
            if everloop[i] ==  'black':
                if debug:
                    print('Found empty space n°' , i , ', shifting balls\n')
                for j in reversed(range(1,i+1)):
                    everloop[j] = everloop[j-1]
                everloop[0] = 'black'
                foundplace= True
                nextPosClockWise += 1
                debugEverloop()
                renderSlow()
                break
        if foundplace:
            isChanged = True
            RecursiveMixClockWise()
            direction = 0
        else:
            print('Game Over')
            break
    elif direction == -1: #counterclockwise
        if everloop[0] == 'darkgoldenrod': # lucky man
            for i in  reversed(range(nextPosCounterClockWise,35)):
                everloop[i] = 'black'
                renderFast()
            everloop[0] = 'black'			
            nextPosCounterClockWise = 34
		#find place for the new ball
        for i in reversed(range(nextPosCounterClockWise,35)):
            if everloop[i] ==  'black':
                if debug:
                    print('Found empty space n°' , i , ', shifting balls\n')
                for j in range(i,35):
                    everloop[j] = everloop[ (j+1) % 35]
                everloop[0] = 'black'
                foundplace = True
                nextPosCounterClockWise -= 1
                debugEverloop()
                renderSlow()
                break
        if foundplace:
            isChanged = True
            RecursiveMixCounterClockWise()
            direction = 0
        else:
            print('Game Over')
            gameOver()
            break

Snips Skill to control the robot

Snips skill to play Simon Says Game

Credits

Amine Amri

Amine Amri

10 projects • 19 followers
I’m a financial risk engineer in Paris, France with a passion for computer science, electrical engineering, robotics and embedded systems.

Comments