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.
Monday, April 4, 2011
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();
}
}
}
}
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
}
}
}
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;
}
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;
}
Subscribe to:
Posts (Atom)