Category Archives: robotics

cheap RTK-GPS hardware might soon be available!

As mentioned previously I used two loaned u-blox LEA-6T devkits for my robot mower prototype which seemed to get acceptable precision (~10-20cm) with RTK-GPS using RTKLIB. Problem with this solution was that these devkits cost around 300 EUR which is far too much for my intended usage.

Until now I planned to switch to Yuan 10 for the next prototype. Yuan 10 costs 97.60 per board (antennas not included) and uses SkyTraq S1315F-RAW chip internally which is able to output raw measurement at 5Hz.

It turns out though that there is currently an NavSpark fundraising campaign by the SkyTraq itself which, if sucessful, will get you 2 boards with this chip + active antennas for 50$. At the moment of writing more than half of the campaign time has passed and they are less than 30% funded so if you want cheap RTK-GPS to happen support them and spread the word.

Getting such an high precision GPS solution for so cheap would certainly open many new interesting usage possibilities!

PS. This RTKLIB compatible perk was actually added quite late to their project. Main goal is to produce tiny sub 20$ GPS boards that can be programmed, run at 100Mhz and have lots of usable GPIO pins, which is also awesome.

another iteration of the bot

I did a bunch of hardware modifications to my bot over the weekend to make it more sturdy and to get rid of most of the loosely connected wires and the separate proto board. This is what the current iteration looks like:
ukerdis_rev_03

The main changes are:

  • 5Ah Li-ion battery replaced with two 4.6Ah NiMH batteries connected in parallel because for me the relative safety of the NiMH outweighs the capacity/weight gains of the Lithium based chemistries. I really don’t want to worry about my house burning down while charging the battery packs.
  • Replaced the Wifi dongle with a far smaller one. The new dongle is using Realtek 8192cu chipset which isn’t supported out of the box as well as the old Atheros based dongle was but I think I got it working reasonably well in the end.
  • Replaced the older generation BeagleBone with Beagle Bone Black (BBB).
  • Moved the bidirectional level shifter that is used for serial communication between the Wild Thumper Controller and BBB from separate proto board to BeagleBone proto cape.
  • Changed BBB’s power supply from 1.5A Recom 78b5.0-1.5 to 3A BEC. This change was actually done because the 3A BEC comes in a nice discreet package which is already more or less protected from the environment and having more power available is just a nice side effect.

With that the platform is stable enough that I can actually concentrate on the navigation. On that front I set up an RTK-GPS solution with RTKLIB and couple of borrowed u-blox LEA-6T evaluation kits.
This is how my ad-hoc base station looks like:
gps_base_station_1024

This is what the signal levels look like in RTKNAVI:
rtklib1_nocoord

To get a good set of waypoints for testing the robot I walked a couple of times up and down my driveway:
rtkplot showing me walking up and down the driveway

The yellow dots show the FLOAT solution and the green ones show where I had the FIX solution. Basically getting the FIX solution is more precise and means the calculations that RTKLIB does, lead to a single unambiguous solution at these points.

Zooming in we can see that the points from different times are at most about 20cm apart which is really good considering that I was just trying to walk in the track of the car wheel and certainly veered off a bit at times.
RTK solution closeup

two steps forward one step back

I spent most of today working on my autonomous lawnmower project. What I currently have is this:

robot_from_the_back_1024

The main changes from the last prototype are the plywood box around the cutting motor and the relocation of the motor controller board to a higher place where there’s more room and less chance of getting covered with wet grass. I also switched the main controller board from Nokia N900 to Beaglebone since I had a bit of trouble getting USB host mode & WIFI working together in a stable manner on the N900. Sadly I managed to fry my Beaglebone Black so I’m currently using an older generation Beaglebone that has so far served as my main automation controller.

There are still far too many fragile loosely connected wires all over the place and if you look carefully there’s actually even a breadboard so I still have a lot of work to do before it’s ruggedized enough for its intended purpose.

an autonomous lawnmower

A while ago I moved into new house that happens to have almost 1ha of mowable land which has proven to be a great motivator to start building an autonomous lawn mower.

Of course there are many commercial robot mowers available off the shelf so why didn’t just buy one?

First of all that wouldn’t be neither fun nor educational but it also seems to cost an arm and a leg (pun intended). Most seem to be specified for somewhere around 2500 m^2 and cost between 1-2k EUR. Going by these numbers I would need 4 of these to cover my yard which amounts to far more than I’m willing to pay for automating mowing.

It’s interesting that these robots seem to be really simple and do not contain much of anything.
They just drive randomly around the area that you have fenced with a perimeter wire and drive on the wire to get to the charging station when empty. There’s no navigation whatsoever and the only sensors are bumpers and tilt switches. Safety is achieved by having a rather weak cutter that has small blades and is hidden deep under the mower.
It’s supposed to be constantly cutting so it only has to nibble a couple of mm of grass each time around so having a weak cutter works out just fine.

I imagine the bill of materials for one of these won’t be more than ~300 EUR so the margins must be huge.

So in order to build an autonomous lawnmower you don’t really need much. One of my favourite DIY builds doesn’t even have a microcontroller.

I want to build something that actually navigates though so I will use GPS for navigation instead of the perimeter wire which will make my mower a bit more costly and complex to build.
High precision GPS however is an topic in itself so more on that in a separate posting later.

first proto sideview 08 2013

What I currently have is a simple radio controlled mower built around 6WD Wild Thumper platform that I had lying around. I also plan to use assortment of other sensors that I happen to have. While in total these components cost as much as a good commercial mower the result will also be far more interesting and since I have acquired these components over many years the cost is mostly long forgotten.
If i get it running as well as I like then I will try to build the next version from cheaper components and materials.

For the first cutter prototype I just attached a couple of blades to the largest server fan that I could find in the scrapheap:
first proto of the cutter
While it looks evil it didn’t cut all that well so it was back to the drawing board.

Next I used a really powerful cordless drill motor with a blade holder disk cut out of aluminium sheet.
cutter_proto2_on_testbench_xx072013_resized
I have no idea what these blades are really meant for but they are rather cheap and available in most local hardware stores.
This cutter proved to be really effective and can easily cut even long grass.

So all I had to do was to create a mowing section for my Wild Thumper chassis:
first proto underside

Here’s a video of the first mowing test which went far better than I expected:

drgb camera

I just bought myself an Asus Xtion PRO Live Depth+RGB camera which I plan to use for robotics experiments. It uses the same technology from PrimeSense for depth as Microsoft Kinect but is about half the size, can be powered solely over USB and weighs around 170g which makes it a better match for robotics.

asus xtion pro live vs. matchbox

xtion_pro_on_wild_thumper_20111221_003

Here are my notes on getting the basic Openni / NITE demos running on ubuntu 11.10:

sudo apt-get install build-essential libusb-1.0-0-dev freeglut3-dev

install openni

mkdir openni
cd openni
git clone https://github.com/OpenNI/OpenNI.git
cd Platform/Linux-x86/CreateRedist
./RedistMaker
cd ../Redist/
sudo ./install.sh

install sensor

git clone https://github.com/PrimeSense/Sensor.git
cd Sensor/Platform/Linux-x86/CreateRedist/
./RedistMaker
cd ../Redist
sudo ./install.sh

install primesense NITE. This seems to be closed source but free of charge
download from http://www.openni.org/Downloads/OpenNIModules.aspx under Middleware binaries. In my case it looks like this:

tar -xf nite-bin-linux64-v1.4.2.3.tar
sudo ./install.sh

this will prompt you for a key, which is: 0KOIk2JeIBYClPWVnMoRKn5cdY4=

then go to directory containing NITE samples and try out some demo apps for example Sample-Players:

cd Samples/Bin/Release
./Sample-Players

This is how SamplePlayers looks when it has identified me in the picture:
openni nite SamplePlayers demo

outdoors robot navigation

wild_thumper_with_sonar

I spent some time experimenting with SRF-08 sonar for outdoors robot navigation usage. While this sonar is said to have range of 6m I haven’t gotten any measurements beyond ~1m even indoors.

Outdoors it’s of course even more unreliable and there the usable range at the 20cm height seems to be about 30cm, which depends a bit on height of the grass and evenness of the terrain. Since the speed of this robot is about 5 km/h I have about 200 ms from the beginning of the measurement cycle to actually hitting the obstacle. This might be just about enough if I turn up the ping frequency to 10ms range and avoid doing anything else in the main loop.

Another option is of course to cap the robot speed to something slower but that wouldn’t be much fun.

I wonder if MaxSonar WR range would offer better range in this scenario, especially the models with narrower beam width. For some reason I couldn’t find any actual reviews of its outdoor performance and 100$ seems a bit much just for finding out.

Wild Thumper

One of my long term goals is to create an outdoor robot that would automate certain kinds of gardening tasks. I have built some simple indoor robots over the years but haven’t really gotten around to building something that can be used outdoors since there’s a rather large gap in the complexity between these two environments.

For indoor robots you can basically just use toy car wheels directly attached to the servos and use simple wheel encoders to navigate. Outdoors you need a lot bigger wheels, DC motors, motor controllers, suspension, large batteries and preferably a shell that provides protection against the elements. Navigation also becomes a challenge – wheel encoders become rather useless because of the constant slippage and GPS is currently still far too imprecise for navigating in a garden.

So to avoid spending too much time on the mechanics I decided to get Dagu`s Wild Thumper 6WD platform which can handle uneven terrain well, as can be seen from the following demo video from Dagu:

Here’s a picture of my Wild Thumper with Wild Thumper motor controller & 5000 mAh Li-ion battery:
wild_thumper_6wd

Here’s my own first radio controlled test run:

And here’s a demo of the steering with Nokia N900 accelerometers:

By the end of this year I hope to get it autonomously navigating in my garden which is a precondition for most of the interesting applications but is a very complicated task all by itself too.

beginnings of greenhouse automation

Last year I bought a new larger greenhouse (lwh: 6x4x2.8m). Currently it looks like this:
greenhouse in winter

Which means that I don’t have to deal with actually growing things at the moment and now is a good time to make preparations for the next season.

My ideal is to automate it as much as possible, so first I will try to automate the obvious things like watering and ventilation. In the future things like heating and growlights might be added too.
I have spent several weekends on that project with my friend Kalle who helps me on the electrical engineering front and finally we have something that more or less works.

The current solution consists of controller board & sensor board in the greenhouse. Controller is run by Arduino and controls 220V power outlet & gathers information from various sensors. Bidirectional datalink with the house is done over ZigBee radio. In the house I have a Beagleboard which logs data, draws nice graphs, serves these over the internet and can control Arduino.

The greenhouse controller looks like this:
controller_smaller
It consists of:

Some of the Arduinos IO pins are connected to the CAT5 cable that runs to small external sensor board:
sensor_board_smaller
The sensor board has following sensors connected to it:

The sensors and connections are protected from the environment mainly by having them covered by a thick layer of hot glue.

First version of the sensor board used LM35 analog temperature sensors which were nice and easy to interface with but thanks to their analog nature were rather sensitive cable length and small voltage flux on the Arduino that was caused by the relay switching and other sensors. Besides LM35 outputs negative voltage for temperatures below 0 deg. C which you can’t measure in a direct way from Arduino.

I haven’t had time yet to document the schematics & connections but for similar well documented project you can take a look here and here.

And here’s how it’s currently “installed”:
ad_hoc_installation_smaller
The power socket/switch that you see right next to the controller box is meant for the water pump and switch is used to override Arduinos decisions if need be.

Software wise things are quite simple at the moment – controller periodically gathers data from all the sensors and prints them in a line similar to:

H121 T-28.8 T-10.0 L192

Where letter indicates sensor type and number is determined by the position. Since the arduinos serial output is really connected to the ZigBee module I can just read it from the other side of the radio link as though the devices were directly connected with serial cable.

So the code running on Arduino is just this:

#include <OneWire.h>
#include <DallasTemperature.h>
 
#define ONE_WIRE_BUS 2
 
OneWire oneWire(ONE_WIRE_BUS);
 
DallasTemperature sensors(&oneWire);
 
#define MEASURE_CYCLE_TIME 5000
 
int humidity_pin = 1;// input pin for the humidity sensor
int light_pin = 5; // input pin for the light sensor
int relay_pin = 12;   // relay switch
float val = 0; // variable for storing sensor value
 
void setup() {
  pinMode(relay_pin, OUTPUT);  
  digitalWrite(relay_pin, LOW);
  Serial.begin(9600);
  sensors.begin();
} 
 
float get_temp(int pin) {
  float val;
 
  return sensors.getTempCByIndex(pin);
} 
 
void show_temp(float v) {
  Serial.print("T");
  Serial.print(v);
  Serial.print(" ");  
} 
 
void loop() {
  sensors.requestTemperatures();
  val = get_temp(0);
  show_temp(val);
  val = get_temp(1);
  show_temp(val);
 
  val = analogRead(humidity_pin);
  Serial.print("H");
  Serial.print(val);
 
  val = analogRead(light_pin);
  Serial.print(" L");
  Serial.print(val);
  Serial.print("\n");
 
  delay(MEASURE_CYCLE_TIME);
}

And on the Beagleboard it’s even simpler:

import serial
import os
import time
import traceback
 
SAMPLE_WRITE_TIME = 5*60
DATA_DEVICE = "/dev/ttyUSB0"
 
"""
to create the RRD file:
rrdtool create temperature.rrd --step 300 \
  DS:temp1:GAUGE:600:-273:5000 \
  DS:temp2:GAUGE:600:-273:5000 \
  DS:light:GAUGE:600:0:1000 \
  DS:humidity:GAUGE:600:-273:5000 \
  RRA:AVERAGE:0.5:1:1200 \
  RRA:MIN:0.5:12:2400 \
  RRA:MAX:0.5:12:2400 \
  RRA:AVERAGE:0.5:12:2400
"""
 
last_ts = None
 
ser = serial.Serial(DATA_DEVICE, 9600)
 
def calculate_relative_humidity(raw_humidity_val, temperature_c):
    """converts raw HIH4030 output to relative humidity %"""
    # see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267245927/3 for discussion
    if __debug__:
        print raw_humidity_val,temperature_c
 
    ZERO_PERC_VOLTAGE = 0.8
 
    max_voltage = (3.27-(0.006706*temperature_c))
    relative_humidity = ((((raw_humidity_val/1023)*5)-ZERO_PERC_VOLTAGE)/max_voltage)*100
 
    if relative_humidity > 100.0:
        # if it's  saturated/frozen it outputs raw values around 920 which would lead to
        # RH% in the range on 120 which is theoretically possible but probably just an
        # measurement error / problem with the equation
        return 100.0
 
    return relative_humidity
 
def write_sample():
    global last_ts
 
    l = ser.readline()
    # input is expected to be similar to "T-23 T-10 H100 L20\n"
    if __debug__:
        print "raw:",l,
 
    temp1, temp2, humidity, light = [float(x[1:]) for x in l.strip().split()]
    humidity = calculate_relative_humidity(humidity, temp2)
    if __debug__:
        print temp1,temp2,humidity,light
 
    if last_ts is None or (last_ts + SAMPLE_WRITE_TIME) < time.time():
        cmd = "rrdtool update temperature.rrd N:%f:%f:%f:%f" % (temp1, temp2, light, humidity)
        os.system(cmd)
        last_ts = time.time()
        if __debug__:
            print "cmd:",cmd
 
while 1:
    try:
        write_sample()
    except KeyboardInterrupt:
        raise
    except:
        print "write failed"
        traceback.print_exc()

Here’s some sensor data from today:
temp_211220101
light_21122010
humidity_211220101

live data available through Pachube feed

And here’s a picture of the Beagleboard at the garage that gathers data & serves the graphs
beagleboard_installation

Actually getting the Beagleboard working in a suitable manner turned out to be the most complicated part of the whole project. It took 3-4 days in total over a month or so while I reinstalled different distributions, replaced broken SD card, tried more than 10 different versions of the kernel and u-boot and finally removed a capacitor from the Beagleboard to get it stable. Hopefully I will write a separate post about that in the near future 🙂

openmoko and robotics

It’s often said that open source software fosters innovation because people can be inspired by work of others and use it in ways that the original author never thought of. The same applies to open hardware and the Openmoko Freerunner is open both sw and hw wise so it lends itself easily to such unforseen uses.

Among other things I use mine for robotics. With high res touch screen, 400Mhz CPU, Wifi, Bluetooth, 2 accelerometers, GPS, USB and other stuff it really has basically all that I have ever needed for a robotics project and I can’t think of anything else that would offer the same specs in similar size for 350€. Obviously you also need a some GPIO lines, PWM, I2C ant other similar IO stuff for a robot and for that purpose I use another open source product – Arduino Duemilanove.

mokobot

Basically I prefer to design my robots in two logical parts:

  • The brain that analyzes the sensory input and makes decisions. In this case this is the Freerunner.
  • The peripheral nervous system that handles sensors and actuators. This role is handled by the Duemilanove in this project.

Using this separation allows me to more or less easily switch either of those boards for something else. For example when I need more CPU power for the brain part I might just swap the Freerunner with Beagleboard and the only thing that I would have to change is the USB cable that connects the boards. Having the boards connected just by USB cable means that I didn’t have to rip the Freerunner apart and so when I’m finished with hacking on the robot I can just take the Freerunner and use it for other purposes. Another nice thing about this kind of bot architecture is that I didn’t have to solder anything at all besides the USB cable to get a usable robot base, which is important for people who don’t know much about electronics (like me :-)).

Since the Freerunner has onboard Wifi I just SSH into the robot over it and this allows me to debug and control it without having to connect any special wires / programmers when I want to change something. Openmokos touch screen is also a really good place for displaying various debug information – for example what the environment looks like from the robot’s perspective.