Darko Vranesa
Published © MIT

Lego EV3, Amazon ALEXA, RPi3 - 3 gadgets talk to each other

Lego EV3, Amazon Alexa Dot 3 and Raspberry Pi3 talking together, voice commands from Alexa cloud to RPI3, MQTT communications to Lego robot

IntermediateFull instructions provided10 hours1,373
Lego EV3, Amazon ALEXA, RPi3 - 3 gadgets talk to each other

Things used in this project

Story

Read more

Schematics

Networked gadget schematic diagram

All is connected in my home wifi network

Code

mqqt-12.py

Python
You must copy program to lego robot running ev3dev development enviroment
# Copyright 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
# 
# You may not use this file except in compliance with the terms and conditions 
# set forth in the accompanying LICENSE.TXT file.
#
# THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY DISCLAIMS, WITH 
# RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 
# THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.

import paho.mqtt.client as mqtt
import threading
import time
import ev3dev.ev3 as ev3
import json

# This is the Subscriber

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("ev3/command")

def on_message(client, userdata, msg):
    print("def on message")
    print("msg =",msg)
    print("msg.payload =",msg.payload)
    decoded_msg = msg.payload.decode("utf-8")
    print("decoded_msg =",decoded_msg)
    payload = json.loads(decoded_msg)
    print("payload =",payload)
    if 'voice' in payload:
        ev3.Sound.speak(payload['voice']).wait()
    if 'robotControl' in payload:
        arm_control(payload)
    if 'moveRobot' in payload:
        move_robot(payload)

# Move robot (direction and speed is defined in payload)
def move_robot(payload):
  print("def move robot")
  if 'direction' and 'speed' and 'time' in payload['moveRobot']:
        speed = int(payload['moveRobot']['speed'])
        duration = int(payload['moveRobot']['time'])
        direction = payload['moveRobot']['direction']
        print("speed =",speed)
        print("duration =",duration)
        print("direction =",direction)
        left = ev3.LargeMotor('outB')
        right = ev3.LargeMotor('outC')
        speed_l, speed_r = 0, 0
        if direction == 'fwd':
            speed_l = speed
            speed_r = speed
        elif direction == 'left':
            speed_l = -speed
            speed_r = speed
        elif direction == 'right':
            speed_l = speed
            speed_r = -speed
        elif direction == 'back':
            speed_l = -speed
            speed_r = -speed
        elif direction == 'stop':
            speed_l = 0
            speed_r = 0
        else:
            ev3.Sound.speak('Please tell me direction').wait()

        if left.connected and right.connected:
            left.run_timed(time_sp=duration, speed_sp=speed_l)
            right.run_timed(time_sp=duration, speed_sp=speed_r)

# When motor is stopped, its `state` attribute returns empty list.
# Wait until both motors are stopped:
        while any(left.state) or any(right.state):
            time.sleep(0.1)

# Move robot arm (Speed and duration is defined in payload)
def arm_control(payload):
    m = ev3.MediumMotor('outA')
    speed = int(payload['robotControl']['speed'])
    duration = int(payload['robotControl']['time'])
    if m.connected:
        m.run_timed(time_sp=duration, speed_sp=speed)
        while any(m.state):
            time.sleep(0.1)
        print("done")
    else:
        print("Motor not connected")

# On button press, send payload (MQTT)
def publish_data(run_event):
    while run_event.is_set():
        ts = ev3.TouchSensor()
#       if ts.connected and ts.value() == 1:
#           try:
#               ev3.Leds.set_color(ev3.Leds.LEFT, (ev3.Leds.GREEN, ev3.Leds.RED)[ts.value()])
#               payload = ("{\"touchSensorValue\": \"%d\"}" % ts.value
#              client.publish(ev3.publisher_topic, payload)
#               print("Data sent")
#           except:
#               print("Err")
#       else:
#           ev3.Leds.set_color(ev3.Leds.LEFT, (ev3.Leds.GREEN, ev3.Leds.RED)[ts.value()])



# Make new MQTT client
client = mqtt.Client()
client.connect("192.168.1.113",1883,60)

client.on_connect = on_connect
client.on_message = on_message

# Start 
client.loop_forever()

model.json

JSON
Copy the interaction model JSON from that file, and paste it into the editor, or drag and drop the JSON file onto the drop zone to upload it.
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "lego robot",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "movef",
                    "slots": [],
                    "samples": [
                        "go",
                        "forward",
                        "move forward"
                    ]
                },
                {
                    "name": "moveb",
                    "slots": [],
                    "samples": [
                        "go back",
                        "back",
                        "move back"
                    ]
                },
                {
                    "name": "movel",
                    "slots": [],
                    "samples": [
                        "turn left",
                        "left",
                        "move left"
                    ]
                },
                {
                    "name": "mover",
                    "slots": [],
                    "samples": [
                        "turn right",
                        "right",
                        "move right"
                    ]
                },
                {
                    "name": "stop",
                    "slots": [],
                    "samples": [
                        "stop lego robot"
                    ]
                }
            ],
            "types": []
        }
    }
}

Nodered flow Lego EV3 Alexa

JavaScript
Select all code and import it in you working NODE RED on RPI
[{"id":"40239d02.fe0584","type":"tab","label":"LEGO EV3 ALEXA","disabled":false,"info":""},{"id":"ff6b476d.5e6fb8","type":"debug","z":"40239d02.fe0584","name":"","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","x":300,"y":620,"wires":[]},{"id":"265713a6.a88efc","type":"chatbot-telegram-receive","z":"40239d02.fe0584","bot":"b069f500.581368","botProduction":"","x":100,"y":540,"wires":[["ff6b476d.5e6fb8","69847dbf.a64744"]]},{"id":"74639f41.16df3","type":"chatbot-telegram-send","z":"40239d02.fe0584","bot":"b069f500.581368","botProduction":"","track":false,"passThrough":false,"outputs":0,"x":510,"y":540,"wires":[]},{"id":"69847dbf.a64744","type":"chatbot-message","z":"40239d02.fe0584","name":"message","message":[{"message":"Hello from rpi3"}],"answer":false,"silent":false,"x":310,"y":560,"wires":[["74639f41.16df3"]]},{"id":"7b338e0a.74c17","type":"chatbot-alexa-receive","z":"40239d02.fe0584","bot":"ff4f569b.436da8","botProduction":"","x":120,"y":40,"wires":[["cb0bf8e8.a4d158","fa477ea.e4ece8"]]},{"id":"51f7da44.bed6b4","type":"chatbot-alexa-send","z":"40239d02.fe0584","bot":"ff4f569b.436da8","botProduction":"","track":false,"passThrough":false,"outputs":0,"x":800,"y":200,"wires":[]},{"id":"165d22f9.78a1cd","type":"chatbot-message","z":"40239d02.fe0584","name":"turn right","message":[{"message":"Lego robot turned right"}],"answer":false,"silent":false,"x":520,"y":220,"wires":[["51f7da44.bed6b4"]]},{"id":"cb0bf8e8.a4d158","type":"debug","z":"40239d02.fe0584","name":"","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","x":360,"y":40,"wires":[]},{"id":"fa477ea.e4ece8","type":"chatbot-rules","z":"40239d02.fe0584","name":"","rules":[{"type":"isIntentName","intent":"movef"},{"type":"isIntentName","intent":"moveb"},{"type":"isIntentName","intent":"movel"},{"type":"isIntentName","intent":"mover"},{"type":"isIntentName","intent":"stop"},{"type":"messageEvent","event":"start"},{"type":"messageEvent","event":"endSession"},{"type":"catchAll"}],"outputs":8,"x":130,"y":160,"wires":[["42e1278f.661018","15b1f915.e24647"],["db3fecce.9c808","eeaef051.c0d7"],["3fa8fcf8.e34864","5c92a003.130f2"],["165d22f9.78a1cd","4f6c99fb.51b4a8"],["9d1b8650.7e87c8","7965c969.f8cfb8"],["652d05f.a72d1fc"],["be0e70b5.89419"],["829c659.7347118"]]},{"id":"42e1278f.661018","type":"chatbot-message","z":"40239d02.fe0584","name":"forward","message":[{"message":"Lego robot moved forward"}],"answer":false,"silent":false,"x":520,"y":100,"wires":[["51f7da44.bed6b4"]]},{"id":"db3fecce.9c808","type":"chatbot-message","z":"40239d02.fe0584","name":"back","message":[{"message":"Lego robot move back"}],"answer":false,"silent":false,"x":510,"y":140,"wires":[["51f7da44.bed6b4"]]},{"id":"3fa8fcf8.e34864","type":"chatbot-message","z":"40239d02.fe0584","name":"turn left","message":[{"message":"Lego robot turned left"}],"answer":false,"silent":false,"x":520,"y":180,"wires":[["51f7da44.bed6b4"]]},{"id":"9d1b8650.7e87c8","type":"chatbot-message","z":"40239d02.fe0584","name":"stop","message":[{"message":"lego robot stopped"}],"answer":false,"silent":false,"x":510,"y":260,"wires":[["51f7da44.bed6b4"]]},{"id":"652d05f.a72d1fc","type":"chatbot-message","z":"40239d02.fe0584","name":"first message","message":[{"message":"Hello from lego robot "}],"answer":false,"silent":false,"x":500,"y":300,"wires":[["51f7da44.bed6b4"]]},{"id":"be0e70b5.89419","type":"chatbot-message","z":"40239d02.fe0584","name":"last message","message":[{"message":"Good bue  from lego robot "}],"answer":false,"silent":false,"x":490,"y":340,"wires":[["51f7da44.bed6b4"]]},{"id":"15b1f915.e24647","type":"link out","z":"40239d02.fe0584","name":"","links":["74fd12d1.ef638c"],"x":295,"y":340,"wires":[]},{"id":"eeaef051.c0d7","type":"link out","z":"40239d02.fe0584","name":"","links":["6ecf7e64.e422e"],"x":295,"y":380,"wires":[]},{"id":"5c92a003.130f2","type":"link out","z":"40239d02.fe0584","name":"","links":["ea2c6a1e.36f778"],"x":295,"y":420,"wires":[]},{"id":"4f6c99fb.51b4a8","type":"link out","z":"40239d02.fe0584","name":"","links":["7572ffe3.ade0a"],"x":295,"y":460,"wires":[]},{"id":"7965c969.f8cfb8","type":"link out","z":"40239d02.fe0584","name":"","links":["268f3d78.6b1bb2"],"x":175,"y":380,"wires":[]},{"id":"829c659.7347118","type":"chatbot-message","z":"40239d02.fe0584","name":"dont understand ","message":[{"message":"I do not understand your command !\nPlease say valid robot commands:\n go, back,left,right,stop lego robot"}],"answer":false,"silent":false,"x":510,"y":380,"wires":[["51f7da44.bed6b4"]]},{"id":"9568dc5e.6ea7b","type":"inject","z":"40239d02.fe0584","name":"","topic":"sensor","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":460,"wires":[["8ac0f9f2.bf772"]]},{"id":"8ac0f9f2.bf772","type":"chatbot-message","z":"40239d02.fe0584","name":"sensor message","message":[{"message":"message from lego robot:\nto close to barrier !"}],"answer":false,"silent":false,"x":650,"y":460,"wires":[["51f7da44.bed6b4"]]},{"id":"b069f500.581368","type":"chatbot-telegram-node","z":"","botname":"malamlaka_bot","usernames":"","providerToken":"","polling":"1000","store":"","log":"","parseMode":"","debug":false,"webHook":"","connectMode":"polling"},{"id":"ff4f569b.436da8","type":"chatbot-alexa-node","z":"","botname":"alexa","usernames":"","store":"","log":"/logs/chatbot-alexa.log","debug":true}]

Credits

Darko Vranesa

Darko Vranesa

5 projects • 6 followers

Comments