Sunday, April 29, 2012

Raspberry Pi, and a video

I haven't put in much effort or made much progress lately. I have a problem with increasing the brightness of the IR LED (ie current through it) which broadcasts serial in IR, modulated with a 38KHz carrier signal. Using an AND gate, or just plain transistors, it just doesn't seem to transmit the same signal. I think I will leave the detail for another post.

The other thing is that I'm waiting for my Raspberry Pi Linux on ARM mini-PC to arrive (in about 5 weeks). I'm planning to try to use this to compress and transmit video from a USB HD webcam, at as high a resolution as it can do quickly, over WiFi. Framerate and latency are the most important, followed by resolution and quality. This will also provide network connectivity for the Arduino, in the form of a serial-to-network program, much the same as I currently have with the wireless IP Camera, except a lot smaller, lighter, lower-power, more powerful and hackable :)

So I'm not going to put any more effort into improving analog video capture as hopefully that will all be redundant soon, it will be all purely digital :)

I'll leave this post with some video of my current car being driven around at Hackerspace Brisbane. Sorry it seems to be upside down.


Wednesday, January 11, 2012

Camera update

I discovered the Wifi cam that I disparaged isn't as bad as I thought. However, the actual USB webcam inside does a maximum of 15 FPS - see the datasheet. So the specifications of the Wifi IP cam which say it does 30 FPS is a lie. But the advantages of wifi make it attractive to keep it around, if only just as a wifi <-> serial bridge for the Arduino.


I say it's not as bad as I thought. It turns out that part of the reason it seemed so slow was because the Processing app's Capture class uses lots of CPU, and this in turn seems to slow everything down - my serial pings went over 100ms, and the latency seemed terrible. But when I ran the video stream separately in Firefox, and ran the app, the serial ping was back to normal 17-35ms, and I could actually navigate! However, Firefox's CPU usage was still very high - this may be a problem with the HTTP server implementation if it doesn't state the image size in the MJPEG stream, it has to examine the stream to find the end of each JPEG.

15 FPS is still too slow, but the image quality is much better than a captured analog PAL source. So I wonder if I could plug in another webcam which does better? Probably not, as it would have a very limited driver support. I would have to significantly hack on it, and it's not an ideal platform, so I'd probably want to develop my own ARM board which is getting quite complicated. There are ARM development boards at 60 MHz though which aren't too expensive, about $60, ie about the same as an Arduino Mega with a whole lot more flexibility. I don't know what CPU speed the wifi cam runs at. Just add a USB wifi adapter, much the same as the wifi cam, which is cheaper than an ethernet shield.

So in case I do end up going down this (convoluted, yak-shaving) path, I looked at what decent webcams are available, with the following requirements in order:
  1. frame rate - at least 30FPS at 640x480.
  2. USB 2.0 - it's not going to be able to do high resolutions or frame rates limited to USB 1.1 12 MB/s. Needs 480MB/s.
  3. image size - as stated, at least 640x480, ideally 720p, which means also 16:9
  4. field of view - all the cheap stuff is really narrow view. if I want widescreen, and gaming style, it should be high FOV like 80 degrees hopefully.
  5. onboard JPEG compression, so a device can simply take those JPEGs and put them in an MJPEG stream with minimal CPU overhead. Most do this anyway. 
  6. good visibility in low light, or I could just put headlights on the car. So then, quick white balance.
Other nice-to-have features are autofocus, and really nice would be switching between visible and IR light. 

Note that due to the USB 2.0 probably no camera can really do 720p at 30fps.

I found the following cameras which are actually all quite decent, and less than $100:
  • Logitech Webcam Pro 9000 - 720p at 24 fps, or 30fps at a bit lower resolution, limited by USB bus.
  • Logitech HD Pro Webcam c910 - full 1080p, though I'd never use it, apparently better low-light performance, and quite wide FOV. 
  • PlayStation Eye - 640x480 at 60 Hz is max res, also 320x200 at 120 Hz. I like the high res, would like to play with one and see. But may be better for machine vision or UI stuff (which is its intention).
  • Microsoft HD 5000 - 720p, not sure about FOV, but this got me - auto focus! Which is also tunable. 
But for the time being I have a new 5.8GHz wireless analog system so I will try that out. Still limited by the capture device but the range is much better.

Saturday, December 10, 2011

Quick test for servo characteristics

I got some new servos and wanted to see what their range and noise was like. Running a looping test is not very informative, and typing commands over and over is tedious. I like interactive stuff.

So I wrote up a quick program in Processing to allow you to use the  mouse or keyboard to set the angle of a servo on any pin. You just move the mouse within a white box to set the angle, or use keys for more fine control (if you're Michael J. Fox, for example). You move the mouse quickly up and down in the box to get an idea of how fast/responsive the servo is.

I hope someone finds this useful. The Processing PDE source file is pasted below. There's no code for Arduino, just the bitlash library.

Requires:
  • Arduino IDE
  • Bitlash Arduino library: a command-line-like interface to arduino functions and pins - http://bitlash.net/wiki/start - I used 1.1, there is also a new 2.0 RC4 which may be compatible.
  • Processing IDE - processing.org
 Caveats:
  • Only works for angles between 0 and 200. every servo I've ever used only has a range of at most 170 degrees, usually starting 5 - 20 degrees, ending 165 - 180 degrees. It's not hard to change if you have special servos. Using this program I have determined my new Dynam 34g servo's range to be 5-175 degrees, but I would limit it to 10-170 in order to avoid damaging them.
Possible improvements:
  • Allow individual, or simultaneous control of multiple servos; the standard arduino can control up to 8, and so the bitlash code only supports 8. The Mega can control more, but this requires a small change to the bitlash servo example. There are also shields and other things which can expand the servo control capabilities, which would require more extensive changes in bitlash; in fact with a large number, it might be worthwhile developing a custom protocol.
  • Put it in source control for shared access and versioning. Link to that instead of pasting source here. 
Source for ServoTestBitlash.pde:

/**
  * Quickly test servo min and max angles, speed, torque and noise, using Arduino with Bitlash library.
  *
  * 1. upload bitlash servo code to arduino (part of library examples).
  * 2. configure the variables below for the pin your servo is on, and serial port.
  * 3. run it.
  *
  * The angle is initialised to 90 degrees (roughly center).
  * Move the mouse cursor up and down in the white area to change the angle.
  * The current angle is shown at the top.
  * For more fine control, move the mouse off the screen and press W and S to increase and decrease the servo angle.
  *
  * Author: Joel Byrnes, December 2011.
  * email: arduino (at) adeptusproductions.com
  */

import processing.serial.*;

/***** modify this for your setup ******/

int servoPin = 9;
String serialPort = "/dev/tty.usbserial-A700eEtE";

/***** end modify part *****/

int pos = 90;
Serial port;
int lastMouseY;
  
void setup() {
  port = new Serial(this, serialPort, 57600);
  port.write("\n");
  setPos(servoPin, pos);

  size(350, 350);
  noStroke();
  frameRate(50);
}

void draw() {
  if (mouseY != lastMouseY) {
    if ((mouseY-50) < 0 || (mouseY-50) > 200) return;
    lastMouseY = mouseY;
    pos = mouseY - 50;
  }

  background(0);
  rect(50, 50, 250, 250);
  text("0", 10, 50);
  text("200", 10, 300);
  setPos(servoPin, pos);
}

void keyPressed() {
  if (key == 'w') {
    pos++;
  } else if (key == 's') {
    pos--;
  }
  else return;
 
  setPos(servoPin, pos);
}

void setPos(int pin, int position) {
  println(pos);
  text("angle: " + pos, 150, 25);
  port.write("servo(" + pin + "," + position + ")\n");
}

Monday, October 3, 2011

Augmented reality? Local Positioning System?

It occurred to me the car video would be a good target for augmented reality. I already have overlays, but you could insert location-based data over the video, for example the other cars, pit stops, navigation, maybe even explosions!

The trouble (as with any augmented reality system) is tracking distance, rotation, angle etc so as to place the augmented items correctly on screen. For a while I have been considering the idea of a LPS (local positioning system), like GPS, for accurate location of items in a small area. Fast compass measurements would also be necessary.


I recently attended a talk on lightweight java game library, which is mainly a simple, fast wrapper for OpenGL, so rendering objects is actually pretty easy :) Minecraft uses LWJGL.

Just thoughts, so far...

WiFi IP camera

While I haven't posted for a while, there was some fervent activity for a bit. My hackerspace comrade tjhowse found that there are cheap WiFi cameras you can get with an ARM processor and embedded ucLinux, which are in fact quite hackable. They also have pan-tilt stepper motors, but they have been geared way down so they are incredibly slow. Finally, they have decent IR leds so they can see in the dark; they are designed as controllable IP security cameras after all.

The innocent Wifi camera before being hacked.

The default web UI is quite decent.


I won't go into detail right now but the photo album is here and here are some threads on the topic:

http://groups.google.com/group/hackerspace_brisbane/browse_thread/thread/f5eae6b6d9922e00

http://groups.google.com/group/hackerspace_brisbane/browse_thread/thread/7336980c0f887d25

Added wires for serial connection and power.
Ultimately though, I found that:
  • The latency is actually quite low on a non-congested wireless network - as little as 35ms, which is quite adequate. 
  • The latency spikes a bit sometimes, not sure if this is congestion or CPU problems on the system
  • It is hard to connect up the Arduino over serial reliably, though I have basically solved that. 
  • It is great to have clear video without interference and static
  • However, the video is too slow. Framerate is uneven and low, and there is a significant delay - no good for what should be a fast-paced reflexive game. Not sure if this is due to CPU power, the capture device, or network problems.
So it was fun hacking it, and in fact I might keep it for data comms. Maybe remove the camera and just run the base board. That will require hacking the firmware, but that's a solved problem.

I was able to run the camera off the car's battery, through the Arduino's regulator! The reg got hot quickly though.

Thursday, June 2, 2011

Debug pin with software serial

I have been intending to re-purpose the hardware serial interface on the JeeNode to run IR comms, because being hardware and buffered it won't miss data if it's doing something else other than listening, as it would with any software serial library.

But at the same time, while doing development, I like to have debug output. Until I actually start doing the IR thing, I can still use the serial port for this. But I would like to keep that ready to do at any time. Or I can send them over the RF12, but I would like to reduce my wireless usage as much as possible, and not clutter up my UI's text window. Again, until I have multiple cars going, wireless contention isn't as much of an issue, but I prefer to do things properly the first time as long as it isn't going to be harder than fixing it later.

Then I thought, I could use software serial. It's slower and ties up the CPU, but I don't have a lot of or very frequent debug output, so it should be fine. Furthermore, I can just turn off debug output when it's not useful (mainly, when the car is moving around). I added #define and #if-#endif statements to turn the serial output on or off entirely, in a method like this (from memory):

#define DEBUG_ENABLED 1

void debugln(char[] msg) {
  #if DEBUG_ENABLED
  debugSerial.println(msg);
  #endif
}

So if I turn off DEBUG_ENABLED, then calls in the code such as debugln("Car ready") won't have any impact. And including a library should only take up some memory.

First I tried NewSoftSerial, which I have tested out before and decided was too slow (with Arduino and XBee). This caused my steering servo to freak out at the same interval as the messages being sent, no matter what pin I tried to use for debug. I also didn't see any serial output. I think the freak out was because NSS uses interrupts, which is probably shared with either that servo output (it's probably a PWM pin, I didn't check) or the RF12 code. I don't need or want an interrupt-enabled library because this is going to be used sparingly and only for output.

Side note: it's annoying that every such library demands you give it both an Rx and Tx pin. If I only want to send, why do I have to give it a receive pin?

So I tried out SoftwareSerial instead, which is part of the core Arduino library. It didn't cause any apparent problems with servo or RF12, but it also didn't seem to work at all. No matter what pin I chose, from a digital to an analog, or a few other pins on the JeeNode ISP or other headers which are not used at the moment, nothing came out. I set it to 4800 baud (9600 being the max anyway) but the LEDs didn't even light up. I added Serial.println after the debug and that was still outputting.

In short: is the RF12, Ports, or Servo library interfering with SoftwareSerial?

Update: it turns out you need to set the Tx pin to OUTPUT mode. I would have thought the library would do that, I really would.

So that started working, but then I had a problem with debugging just after sending a status update: the output was scrambled. I guessed that the rf12 library was sending and that was throwing off the serial timings. I asked on the JeeLabs forums if there was a way to fix it, and jcw himself (creator of Jeenode) replied. If you add a rf12_sendWait(1); after the sendStart command, it waits for the send to complete before returning to the program flow. That's a double-edged sword; You can guarantee your timings won't be thrown off by the background sending, but at the same time you delay returning to the program, I'm not sure for how long. If I want to keep the loop very tight, it might be a problem. I could also reduce the size of my sends as much as possible. But so far it seems ok.

Forum post is at http://forum.jeelabs.net/node/259

Now with pan/tilt mount

I thought of a quick and dirty way to test how the pan/tilt mount would work with the new car, without having to build the whole support and everything...



That tape is actually pretty sturdy... but I haven't driven it around much. At all actually. There isn't much room and it's late and the car is noisy. But it should be pretty awesome :)

This new car with its 7.2V battery (which after charging is like 8.5V) also means I can run the camera off the same battery, yay! So I don't need an extra battery holder for that. I will also add a MOSFET so that when I turn on the car, it allows current to the camera - so a single switch to turn everything on/off.

I'll record some video from the car camera when I am able to drive it around.

I also need to update that UI - I have the prototype pretty much done, I just have to do the work to put it into the app.

New car test through laptop

We took the new RC car for a spin with the UI and the camera. Buzz wanted to try out his own camera, which is much more expensive and better than mine, so we mounted it.

Camera mounted to car with additional rails... and tape. 

That's a true hack job there :) TJ suggested putting rails on it between the back and front shocks. We'll get around to actually cutting them to size, tapping and screwing them, but for now they're zip tied on. Then a plastic light cover is taped between the rods, and the camera, antenna and wires are taped down everywhere :)

You can also see the JeeNode at the front. It turns out to be really easy to control both steering, and throttle with an ESC, as they both just use standard servo control. It actually saves me 2 pins compared to the other car!

View from car camera


 Buzz took it for a spin. He was determined to try to drive it under the cars parked in the space. We taped a small flashlight to the front so we could see.


Unfortunately I didn't record any video footage from this. We were also still getting used to the fast car and the controls were twitchy; with just a slightly too-long keypress, I drove the car into a pole so hard the zip-tied rails slid forward out of the rear zip ties. Buzz got it stuck under a car. I tried to drive it outside which I knew was dangerous if I lost jeenode signal and therefore control. I lost both video and control signals at once momentarily, and Buzz went to get the car. He found it trying to reverse while hard up, and making a bad electronics smell. We're not entirely sure what made the smell, and everything still works, but I think it was probably the ESC - it's the only thing that was a bit warm.

I have been aware of the danger of driving out of signal for some time, because there's nothing stopping the car from continuing if it never gets the stop command. There's no way to detect a JeeNode signal in range except to receive data. It wasn't that much of a concern with the smaller car, and I was just careful. So now I have a really compelling reason, and I've done it - if the car hasn't received a command to go forward, reverse or stop for 250ms, it stops. This also requires a change to the UI to send an update every 150ms, just to keep it going if for example you hold down forward for over 250ms, where before there would be no need to send an update.

Wednesday, May 25, 2011

Fancy new UI

I've been working on dramatic improvements to the UI - position indicators, more gauges, and building in the support for a few features to come. Tell me if it looks familiar at all ;)


This would of course finally be full screen, with the video behind, and work in widescreen or 4:3.

Tuesday, May 24, 2011

New car! New control!


Bigger, faster, actually has suspension, proportional steering and throttle, and simplified electronics through an ESC - awesome :)
Also the battery is higher voltage (7.2V) so I should be able to run the camera off the same battery!
However, the canopy is very flimsy so I'll have to create a new mount for the camera + gun.

Oh and what's that behind it?....


It's an old set of steering wheel and pedals that I picked up for $10 at an op shop! It's for a PS2 or Xbox original, but as Xbox is just USB, at Hackerspace tonight I lopped off the end and after a lot of cursing about anti-standard wire colours, got it recognised as a USB device under Windows. Have yet to try Mac. How awesome will it be to drive that car with a proper wheel and pedals!

Thursday, March 10, 2011

JeeNode frequencies and signal quality

A question arose on the HackerSpace Brisbane mailing list about the supported frequencies of the JeeNodes. I was under the impression, in the vacuum of contrary information, that the units I had would work at least to some extent in all the supported frequencies (433, 868 and 915 MHz), although it is difficult to make a single radio that can do that. I was under this impression because I had tested such with the RF12demo on the units when I first unpacked them.

It turns out that because I bought them at the actual JeeLabs Shop, in Europe, I got the 868 MHz versions, rather than the 915 MHz version sold at Modern Device. This might be problematic.

Anyway, I did a number of tests to determine the suitability of each frequency with the modules I have.

Testing more thoroughly with the RF12demo again, I determined the following radio capabilities:

  • changing both to any of the 3 frequencies allows communication both ways (including ack)
  • changing one to 868 and the other 433 allows data 868 -> 433 but not the other way (and no ack reply)
  • sending from 915 cannot be received by either 868 or 433
This indicates all frequencies work, or at least some kind of shared delusion of using the same frequency.

Then I tested the relative signal quality of each frequency. I wrote a sketch that spams my car about every 50ms (it has an echo function for pinging and tests just like this) and reads the echo reply. I ran that on the USB JeeLink attached to my laptop used the highly scientific approach of walking around the house with it. I had it print out a dot for every send, and an R for every receive, so the ideal output looks like this:
.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R
... and so on.
  • 915 was ok, in the same room it got all the packets, and I could get through two or three walls and still receive a significant number of packets.
  • 868 was awesome. I went all over the house and hardly dropped a packet. In fact I had to get the laptop halfway into the fridge before I started losing more packets than I sent! ...R...R.R.R.R....R..R... 
  • 433 was disappointing. It lost packets within the room and lost significant amounts just outside the door!
Note that this was all with unoptimised antennas. Default length of about 90mm. According to this talk page, 868 should be at 82mm (pretty close), and 433 at 165mm, which might explain its poor performance. I don't think 1/8 wave works very well. 
 
 

Car fully working with JeeNode

I pulled out the old RBBB Arduino clone, and hastily blue-tacked the JeeNode in its place. I left all the breadboard wiring in place in case it didn't work and I had to revert to the RBBB. But, success! It was a bit fiddly jumping all the wires from their otherwise neat ribbon cables into the JeeNode ports, but here it is:


The small ribbon cable with the black lead goes to the wheel motor controller, and the larger cable with red is for the pan/tilt servos, IR gun and has room for expansion.

So I've connected up everything, and it successfully goes forward, back, left, right, moves the camera, shoots and measures the battery voltage! Just as responsive as before! Only this time with better range! More on that in another post.

Saggy reprap parts :(

I often leave my stuff in the car, in the sun, while I'm at work, when I'm heading to HackerSpace Brisbane that evening. This must have happened on a particularly hot day:


The base of the pan/tilt mount is badly warped. The tilt doesn't work very well any more because the distance is greater, so you tilt up halfway and it starts going down again. Infinite sadness.

Do I put it on a flat surface and hit it with a hair dryer to get it back in shape? Do I just print a new part? I planned to design a new one with a support that went all around instead of just at the front. That should help with warping. Also a smaller base would be better, and the corners on this one catch on the servo wire, so it should be more rounded.

Tuesday, March 8, 2011

JeeNode working!

After quite a while porting my arduino code to use the jeenodes instead of serial/xbee, and figuring out which pins on the "ports" map to digital pin numbers, I got it to work! I can control the pan/tilt mount remotely! (that's all I've tried so far) And it's quite acceptably fast - in fact pings hover aound 54ms!

The main challenge with porting the code was that instead of just throwing data at the serial port and letting the xbees deal with it, I have to think about how to break it into packets, and which packets I really need to send and which I don't. There is also the issue of sometimes having to wait to send data, which might become a problem later. For now I have two methods, one says "send it now if you can, else drop it" and the other says "try to send forever". If the channel was tied up, it would just freeze up there. Obviously there will need to be some middle ground, if I run into problems.

I also had to write code for the JeeLink (the usb dongle, which is basically just a SMD AVR and antenna), to make it appear to be a plain serial connection for the frontend software. It was easiest if the frontend changed as little as possible (not at all, actually). In future it will be extended to provide the sender node ID and so on. This may probably become a central server node that directs all the traffic to the clients.

I had to figure out the mapping of pins to the existing arduino pins I was using so I could plug the servos into the right ports. Also there are only 4 digital and 4 analog-in ports provided on the JeeNode, so I was worried that I was already using all the pins I had available. I looked at the JeeNode diagram and the arduino diagram and painstakingly mapped it out. Basically the RF12 module steals 5 of my digital pins, two of them PWM. But some pins are mapped to the I2C and SPI/ISP connectors also available on the JeeNode, and to the INT pin on each Port. So I should be able to recover 3 digital pins, 2 of which are PWM, and two more analog-in pins. So that provides enough room for some additional things I want to do :)

Wednesday, February 2, 2011

Pan/tilt mount evolution

The first pan/tilt mount for the camera was just servos blutacked or polymorphed together (version 1). Then it was a tilt mount out of bent metal (version 2). Now I have designed and printed a mount on the Hackerspace Brisbane reprap!

Version 2:


Design of Version 3:



Installed:

Then with the old tilt mount.


And here are some images of the new tilt mount being assembled.

Design in OpenSCAD









Tuesday, February 1, 2011

JeeNodes

I've ordered 2x JeeNodes (v5) and a USB JeeLink, which I will test out as a replacement for the offboard XBee I'm using now. Combining a RBBB Arduino-compatible board and a radio, they are cheaper and hopefully also have better signal, more than the 2mW XBees I have. They didn't actually give me an option in the shop for the frequency I wanted (they come in 433, 800 and ~900 MHz versions, depending on your country's laws), but I'm hoping for 433 or 868 MHz versions, as I have heard bad things about 900 MHz, mainly because they share a common mobile phone frequency. I hope at the very least that they are all on the same frequency!

My original concerns about these devices were that they wouldn't be fast or efficient enough, but there wasn't much info available at that time. Since then I have gleaned that the radio comms run at 57600 baud and use interrupts, over the SPI interface, so it should be fast enough. That leaves the inbuild hardware serial for other purposes - IR comms!

Suddenly, an update!

It's been a reeeeaallllyy long time since I updated, but lots has happened recently. Here is a demo of the new fullscreen UI!

You should really watch it in max HD so you can see the text change. 

Monday, October 4, 2010

User Interface

I decided I should post some of the UI and hopefully some video; this is after all, or should be, a very video and UI-heavy project. Work on the hardware side has left the software side behind.

So here is a screenshot of my current basic UI! Click for the full-size version.


The camera view is shown with EasyCapViewer (mac) or AmCap (Windows). Processing is used to create a basic control and indicator interface between the user and the serial port. 

Let's break down that UI a bit:


The camera is controlled by moving the mouse cursor within this grey box. The mouse position is mapped to degrees for the servos; left is as far as the pan servo will turn left, middle is straight forward, at the bottom is as far as the tilt servo can go down. This is not ideal as the mouse can go out of the box while you're watching the video, and you have no idea of absolute position; I often look down to see where the bonnet of the car is so I can tell where it's pointing!

The 4 squares at the top indicate the movement that should occur; basically they map the WASD keys to forward, back, left and right; they turn yellow when the relevant key is pressed. This was used for debugging.

Next the two V labels indicate voltages sent back by the arduino every second. Vcc is the inbuilt voltage meter of the arduino and Vcar is the voltage of the car battery, max 6V, which is input with a 1/3 voltage divider so that the arduino could even read 9V if I was running it at 3.3V. It cannot read a voltage above Vcc. There can be variation in these voltages near max capacity, but as it is currently well below that they are the same.

There is a text box which allows me to type any command to the arduino; currently it uses a simple string-based command system which is easy to debug but not the most efficient. It might be improved later but works for now.

Finally the ping time; yes, latency! It measures the round-trip time of a timestamped message to be sent, received and processed by the full stack, sent every second. One of the first things I implemented with the string-based command system was an echo response, so this sends a message of "ping <current-time>" where current-time is the number of ms since the program was started. When an echo is received, it compares the time in the message with the current time and there is your latency. The latency bounces between 33 and 66ms at the moment; I have another post to write about that. It does not measure lost packets, but if it has been over a second since it received a ping echo, it says "Ping timeout!!"

As for the video, well, it's not great, but I'm actually pretty impressed given the amount I paid for it all! There is some bands of interference near the top and bottom of the image; this is due to the wireless transmission. Bypassing the wireless makes the image clearer. But there should be a better wireless camera kit on the way.

So this is far from ideal. I want the video fullscreen, with the mouse free to move anywhere, I want the voltages and latency overlaid on the video like a HUD, and I want some graphics to indicate camera angle overlaid as well. There will be more overlays later too.

I met a new guy at Hackerspace who has experience with doing games and video programming and is interested in the project, which is great! He's a Windows guy, which is less great, but we'll figure it out :) So hopefully I will get some of this improved soon.

Need to fix up the camera feed

The biggest current problems I have with Phase 1 are just around video, mainly due to buying cheap shit electronics from China - the camera image itself is surprisingly clear, but the refresh rate is low and you can't see anything when there's vibration (ie driving fast). I have ordered a much better camera and mounting system from hobbyking, but seems they're waiting for stock to come in.

And then there's the very cheap USB video capture devices I bought - they were so cheap I got 4 for $36 including shipping! They're apparently DC60 devices; DC60+ are apparently *completely* different and do work on mac and better in general. That's probably why they were so cheap. They're ok for just checking what the camera is seeing, but the driver support is very low, there are no drivers for mac, so I can't write a program to integrate the video from it. There is only one decent program I've found that lets you see the image, EasyCapViewer, which is a mac port of a Linux driver. Unfortunately, it's only a standalone program, and doesn't create devices I could use in another program. And it's written in some language I don't know which uses .m source files - Objective-C maybe? I would rather write in Python or even Java. I've hacked up a basic UI in Processing but it doesn't integrate with the video at all.

So I'm also looking for better capture devices but everything on ebay is variations of the same chip. Also everything is geared towards either viewing your console game in real time or capturing VHS tapes to DVD, so there aren't general drivers that you could plug into any software. Nothing seems available in USB which is a shame because I wanted to use my laptop so I can move around with it. I will try a PC video card capture just to see if that works better.

Servo control and Arduino PWM outputs

tl;dr Arduino PWM (ie analogWrite) doesn't work for servos. Use the built-in Servo library or one of the many variations and deal with the loss of some analog output pins or having to call a function at least every 50ms.

I had problems with the servos being a bit jerky, or twitchy when not being moved. I'm using the built-in Servo library, but was annoyed that it disabled PWM outputs on some pins - I used these pins for the motor control, and this particular issue wasted several hours debugging. After I discovered this, I was annoyed because I had found a convenient place to plug in motor control and was too lazy to move it.

I tried the SoftwareServo library and found it no better, in fact possibly more twitchy, sometimes not responding at all - but this may have been due to power problems. But I put a LED on the output pin and it seemed to flicker inconsistently, due to it not being a hardware output and dependent on processing loop time, whereas it should have been a smooth or at least consistent flicker.

I thought all this was silly, why were there different libraries for servo control, and both had annoying issues? I could just control the servos directly with the hardware PWM, right?

Well I tried just that, and the servos did very weird and completely wrong things - a single change it degree made it move a little, or maybe 90 degrees.

Turns out that servo motors are not controlled by PWM, or Pulse Width Modulation, at least that which is output by the Arduino (the timing is probably wrong). They are controlled by Pulse Position Modulation (PPM). The wikipedia page on servos is a little misleading on this matter, although it is possible there are servos that are controlled by different kinds of PWM.

All this behavior finally became clear when I found this post on the arduino forums: 

Help with PWM for controlling servos and speed con

So after moving my motor PWM pins, making sure the arduino power was isolated from the servo power, replacing the oversized pan servo with a smaller, faster, lower-power one, and replacing the tilt servo with one that hadn't been put through the first batch of testing where it held up the camera itself, I have a stable camera :)