Johnny Pi, I am your father — part 1: moving around

--

The introduction showed you the big picture, now let’s get to work. In this post, we’re going to take care of the following tasks:

  • connect the robot to AWS IoT,
  • implement commands to move the robot around,
  • implement commands to drive the ultrasonic sensor.

What we’ll need

I’m hoping that some of you will actually build this from scratch, so here’s the shopping list for part 1:

  • a GoPiGo robot
  • a MQTT test tool. I’ve been using MQTT.fx for a while and I really like it (please consider making a donation). It can connect to AWS IoT in exactly the same way as a device (i.e. with a certificate and a key pair).
  • Alternatively, you can use the MQTT client embedded in the AWS IoT console.

Looking at the GoPiGo API

Once you’ve built your robot and connected it to WiFi, you can ssh to it (user:pi, password: robots1234) and run some basic commands to get familiar with the GoPiGo Python API. It really couldn’t be simpler, here’s a small example inspired by the Logo turtle. Make sure you have enough space around the robot… and stay clear of stairs or any other fall hazard!

Feel free to play with the other commands. If you have connected the servo and the ultrasonic sensor, you should definitely try the associated commands as well. Once again, it’s all super simple and even Python beginners should feel comfortable very quickly.

Installing the AWS IoT SDK

Of course, we’re not going to run Python scripts to drive our robot. We’re going to send commands through the AWS IoT message broker: more precisely, the robot is going to subscribe to MQTT topics (one for robot movement, one for servo movement), where we’re going to publish simple commands like ‘left’ or ‘right’.

In order to communicate with the message broker, we first need to install the AWS IoT Python SDK. Just ssh to the robot and issue this single command:

$ pip install AWSIoTPythonSDK

That’s it. Now let’s register the robot in AWS IoT.

Registering the robot in AWS IoT

In AWS IoT, a device (or “thing”, as they’re called) needs:

  • a name (how about “JohnnyPi”?),
  • an identity, composed of an X509 certificate (for authentication) and an RSA key pair (for communication encryption),
  • an IAM policy, listing the IoT APIs that the device is allowed to invoke and the topics that it’s allowed to access (we’ll need JohnnyPi/move and JohnnyPi/scan for now),
  • the root certificate of the AWS IoT message broker.

For the sake of brevity, I won’t cover how to get through these steps, which are explained in full detail in the AWS documentation.

Just a quick note on the IAM policy: in this context, it’s probably ok to use a very loose policy (iot:* and resource:*), but here’s the one you should really use.

Last but not least, don’t forget to copy the root certificate, the certificate and the private key to the robot, why not in a dedicated certs directory?

We will definitely need them to connect to the IoT message broker, which happens to be the topic of the next section!

Connecting to AWS IoT

First, let’s create the iot_config.py file and define all parameters required to connect. Obviously, you’ll need to replace XXX with the appropriate values, namely:

  • the prefix of the private key and the certificate,
  • the hostname of the IoT broker, which you’ll find either in the console or by issuing the ‘aws iot describe-endpoint’ CLI command.

Next, let’s write the iot_connect.py file, holding two simple functions: one for connection and one for disconnection. Nothing weird here, we’re just using the appropriate AWS APIs.

That’s all it takes. Make sure to test this before proceeding: just check that you can call the connectIot() function without any error and that you see a connection in the dashboard of the AWS IoT console :)

Subscribing to MQTT topics

Now, let’s subscribe to the two MQTT topics. We just have to call the subscribe() API in the AWS IoT SDK, passing:

  • the topic name,
  • the quality of service (QoS) we require. ‘0’ means none (messages may be lost), ‘1’ means ‘at least once delivery’ (lost message will be retransmitted and possibly received more than once). We’ll use ‘1’, because we definitely don’t want our robot to miss a command.
  • a callback, i.e. a function that will be executed each time a message is received. We’ll code them in the next section.

Processing movement messages

Our MQTT messages will contain self-explanatory movement commands: ‘forward’, ‘backward’, ‘left’, ‘right’, ‘faster’, ‘slower’, ‘stop’. Thus, the role of the callback is simply to extract the command from the message payload and call the appropriate GoPiGo API.

Then, the callback sleeps for a second and stops the robot. This is a precaution to make sure that it won’t run out of control, fall off the stage, etc. Feel free to tweak this to your own liking.

Processing servo messages

Similarly, the servo callback will process simple commands:

  • ‘right’ rotates the servo 30° right,
  • ‘left’ rotates the servo 30° left,
  • ‘reset’ puts the servo in a central position,
  • ‘scan’ measures the distance to the object in front of the ultrasonic sensor and builds a text message. In future posts, we’ll send this message to Amazon Polly and to our Amazon Echo for additional fun ;) In case you were wondering, the ‘15’ parameter passed to us_dist() is the pin on which the servo is connected (by default, port A1 i.e. pin 15).

Testing

Ok, that’s all the code we need for today: you can grab it on Github.

In order to test all of this, we need to:

  • ssh to the robot and start server.py,
  • publish MQTT messages to the two topics, containing the commands we implemented on the robot.
Using MQTT.fx, send the ‘left’ command to the JohnnyPi/move topic with QoS 1

Please make sure you test all commands. Check out the server.py output for any potential error.

What’s next

In the next post, we’ll continue to work on movement: I’ll show you how to drive the robot using a joystick connected to an Arduino Yùn :)

Until then, thank you for reading!

--

--