Sunday, October 12, 2014

Robo Push-To-Deploy (Part 1 / 2)

It's been a while since my last post - as it happens the past few weekends were full of other activities - but I decided that today I'd write a bit about the workflow I devised for updating my little robo's software.

The Software

The robot will have a whole bunch of software on it eventually, and as we are living in modern times, one language will not fit it all. As of now, we have to account for three different programming languages:

LanguageUsed forDeployment
PythonMost of the robot's logic, sensor measurements, server-side UI codeCompiled to byte-code upon execution. Just copy to the robot and execute.
Arduino SketchUsed for controlling the Arduino motor shield.Must be compiled and uploaded to the Arduino. Two options:
  • Deploy Source code to the Raspberry Pi part of the robot, compile there and upload to Arduino
  • Compile to binaries on the development machine, copy binaries to the Raspberry Pi and upload to the Arduino
JavaScriptClient-side UI logic.The client-side UI will make extensive use of Google Closure Library. JavaScript can generally be executed as is, so copying to the robot is all that is needed. However, as the JavaScript code grows more complex, it might be interesting to apply Closure Compiler to make it more efficient

Suddenly, the task of deploying a whole new set of software to the robot seems to have gotten a whole lot more complex. Wouldn't it be nice to deploy all the above with a single command and then maybe even reinitialize the robot so it runs our new software?

Editing software on the robot

OK, this is going to be a longer post (this is why it is using headings, in a desperate attempt to give it some structure). As long as we've been just fooling around on the software side it was fine to do everything on the Raspberry Pi itself. In fact, Raspbian comes with a decent set of editors, compilers and interpreters so you can get started right away. But here comes the first downside to this: My little Robo is headless. Both in a very literal way and because it does not have a display attached to the Raspberry Pi. In fact, the way it is constructed right now the Pi's HDMI connector is not easily accessible. And even if it were, I wouldn't want to plug a keyboard, a mouse and a display into the robot everytime I want to change it's software. Moreover, I might have to debug it while in action later on, and I have a feeling that a robot dragging mouse, keyboard and display after it while roaming around wouldn't make this task any easier.

WIFI, we need WIFI

So to make my life quite a bit easier, I ordered a Wireless USB 11N Nano Adapter from http://www.rasppishop.de/, a mere € 6.99 that are well-invested indeed. To get the WIFI up an running, you have to configure it to connect to your router of course. If you are interested, howtogeek.com has instructions for Raspbian. 

Talking to my little Robo, remotely

Now that WIFI is setup, I should be able to talk to my robo as long as it is in WIFI range. No need to attach keyboard or mouse, or even a network cable. To log into the robot, we need one more thing: SSH. If your desktop PC or laptop runs Linux or Mac OS X, you are all set already. All you need to know is the robot's IP address or, more elegantly, its hostname (which can be set in /etc/hostname on your Raspberry Pi). When you connect to your robot, you have to specify a username that exists on the robot. Raspbian comes with a default user called "pi". This is what I'm using on my robot, I merely gave it a new password. To connect to the robot as user "pi", open a terminal window on your PC and type

ssh -l pi mylittlerobo

During the first login, ssh will ask you to confirm the identity of the host you are connecting to. In a controlled environment like ours (the robot being on the same network), it should be safe to just answer yes to this question and not be bothered with it again.

You can now work on the commandline, e.g. start your favorite editor and start writing software. If you are working on Linux (or OS X with an X window system installed), you can specify the -X when logging into the robot. This will enable X forwarding, so you can even start graphical applications such as the Arduino Sketch editor:


If you are missing out on a piece of software, type apt-get install <package-name> to install it. This is clearly a start.

To recap: With the right tools installed, we can now log into our robot and use it to program our robot right there. All software, regardless of language, lives on the robot. We can even use Git or Mercurial to do version control (locally or with a remote repository e.g. on https://github.com/).

There are disadvantages to this setup, however:

  • Especially when using a graphical IDE such as the Arduino Sketchpad, you will usually notice quite a bit of latency.
  • Version control in its simplest form will be done locally. Sure you can upload your stuff to Github, but you will want to put some thought into this, because you might not want to share all your sources with the world (or at least not at the very beginning).
  • We will write lots of code and as our software grows more complex, less and less of it will interact with hardware directly. During development, we will have tons of tests we want to execute instead. While our Raspberry Pi is fast enough for controlling a robot, wouldn't it be nice if we could execute our tests at "maximum speed", that is, using a powerful desktop CPU instead of the Pi's ARM CPU?
We will tackle these disadvantages in part two of this post. Stay tuned for more :-)









Tuesday, August 19, 2014

Robo UI - Part 1

This is the beginning of what I expect to become a bit of a larger story: My little robot needs some kind of UI. First and most obviously, because it is supposed to create kind of a map, and I need to display that map somehow. But also, because I will probably need a bunch of additional controls: sensors and motors will need calibration, and I might want to build some manual controls for steering. As mentioned this is going to be a somewhat larger story, and this is why:
The map will not be there all at once. Instead, it will build up gradually as the robot is moving about. I will want both the robot's location (and orientation) as well as the map in progress to be updated continuously. So I guess a little Java-Script coding will be in order, in addition to some server-side code that will export a simple http service. But so far, we are not there yet. Instead, I built a very primitive piece of server code that looks vaguely like this:

RoboRequestHandler - A simple web UI for our Robot

This UI implements simple http and some dynamic content
such as a map and a json protocol for status information

'''
class RoboRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

  def do_GET(self):
    if self.path == "/":
      SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
    elif self.path == "/dyn/map.jpg":
      self.handle_dyn_map()
    else:
      self.send_response(403)
      self.send_header("Content-type", "text/html")
      self.end_headers()
      self.wfile.write("<html><head><title>403 Forbidden.</title></head>")
      self.wfile.write("<body>403 Forbidden.</body></html>")

  def handle_dyn_map(self):
    self.send_response(200)
    self.send_header("Content-type", "image/jpeg")
    self.end_headers()

    i = Image.new("1", (320, 200), color="white")
    draw = ImageDraw.Draw(i)
    draw.ellipse((0,0,319,199), outline="black")

    i.save(self.wfile, format="JPEG")

# Start a web server and return
def start():

  # Listen on standard http port to test privileges
  PORT = 80

  Handler = RoboRequestHandler
  httpd = SocketServer.TCPServer(("", PORT), Handler)

  print "http serving at port", PORT
  thread.start_new_thread(httpd.serve_forever, ())

I use Python's SimpleHttpRequestHandler as a basis for a custom RoboRequestHandler. The reason for doing so is because this way I can easily serve static content by delegating to the base class (it wouldn't be much of a big deal in either case, I know. But why repeat code that's already there?) It seems like a good idea to not give people access to all the files in the robot's software working directory, so we return a 403 response for everything we don't want people to see. We will happily serve an index.html file located in our working directory, though. And contained in that is an image, dynamically generated by the handle_dyn_map method and served as "/dyn/map.jpg". This is all a bit static for now, but I guess you can see where this will be going:

Don't blame me for having come up with the most ugly html page ever. I promise to keep improving on it ;-)

Sunday, August 17, 2014

Software to control the motors

Now, I think I did not yet reveal to you why I chose the particular setup of having an Arduino plus Motorshield v2.0 drive the DC motors of my robot. The answer is surprisingly simple: The Adafruit Motorshield v2 is a pretty awesome piece of hardware that allows you to control up to 4 DC motors, two stepper motors and two servo motors at the same time. Way enough headroom for future ideas. The Motorshield v2.0 is controlled via I2C bus, so I guess in theory I could wire it up to the Raspberry Pi directly. For this first version of my robot, however, I decided to connect it to the Arduino and write a very small piece of Sketch code to run on the ATMega controller. All it will do is to accept motor control commands from its serial interface and pass them on to the motor shield. The Arduino comes with a USB COM port driver chip, so connecting the Arduino to the Raspberry Pi is as simple as plugging in a USB cable and figuring out the device special file to use on the Raspberry Pi side. This is the sketch I put on the Arduino:

/*
  Control code for DC motors using Motor Shield 2
  
  This code reads commands in the form of n{+,-}x\n where
  n is the motor number and x is the desired speed.
  Use '+' to let the motor run forward and '-' to
  let it run backwards.
  
 */
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

const int numMotors = 4;

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *motor[numMotors];

void setup() {
  // initialize serial:
  Serial.begin(115200);
  
  // Initialize motors
  AFMS.begin();
  for (int i = 0; i < numMotors; ++i) {
    motor[i] = AFMS.getMotor(i + 1);
  }    
}

void loop() {
  while (Serial.available()) {
    int motoNum = Serial.parseInt();
    char sign = Serial.read();
    int speed = Serial.parseInt();
    if ((Serial.read() == '\n') && (motoNum < numMotors)) {
       // and execute command
       motor[motoNum]->setSpeed(speed);
       motor[motoNum]->run((sign == '+')?FORWARD:BACKWARD);
       Serial.print("Set motor ");
       Serial.print(motoNum);
       Serial.print(" to ");
       Serial.print(sign);
       Serial.println(speed);
    }
  }
}

The Raspberry Pi counter part is implemented in Python and looks like this:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# import required modules
import serial
import time

# main function
def main():
  comm = serial.Serial("/dev/ttyACM0", 115200)
  while True:
    for m in range(0,4):
      for s in range(0,256):
        comm.write(str(m) + "+" + str(s) + "\n")      
        time.sleep(0.1)

if __name__ == '__main__':
  # call main function
  main()

This will make the robot turn on its motors, one after another, and gradually bring them to full speed.
Not very useful, but I think it shows the trick.


Saturday, August 16, 2014



So we have an ultrasonic sensor now, courtesy of SainSmart. This sensor is particularly straight-forward to use. The only thing to actually take into account is that the GPIO pins of the Raspberry Pi use a signalling voltage of 3.3V, while our sensor produces 5V. So following the excellent instructions at http://www.gtkdb.de/index_36_2272.html, I built a voltage divider, using a screw terminal to fixate the resistors. Running a small Python test script finally confirms that the sensor is working. I've connected it directly to the Raspberry Pi for now as opposed to wiring it up to the Arduino. Let's see how that goes. The sensor's logic is simple: Setting its input to high for about 10 μs will trigger a measurement. You then count the time until its output pin becomes high. Now the time counting piece is what makes me a bit worried as I start doing more complex stuff on the Raspberry Pi. Plan B would be to wire the sensor to the Arduino, whose ATMega controller is capable of dealing with this in real time.

Welcome to my blog

I've been passionate about building a robot for a while. Not just a simple one, but one that would actually be able to do something useful. Lots of ideas have crossed my mind... but I decided to start with something fairly simple: A robot that will be able to track its location, without any prior knowledge of its surroundings. Watch this blog to see what comes out of it, but notice that I'll try to not only cover the essentials, but will report about the practical advancements I make.


A nice supply of batteries, delivering 7.2 V at 3000mAh. The Raspberry Pi I'm planning to use is pretty picky about voltage, so I'm using a voltage regulator to deliver a stable 5V via a custom made USB power-plug cable. To get a USB plug, I recycled a mobile phone charger (be careful with this, the condensators in chargers and power adapters may remain charged for quite a while!)


















While I was at it, I also did some further recycling work: The thingy below used to be a DVD burner. I turned it into a pile of parts, some of which are stepper and servo motors. Just the stuff I might need later on.






And this is the first tangible result: The wiring is pretty much complete at this stage, but so far the robot is missing any kind of sensor at all.