Lessons on the First Open Water Test

It’s never too early to go out and play with robots.

Just returned from Lake Berryessa for my first ever autonomous boat test on open water.  Some notes so I don’t forget the lessons learned.

  • I managed to get three test runs in for trimming and adjusting the turn rates.  Unfortunately,  it turned out the boat leaks and that was all I could do.  I did test it in a tub and in a creek, but I should have let it soak for a long time to determine if any issues would arise by longer periods of time in the water.  I was about to send it off on a longer journey so thankfully I checked, I don’t think I would have gotten it back.
  • I set a GPS point too close to shore.  I didn’t have the confidence to set it way out in the open water as I have no means of retrieving it(like say, if it started leaking).  A couple of times during a test I had to take manual control since it was going to run ashore.  This didn’t allow me to determine if it was actually going to the waypoint or not, and what might have been going wrong.
  • Think I’m going to need some type of recovery vessel.  I have a wet suit, perhaps I should have brought that for worst case scenarios.
  • A headlamp flashlight would have been ideal.
  • It was a steep hike to the shore, all my gear should have fit in one backpack.
  • Obviously, cheap DIY foam board boats are out.  It’s time to brainstorm a new craft.
Lake Berryessa 1/15/18

Not quite a success.  Not quite a failure.  Of all things to happen, it was actually  pretty good.  Some important lessons learned without any losses.  And some nice pictures.  Got to experiment with robots, see nature, take some pictures.  Maybe it was a success.

How to use a Spektrum DX4C’s Switches in Arduino

These are my notes on how to use a remote control’s switches to control extra features of a robot.  In my case, I have an autonomous rover and would like to build a switch to press on the remote control to stop the rover and take manual control over it.

I used a Spektrum DX4C transceiver.

Switch Channel 3 is highlighted in red.

First, I configured the Spektrum  DX4C profile model in memory so that Channel 3 will be used as a switch.  To do this:

  1. Press the scroll wheel and select your Model to configure
  2. Next, scroll down to Switch
  3. For menu selection “A:”, choose Aux1 SP2

Next I connected a pin wire from the receiver.  On my Spectrum SR3100, this was labelled Aux.   I connected the wire to an Arduino PWM capable pin(5).  Make sure the receiver has power.  You can get it from the Arduino board’s 5v and ground pins.

The following sketch allowed me to read the values of the switch:


/*
 * To read the values go to Tools | Serial Monitor
 */

byte pin = 5;
 
int value;
 
void setup() {
  pinMode(pin, INPUT);
  Serial.begin(9600);
}
 
void loop() {
  value = pulseIn(pin, HIGH);
  Serial.println(value);
  delay(500);
}

 

Pressing the switch gave me approximately the following PWM values:

Switch On:  1900

Switch Off: 1100

Radio Off:  1500

In conclusion, these values would be used in an Arduino sketch to control a robot’s behavior.  Use code logic to determine if the switch is on/off and use that to display a light, play a sound, or any behavior altering characteristic you can imagine.

 

Lessons Learned Making My First Boat

Just got the boat on the water for the first time and I wanted to jot down my thoughts while they’re still fresh.  This was the first time I’ve ever made a boat, or an RC model of any kind.   When I realized I could make them from Dollar Store foam and hot glue I was very impressed and happy to do so since I could get on the water for free, essentially.  As the build progressed though, I started to feel like it was a lot of work for a temporary boat.  Once on the water it snagged in some tree limbs and now has a small hole poked in it.  So the foam board build is out for sure.   Not sure I even want to do more testing, it’s not very robust.  Possibly on a lake it might work.  Possibly.  On the plus side, if something goes wrong and I lose the craft, I wouldn’t have lost much.  So there’s that.  If I were to do this again, for the effort, I would use a kit or spend on a pre-made boat.  But then you have the consequence of losing something more valuable(money, time, effort to build).

The boat did float very well.  The hull was made two inches high and it barely sank below the water line but a quarter of an inch.  This shape will tolerate quite a bit of weight, like extra batteries, solar cells, sensors, radio.  Probably also means it’s more than I need and I could go with a catamaran style with less friction that will go a little faster for the same energy.

It’s not an easy platform to test.  You need water and if something goes wrong, retrieving it is not simple.  I was testing in a creek and navigation was weird.  I’m so used to thinking of boats with rudders that an airboat is something to get used to.  I suppose it would be fine in large open space, but since the end goal is the ocean, I really doubt I would use an airboat so I’m at a bit of a loss on what to do next.  The boat sailing at minimum speed has a very low current draw(240mA), which is really nice.  It’s hard for me to imagine, but based battery capacity, that’d be a couple of hours of run time.  It would seem I could go multiple miles at that rate.  That would need to be tested, but that’s very appealing.

 

240mA current draw

 

As I wrap this up, I think I’m concluding that I will move forward with putting my Arduino GPS system in this boat and take it on a lake.  It’s inexpensive, if something goes wrong it’s not a big deal.  If I can get it to navigate two waypoints over a hundred yards it would be a smashing success.  I’ll have more faith in the code and hardware I’ve built to scale up to the next level of cost and effort.

Having a blast.

 

New Project Announcement: AquaBitsOne

We here at remotebits.com(aka, me), are excited to announce our next phase in rover robotics: AquaBitsOne.  This will be a prototype vessel that shifts us from terrestrial exploration to aquatic.

 

Protype in aquatic form
Taking us to the next phase in autonomous robotic exploration.

Over the years I have begun to fine tune my own personal development methodology, which involves setting up one big annual goal divided up in to steps that I map out as monthly goals.   You could say it is Agile Methodology applied on a personal level.  One Epic of twelves sprints that are four weeks long each.  With the New Year brings new goals in my life and the beginning of my 2018 Epic.

And this will be to achieve an oceanographic vessel that travels autonomously using GPS and transmitting its current location with APRS.  It should be capable of traveling at least one mile in the Pacific Ocean in good weather.  I also have a stretch goal of being able to record thirty minutes of underwater audio using a hydrophone.

We begin with the first Story of our first Sprint.  AquaBitsOne.  This is essentially an airboat using salvaged aircraft electronics.  It is the first prototype, and is made from cheap dollar store foam that has been waterproofed with polyurethane.  I chose this form because I already had everything needed to get started.  It means I can start testing the code and hardware developed from BitZero, on the water and at no cost.  Will it work?  I don’t know.  Does it matter?  No, we will iterate until it does work.  Is this thing going in the ocean?  Doubtful.  Again, we will iterate and learn as we go along.

So let’s do this.

Happy New Year!

How to Arm E-Flight ESC with Arduino and without Guessing

If you read one of my first posts here at remotebits.com, on arming an ESC, I happened up the solution by accident.  Today I wanted to try to arm an RC airplane ESC and it occurred to me that I didn’t have to guess how to do it.

Disclaimer: use this information at your own risk.  I am not responsible for any damage.

A more elegant solution was to read the PWM values first while turning on the transceiver and watching the Serial Monitor as the radio attempts to bind.  I wired up the ESC signal pin and I read the PWM signal value as 0.  Then I turned on the radio and got a PWM of 1095 microseconds.  1095 microseconds is nearly zero throttle.  I was expecting an actual sequence, such as full throttle, half throttle, no throttle, but I didn’t see that.  My only concern was that it happened so fast I couldn’t measure it in the Arduino Serial Monitor.  But when I sent the same value to the ESC, I got the characteristic bind chimes right away!  I was quite surprised.  I then decided to see if I could turn the motor with around 1500 microseconds.  To my disappointment, it no longer worked. I didn’t even get the bind chimes.  I poked at it a few times with some PWM values when it occurred to me perhaps it is expecting the PWM for a certain length of time.  I started to experiment with this but still didn’t hit the answer.  Until I decided to try it again with the radio and listen to the chimes.  When I heard the boot chime, I turned on the radio and it was a full three seconds before the bind chimes rang.  Ah ha!  So I added a minimum 4 second delay before attempting to turn the motor, and that was the key.

The reason I hit the jackpot so fast on the first time was because my loop was empty.  So after the setup ran, there was nothing going on.  Or, in other words, the “nothing going on” was actually meeting the minimum amount of time at 1095  microseconds to arm the ESC.  Only after that could you successfully send PWM for turning the motor.

The first time I went through this exercise, I spent an entire evening trying to figure out the magic.  This time around I did it in less then half an hour.  It’s a great feeling.

So if you’re reading this trying to figure out what PWM signals you need to arm your brand’s ESC, try reading the values from the radio during the binding sequence instead.  It’s a whole lot easier than guessing.


/*
 * This sketch arms an E-flight brand electronic speed controller
 * 
 * The trick to figuring this out was to hook up the radio to an Arduino input pin and read the PWM during binding beforehand.  For me, this gave a value of 1095.
 * After that, the hint needed was listening to the binding chimes while turning on the radio.  I counted at least three seconds before the confirmation tone.
 * So you need to add a minimum delay value before trying to run the motor or else it won't bind.
 */
 
#include 

Servo motor; 

void setup() {
   motor.attach(3);
   motor.writeMicroseconds(1095);
   delay(4000);
}

void loop() {
    motor.writeMicroseconds(1250);  // now we can turn the motor on.
}

BitZero Upgraded with Servo Shield and GPS

In my last BitZero update, I installed a GPS module and began having a problem where the servos seemed to be glitching every second or so.  This turned out to be a resource contention.   The GPS module communicates to Arduino with interrupts, and this was disrupting the PWM pins from sending proper signal to the servos.  The solution turned out to be using the Adafruit Servo Shield.  The PWM processing is offloaded to the shield and can continue to run when the Arduino chip gets an interrupt.

Next I got the GPS module running.  At the time I had a compass installed as well but was dissatisfied with its accuracy.  North was off by at least 30 degrees and sometimes the compass reading was zero.  It occurred to me later that I could read samples from the compass and average them.  I may revisit this later.  But I noticed that even when the compass failed entirely, the GPS module would eventually take over and the vehicle reached the destination just fine. The GPS module can calculate direction from its previous location and current location.  So it just needs to drive around a bit until it figures out where to go.  I was hoping to have a robot a little bit smarter than having to sniff around, but that’s life.  This is fine for now.

One thing I think I’m coming to find is that the resolution of GPS is not granular enough for this scale vehicle to drive in the streets.    I can place a point in the middle of the street and really any where across the width of the street is recognized  as the same point.  This makes it impossible to be used autonomously in residential area.  A wide open space is required.  And I have ideas around that which will be announced soon.

And finally, I’ve upgraded the code to store multiple waypoints.  Here is a demonstration.

Bold Robot Nearly Escapes

Close call today, folks.  Almost lost BitZero.  It’s amazing what a software bug can mean.  Life or death, really.  So I was doing some testing at the local playground.  I had coded in three GPS points, and let the robot go.  Around the park it went.  To all of it’s designated points.  It reached the third and final waypoint, and was supposed to shutdown.  But it suddenly turned eastward, slightly south, and kept on truckin’.  Really going for it too.  Not glitch either.  It was clearly headed to a new and unknown to me waypoint.  But where?  All I know is I had to chase it.  Now or never, it would be gone forever if I didn’t move fast.

Thankfully, I did catch it and able to return back to the Remote Bits Lab and deconstruct exactly what happened.  I checked the code.  Everything seemed right.  The waypoints, there they where.  How could this be?  What could have happened?  Where was it going?  And then all was revealed.  It became clear.  The array size was four, my very first test around the block.  But I had only put in three way points this time.  So what then was the forth waypoint if I didn’t set it?  I redirected the output to the teletype, and out it came: 0, 0.  That’s it!  Without a proper waypoint, the navi comp sent the vehicle to Decimal Degrees 0,0.  That is to say, 0°00’00.0″N 0°00’00.0″E.

And where is that?  Africa.

My bold little robot made a run for Africa.

Announcing: Project BitZero

What is Project BitZero? I’m glad you asked. It’s the beginning of this journey to document all of my side projects.  And the first project is a prototype for small scale autonomous vehicles.  Being the first project, and being a software development blog, counting begins with zero. Each Bit will be a part of this blog, which is of course,  also a play on words for site’s theme: computer programming.  I will also cover many topics on wireless tech.  That’s what remote is about.  Remote sensing and remote control.  Remote Bits.

And it’s just the beginning.  It all starts here,  with this project.   I present to you, BitZero…

APRS on Linux

So want to track your high-altitude balloon or autonomous rover in the middle of the desert without an Internet connection?  Me too!

Here’s my notes how I set it up on Ubuntu 16, using Dire Wolf and YAAC.

Dire Wolf is a cleverly named software TNC: Decoded Information from Radio Emissions for Windows Or Linux Fans.   It will decode APRS messages from your radio audio jack connected into a computer’s soundcard.  We then use YAAC, Yet Another APRS Client, to retrieve the information and display it on a map.  This is a stand-alone setup that will allow you to track APRS without a network connection.  Just a radio, antenna, and computer.

First thing you need to do is, turn on your radio and make sure you’re hearing some APRS signals.  If you don’t have a transmitter, find the APRS frequency in your area.  Mine is 144.390MHz.  Listen for a couple of minutes.  Adjust the volume to a reasonable level as we will need to fine tune this later.  Once you are sure you’re receiving signals, connect your radio’s external speaker jack to your computer’s microphone jack.

Open up Sound in System Settings.  Click the Input tab and find your computer’s soundcard.  You’ll want to adjust the Input Volume slider so that when an APRS message comes in, you don’t overload the microphone.  If the volume indicator is pegged on the high side, turn down the volume of the radio.  It’s faster to do this by turning off your squelch so you’re sending constant audio into the mic.  Fine tune both volumes so that you’re around 50%.  We’re just guessing.   Dire Wolf is going to tell us if it’s too loud or not so don’t worry too much about it.

Install Dire Wolf

Next we will want to install the software which is going to decode the APRS messages.  Follow the Dire Wolf download and installation instructions:

git clone https://www.github.com/wb2osz/direwolf
cd direwolf
make
sudo make install
make install-conf

I got on error on make regarding: /usr/bin/ld: cannot find -lasound

Was able to get past it by installing:

sudo apt-get install libasound2-dev

After that the installation ran fine and it gave a prompt to run another command to install an icon.  Type direwolf in Dash and it should be there.   Open up the application.  A window will open up telling you it’s listening for AGW client connections  on port 8000:

 

 

Now monitor your radio’s Signal Meter, when you see a strong signal come in, check the Dire Wolf window.  You might get an output such as this:

The red text tells you the audio is too high.  The line above tells you it’s 117 and reduce it so that it’s around 50.  You can adjust it in two places.  Turn your radio volume down, or turn down your computer’s microphone input volume.

When you’ve got the levels correct, you should be seeing lots of green

 

Installing YAAC

You probably want to see the data conveniently on a map, and that’s what YAAC will do for us.  First, make sure you using Java 8, type:  java -version

If not, download and install from the Oracle website.

Next, download and install YAAC:

  1. Open a terminal (lxterm) window.
  2. Download the YAAC.zip file
  3. mkdir YAAC
  4. cd YAAC
  5. unzip ../Download/YAAC.zip

Run YAAC

  1. java -jar YAAC.jar

Configure YAAC

  1. If it asks you to Install by Wizard, select that.  Otherwise go to File -> Configure -> By Wizard
  2. Enter your call sign in the box and select Next
  3. Select Fixed checkbox
  4. Unselect Digipeater/I-Gate
  5. Select Next
  6. Select No GPS and then Next
  7. Select “Add AGWPE Port”  (this is the important part!)
  8. Hostname is localhost and Listen Port is 8000 (this is Dire Wolf)
  9. Protocols select APRS
  10. Select Next

You should have be looking at a blank grid.  Provided Dire Wolf is running correctly(check that window and make sure you are getting APRS messages), you’ll soon start seeing icons show up on the grid.

Adding a Map to the Grid

  1. Select File  -> OpenStreetMap Extract Datasheet
  2. Select Geofabrik.de (there may be other ways to import maps, but this worked for me and allowed me to pick just my state and not the whole huge world which is a very big file)
  3. Select your Sub-Region and drill down to your local area.
  4. Choose the file under “Other Formats” that ends with the extension .bz2
  5. It will take a long while to download
  6. When it is complete, go back to YAAC and File -> OpenStreetMap Import Raw OSM File
  7. Browse to your downloaded .bz2 file

Once that is complete, instead of a blank grid, you should be seeing icons representing nearby stations on a local map.

How to Calculate Compass Heading from GPS Points

So you’re building a robot with an Arduino, GPS, a compass and you want it to know which direction to turn so it goes to a waypoint?  Me too!   Here is my demo sketch on how to calculate the waypoint heading.   It amounts to using the atan2 function to calculate the angle between two points, converting the angle to degrees, then normalizing it to a compass reading.

The below values are hardcoded. You can run the sketch yourself to test the calculation.   I’ve spot tested points between all the 90 degree angles but did not include them for brevity.  If you want to modify with your own values replace the variables currentLatitude and currentLongitude with your own coordinates in Decimal Degrees format. Simply go to Google Maps, right click a place on the map, select “What’s here?”. At the bottom click the link to the coordinates. From there you can copy the values out of the text box and paste it directly in to the sketch. Do the same for your destination and paste it in the call to getWayPointHeading().


/*
 * This sketch demonstrates how to calculate a compass heading from two GPS points.
 * Prints out the 0-360 compass heading from the current location to the target waypoint
 */

// Sample GPS coordinates representing the current location. 
float currentLatitude  =   38.590214;
float currentLongitude =  -121.767142;


void setup() {
  Serial.begin(9600);
}

void loop() {

  Serial.print("North: ");
  Serial.println(getWaypointHeading(38.601164, -121.767199));  // a point due north

  Serial.print("East: ");
  Serial.println(getWaypointHeading(38.590264, -121.761617));  // a point due east

  Serial.print("South: ");
  Serial.println(getWaypointHeading(38.586864, -121.767143));  // a point due south

  Serial.print("West: ");
  Serial.println(getWaypointHeading(38.590215, -121.803073));  // a point due west
 
  while(1);

}

/*
 * This function takes a lat/log and returns the 0-360 compass heading from the current 
 * globally defined lat/log
 */
int getWaypointHeading(float targetLatitude, float targetLongitude) {

  // radians
  float heading = atan2(targetLatitude - currentLatitude, targetLongitude - currentLongitude);

  // convert to degrees 0 to 180/-180
  heading *= (180 / 3.14159);

  // convert to 0-360 compass degrees, North = 0
  heading = (450 - (int)heading) % 360;

  return heading;

}

Sample Output


North: 0
East: 90
South: 180
West: 270