Hi my name is Martin and this site is about the world of underwater ROV’s (Remote operated vehicles)

I’ve been building ROV’s  for some time now, having dream’t about building one for years.

I debuted the first one I built at the Newcastle Maker Faire in March 2011 and shortly after presented it at the Scottish Ruby conference in Edinburgh. I’ve attended Mini Maker Faires all over the UK showing my original ROV and a couple of Micro one’s that kids could play with.

At the beginning of 2013 I decided to start to build an Open Source OpenROV and this site covers much of the build process and ongoing improvements. OpenROV has a great community and it’s well worth becoming a member.

 

 

 

I saw a couple of articles on hacking reverse parking sensors using micro’s other than an Arduino and decided to have a go myself. A lot of information I got from the following two sources http://www.mp3car.com/hardware-development/121995-custom-usb-parking-sensor-interface-formally-pdc-usb.html and http://ishankarve.blogspot.co.uk/2011/06/decoding-ultrasonic-parking-sensor.html There a lots of different versions available on eBay but I decided to go with the wireless version from the first link. The manufacturer was listed as CISBO. First action was to remove the  screws to get access to the circuit board

IMG_1144 IMG_1142 IMG_1143

 

As can be seen here

IMG_1146

IMG_1147

I solder wires to ground and data in then hooked up to my saleae logic Analyser

IMG_1152

I obtained the following trace

trace

The trace is made up of three bytes, 1st byte identifies which  Sensor A, B, C or D. The next two bytes provide the distance measurement in cm’s.

Next it was time to hook up to an Arduino

IMG_1159IMG_1164

And write some code

int pin = 7;
int ledPin = 13;
unsigned long pulse_length;
byte sensorValue[24];
byte pulse_value;
byte temp = 0;
byte distance = 0;

// const sensor address's
const byte senA = B11110000;
const byte senB = B11010010;
const byte senC = B11100001;
const byte senD = B11000011;

void setup()
{
pinMode(pin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
}

void loop()
{
int i;
//look for starter pulse
pulse_length = pulseIn(pin, LOW);
while (pulse_length < 18000) {
pulse_length = pulseIn(pin, LOW);
}
for (i = 0; i < 25; i = i + 1) {
pulse_length = pulseIn(pin, HIGH);
if (pulse_length > 290 && pulse_length < 310) {
pulse_value = B0;
digitalWrite(ledPin, LOW);
}
else {
pulse_value = B1;
digitalWrite(ledPin, HIGH);
}
sensorValue[i] = pulse_value;
}

Serial.println(" ");

for (i = 0; i < 25; i = i + 1) {
Serial.print(sensorValue[i], BIN);
}
Serial.println(" ");

for (i = 0; i < 25; i = i + 1) {
pulse_value = sensorValue[i];

// write pulse_value to bit 0
bitWrite(temp,0,pulse_value);
switch (temp) {
case senA:
Serial.print("Sensor A: ");
Serial.print (temp, BIN);
Serial.print(" ");
pulse_distance(i+1);
i = i + 16;
break;
case senB:
Serial.print("Sensor B: ");
Serial.print (temp, BIN);
Serial.print(" ");
pulse_distance(i+1);
i = i + 16;
break;
case senC:
Serial.print("Sensor C: ");
Serial.print (temp, BIN);
Serial.print(" ");
pulse_distance(i+1);
i = i + 16;
break;
case senD:
Serial.print("Sensor D: ");
Serial.print (temp, BIN);
Serial.print(" ");
pulse_distance(i+1);
i = i + 16;
break;
}

// shift left
temp = temp << 1;
}

}
void pulse_distance(int i) {
//read next 8 bits
int j;
distance = 0;
for (j=0; j < 8; j = j + 1) {
pulse_value=sensorValue[i];
// shift left
distance = distance << 1;
// write pulse_value to bit 0
bitWrite(distance,0,pulse_value);
i = i + 1;
}
distance = ~distance;

Serial.println(distance, BIN);

}

Which produced the following output

IMG_1163

I then wrote a processing sketch to display the data more elegently

import processing.serial.*; /* Needed for Serial Communication */

/* Global variables */
Serial comPort;
String [] comPortList;
String comPortString;

sliderV sV1, sV2, sV3, sV4;

color cor;

/*--------------------------------------------------*/

void setup(){
size(500,500);            /* Set the size of the window  */
//background(0);            /* Set the background to black */

/* Get the available com ports. If there is at least one
com port available, then start communicating on it.
If there are more than one com ports available, we will
only open the first one (i.e. comPortList[0])
The bufferUntil('\n'); statement will generate a serial Event
when it reads a carriage return */

comPortList = Serial.list();
if(comPortList.length>0){
comPort = new Serial(this, comPortList[0], 115200);
comPort.bufferUntil('\n');
}

// create 3 instances of the sliderV class
sV1 = new sliderV(100, 100, 90, 255, #FF0000);
sV2 = new sliderV(200, 100, 90, 255, #03FF00);
sV3 = new sliderV(300, 100, 90, 255, #009BFF);
sV4 = new sliderV(400, 100, 90, 255, #FF9BFF);
}

/*--------------------------------------------------*/

void draw(){
/* The serialEvent function will update the display */
}

/*--------------------------------------------------*/

void serialEvent(Serial cPort){
comPortString = cPort.readStringUntil('\n');
if(comPortString != null) {
comPortString=trim(comPortString);
String items[] = split(comPortString, ':');

// if there was more than one string after the split
if (items.length > 1) {
// remove any whitespace from the label
String label = trim(items[0]);
// remove the ',' off the end
String val = trim(items[1]);
// check what the label was and update the appropriate variable
if (label.equals("A")) {
sV1.p = int(val);
}
if (label.equals("B")) {
sV2.p = int(val);
}
if (label.equals("C")) {
sV3.p = int(val);
}
if (label.equals("D")) {
sV4.p = int(val);
}
}

/* Print to the Debug screen in Processing IDE */
println(comPortString);
}

background(0);
sV1.render();
sV2.render();
sV3.render();
sV4.render();
}

/*
Slider Class - www.guilhermemartins.net
based on www.anthonymattox.com slider class
*/
class sliderV {
int x, y, w, h, p;
color cor;
boolean slide;

sliderV (int _x, int _y, int _w, int _h, color _cor) {
x = _x;
y = _y;
w = _w;
h = _h;
p = 90;
cor = _cor;
slide = true;
}

void render() {
fill(cor);
rect(x-1, y-4, w, h+10);
noStroke();
fill(0);
rect(x, h-p+y-5, w-2, 13);
fill(255);
text(p, x+2, h-p+y+6);

if (slide==true && mousePressed==true && mouseX<x+w && mouseX>x){
if ((mouseY<=y+h+150) && (mouseY>=y-150)) {
p = h-(mouseY-y);
if (p<0) {
p=0;
}
else if (p>h) {
p=h;
}
}
}
}
}

which gave the following output

IMG_1167

 

 

 

I’ve had a lot of problems trying to update the OpenROV software from the default image. I keep on getting npm errors and install script errors.  I’ve tried all the suggestions from the wiki and also forum.

So I decided to try and build my own image from Source after noticing on Github a recent change to using Vagrant with instructions on building your own image. I already had a copy of Virtual box and so decided to give it a try. I’m on Mac OSX system but it should work on other systems.

I had some problems with the build and after speaking to Bryan A on the OpenROV  downgraded my copy of VirtualBox to version 4.2.10.

  1. Download and install a copy of Vagrant from http://www.vagrantup.com/
  2. I already had a recent copy of Virtual box, but this can be downloaded from http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html
  3. Clone the github file from https://github.com/OpenROV/openrov-image locally I used GitHUB desktop to do this.
  4. Using Terminal chang into the directory where cloned the repository openrov-image
  5. Type the command “vagrant up” On my system this started a number of commands but hung at “Waiting for VM to boot. This can take a few minutes.” A quick trip to Google revealed that others have experienced the same problem. First I had to stop the running image this can be done by typing the command “VBoxManage list runningvms” followed by BoxManage controlvm <id of running image> poweroff
  6. I fixed it by running up the Virtual box and starting the image manually. I closed the image then tried the Vagrant up command again this time the image seemed to spin up and download a number of different files before exiting back to the command prompt
    vagrant_up
  7. Type the command “vagrant ssh” to ssh into the image, Windows users will probably need to use putty to do this.
    vagrant_ssh
  8. change to the vagrant directory cd /vagrant
  9. and run the build “./build.sh”
  10. This will take sometime so go and have a cup of tea, at the end hopefully we should have a completed build ready for installation to the SDCard
  11. One problem was getting the system to recognise the SDCard the following instructions from http://superuser.com/questions/373463/how-to-access-an-sd-card-from-a-virtual-machine/#45808  was one solution and these instructions are repeated below:

On newer MacBook Pro’s the SD card slot is no longer exposed as a USB device. Because of this you’ll need to attach the raw device to the VM in order to gain raw access to the whole card. Full documentation is in the Advanced Storage Configuration section of the VirtualBox documentation.

As clearly stated in the docs:

Warning – Raw hard disk access is for expert users only. Incorrect use or use of an outdated configuration can lead to total loss of data on the physical disk. Most importantly, do not attempt to boot the partition with the currently running host operating system in a guest. This will lead to severe data corruption.

As a quick guide these are the steps to attach the device to a linux VM:

  1. Identify the raw disk block device on your host system
    1. Insert the SD card into the slot
    2. Open a Terminal and type “mount”. You’ll see output identifying the mounted volume from your SD card. On my system I get the following
      <code>$ mount
      /dev/disk1 on / (hfs, local, journaled)
      devfs on /dev (devfs, local, nobrowse)
      map -hosts on /net (autofs, nosuid, automounted, nobrowse)
      map auto_home on /home (autofs, automounted, nobrowse)
      /dev/disk2s1 on /Volumes/NO NAME (msdos, local, nodev, nosuid, noowners)`
      </code>
    3. In my case the “NO NAME” volume is the SD card, so I take note of the /dev/disk2s1 part. In this particular case the s1 part represents a partition (slice) on the raw device, so the part we’ll use later is just the /dev/disk2 part.
  2. Open Disk Utility and “Unmount” the volume. Do not “Eject” it. Note that you may need to unmount the volume once in a while during the next steps as I found OSX would automatically remount it at random.
  3. Now we set up VirtualBox to be aware of the raw device with the following command in the Terminal.
    1. Note that the /path/to/file.vmdk can be put anywhere, though it’s a good idea to store this in the guest VM folder such as ~/VirtualBox VMs/guest-vm/sdcard.vmdk
    2. Note that the -rawdisk we use doesn’t reference the partition (slice) but only the block device as a whole.
      <code>$ VBoxManage internalcommands createrawvmdk -filename /path/to/file.vmdk -rawdisk /dev/disk2
      </code>
  4. Next we attach the raw disk to a guest VM within the VirtualBox UI
    1. Ensure the guest VM is not running.
    2. Open the settings area for the guest VM
    3. Click on “Storage” in the toolbar
    4. Next to the controller click on the icon to “Add Hard Disk”
    5. Select “Choose existing disk”
    6. Navigate to the /path/to/file.vmdk you used in step 3 and select it
    7. You should now be returned to the Storage tab and see your file.vmdk in the list.
  5. Start the VM
  6. Depending on whether you have a GUI or not the SD card may or may not automatically mount. If you need to mount is manually it is simply exposed as another standard block device, so on my guest this was exposed as /dev/sdb.

With the system now recognising the SDCard we could move onto installing the image to it

  1. Change to the build directory  cd  /vagrant/work/omap-image-builder/deploy/2013-07-20/ubuntu-12.04-r8-minimal-armhf-2013-07-20/
  2. Probe to get the SDCard “sudo ./setup_sdcard.sh --probe-mmc" 2013-07-20_22-31-52 Note /dev/sdb
  3. I also needed to install some extra dependencies to get the install to run “sudo apt-get install wget pv dosfstools parted git-core”
  4. Finally we could install the image to the SD Card by issuing the command “sudo ./setup_sdcard.sh --mmc /dev/sdb --uboot "bone""
  5. When finished you can log out of the VirtualBox and then call “vagrant halt” to stop the virtual system

 

Posted in ROV.

For the past two years I’ve been working on producing a book based on the Arduino called Arduino in Action for Manning publications. This was the first book that I have written and I now have the utmost respect for all authors.

I was helped in writing the book by two other author Joshua Noble and Jordan Hochenbaum. As well as writing I also had to produce all my own photographs, diagrams and circuit diagrams.

The book can be ordered in the UK from Amazon or from Manning publications directly Arduino in Action

Posted in ROV.

I organised an event called Hack n Make to showcase Scottish Makers, mainly from the North East. Help to organise the event and make it a success included Jo Donaldson, Iain Gildea, Bruce Scharlau, Steve Milne, Phil Thomson and Heather Evans. The event took place on Sunday the 12th May and was part of The University of Aberdeen May Festival. The University were incredibly supportive, providing the venue as well as catering on the day.

It was a free event a all those that attended spoke very warmly about it.

IMG_1125 IMG_1129

Posted in ROV.

The UK Maker Faire took place over the weekend of the 27th and 28th April 2013, over the weekend more than ten thousand science and technology fans flocked to the Centre for Life.

We traveled, Luke (9 year old son and myself) down on the Friday to get set up. We shared a display area with Paul Foster from Microsoft who brought a hot tub with him (Unfortunately filled with cold water) to use as a pool. Paul works with a local school’s Sci Tech club teaching them about technology and building ROV’s. He had brought an example  ROV with him based on a sea perch as well as some other gadgets. Paul made us really welcome and it was a great experience to share the space with him.

The crowds and Paul’s Hot tub

IMG_1089 IMG_1092 IMG_1093

We did try the OpenROV in the pool but it kept browning out which is something I am trying to fix

IMG_1111 IMG_1113 IMG_1110 IMG_1099 IMG_1094 IMG_1122 IMG_1120 IMG_1116 IMG_1121

Posted in ROV.

I purchased a 100m reel of ethernet cable and removed the twisted pairs. I got a pair of  Tenda P200 powerline mini adapters that were stripped down. One was connected to each end of the tether.

I also wired up the ESC’s and connected them to a Quadcopter distribution board.

Dismantling the Tenda P200′s

IMG_1039 IMG_1042 IMG_1043 IMG_1045 IMG_1047 IMG_1048 IMG_1050

The Tether

IMG_1030IMG_1031  IMG_1032

Wiring the ESC’s and internal wiring

IMG_1037 IMG_1052 IMG_1051 IMG_1054 IMG_1055 IMG_1057

Posted in ROV.