Handling sensors and smoothing input

I haven’t had time to put up more photos or instructions, but have made a little progress with adding sensors to my Arduino (aka Freeduino) board. I now have a range of code and devices working including:

  • my GPS receiver (Garmin eTrex Legend) – parsing coordinates and, for example, positioning the camera in ossimPlanet
  • a Wii Nunchuk game controller (no, I don’t own a Wii… who has time for games!? :). I can use the accelerometer readings to turn the camera in ossimPlanet using 2-3 axes.
  • more recently I’m now taking readings from this digital compass chip/module.

I haven’t combined these yet, but that is the plan. The next challenge, however is to try to smooth the inputs to manageable levels. Of course the 1 sec rate of the GPS isn’t too bad, but the jitter of the compass and the accelerometers is quite high. So now I’m investigating the various techniques for making these readings more usable.

I’ve looked so far at some basic methods, like weighted or running averages, but also at application specific ones – such as ones used in open source projects for navigation via Kalman filtering (Autopilot uses it and so does the Paparazzi platform), designed for reducing fuzzy input into more manageable vectors.

So without going cross-eyed and learning more about partial derivatives.. what do you think is the right way to go? A few moving averages might be enough, but in the end I basically want similar functionality to an IMU. Is that biting off too much?

GPS Controls OSSIMPlanet

With OSSIMPlanet’s nifty camera control and listener functionality, as demonstrated in my last post, you’ve got so many neat opportunities. A couple nights ago I got a basic GPS NMEA parser working. Here’s a pic of the ultra-professional connection method I use to hook it to my arduino board 🙂

Two wires to hook an eTrex data cable up to the Arduino
Two wires to hook an eTrex data cable up to the Arduino

Oops, just realised that the picture shows the wires in the wrong spot (it was a late night photo). Pin 2 from the serial cable goes into the Power GND on left side of board. Pin 5 from serial cable goes into the Digital Pin 0 aka RX pin on lower right.

Note that I had a lot of confusion regarding the pin-out options for the Etrex. I looked at several diagrams and couldn’t get the right pins to work. It appears that you may actually need to swap the ground/TX pins to make it work – that’s what I had to do. This is something to do with how the serial connection works.. something I won’t pretend to understand – but swapping the wires worked, that’s all I know!

Of course you could always use your nifty new bluetooth GPS receiver, or plug your receiver directly into the PC and this would still work. But for me, I will have additional devices going into the arduino, where their signals will get mixed together before being sent to the PC.

Arduino setup

The arduino doesn’t do much here, except filter the strings coming from the GPS. It grabs only the $GPGGA string that has the location info I want. I specifically used the GPGGA because the Python NME parser code example I had used that one and I didn’t want to have to learn how to handle the $GPRMC strings.

Here’s the basic code I run on the Arduino:

Tmitchell: on etrex port - pin 1 (at notch end) is for TX and pin 3 for GND
On serial cable out Pin 2 -> GND, Pin 5 as TX (hooks to Digital 0=RX on board)
*/ 
#include <string.h>

#include <ctype.h>
int ledPin = 13;                  // LED test pin
int rxPin = 0;                    // RX PIN 
int txPin = 1;                    // TX TX
int byteGPS=-1;
char linea[70] = "";
char comandoGPR[7] = "$GPGGA";
char latdms[9], londms[10], latdir[1], londir[1] = "";
int latdd, londd, heading = 0;
int cont=0;
int bien=0;
int conta=0;
int indices[13];

void setup() {
  pinMode(ledPin, OUTPUT);       // Initialize LED pin
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  Serial.begin(4800);
  for (int i=0;i<70;i++){       // Initialize a buffer for received data
    linea[i]=' ';
  }   
}
void loop() {
  digitalWrite(ledPin, HIGH);
  byteGPS=Serial.read();         // Read a byte of the serial port
  if (byteGPS == -1) {           // See if the port is empty yet
    delay(100); 
  } else {
    linea[conta]=byteGPS;        // If there is serial port data, it is put in the buffer
    conta++;                      
    if (byteGPS==13){            // If the received byte is = to 13, end of transmission
      digitalWrite(ledPin, LOW); 
      cont=0;
      bien=0;
      for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
        if (linea[i]==comandoGPR[i-1]){
          bien++;
        }
      }
      if(bien==6){               // If yes, continue and process the data
        for (int i=0;i<70;i++){
          if (linea[i]==','){    // check for the position of the  "," separator
            indices[cont]=i;
            cont++;
          }
          if (linea[i]=='*'){    // ... and the "*"
            indices[12]=i;
            cont++;
          }
        }
          Serial.print(linea);  // This is the important line :)
      }
      conta=0;                    // Reset the buffer
      for (int i=0;i<70;i++){    //  
        linea[i]=' ';   
      }                 
    }
  }
}

 

I had originally hoped to do the XML prep in the arduino, but skipped it for now due to my poor understanding of variable types in the processing language. So for now I’ve still got a lot of cruft leftover in the above, that I didn’t need from the original tutorial code. But as I add more sensors I’ll want to do more mixing in the board itself.

So the arduino board just sends a raw NMEA $GPGGA string to the serial port, where Python takes over.

Python Serial Reader and OSSIM Controller

I then use a Python script that checks for strings coming from the arduino board. It does a bit of filtering, but not much error checking at the moment. This is the first time I’ve used Python to connect to the serial port, so it was fun to learn and so simple!

I found this GPGGA parser code and incorporated it into my script. I won’t paste it here as it is quite long. But here is the rest of my script – reading from Serial, parsing results, then reformatting and sending to OSSIMPlanet… comments, cruft and crummy coding.. all yours for free!

Be sure to have OSSIMPlanet running and set its Preferences to listen on port 5000 first.

# Uses PySerial
import serial

# GPGGA Parsing code next

class GPGGAParser(object):
import logging

# Open connection to Arduino
s = serial.Serial('/dev/cu.usbserial-A6001VQr', 4800, timeout=1) heading = 0
# initialising here so I can rotate the heading during each cycle.. just for fun

# Read Arduino output

while (1>0):
char = s.read(1)
while (char <> '$'):
char = s.read(1)
else:
sentence = '$' + s.read(70)
# Parse output
#############
print sentence.strip()
if (len(sentence.strip())<=30) or (sentence[1:5] <> 'GPGG'):
continue
else:
parsed = GPGGAParser(sentence)

if (parsed.latitude <> 0 and parsed.longitude <> 0):

#####################
# Reformat to XML
## Hacked method first
heading += 10 # during testing I never moved,
# so I made it hover over my location and
# slowly spin 10 degrees each second
if (heading >= 360): heading = heading-360
pitch = 70
altitude_mult = 10
ossimxml = '<Set target=":navigator" vref="wgs84"><Camera><longitude>%s</longitude><latitude>%s</latitude><altitude>%s</altitude><heading>%s</heading><pitch>%s</pitch><roll>0</roll><altitudeMode>absolute</altitudeMode></Camera></Set>' % (parsed.longitude, parsed.latitude, parsed.altitude * altitude_mult, heading, pitch)
print ossimxml # show xml being sent to ossimplanet
## Proper DOM tools second - will do this "right" at some point :)
## But not written yet

#######
# Open connection to OSSIMPlanet listener
import socket
ossim = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ossim.connect(("127.0.0.1", 5000))
# Send view updates
# Optional: connect to OSSIMPlanet broadcaster
## adjust coordinates based on current view
## I will do this when using nunchuks, but for now nothing
ossim.send(ossimxml)
ossim.close()
# Lather, rinse, repeat....

That’s about it. In OSSIMPlanet the updates are practically instantaneous, but I wait 1 sec for new GPS data to come in. When I start using the nunchuks I’ll want to do more updates faster to emulate the movement smoother. But that’s for another day…

%d bloggers like this: