Pages

Friday, 28 June 2019

Sambot - MeArm, servos, the Babelboard and Jetson Nano

Jud McCranie CC BY 3.0 via Wikimedia Commons
Way back in 1974 I took Tom Westerdale's Adaptive Systems course as part of my Masters degree. Tom's thesis advisor was John Holland, and a lot of the course covered genetic algorithms. Before that it covered early machine learning applications like Samuel's Checkers Player.

I've wanted to revisit those early AI applications for a while, and I recently decided to put a new spin on an old idea.

I want to build a robot that plays Checkers (that's draughts to us Brits) using a real board, a robot arm and a Jetson Nano using a Raspberry Pi camera.

The game play could be done using a variant of Samuel's approach, a Neural network, or a combination of the two. If AlphaGo can master Go playing against itself it shouldn't be too hard for a pair of Machine Learning programs to maser draughts!

First, though, I need to build a controllable arm that can pick up and move the pieces and a computer vision system that can recognise the location of the peices on the board.

I'm up to my eyes in projects and work at the moment, but I have justified making a start on the robot arm because it ties in nicely with a current priority. It's a chance to explore and explain how to do Physical Computing with the Jetson Nano.

Jetson Nano
One of the many things I love about the Nano is its use of the Raspberry Pi header layout. The Nano's heatsink (needed to cool its GPU brain) means that Pi hats cannot sit over the Nano, but the Pi header has been rotated thought 180 degrees, allowing you to use Raspberry Pi hats unmodified.

Recently I've been making use of the Grove system from Seeed studio, and I've built a series of low-cost boards to let me use the Grove components with the Pi, the Nano and Adafruit Feathers. I call them babelboards.

They are the hardware hacker's equivalent of Douglas Adam's babelfish. They allow lots of different hardware components to talk to each other using the I2C protocol.

Nano with minimal babelboard
The simplest Bableboard is a small piece of stripboard with a couple of connectors. On the right you can see it plugged into a Nano, with a Grove 4-wire cable plugged in, driving a Grove 16-channel servo controller. That's overkill, as I think my Checkers player will only need 4 servos, but I happen to have one to hand.

I've had a MeArm robotic arm waiting for me to assemble it for ages, and today I made a start. I'll talk more about that in a later post, but today I will focus on getting the Nano to control the MeArm's four servos.

The Grove servo controller uses the PCA9685. That's the same chip that Adafruit use in their servo controllers, and they have a Python library to control it.

Better still, Adafruit have ported their Blinka library to the Pi and the Nano so you can use their family of CircuitPython libraries on the Pi and the Nano as well as the Adafruit CircuitPython boards. Awesome!

I installed the software following the instructions on the Adafruit website, by invoking


pip3 install adafruit-circuitpython-servokit --user
Since some of the Adafruit code uses gpio as well as I2C, I made sure I could access them all from my user account, and then rebooted to make the changes take effect:

sudo groupadd -f -r gpio
sudo usermod -a -G gpio $USER
sudo usermod -a -G i2c $USER
sudo cp /opt/nvidia/jetson-gpio/etc/99-gpio.rules /etc/udev/rules.d/
sudo reboot


Next I connected a servo to the servo controller, and ran some sample code from the Adafruit website:

import time
from adafruit_servokit import ServoKit

kit = ServoKit(channels=16)
kit.servo[0].angle = 180
time.sleep(1)
kit.servo[0].angle = 0

And lo - the servo moved!

In the next post I'll give more details about the Babelboards and how to build them.

If you want to keep an eye on what I'm up to, I'm @rareblog on Twitter.

Monday, 24 June 2019

An excellent course for Jetson Nano owners

Jetson Nano
Regular readers will know than I'm a keen Jetson Nano owner.

Recently I posted a series about how to started with the computer but NVIDIA have now published an excellent course,  'Getting Started with the Jetson Nano', which is  free for members of the NVIDIA developers' program.

The course comes with a pre-built image which can run the Nano in headless mode. That's very useful - I had to buy a new monitor to get going, as none of my old monitors had native HDMI support.

The image provide with the course just needs a Nano and a Laptop or Desktop computer with a USB port.

The course is a great introduction to deep learning with a GPU. Once you've completed it you may want to delve deeper; there are lots of excellent Deep Learning courses available on-line, and many of them use Google's Colab for practical sessions.

Google Colab gives you free access to top-of-the range NVIDIA hardware, and if you want to run your trained models locally it's easy to move them onto the Nano. Of course the Nano is small enough to use for mobile robotics!

I'm designing an autonomous robot with the Nano, and I have been delighted with Adafruit's Nano port of their Blinka library. It makes it really easy to write Physical Computing code that runs without change on the Nano, the Raspberry Pi and  Adafruit's CircuitPython-enabled boards.

Come and see the Nano


Tomorrow I'll be at the London Raspberry Pint meet-up showing a Nano driving Adafruit, Grove and SparkFun peripherals using a simple interface board (the babelboard) and some straightforward Python code.

If you're in or near London, do come along. The meet-up starts at 7 PM. It's at CodeNode, and you'll save a lot of time if you pre-register at the CodeNode site.

If you can't join us, a video of the talk will be available in a few days and I will be blogging more about the babelboard later this week.

Thursday, 20 June 2019

Use websockets to build a browser-based Digital Voltmeter

This is the third and final part of a series about building a browser-based six-channel Digital Voltmeter (DVM) using an Arduino and a Raspberry Pi.

Part one covered the software on the Arduino and the USB connection to the Raspberry Pi.

Part two showed you how to use the pyserial package to read that data into a Python program and print the results as they arrived.

In this final part you'll see how to use Joe Walnes' brilliantly simple websocketd. You'll see how you can turn the Python program into a server without writing any additional code! Finally, you'll view a web-page that displays the voltages in more or less real-time.

Web sockets with websocketd


HTTP makes it easy for a web browser to ask for data from a web server. That approach is known as client pull because the client (the web browser) pulls (requests) the data from the server.

For the DVM application you want to use server push; in other words, you want to send changes in the voltages from a server on the Raspberry Pi to your browser. Websockets give you a simple, well-supported way of implementing web push.

You'll use websocketd to send the data from the Pi to the browser. websocketd is a really useful program which allows you to wrap any program or script that prints output and send that data to a browser via a websocket. (You can send data back from the browser as well, but the Web DVM doesn't need to do that.)

Four steps to use websocketd


I followed four simple steps to install and use websocketd with the Python program form part 2.

  1. I installed the Python program which you saw in Part two.
  2. Next  I copied the websocketd binary program onto your Raspberry Pi.
  3. I installed a web page with some simple javscript as well as some html.
  4. To wrap the program, I started websocketd and told it where to find the program it should run. For the web DVM I wanted webstocketd to act as a conventional web server. To do that, I provided an extra parameter telling websocketd where to find the web pages to serve.
To make things as simple as possible I have set up a public repository on GitHub which contains all the required software as well as the web page you'll need.

As you'll see below, you just need to download and unzip a file and then run the command that starts the server.

If you're a confident GitHub user you can fork or clone the repository instead of downloading the zip file.

The code on GitHub assumes that you are using a Raspberry Pi with the hostname of raspberrypi. If you want to use your own choice of hostname, you'll need to make one simple change to the web page. I'll cover that in the final step of this post.

Installing the Web DVM project on the Pi


Open a terminal window on the Pi and move into a directory of your choice.

Type

wget https://github.com/romilly/WebDVM/archive/master.zip
unzip master.zip
cd cd WebDVM-master/
./websocketd --port=8080 --staticdir=. ./read-dvm.py

You should see websocketd displaying messages as it starts up.

 

 Testing the application

If you open a browser on rasberrypi:8080  you should see a web page like this >>

For demo purposes, I've connected the analog inputs to various fixed and variable voltages. For example, A0 is ground,  A2 is connected to a light-dependent resistor and A3 is connected to the Arduino's 5V rail.

How does the web page work?


The web page is a basic html page with a little JavaScript.

Here's index.html:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Web DVM</title>
</head>
<body>
<h1>Web DVM - 6 Analog Channels</h1>
<div>A0: <span id="A0"></span></div>
<div>A1: <span id="A1"></span></div>
<div>A2: <span id="A2"></span></div>
<div>A3: <span id="A3"></span></div>
<div>A4: <span id="A4"></span></div>
<div>A5: <span id="A5"></span></div>
<script>
    
  // setup websocket with callbacks
  var ws = new WebSocket('ws://raspberrypi:8080/');
  ws.onopen = function() {
  };
  ws.onclose = function() {
  };
  ws.onmessage = function(event) {
      data = event.data.split('=');
      if (data[0].length === 2) {
          document.getElementById(data[0]).textContent = data[1];
      }
  };
</script>
</body>
</html>


The work is done by a small bit of JavaScript. The code
var ws = new WebSocket('ws://raspberrypi:8080/');
opens a websocket.

That's the bit of code you'll need to change if you want to use a different hstname for the Pi.

Whenever the websocket receives a message, the
ws.onmessage
code processes it and updates the contents of the web page.



Summary


In this three-part series you've met several useful techniques, and built the WebDVM. That's a useful piece of Test Equipment!

You can use the approach to  make lots of different measurements, and there are several ways in which you can add functionality.

In a future blog post I'll show you how to add scrolling graphics to your web-based DVM.

The babelboard is coming


Before that I'll be exploring the babelboard, another simple tool which you can use to quickly prototype physical computing applications.

The babelboard can be used with a Raspberry Pi or a Jetson Nano. Later posts will show how to build versions for the Adafruit feather and the BBC micro:bit.

The babelboard is a simple piece of open source hardware which you can build in an hour using readily available components.

To make sure you don't miss the next series, follow @rareblog on Twitter!
 
 

Friday, 14 June 2019

Using pyserial on a Raspberry Pi to read Arduino output - WebDVM part 2

This series describes how to build a simple web-based DVM (digital volt meter) that can display up to six voltages in a web browser.

It's a really useful hack if you need to measure several voltages at once.

In part 1 you saw how to send analog voltage data over a serial link to a Raspberry Pi. For testing purposes you displayed the data in a terminal window on the Pi.

In this part you will use read that data using Python on the Pi and print the data to standard output.

In the next part you'll turn your Python script into a dynamic application that displays the 6 voltages in a browser, updating the web page as the values change.

The code (available on github) uses the pyserial package. It's a simple approach, but there are a few issues to find your way around. You'll see the problems and solutions below.

Pyserial


pyserial is a Python package that allows Python programs to read and write data using serial ports. You can install it via pip.

pip3 install pyserial

When you connect the Arduino to the Pi via a USB cable, the Arduino connection appears as a serial port.

That's where the first problem bit me.

For part one of this series I used a Raspberry Pi zero with an Arduino Uno.
When I connected them the Arduino connection showed up as device /dev/ttyACM0.

For part two, I decided to use an Arduino Nano instead of the Uno. The Nano is smaller and cheaper than the Uno. Like the Uno it has six analog ports, so it looked ideal.

When I ran the software it fell over.

I did a quick check listing the teletype devices in /dev/tty*

There was no /dev/ttyACM0 but there was another new device: /dev/ttyUSB0.

I'd forgotten that the Nano uses a different approach for its USB-to-serial converter, and the Pi sees it as a different device.

So the software now starts with a check to see which device is available.

devices = [port.device for port in list_ports.comports()]
ports = [port for port in devices if port in ['/dev/ttyACM0','/dev/ttyUSB0']]
if len(ports) != 1:
    raise Exception('cannot identify port to use')
port = ports[0]

Once the script has found which prot to use,  pyserial reads from that device in much the same way as you would read from or write to a file.

Unlike a file, though, data will only be available to read once the Arduino has sent it! For that reason, the script wraps the serial connection in a buffer.

It also needs to  convert the serial input from a series of bytes to a unicode string.

Unfortunately, there is no way to synchronise the Pi and Arduino when they first connect. This means it's possible that the Python program starts reading an invalid sequence of bytes, so the program needs to cope with an error when the bytes are converted to a string.

Here's the code that does all that:

with serial.Serial(port, 9600, timeout=TIMEOUT_SECONDS) as ser:
    # We use a Bi-directional BufferedRWPair so people who copy + adapt can write as well as read
    sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
    while True:
        try:
            line = sio.readline()
        except UnicodeDecodeError:
            continue # decode error - keep calm and carry on

Next the program checks to see that a non-empty line was actually received, prints it to standard output, and flushes the newly printed information. That last step is necessary to make sure that new data is printed out as soon as it has been received. That will become vital in part three of this series.

       if len(line) > 0:
           print(line)
           sys.stdout.flush() # to avoid buffering, needed for websocketd

Part three will describe how to make the anaolg data available in a browser that updates in real time. While you're waiting you can take a look at the code on github.




Tuesday, 4 June 2019

Build a Web-based DVM using Arduino and Pi zero W

This three-part series show you how to build build a Web-based 6-channel DVM (digital voltmeter)  using an Arduino and Raspberry Pi zero.

If you’re experienced and impatient you will find software and basic installation instructions on GitHub.

If you’re less experienced, don’t worry. All you need to know is:
  1. how to compile and download an Arduino sketch,
  2. how to connect your Raspberry Pi to your network, and
  3. how to open a terminal session on the Pi.
The project is fun, useful, and simple. You probably have the parts already, in which case the whole project will take about an hour to program and connect. You don’t need to solder anything.

The WebDVM uses some general techniques that you can apply to projects of your own

In Part 1 (this post)  you will install some simple Arduino code, connect the Arduino to a Pi, and check that the two are communicating.

In Part 2 you’ll use a short Python program on the Pi to read the Arduino’s output.

In Part 3 you'll use a simple technique to turn your Python program into a web server, and you'll use HTML and JavaScript to format the output. You’ll see the web page displaying the voltage the Arduino’s six Analog inputs in real-time.

Why Pi and Arduino?



The project plays to the strengths of both platforms.

The Arduino has 6 analog inputs.

The Pi zero runs Python, it can connect using WiFi without extra hardware, and it’s inexpensive.

Both are widely available.

What hardware do you need?


Here’s what I used:
  1. An Arduino Uno.
  2. A Raspberry Pi zero W with wifi set up.
  3. A battery to power the hardware.
  4. Cables to connect the Pi and Arduino, and to provide power to the Pi.
  5. Something that runs a web browser on the same network as the Pi.

I used an Arduino Uno but an older model or a Leonardo would be fine. If you have a nano or mini you will need a way of connecting what you want to measure using a breadboard and/or headers.

You can use a full sized Raspberry Pi if you want. Any model will work, and you can use a wired (Ethernet) connection instead of wifi.

Arduino software


The Arduino sketch is really simple. It
  1. sets up serial communication,
  2. reads each analog input, and
  3. prints the voltage to serial output.

Here’s the sketch:

const float vcc = 5.0;
const float scale = vcc / 1023;
const int analogPins[] = {A0, A1, A2, A3, A4, A5};
const int delay_ms = 50;
const int channels = 6;

// 6 Channel DVM over serial connection


void setup() {
 //Initialize serial and wait for port to open:
 Serial.begin(9600);
 while (!Serial) {
 }
}


void loop() {
 // read each Analog channel, scale it,
 // and print a formatted version to the Serial output
 for (int i = 0;i   float v = scale * analogRead(analogPins[i]);
   Serial.print('A');
   Serial.print(i);
   Serial.print('=');
   Serial.println(v);
   delay(delay_ms);
 }
}

Compile and upload the sketch to the Arduino.

If you open the serial monitor, you should see a window like this:


Now connect the Pi to the Arduino.

If you use an Arduino Uno or Leonardo, you’ll need a USB cable with an A-type connector at one end; it will probably have a B-type connector at the other. If you want to connect that to a Pi zero, you’ll need an adapater; if it’s a full sized Pi you wan connect directly.

Open a terminal window on the Pi.

If you type  
ls la /dev/ttyACM0
you should see an entry for /dev/ttyACM0



/dev/ttyACM0 is a temporary teletype device that raspbian created when you connected the Arduino.

It’s owned by root, and is in the dialout group. As user pi you should already be a member of the dialout group, so you can access the device.

Type

cat -v  /dev/ttyACM0

This lists the output that the Pi is reading from the Arduino, with non-printing characters displayed.



The ^M characters are newlines sent by the Arduino after each Analog reading.

Coming next


That concludes the first part of the project. In the next part you’ll read the Arduino’s output in a Python program on the Pi.

Don't forget to follow @rareblog on Twitter to see when the next part is posted!