WiFi Tank Robot in about an hour


 (Left to Right, Auric and Oddjob)

If you've been reading here for a while, you will probably remember Auric my large quad-track robot.  If not, you can read all about it here.

Auric is still developing and getting smarter, but it's also really an expensive project.  I wanted something fun for the kids.  It had to be easy to build and able to handle indoor and outdoor conditions well.

The solution came in the form of a "Black Gladiator" chassis from DF Robot.  Mine came from Little Bird Electronics in Hornsby New South Wales, for the princely sum of $A50.

What I really like about this chassis is that unlike quite a few "budget" tracked chassis I have seen, this has an aluminum base plate which makes it not only stronger, but it shouldn't flex so much and cause damage to PCBs attached to it.

It's a kit so you will need a small phillips-head screwdriver, soldering iron, cutters and medium duty hook-up wire.  When I received mine, DF-Robot's website had some problems and the assembly instructions lacked any pictures.  However, Little Bird have step-by-step instructions on their product page.

I'm not going to repeat the details already published because that would be pointless, but I will offer some hints to make the job easier:
  1. Use a pair of small spanners (M5) to lock up the nuts which secure the non-driven wheels to the chassis.  This is the only part of the kit I wasn't happy with, because it took a couple of attempts to eliminate the free play from these wheels.  Bearings would have been nice, but then the cost would be higher.
  2. The cutouts in the tracks face away from the chassis, and then the pegs will slot nicely into the non-driven wheel as well.
  3. In my build I had to remove four segments from each track to get adequate tension.  Yours may vary.
  4. When wiring the motors, determine the polarity which drives each set of tracks forwards, then solder the wiring.  It makes it easier when it comes to hooking up the controller.  Remember that because the motors are opposed 180 degrees, that they need to turn in opposite directions  for normal motion.
  5. The battery holder takes two 18650 batteries, and while most photos show it on the top of the main deck, it mounts really neatly underneath, and there's even a screw hole or two in the right place.  This frees up space on top for other uses.
  6. Cable-tie your wiring to keep it out of harms way.
All up, the assembly should take 20 - 30 minutes if you've got even modest skills.  It's not a race, but it really is easy.


(Put the batteries underneath and save yourself space.  Looks neater too)

Since keeping the cost down was a major part of this exercise, I used a controller I already had.  Actually it's the original motor controller from Auric.  This is a NodeMCU attached to a common motor shield.  Both parts are readily available, but you could also use an Arduino UNO and Motor shield if you wish.


(Ready for action)


The end result is visually quite pleasing as well as fully functional.  To get you started, the code below can be loaded onto the NodeMCU using the Arduino IDE and and you have a simple web-serving remote controlled robot.  Just make sure you set the WiFi values to suit your home or office network.  The code is really very simple, and for the sake of making it easy to understand there is no authorisation or authentication involved.  Something I intend to fix later.


So there you have it...  A fun afternoon project that could serve as a base for future experiments.  I will definitely be looking into using something like Blynk to build a mobile phone control app for it, as well as adding some additional sensors and whatever navigation I can fit into the NodeMCU's memory.

Finally, all robots need to have a name, and this is no exception.  The newest member of the robot zoo is "Oddjob".  He was Auric Goldfinger's henchman in the movie "Goldfinger".  Curiously, he was supposed to be Korean, but all the "Koreans" in the film were actually speak Cantonese!

#include  <ESP8266WiFi.h>

int PWMA=5;//Right side
int PWMB=4;//Left side
int DA=0;//Right reverse
int DB=2;//Left reverse

const char* ssid = "YOUR_SSID_HERE";
const char* password = "PASSWORD_TO_MATCH";

WiFiServer server(80);

void setup() {
// Debug console
  Serial.begin(9600);
  pinMode(PWMA, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(DA, OUTPUT);
  pinMode(DB, OUTPUT);
  stop();
  WiFi.begin(ssid, password);
  Serial.print("Network Connect: ");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println("Connected");
  server.begin();
  Serial.print("IP Address of network: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  WiFiClient client = server.available();
  if(!client) {
    return;
  }

  Serial.println("Waiting for new client");
  while(!client.available()) {
    delay(1);
  }

  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  // Now decode what we got
  if(request.indexOf("/MODE=STOP") != -1) {
    stop();
  }
  if(request.indexOf("/MODE=FWD") != -1) {
    forward();
  }
  if(request.indexOf("/MODE=REV") != -1) {
    reverse();
  }
  if(request.indexOf("/MODE=LEFT") != -1) {
    left();
  }
  if(request.indexOf("/MODE=RIGHT") != -1) {
    right();
  }

  client.println("HTTP/1.1 200 OK"); // standalone web server with an ESP8266
  client.println("Content-Type: text/html");
  client.println("");
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<br><br>");
  client.println("<table>");
  client.println("<tr>");
  client.println("<td>&nbsp</td>");
  client.println("<td><a href=\"/MODE=FWD\"\"><button>FWD</button></a></td>");
  client.println("<td>&nbsp</td>");
  client.println("</tr>");
  client.println("<tr>");
  client.println("<td><a href=\"/MODE=LEFT\"\"><button>LEFT</button></a></td>");
  client.println("<td><a href=\"/MODE=STOP\"\"><button>STOP</button></a></td>");
  client.println("<td><a href=\"/MODE=RIGHT\"\"><button>RIGHT</button></a></td>");
  client.println("</tr>");
  client.println("<tr>");
  client.println("<td>&nbsp</td>");
  client.println("<td><a href=\"/MODE=REV\"\"><button>REV</button></a></td>");
  client.println("<td>&nbsp</td>");
  client.println("</tr>");
  client.println("</table>");
  client.println("</html>");

  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");
}

void forward(void) {
  digitalWrite(PWMA, HIGH);
  digitalWrite(DA, HIGH);
  digitalWrite(PWMB, HIGH);
  digitalWrite(DB, HIGH);
}


void reverse(void) {
  digitalWrite(PWMA, HIGH);
  digitalWrite(DA, LOW);
  digitalWrite(PWMB, HIGH);
  digitalWrite(DB, LOW);
}


void right(void) {
  digitalWrite(PWMA, HIGH);
  digitalWrite(DA, HIGH);
  digitalWrite(PWMB, HIGH);
  digitalWrite(DB, LOW);
}


void left(void) {
  digitalWrite(PWMA, HIGH);
  digitalWrite(DA, LOW);
  digitalWrite(PWMB, HIGH);
  digitalWrite(DB, HIGH);
}


void stop(void) {
  digitalWrite(PWMA, LOW);
  digitalWrite(DA, HIGH);
  digitalWrite(PWMB, LOW);
  digitalWrite(DB, HIGH);
}






Seriously, WHY would you do that?





Chapter I  A New (Old Stock) Hope

The first computer I got to use was a PDP-11 owned by a time-sharing bureau in Wollongong in the 1970's.  From memory they ran services for car dealers or some such thing.  The operating system was RSTS/11.

When I finished high school I was able to get access to a VAX/VMS system owned by the Department of Education.  Security wasn't a big thing, and my lecturer even gave me the phone number for a dial-in port so I could get access on the weekends.  I discovered the machine I had access to was part of a larger network of VAXes and with a few simple commands, I could jump from one to another.  Just looking around mind you, nothing even remotely interesting was attempted.

VAX/VMS, and later OpenVMS on Alpha have played a moderate part in my career, and I still enjoy tinkering because of the generous way that Digital,then Compaq and now HP/E have supported the hobbyist community.

Emulators are one thing, but getting your hands on real hardware has something even more special about it.  So let's look at the options shall we?



Getting hold of a VAX in any working form these days is near to impossible, and if one does come on the market, the prices are just stupid.  I live in hope that I will come across a 780 or similar on the side of the road, but realistically, it's not going to happen.



The Alpha was Digital's big bet on RISC, and it did make a good replacement for the aging VAX architecture, and positively screamed under VMS, but Compaq didn't seem to understand it, or see a market so they killed it off.  Like the original VAX machines, these are pretty hard to get now because they just didn't sell all that well in this part of the world.  Sadly I had an Alpha, but I let it get away...

So I'm out of luck, right?  Wrong.  When HP acquired Compaq they did see value in the VMS and other parts of the business that Compaq had neglected.  They also had their own architecture, PA/RISC, which was in serious need of an update.

The timing was great, because Intel had second-generation Itanium processors available.  Rumour says HP and Microsoft were heavily involved in the development of a clean-sheet design.  HP seemed to have more sway, because there is a lot of carry-over from PA/RISC.

HP ran with the Itanium family in it's Integrity and Superdome products even after Microsoft pulled the plug on Windows for IA64 during the Server 2003 lifecycle.  You could until quite recently buy these machines configured for HP/UX or OpenVMS.

The last of the Itanium machines were discontinued somewhere around 2016 or 2017. (Correct me if I'm wrong there), and right now complete systems are coming off maintenance at little more than scrap value.  Snap them up while you can, because they won't be available forever.

There's the two main families you need to consider.  The Superdome, which I know not much about is the heavy hitter.  Modular and built to be fault tolerant.  Most of them need power I can't connect in my garage anyway.  But they can be really cheap for this reason.

The Integrity family were in my opinion more of an entry system, and available in either blade or conventional 19-inch variants.

I think by now, you can see where this is going.  Yep, I found some!
Make sure you get RAM with the machine, as it's ECC and not so easy to find.  You won't need a huge amount.  2GB or 4GB should be heaps for our needs.  The drives are old-school 76GB SCSI (Ultra 320), which are easy enough to find.  I'll grab some spares for future use while I'm at it.

Now we wait for delivery.  And Chapter 2...



Make your Raspberry Pi faster


I have heard many people (including yours truly) say that the Raspberry Pi should be faster than it is.  In it's Mk 3 form, with all cores firing it ought to be a lot of performance for the price, but many of us are strangling the performance, often without even realising what we are doing.

Here's some simple tips to getting the best performance:

Power it properly

Just because the Pi has a micro-USB connector for power doesn't mean you should use some ancient phone charger to power it.  This board needs a stable five volts at around two amps to operate properly, and even more under heavy compute loads.  Most small plug pack supplies will struggle to sustain one amp.  Try to draw a higher current and the output voltage will almost certainly droop (drop slightly).

When this happens, you might see a "lightning bolt" on the monitor (if you have one connected") or notice "undervoltage" messages on the console.  Then the Pi detects an undervoltage condition, it scales back the CPU, robbing your performance.

The solution is to invest in a decent quality adapter such as the M8820 from Altronics.  For permanent installations I usually fit a small closed-frame switchmode supply.  You want something rated 30W or greater, and they aren't really that expensive.

I also try to avoid powering other devices from the USB ports on the Pi.  If you need a number of USB devices, consider a powered hub.

SD Performance

The only storage the Raspberry Pi has by default is the SD card it booted from.  These are not the fastest media out there to start with, but cheap ones can be many times slower than high transfer rate cards from the major vendors.

To be fair, we shouldn't be relying on high I/O rates with a Raspberry Pi anyway, but a relatively small price premium gets a higher speed card, and that can mean a much shorter boot time.

Keep Your Cool

Here's an experiment:  Run a very compute-intensive job on a Raspberry Pi and put your finger on the big chip in the middle.  You will notice it can get uncomfortably hot.  The Raspberry Pi kernel implements a thermal governor, which will throttle back the CPU if a predetermined temperature is exceeded.  A small heatsink on the CPU can delay this problem, or eliminate it altogether depend on the workload and external environment.

The only problem with adding a heatsink is that it may foul any add-on HAT boards you install, so be careful.

You could add an external fan, or even liquid cooling if you want, but the latter at least is probably a little excessive.

Memory Sharing

If you are running your Raspberry Pi and not using graphics or gpu-based mathematics (it is possible, but that's another article), consider reducing the amount of memory shared with the GPU.  This is configured with raspi-config

I hope these hints help you to get the most of your Raspberry Pi board.



A "Proper" Robot


It seems to be that this time each year I introduce a new project, and 2019 not going to be any exception.

My projects have become increasingly complex in recent years, and whilst I am still spending a lot of time on autonomous vehicles, according to feedback I have received, it is time to launch something that most enthusiasts could build if they wish.

So, what does the list of requirements look like this time?  I am still drawing this one up, so as usual, you can follow the build and watch it evolve.  For now, here is what I have decided:

  • The finished cost needs to be less that $A300.  Before you groan and say that it's way too expensive, Auric cost about eight times that amount, and is still not done.  I'm going to use off-the-shelf parts, especially from those low-cost marketplaces.  You can use upscale parts if you want, but you don't need to.
  • Use a Raspberry Pi as the controller, and integrate all motion control.  The code for the autonomous vehicles was in C++, which is not as popular these days as languages such as Python.  I/O capacity is not a problem with the Model 2 and later boards either.
  • Allow the use of a middleware platform such as ROS.  I have done it all myself in the past, but that's a lot more work.  Using something like ROS allows builders more flexibility, and opens up applications such as Amazon's RoboMaker
  • Be compact, and tough.  I envisage this particular platform being used for teaching, so it needs to be small enough to be portable, but able to withstand a rough and tumble life.
  • Look like a robot.  OK, so I grew up in the 60's and 70's when movie and TV robots had a certain style about them.  I'm chasing a scaled-down version of those motorised rubbish bins.
To make it easier for others to build, I am also sharing the mechanical design via my OnShape account.  You can access the drawings with a free account at:

https://cad.onshape.com/documents/0d4639caaf7cce8276354c79/w/aa2a04f4f06724823d60edf5/e/9a502c6c5dd6a1fde5ccc783

The base plate, render in OnShape CAD


The only question for now, is what to call it.  A proper robot needs a proper robot name.  Leave your suggestions as a comment.

Life with Deep Racer - Part 2

 An Update on AWS Deep Racer

OK, so AWS Summit Sydney has been run and won.  Not by us however, but there are few interesting tidbits to report:


The console is now widely available

This is actually pretty big news, because:
  • The console ties together Robomaker, SageMaker and everything else you need in a convenient package
  • There are actual examples of functions included
  • It seems to stay running now

There is new firmware for the car

Also important; this includes a rolling update for the Ubuntu base as well as the Deep Racer specific bits.  WiFi connection seems more reliable now as well.

Our car has a new look

Since my employer (Versent) was generous enough to send me to Re:Invent last year (where I got the Deep Racer), I thought it appropriate to deck it out in the company colours, and it was well-received at Summit last week.





Auric: Learning from testing



It's amazing what you learn when testing in the real world...

Auric went out for a long drive last weekend, while things went pretty well, there are always things to learn:


1.  Solving a performance problem

Halfway through the long test I noticed that Auric was pulling to the left, and I suspected a motor drive problem.  After putting the machine up on a bench for a closer look I noticed something, well, "green"


Upon closer inspection, Auric had decided to become an autonomous lawn mower and managed to wrap a 60cm grass runner around the front left drive.  Side effect was that the motor was loaded down and that caused thermal protection in the driver board to kick in.

The final insult was when the imaging detected off-course behaviour and resulted in the motion controller trying to drive the jammed motor even harder, resulting in a vicious cycle.

The end result of all of this is twofold.  Firstly, removing said grass solved the problem, and I wish to add "WEEDING" as a term in the robotics lexicon for the process of solving environmentally caused mechanical issues.

2.  When the board is not what it seems

Dear SparkFun, I owe you an apology.

In my last article, I wrote I was using your "Monster Moto Shield" as part of the motion controller.  Those with keen eyes will spot something completely different at the back of Auric at present.  So what happened?

I purchased two boards from an online reseller because my usual suppliers had no stock, and it would take too long to get them from the US.  Both boards failed in exactly the same way.  The driver for motor 2 would only drive the motor in reverse.  In forward, the potential across the motor was about 0.8 volt, regardless of the motor being used. supply voltage, etc.

I thought this was highly unlikely, so I looked closely at the boards.  While the say SparkFun on them, have the right logo and all, they don't appear exactly like the board on SparkFun's website.  The two driver chips have wildly different manufacturing ID numbers as well.

So what did I get then?  A pair of pretty good looking knock-offs.  Oddly enough, the seller has gone to ground so I have done my money on these ones, and will stick to my preferred resellers in future.

To meet the deadline, I switched to a Deek Robot motor driver which has got me past the deadline, but I am looking forward to getting my real Monster Shields soon!

3.  If it sticks out, it will get broken
In the interest of getting some more interesting video, I attached a Moovie Action camera from Jaycar electronics just above the front track.  This short clip clearly shows what happens when the front camera extends beyond the line of the front tracks:






Auric: All about batteries

Batteries are really important if you're living off them

OK, so this is going to be pretty boring, but it is important so bear with me.

I learned from my experiments with the self-driving car that battery performance is critical, and to be honest last time I didn't pay enough attention.  I am making up for that oversight this time around.

The Lovbio car used a 6V lead-acid battery to run it's motor.  Because that didn't give me too much headroom for my 5V powered electronics I had to run a separate 7.4V LiPo pack (commonly known as a "2S" pack) to run the electronics.  While it worked in the short term and helped the car to meet it's goals, it was not a viable solution.

Because Auric is a ground-up design I had the opportunity to address a lot of the shortcomings from the last car and one of those was the power supply.  This time, it's a single battery and it's a big one, a 6200mAh 2S LiPo pack.  Basically it was the highest capacity 2S pack I could get my hands on.

I arrived at the 7.2V figure after some estimation.  The motors driving Auric's tracks are recommended for operation from 6V - 9V.  Each LiPo cell is typically 3.7V, so if I went to a 3S battery, I would have to regulate down from 10.9V which would have made things complicated.  But even then it wasn't that simple.  The NanoPC T4 processor board I am using needs 12V to operate.  I am not sure who thought this was a good idea because most comparable boards will operate from 5V - 6V.  To get around that I have to use a small switchmode power supply to provide the power for the processor.

But we are still not out of the woods yet.  Unlike SLA (Sealed Lead-Acid) or NiMH rechargeable cells, LiPo cells have a few other quirks we need to be aware of.  Firstly a fully-charge 2S package will measure well over 8V.  Mine measured 8.25V under load when I started testing.  The second thing is that they do not take kindly to being discharged below around 3V/cell, or 6V in my case.  I'm sure you've seen videos of burning battery packs which will clearly illustrate my point.

This means we are operating with a headroom of around 2.5V, and we need to be careful to shut things down before we get dangerously under voltage.  In a future version of the system software, Auric will manage it's own battery events, but I don't have time for that right now.  As a result, I needed to understand how long I could run the completed system before the battery voltage dropped to the critical point.

How are we going to measure this?  It's pretty simple actually, I dropped Auric onto the "RoboDyno" and let it run while measuring the terminal voltage of the LiPo pack every ten minutes.  My results are shown further down this page, and they highlight some interesting information.

If you plug "LiPo discharge curve" into your favourite search engine, you will find graphs a lot like this one:

You can see from these ideal values that there is a steep initial drop in voltage, followed by a long period of moderate drop and finally the point where the terminal voltage "drops off the cliff" and we really need to shut down.

In my testing, the terminal voltage decline was quite linear, typically 40mV (0.04V) every ten minutes.  However if you plot the available headroom (as a percentage), the chart is much more dramatic.  My battery went from 40% (6.95V) to -10% (5.77V) in the 10 minute window!  Had I used a shorter sample window I would have gotten a more typical curve, but mine does at least follow the text book.

When I plugged in the charger it showed one cell bank at 3V, the other at 2.8V; so the inbuilt measurement is reasonably consistent.

So what did I learn?  A few things actually:
  1. Auric can run safely for around two and a half hours across level terrain.  Hills and soft surfaces would affect this adversely.
  2. The battery cliff is very real
  3. The revised motion controller got to 40C, so I added a heatsink to the driver chip just to keep myself happy.  The datasheets say it can run to 50C, but why take chances?
  4. It takes 3 hours to get 3 hours worth of results.
In conclusion, I am writing this on the eve of what should be Auric's most epic voyage so far.  But at least now I am comfortable that it has the power to last the distance.  I just have to solve whatever other problems come up along the way.





Auric: An update


I've been rather busy of late, and have not had as much time to spend on Auric as it has needed.

The motor control has been a problem on this model right from the beginning, and I put some of it down to the L289 controller that is on the NodeMCU carrier.  I realise that this sounds like a poor workman blaming his tools, but early on, back-to-back testing showed the more common L298N-based drivers could drive the motors harder.  Packaging issues got in the way last time, and so I went with the NodeMCU and its carrier.  I paid the price in terms of performance.

Unfortunately, there is still the packaging issue.  There are very few options for shields or carriers for a NodeMCU (to be honest, I can't find any other options), and there is simply not the space on Auric's deck for a separate driver module.  This may well mean changing out the controller altogether.  If I go to an Arduino UNO, such as I used the Self-Driving car, then I have a few more choices:


  • ADAFruit Motor Shields v1 or v2.  There are also a heap of clones of the v1, both of which are based on the L293D chip.  These boards are rated to 2.5A
  • SparkFun Monster Moto Shield.  This uses a pair of ST Microelectronics VNH2SP30 chips, which are commonly found in automotive applications and can operate at 6A without a heatsink.

Both of these look promising because they solve the packaging issues and should be more than up to the current requirements of Auric's motors, but clearly a test was required.

My test rig consists of a pair of heavy duty 12V geared motors (ZYTD520) which should roughly simulate the load of the four motors used on Auric.  Power supply was a 7.4V LiPo pack.

ADAFruit Board

...and SparkFun

Observations

The first stage was to simply run the motors at full speed to measure speed and current draw, as well as the temperature of the driver chips.

The ADAFruit board ran much hotter.  So much so in fact, that I added a pair of heatsinks to the board because I was worried it would shut down or be damaged.

The VNH2SP30 has a few interesting features, which while not essential make it potentially a better choice in the long term.  The first is inbuilt current monitoring, I can read back the motor current on an analogue pin.  Quite useful for battery life monitoring.  The other interesting feature is brake functionality.  We don't need it now, but being able to issue a force stop or hold would be useful in the future.

Unfortunately, both shields bring their connections out in dissimilar ways to the SZ-Doit board I was using,  so this means new cables for battery and motor.  Not a big problem in the grand scheme of things, but just annoying since I had everything so neatly cabled up.

Changing these shields will also mean large scale changes to the code which runs on the UNO, since these controllers are operated in a different manner.  I will look into making the choice of shield a compile-time option, and make it possible for others to follow my work, but make their own choice of controllers.

In conclusion

After an unusually thorough test process (for me, anyway) I have decided to use the VNH2SP30-based board.  In the next article, I will show how it gets integrated into the rest of Auric's systems and hardware.


Wasting your and my time

I had a really interesting experience recently which I hope might enlighten others as much as it did me: I was approached (via LinkedIn) by ...