Mark Gilbert's Blog

Science and technology, served light and fluffy.

Rover v2: Technical Breakdown

In Episode 31, Lucy and I show off the new Raspberry Pi-powered rover that we built.  In this post, I’ll go into the technical details of how we did it.

Parts List

The GPIO Overlay is a simply piece of thick paper with holes punched so that it can sit over the pins on the RPi, and has labels for all of them.  It was a minor indulgence, but it made hooking up the wires so much faster.

Up to this point, I only had male-to-male hookup wire, which worked great going from an Arduino’s female pins to a breadboard.  The RPi, however, comes with male pins, so I had to buy some different hookup wires.  This particular set worked extremely well, even when placed on consecutive pins on the RPi.

Each of the TN6612FNG motor drivers could control 2 motors, and since the chassis was a four-wheel drive, I purchased two of these boards.  So far, the rover only moves its motors in pairs (the left wheels always move in the same direction as each other; ditto for the right wheels), so I probably could have gotten away with a single motor driver.

Prepping the Motor Drivers

The first thing I did was solder some straight headers onto the two motor drivers.  That allowed me to place the drivers onto the breadboard, and wire them up with the hookup cables.  It also means we can completely tear the rover’s components down, and re-use these drivers with other projects.

On the podcast I mentioned that I soldered the headers in upside down.  That was so I could read the pinouts printed on the underside of the board.  That saved me having to think about which pin was which when I was wiring it up.

Raspberry Pi

We wanted to be able to upload programs to the Rover remotely, without a tether.  While it is possible to wirelessly reprogram an Arduino, I thought it would be simpler and a little less expensive to do so with the Raspberry Pi 2 (RPi) and a wireless USB dongle.  The RPi would appear on our home network as just another device, which means we could remote into it from any of our other machines.  I had also never worked with an RPi, and this project gave me the perfect excuse to learn.

So, the first task was to get the Raspberry Pi configured so that it could boot "headless" – without a keyboard, mouse, or monitor connected.

But before I could do any of that, I found I had to get an operating system for it.  I mistakenly assumed that the RPi would come with Linux pre-installed, and I could just boot it up.  When I got the unpacking instructions, and Step 2 was "Insert your microSD card", I had to stop and re-evaluate that assumption.

I started by temporarily appropriating the microSD card I’ve been using for my wearable, and formatted it using the SD Association’s Formatting Tool.  Next, I downloaded the basic, and appropriately-named, OS package called "noobs", for "New Out-Of-The-Box Software".  This was actually Debian Linux optimized for the Raspberry Pi (hence its proper name "Raspbian").  I extracted the contents from the ZIP file, and copied them to the root of the microSD card.

When that was done, I put the card into the RPi, and booted it up.  The RPi provides onboard HDMI output for video.  Luckily we had a male-to-male HDMI cable, but the only "monitors" we own with an HDMI input are actually our TVs.  I set up a card-table in front of one, and ran extension cords for power, plugged in a mouse and keyboard, and fired up the RPi.  It allowed me to select which operating system to boot into – my choices were Rasbian Linux, or direct to Scratch.  If you’ve never seen or used Scratch, it’s worth it to check it out.  It’s a visual programming language, where all of the statements like "if then" or "while" are actually blocks that you can snap together.  Only compatible blocks will fit, so it’s very easy for kids to learn what makes up a valid statement.  This was at the top of my list for the programming language for the Rover, so seeing a "boot straight to Scratch" was a nice bonus.

For now, though, I focused on just trying to get the RPi running Raspbian on our network.  Having relatively little experience with Linux compared to Windows, this was harder than I had anticipated.  I spent three nights playing settings-roulette, trying to get the RPi to be visible on the network, with a static IP, so I could remote into it.  (For the record, this had nothing to do with the Raspberry Pi – this was purely me being a noob when it comes to Linux.)

My network is WEP-secured, so I had to find a way to pass the network ID and key from the RPi.  I read several posts talking about modifying the /etc/network/interfaces, and ultimately that is what I ended up doing.  Here is my final interfaces file:

    # The loopback network interface
    auto lo
    iface lo inet loopback

    # The wired network interface (using dhcp)
    iface eth0 inet dhcp

    # The wifi network interface (static IP)
    auto wlan0
    allow-hotplug wlan0
    iface wlan0 inet static
        address 192.168.1.202
        netmask 255.255.255.0
        gateway 192.168.1.1
        wireless-essid ID_Here
        wireless-key Key_Here
        dns-nameservers 12.34.56.78 12.34.56.79

    iface defalt inet dhcp

Obviously, the "ID_Here" and "Key_Here" portions were replaced with my actual ID and Key.  One of the issues I had was how these appeared in the file, specifically with or without being surrounded by double-quotes.  The configuration that worked was without – the ID and Key just appear inline.

Additionally, the DNS Server IP Addresses shown here are fake – I filled those in with my provider’s actual IPs.  I ended up downloading a package directly to the RPi (see below), which meant the RPi needed to be able to get to more than just my home network.

With this setup, I could boot the RPi up on my desk, wait a minute or so, and then remote into it using PuTTY.  The RPi was now officially headless.

FTP Server

The next piece of the puzzle was an easy way to upload our programs to the RPi.  For that we needed an FTP server.  I looked at a couple of FTP servers for Linux, and settled on vsftpd.  I followed this procedure for setting it up (minus the initial step of changing the permission on the /var/www folder, since that’s not where I wanted things to be uploaded to).  It took me about 5 minutes to get installed and configured, and works like a champ.

Programming Language

Now it was time to decide what language would we be programming in.  As I mentioned before, I favored Scratch for its simplicity.  However, I also wanted to be able to define custom blocks to represent the commands MoveForward, MoveBackward, TurnLeft and TurnRight.  I found that Scratch 2.0 allows you to do exactly that.

Unfortunately, Scratch 2.0 requires Adobe Air, which does not run on the RPi.  The latest version of Scratch that does run on the RPi – version 1.4 – doesn’t allow us to define custom blocks.  So, scratch Scratch.

The next easiest language was Python, which also came bundled with Raspbian, so we went with that.  Now the question became how do we control the general purpose input/output (GPIO) pins on the RPi using Python?  For that, we turned to a Python module called RPi.GPIO which does exactly that, and which also came bundled on the OS image.

To control our motors, we simply needed to set the correct GPIO pins either high or low.  Doing that using the RPi.GPIO module is trivial:

    import RPi.GPIO as GPIO

    GPIO.setmode(GPIO.BCM)

    GPIO.setup(18, GPIO.OUT)
    GPIO.setup(23, GPIO.OUT)

    GPIO.output(18, True)
    GPIO.output(23, False)

    GPIO.cleanup()

Let’s break this down:

    import RPi.GPIO as GPIO

This simply imports the RPi.GPIO module, and gives it a local name of "GPIO".

    GPIO.setmode(GPIO.BCM)

This sets up the board in "BCM", or "Broadcom SOC channel" mode.  The other available option is "GPIO.BOARD", which simply numbers all of the GPIO pins from 1-40.  You can find out more information about these two modes, and what the numbering is, from this post on StackOverflow.

    GPIO.setup(18, GPIO.OUT)
    GPIO.setup(23, GPIO.OUT)

Like with an Arduino, you need to configure which pins you will be using, and whether they are going to be inputs ("GPIO.IN") or outputs ("GPIO.OUT").  In this example, I’ve configured pins 18 and 23 to be outputs.

    GPIO.output(18, True)
    GPIO.output(23, False)

Each pin can be set high ("True") or low ("False").  In this example, I’ve set pin 18 high and pin 23 low.

    GPIO.cleanup()

I found that if I didn’t reset the pins after each execution of the program, it would throw a bunch of warnings the next time I ran it, to the effect of "that channel is already in use".  So, I needed to be a good little Boy Scout, and clean up after myself.

Another interesting things I learned about the RPi is that all of the channels are digital.  The RPi doesn’t do analog at all – at least not natively.  I did find a post on the Raspberry Pi forums that described building a "poor man’s analog" circuit from a resistor and a capacitor in parallel, but for our first attempt I figured "on" and "off" for the motors would be sufficient.

Getting the wheels moving

Now it was time to put everything together, and actually get the rover moving.  Using this hookup guide, I wired up one set of wheels with the first motor driver, the battery pack that came with the rover chassis (which held 4 AA batteries) and the RPi.

Each motor required 5 pins on the motor driver – 2 that would lead to the motors themselves, and 3 that would be connected to the RPi: IN1, IN2, and PWM.  Form the RPi’s perspective, IN1 and IN2 were always set to be opposite to each other – one high and one low.  Setting IN1 high would drive the motor in one direction, and setting IN2 high would drive it in the other.  The PWM channel was basically the speed at which the motor would turn.  If I were using an analog signal, I could send a number from 0 to 255, where 0 is "stop" and 255 is "ramming speed".  Since I could only generate a digital signal, I just set this channel high (True, or the equivalent to 255) when I wanted the motor to turn, and low (False, or the equivalent to 0) when I wanted it to stop.

Once it was all wired up, it was just a matter of setting the correct pins high or low.  I started by creating my basic control functions:

    MoveLeftWheels(direction)
    MoveRightWheels(direction)
    StopLeftWheels()
    StopRightWheels()

Where "direction" is one of two constants (also defined in the script) – FORWARD or BACKWARD.  The wheels would keep turning until I explicitly told them to stop, which meant something like "MoveForward" was really a combination of "move all the wheels forward, wait a moment, and then stop all the wheels":

    def MoveForward(distance):
        MoveLeftWheels(FORWARD)
        MoveRightWheels(FORWARD)

        time.sleep(.1 * distance)

        StopLeftWheels()
        StopRightWheels()

        time.sleep(1)

We wanted to be able to control how far the rover moved with each step, so this function takes a parameter called "distance", which gets converted into the number of seconds to run the motors.  I wanted to be able to have the numbers represent the number of centimeters to move the rover.  However, these aren’t stepper motors, so we couldn’t get very precise with them.  The basic idea holds, though: pass a larger number to MoveForward, and the rover will move further (or at least, the wheels will turn for a longer time).

The "time" module is actually another Python module, and is included in the script by simply adding "import time" at the top.  The "sleep" function takes a parameter in seconds, or fractions of a second.  The RPi doesn’t go to sleep like a laptop goes into hibernation, though.  Whatever GPIO pins I set high and low would retain their settings while the RPi was "sleeping", which meant the motors would keep running.  Basically the MoveFoward function says "Run the motors forward while I snooze, and when I wake up I’ll tell you to stop."

Once I had this working, I wired up the second motor driver and the other two motors, and wrote the other three functions:

  • MoveBackward looks just like MoveForward, except it moves the wheels backward (the parameter passed to MoveLeftWheels and MoveRightWheels is BACKWARD instead of FORWARD).
  • TurnLeft() involves running one set of wheels (either left or right) in one direction, and the other set in the other direction.  These functions don’t currently take a parameter (for degrees of arc, for example), but they could be easily modified to do so.  With our current setup, though, turning will be just as imprecise as movement is.
  • TurnRight() does the same thing as TurnLeft(), but reverses the direction of all of the wheels.

I also created functions that would set the board up (SetUpBoard), and shut it down cleanly (CleanUp).  All of the commands that you want to send to the rover are made between these two calls.

The complete program, configured for use with the GPIO pins we used for our rover, can be found here.

Buttoning everything up

So far we have the hardware in place, the operating system configured, we can write programs in Python to run our motor, and we can upload them via FTP.  Now it was time to put something in place that would kick off the programs we uploaded.

My original intention was to be able to upload files to the RPi, and then have the RPi automatically run it.  That posed a couple of challenges:

  • Detect when a new program was present and run it in a timely manner.
  • Don’t try to run two programs, or two copies of the same program, at the same time.

My first thought was to set up a cron job (an automated scheduler for Linux) that would run a small shell script.  The shell script would look for new Python programs in a pre-defined folder, start them if found, and remove the program when it was done.  However, cron jobs can only be scheduled for at most once every minute.  That seemed like a long time to wait for the program to start once we uploaded it, and it would complicate debugging.  If the rover didn’t move, was it because we didn’t wait long enough, or was there actually a bug in our program? 

This approach also didn’t address the second challenge – if I managed to get the RPi looking for and running programs every 3 seconds (for example), but the current running program requires 15 seconds to complete, how do I prevent it from spinning up a second copy of the same program 3 seconds from now?

In the end, because I wanted to get the thing working quickly, I decided to just kick off the programs manually, via PuTTY.  We write our program on our laptop, upload it to the rover via FTP, then execute the program from the command line like so:

sudo python rover.py

It would not surprise me at all to learn that someone has built a better cron for Linux, so we can revisit this piece later.

What’s next?

We’d like to add a digital camera and transmit back pictures (or rough video) of what the rover was seeing.  That would add to the illusion that this little rover is on another planet, and we’re Mission Control.  The RPi actually has a dedicated camera slot onboard, and we’ve considered getting this camera for it sometime in the future.

The impreciseness of the motors in moving and turning can get a little frustrating.  Short of getting a different chassis with more precise motors, I’ve wondered if we could add a gyroscope or an IMU to the RPi to improve at least the turning.  We would send a TurnLeft or TurnRight signal to the RPi, and instead of simply running the motors for a certain number of seconds, the RPi would read the input from the gyroscope to determine when it had completed a 90 degree turn.

It occurred to me after the fact that having the entire operating system on the SD card meant that I could configure other operating systems, and swap them in when I needed.  Windows 10 IoT Core, for example, will run on the Raspberry Pi 2, so that may be something for us to explore later.

 

All in all, this was a fun project, and I’m still amazed at how quickly it came together.  I think we’ve put together a great platform for experimentation.

August 7, 2015 Posted by | Engineering, Raspberry Pi | Leave a comment

Science & Technology Podcast, Episode 31 – Rover v2

In this episode, Mark and Lucy build a programmable rover based on the Raspberry Pi 2:

https://markofquality.wordpress.com/2015/08/01/science-technology-podcast-episode-31-rover-v2/

August 1, 2015 Posted by | Podcast, Science | Comments Off on Science & Technology Podcast, Episode 31 – Rover v2

iSelf 0.2

Over a week ago, I unveiled a project I’ve been working on tentatively called “iSelf”.  Since then, I’ve finished the rough versions of the software components (both the program that runs on the Arduino Micro, as well as the custom downloader for the device) , and and greatly refactored both. 

Late last week, I took delivery of the newest hardware components – a lithium ion polymer, or LiPo battery, and a PowerBoost 500c from Adafruit.  This morning, I hooked them both up to the iSelf prototype, and removed the set of AA batteries that I had been powering it with up to this point:

20

The “c” in the 500c stands for “charger”.  I can have a battery plugged in to power the device(battery shown at the top, center of the picture below) .

10

I can also plug in a microUSB charging cable (the black cable going off to the right of this picture), and simultaneously power the device and recharge the battery.

I have a couple of additional hardware components to work in (a power switch, and a couple of external LEDs), and probably a few additions to the software, but iSelf is nearly feature complete.  The next major tasks will be soldering the components down onto a single board, and then getting a case for it.

July 14, 2015 Posted by | Embedded/Wearable, Science | 1 Comment

Curse those bugs

I can honestly say that my day as a software developer is going FAR better than some others out there.

Curse those bugs

Source: https://news.google.com

July 8, 2015 Posted by | General, Software Process | Comments Off on Curse those bugs

What a Headache

For the last several months, I’ve been working on a new project that I’m tentatively calling "iSelf".  Here is the official version 0.1.0:

10

I’m building my own, custom wearable.  And before you ask, the answer is "no", the title of this blog does not refer to the spaghetti of breadboarding wires you see before you.  The title actually refers to what I hope iSelf will help me with.  Allow me to set this story up.

For more than a decade, I’ve had daily headaches.  I first noticed them as such in 2003.  At that point, I would feel the headache coming on mid- to late afternoon.  I would take two Excedrin with dinner, and by 8pm or so the headache would be gone.  About 2011 or 2012, I started noticing that the headaches were getting longer.  I’d feel them start earlier in the day, and it would be later into the evening before the Excedrin would kick in.

Then during the summer of 2013, I realized that I was waking up with a headache, and Excedrin was no longer knocking them out.  In other words, I’ve had a headache all day, every day, for the last two years.

In late 2013, and then much of 2014, I got even more serious about trying to determine what was causing them.  I spoke with my general doctor about it.  He had me try a couple of different medications.  When those didn’t work, he referred me to a neurologist, who tried a few different medications, which didn’t work.  He also had my head examined – both an MRI (which you can read about here).  Thankfully, nothing abnormal turned up.  They found a brain, and it showed no signs of bleeding or tumors.  Check and check.

I also went to see an ear, nose, and throat doctor.  Even after a CT scan, two home sleep studies, and a third sleep study in an overnight lab, he wasn’t able to find anything wrong with me either.

Whenever I went in for an exam or a follow-up, the doctors would usually ask me "on a scale from 1-10, how is your headache today?" and I would respond with some number.  But that question was asked once every two weeks, at most.  I don’t have the same headache every day – there are some days it is easier to move it to the background than others.  But why?  What is influencing the "badness level"?  If I can’t find a solution to the headaches and make them go away completely, could I find out if there is some external influence affecting their quality?  To answer that, I needed data – lots and lots of data.

So, in late 2014 I started sketching out what kind of data would I want to collect, and how could I analyze it.  I decided that taking readings every 30 minutes of the headache "badness level" was probably a good place to start, but I also wanted to capture things like what temperature and barometric pressure was I being exposed to (two things I’ve read affect headaches in some people).  I also wanted to record how long I stood, sat, and walked in a day.  That’s where the wearable comes in.

I considered buying an existing, off-the-shelf wearable, but after looking at a dozen different brands, I couldn’t find one that recorded the data points I wanted, and as far as I could tell none of them let me get at the raw data that they did collect.  They all had their own cloud- or mobile apps for displaying really pretty, interactive charts, but I none had anything like a "download to Excel" feature.  So, custom it was.

iSelf v0.1.0 features a temperature/pressure sensor that I scavenged off of the stratoballoon instrument pack, a microSD card reader/writer (also from the stratoballon), and an Arduino Micro as the processor.  I’m getting very near to the point where the software is ready, and I can solder the components together, get a case for it, and be able to wear it on my belt like a phone.

Eventually I’ll add an IMU (which stands for inertial measurement unit, a combination of a 3-axis accelerometer and a 3-axis gyroscope) so I can track how long I am sitting/standing/walking, and a Bluetooth Low Energy (LE) module so I can communicate with my mobile device.  The plan is for iSelf to send a signal to the mobile device (initially my Nook, but eventually a phone) to tell me to take a survey every 30 minutes.  I’ll answer one or more questions (how bad is your headache right now, are you hungry, etc.), and the mobile device will transmit the answers back to iSelf, which will add them to the raw data points that it collects directly.  At night, I’ll download the day’s data.

Once I have several weeks’ worth of data, I can start asking questions like "does my headache get worse when I’m hungry?" or "does my headache get better when I’m exposed to higher temperatures?"  I’ll hopefully be able to spot some patterns in the data, and that will allow me to create some experiments to run on myself.

There is a crazy number of things that can cause headaches.  I’ve eliminated a few.  At worst, iSelf will allow me to eliminate a few more.  At best, it will show me a couple that contribute.

July 3, 2015 Posted by | Embedded/Wearable, Science | 1 Comment

Science & Technology Podcast, Episode 30 – Baking Soda and Lemon Juice

In this episode, Mark and Lucy explore mixing acids and bases – and try to avoid volcanoes.  Given that today is the 35th anniversary of Mount St. Helens eruption, we think that’s an admirable goal.

 

https://markofquality.wordpress.com/2015/05/18/science-technology-podcast-episode-30-baking-soda-and-lemon-juice/

May 18, 2015 Posted by | Podcast, Science | Comments Off on Science & Technology Podcast, Episode 30 – Baking Soda and Lemon Juice

Science & Technology Podcast, Episode 29 – Snap Rover

In this episode, Mark and Lucy build an RC Snap Circuits Rover.

https://markofquality.wordpress.com/2015/03/29/science-technology-podcast-episode-29-snap-rover/

March 29, 2015 Posted by | Podcast, Science | Comments Off on Science & Technology Podcast, Episode 29 – Snap Rover

Science Podcast, Episode 28 – Robot!

In this episode, Mark and Lucy build a robot!

https://markofquality.wordpress.com/2015/02/14/science-podcast-episode-28-robot/

February 14, 2015 Posted by | Podcast | Comments Off on Science Podcast, Episode 28 – Robot!

Science Podcast, Epsiode 27 – Stratoballoon Rigging

Mark and Katherine describe how the capsule, radar reflector, parachute, and balloon were all held together.

https://markofquality.wordpress.com/2015/01/19/science-podcast-episode-27-stratoballoon-rigging/

January 19, 2015 Posted by | Podcast, Science | Comments Off on Science Podcast, Epsiode 27 – Stratoballoon Rigging

Science Podcast, Episode 26 – Stratoballoon Capsule Construction, Part 2 of 2

Mark and Katherine finish the details of the stratoballoon capsule construction:

https://markofquality.wordpress.com/2015/01/14/science-podcast-episode-26-stratoballoon-capsule-construction-part-2-of-2/

January 14, 2015 Posted by | Podcast, Science | Comments Off on Science Podcast, Episode 26 – Stratoballoon Capsule Construction, Part 2 of 2

Follow

Get every new post delivered to your Inbox.