Monday, April 4, 2011

Sketches

Good Day

Ive finally compiled a Fritzing Sketch of my project to date. Well what I have running and hopefully continue to run in the future.The main thing I like about the Netduino/Arduino is that I can take in what ever information I like and then I get to choose what and how I want my information to look like on an output or how to log it all.the possibilities are limited only to what we can think of.

Wednesday, March 23, 2011

Followup with Netduino

Just thought I would follow up with what I have done with the Netduino Plus that I am using. Currently this morning when I tested the unit with the GPS and IMU packages I am able to bring this data in and output again in a format that I want for logging purposes. The code I used is below. I did find that coding the Netduino a little difficult at first but once I got used to the coding structure that it was much easier to diagnose problems and add features than the Arduino. I will also add a schematic of each setup later.


using System;
using System.Collections;
using System.IO.Ports;
using System.IO;
using System.Threading;
using System.Text;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
 
 
namespace NetduinoPlusGPS
{
public class Program
{
public static void Main()
{
//create a connection to the led to show we're running
OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
//instantiate the serial port connection
SerialPort serialPort1 = new SerialPort("COM1", 57600, Parity.None, 8, StopBits.One);
serialPort1.Open();
SerialPort serialPort2 = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);
serialPort2.Open();
 
while (true)
{
int GPStoRead = serialPort1.BytesToRead;
int CHRtoRead = serialPort2.BytesToRead;
//*start reading the stream
if (GPStoRead > 0)
{
//blink the LED to show we got data
led.Write(true);
//Thread.Sleep(100);
led.Write(false);
// get the waiting ++data
byte[] GPSbuffer = new byte[GPStoRead];
//serialPort1.Flush();
serialPort1.Read(GPSbuffer, 0, GPSbuffer.Length);
serialPort1.Write(GPSbuffer, 0, GPSbuffer.Length);
String GPSMessage = new String(System.Text.Encoding.UTF8.GetChars(GPSbuffer));
Debug.Print(GPSMessage);
}
if (CHRtoRead > 12)
{
int i = 0;
//blink the LED to show we got data
led.Write(true);
//Thread.Sleep(100);
led.Write(false);
// get the waiting data
byte[] CHRbuffer = new byte[CHRtoRead];
//serialPort2.Flush();
serialPort2.Read(CHRbuffer, 0, CHRbuffer.Length);
if (CHRbuffer[i] == 's')
{
//Print final result
i = i + 7;
int YawVal = (int)((((CHRbuffer[i++] << 8) | CHRbuffer[i++]) << 16) >> 16);
String ShowYaw = YawVal.ToString();
double YawCalc = YawVal * 0.0109863;
String ShowYCalc = YawCalc.ToString("F2");
int PitchVal = (int)((((CHRbuffer[i++] << 8) | CHRbuffer[i++]) << 16) >> 16);
String ShowPitch = PitchVal.ToString();
double PitchCalc = PitchVal * 0.0109863;
String ShowPCalc = PitchCalc.ToString("F2");
int RollVal = (int)((((CHRbuffer[i++] << 8) | CHRbuffer[i++]) << 16) >> 16);
String ShowRoll = RollVal.ToString();
double RollCalc = RollVal * 0.0109863;
String ShowRCalc = RollCalc.ToString("F2");
String CTAP = "$CTAP,R," + ShowRCalc + ",P," + ShowPCalc + ",Y," + ShowYCalc;
Debug.Print(CTAP);
byte[] CTAPArray = Encoding.UTF8.GetBytes(CTAP);
serialPort1.Write(CTAPArray, 0, CTAPArray.Length);
}
else
{
i++;
}
}
Thread.Sleep(500);
//serialPort1.Flush();
}
}
}
}

Tuesday, March 22, 2011

Late update

So yes its been a long time and a lot has transpired for this project. From flipping to a Netduino Plus to flipping back to Arduino to wanting to go back to the Netduino again LOL. Both have their own advantages and disadvantages. The only problem Im having with the Netduino is on the SDA/SCL lines where my barometer is supposed to plug into. When I wire into these pins I get no data or erratic data and when I wire the same sensor to the Arduino I get perfect data every time. I'm waiting on a logic analyzer to arrive to properly test these pins and hopefully diagnose what is going on.

In the interim I have been working on a NMEA parser for the Arduino Uno as well bringing in both GPS and Pitch/Roll data on the Uno. Using the NewSoftSerial driver (http://arduiniana.org/libraries/newsoftserial/) I am able to bring both sensors in and view the data. Next on my task list is to log the data to an OpenLog microSD data logger. (http://www.sparkfun.com/products/9530)

Here is the code I am using to parse out the NMEA strings. It works perfectly and is able to parse multiple NMEA messages on the same port. So now if I need to I can pull out data from a NMEA string like say the Altitude and use that somewhere else in my code.

int incomingByte = 0;      // for incoming serial data
int index = 0;
int count,i = 0;
String GPSStrings[20];
String field;
String message;
void setup() {
  Serial.begin(57600);        // opens serial port, sets data rate to 9600 bps
  message = String("");
  field = String("");
}

void loop() {

  // wait for data to be present on com port.
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    message.concat(char(incomingByte)); //append char to message
   


    if(incomingByte == '\n'){  //if newline is found
      Serial.write("NMEA Message: ");
      Serial.print(message);// print message


      if(message.indexOf(",") != -1){ //if a comma is in message:
       
        do{
          index = message.indexOf(","); //find first comma
          GPSStrings[i] = message.substring(0,index); //grab data to first comma
          message = message.substring(index+1); //toss data to first comma       
                   
          Serial.println(GPSStrings[i]);
         
        }
        while(index != -1); //while there is still a comma
        i++;
      } 
     
      else
        Serial.print(message);//if there was no comma to begin with just print the message.
       
      message = String(""); //wipe out message for next line 
    }
  }
}

Monday, January 10, 2011

Week 2

Well after a little hiatus with Christmas holidays and then getting back into the swing of working full time again I was able to finally sit down and nail out some more of the intricacies of the Attitude Sensor project.

For week 2 I continued to test the hardware I have on hand and then try to interface everything via code and hardwiring.Im glad to say that I am about 75% of the way done with the selected parts. I had some problems with the CHR-6dm sensor and reinitializing it so it has been sent back to manufacturer for reprogramming. Seems like the problem was on my end with a faulty usb - serial adapter. So while I wait for the unit to come back to me I have a Sparkfun 5DOF board to play with and try to convert accelerometer data to angular pitch roll data. After A LOT of reading and searching I have found code that does exactly what I need. I'm confident I could have figured it out but it would have taken months to get to a point where I would be confident with the numbers I am getting. I would like to thank the Arduino forum for this because without it I would be lost. the code can be found at http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286541868 for anyone looking or interested.

My next problem is to take the code for polling GPS data and combine it with the accelerometer code to get 2 solid strings output to my Logomatic Datalogger. The code for the GPS searches for a GPRMC string and then parses the data out to the serial line. The problem I am having is that for every character parsed the accelerometer data is posted so I end up with nonsense data for gps and current pitch roll data. If I insert the pitch roll code into the GPS parser then I end up with current GPS data and lagging pitch roll data because I am only interested in acquiring data every 1s and not continuous. Here is my code to date.... Feel free to read over and tear apart.


#include <string.h>
#include <ctype.h>
#include <math.h>

#define xAcc 0
#define yAcc 1
#define zAcc 2
#define xGyro 4
#define yGyro 5
#define vRef 3.3
#define sen 0.330
#define gSen 0.002
#define gyroZero 1.350


int x0,y0,z1,gx0,gy0,gz0; //x0,y0,z0 is x,y,z axis zero G  ADC value gx0,gy0 no rotation ADC values
float xAngle,yAngle,xAtan,yAtan,zAngle,dxAngle,dyAngle =0;
unsigned long time,dt = 0;

int ledPin = 13;                  // LED test pin
int rxPin = 0;                    // RX PIN
int txPin = 1;                    // TX TX
int byteGPS=-1;
char linea[300] = "";
char comandoGPR[7] = "$GPRMC";
int count=0;
int counta=0;
int countb=0;
int index[13];
const int xpin = A0;                  // x-axis of the accelerometer
const int ypin = A1;                  // y-axis
const int zpin = A2;                  // z-axis (only on 3-axis models)
const int xRate = A4;
const int yRate = A5;
 
 void setup() {
   pinMode(ledPin, OUTPUT);       // Initialize LED pin
   pinMode(rxPin, INPUT);
   pinMode(txPin, OUTPUT);
   Serial.begin(38400);
   delay(1000);
   getZeros();
   for (int i=0;i<300;i++){       // Initialize a buffer for received data
     linea[i]=' ';
   }  
 }

 void getZeros()
  {
  x0=analogRead(xAcc);
  y0=analogRead(yAcc);
  z1=analogRead(zAcc);
  gx0=analogRead(xGyro);
  gy0=analogRead(yGyro);
  }

 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(1000);
   } else {
     linea[counta]=byteGPS;        // If there is serial port data, it is put in the buffer
     counta++;                    
     Serial.print(byteGPS, BYTE);
     if (byteGPS==13){            // If the received byte is = to 13, end of transmission
       digitalWrite(ledPin, LOW);
       count=0;
       countb=0;
       for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
         if (linea[i]==comandoGPR[i-1]){
           countb++;
         }
       }
       if(countb==6){               // If yes, continue and process the data
         for (int i=0;i<300;i++){
           if (linea[i]==','){    // check for the position of the  "," separator
             index[count]=i;
             count++;
           }
           if (linea[i]=='*'){    // ... and the "*"
             index[12]=i;
             count++;
           }
         }
         Serial.println("");
         Serial.print("$CTAH,");
         Serial.print("xpin,");
         Serial.print(analogRead(xpin));
         Serial.print(",");
         Serial.print("ypin,");
         Serial.print(analogRead(ypin));
         Serial.print(",");
         Serial.print("zpin,");
         Serial.print(analogRead(zpin));
         Serial.print(",");                    
         Serial.print(analogRead(xRate), DEC);
         Serial.print(",");
         Serial.print(analogRead(yRate), DEC);
         Serial.println();
         Serial.print("Roll");
         Serial.print("\t");
         Serial.print("Pitch");
         Serial.println();
         GetPR();          
       }
       counta=0;                    // Reset the buffer
       for (int i=0;i<300;i++){    //
         linea[i]=' ';            
       }                
     }
   }
 }

 void GetPR()
   {
    //******************** CF filter******************************************************************
    time=millis();
    xAtan=atan2((analogRead(xAcc)-x0)*vRef/(1024*sen),(analogRead(zAcc)-z1)*vRef/(1024*sen)+1)*180/PI;
    yAtan=atan2((analogRead(yAcc)-y0)*vRef/(1024*sen),(analogRead(zAcc)-z1)*vRef/(1024*sen)+1)*180/PI;

    dxAngle=(analogRead(yGyro)-gy0)*vRef/(1024*gSen);
    dyAngle=(analogRead(xGyro)-gx0)*vRef/(1024*gSen);
    xAngle = 0.9615 * (xAngle + dxAngle*dt*0.001) + 0.0385*xAtan;
    yAngle =0.9615 * (yAngle + dyAngle*dt*0.001) + (0.0385 *yAtan);

    //0.9615 is a and its given by a=tau/(tau-dt), 0.0385=1-a
    // dt is 1-2 ms

    //************************************************************************************************
    Serial.print(xAngle);
    Serial.print("\t");
    Serial.print(yAngle);
    Serial.print("\t");
    Serial.println(dt);
    dt=millis()-time;  
    }