Lego EV3 and the Droid Factory

With the prepared ev3dev environment ev3dev we can Lego EV3 brick comfortably program in Python.

The simple design of the conveyor belt we use as a trainer on which we'll test the Motor, Touch Sensor and Color Sensor. Conveyor belt represents the final part of the production line, of which goes just manufactured Trade Federation droids – light droids and dark droids. The line must be calibrated at first to distinguish the dark drone from the light, and then it can count how many of which crosses the beam of the Color Sensor.

Droid Factory



PThe description of the ev3dev library interface for Python is on the GitHub. We use this library and the function sleep().

import ev3dev
from time import sleep
		

We prepare functions for controlling the motor.

#motor control
def motorstop(m):
    m.stop()

def motorrun(m):
    m.connected
    m.run_forever(duty_cycle_sp=20)	
		

We prepare the function to ensure calibration of the Color Sensor. This is necessary because of the varying level of ambient lighting.

def calibrate(t, c, l):
    l.clear()
    l.draw.text((2, 8), 'light droid first...')
    l.update()
    while (t.value() == 0):
        l.draw.rectangle([2,20,100,28],fill="white")
        l.draw.text((2, 20), 'color = ' + str(c.value()))
        l.update()
    l.update()
    dlight = c.value()
    ev3dev.Sound.beep()
    time.sleep(2.0)
    l.clear()
    l.draw.text((2, 8), 'dark droid next...')
    l.update()
    while (t.value() == 0):
        l.draw.rectangle([2,20,100,28],fill="white")
        l.draw.text((8, 20), 'color = ' + str(c.value()))
        l.update()
    l.update()
    ddark = c.value()
    ev3dev.Sound.beep()
    return [dlight, ddark]
		

Before putting factory into service we set needed variables and we print out the information on the display.

t = ev3dev.TouchSensor()
c = ev3dev.ColorSensor()
c.mode = 'COL-REFLECT'
l = ev3dev.LCD()
l.clear()
calvalues = calibrate(t,c,l)
l.clear()
l.draw.text((2,20),str(calvalues[0])+' : '+str(calvalues[1]))
l.update()
time.sleep(3.0)
l.clear()
l.draw.text((2,20),'FACTORY IS READY TO RUN!')
l.update()
ev3dev.Sound.beep()
time.sleep(0.25)
ev3dev.Sound.beep()
		

After pressing the button we run the motor.

#wait for button press
while (t.value() == 0):
    time.sleep(0.01)
time.sleep(0.5)
#prepare variables
dlight = 0  #counter for light droids
ddark = 0   #counter for dark droids
factoryclosed = False
#then run motor driven belt
m = ev3dev.LargeMotor('outD')
motorrun(m)
		

We'll keep running the belt until the sensor does not catch a droid or until the button is not pressed.

while (not factoryclosed):
    #wait for droid or button press
    isnewdroid = c.value()
    wasbuttonpressed = t.value()
    while (isnewdroid < calvalues[1]) and (wasbuttonpressed == 0):
        isnewdroid = c.value()
        wasbuttonpressed = t.value()
		

Button press stops the whole factory.
PWhen distinguishing between the dark and the light robot we will stop the belt for a while to provide time for a correct assessment of the reflected light intensity.

    #what happened?
    l.clear()
    if (wasbuttonpressed):
        l.draw.text((2,8), 'STOP!')
        l.update()
        motorstop(m)
        factoryclosed = True
    else:
        #necessary to stop and properly scan the droid color
        motorstop(m)
        time.sleep(0.25)
        isnewdroid = c.value()
        if (isnewdroid <= calvalues[1]+4):
            l.draw.text((2,20), 'dark one '+str(isnewdroid)+'-'+str(calvalues[1]))
            ddark += 1
        else:
            l.draw.text((2,20), 'light one '+str(isnewdroid)+'-'+str(calvalues[0]))
            dlight +=1
        l.draw.text((2,8),'L = '+str(dlight)+' | D = '+str(ddark))
        l.update()
        motorrun(m)
        time.sleep(0.4)
		

After the closing of the factory by pressing the button the display prints out the total “production” statistics.

#factory is closing
time.sleep(2.0)
l.clear()
l.draw.text((2,8), 'FACTORY CLOSED')
l.draw.text((2,20), 'overall production:')
l.draw.text((2,32),'L = '+str(dlight)+' | D = '+str(ddark))
l.update()
time.sleep(3.0)
		


Multiprocessing

It is worth trying run the applications in multiple threads. The program starts the motor and it is running until the button is pressed, or until the Color Sensor catches a bright object.
We need the multiprocessing multiprocessing library.

import ev3dev
from time import sleep
from multiprocessing import Process
		

We prepare the functions, which will run in separate threads.

def sensorcheck():
    c = ev3dev.ColorSensor()
    c.mode = 'COL-REFLECT'
    while (c.value() < 10):
        sleep(0.01)
    m = ev3dev.LargeMotor('outD')
    m.connected
    m.stop()
    
def buttoncheck():
    t = ev3dev.TouchSensor()
    while (t.value() != 1):
        sleep(0.01)
    m = ev3dev.LargeMotor('outD')
    m.connected
    m.stop()    
		

We run the motor and start two separate processes.

m = ev3dev.LargeMotor('outD')
m.connected
m.run_forever(duty_cycle_sp=20)
p1 = Process(target = sensorcheck)
p1.start()
p2 = Process(target = buttoncheck)
p2.start()
		

The source code is available for download.

contribute:
Lego EV3 a IPy Notebook