Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FreePilot PinDetect mbed-src
Fork of FreePilot_V2-2 by
Diff: main.cpp
- Revision:
- 26:dc00998140af
- Child:
- 27:9ac59b261d87
- Child:
- 31:c40f16ff3a2f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Fri Jan 16 17:26:07 2015 +0000
@@ -0,0 +1,1186 @@
+#include "mbed.h"
+#include "MODSERIAL.h"
+#include "PinDetect.h"
+#include "IMUfilter.h"
+#include "ADXL345_I2C.h"
+#include "ITG3200.h"
+#include "Point.h"
+#include <vector>
+#include "Line.h"
+#include "stringUtils.h"
+
+// Connect the TX of the GPS module to p10 RX input
+MODSERIAL b(p9, p10);
+MODSERIAL pc(USBTX, USBRX);
+MODSERIAL bluetooth(p13, p14);
+int checksumm;
+
+int dont = 0;
+#define g0 9.812865328//Gravity at Earth's surface in m/s/s
+#define SAMPLES 8//Number of samples to average.
+#define CALIBRATION_SAMPLES 256//Number of samples to be averaged for a null bias calculation during calibration.
+#define toDegrees(x) (x * 57.2957795)//Convert from radians to degrees.
+#define toRadians(x) (x * 0.01745329252)//Convert from degrees to radians.
+#define GYROSCOPE_GAIN (1 / 14.375)//ITG-3200 sensitivity is 14.375 LSB/(degrees/sec).
+#define ACCELEROMETER_GAIN (0.004 * g0)//Full scale resolution on the ADXL345 is 4mg/LSB.
+#define GYRO_RATE 0.005//Sampling gyroscope at 200Hz.
+#define ACC_RATE 0.005//Sampling accelerometer at 200Hz.
+#define FILTER_RATE 0.1//Updating filter at 40Hz.
+double distance_from_line;
+double cm_per_deg_lon;
+double cm_per_deg_lat;
+//all timing objects
+Timer gps_connecting;
+Timer autosteer_time;
+Timeout autosteer_timeout; //timeout work near as timer, but they don't give timing. they just trigger an interrupt once the time we assigned it is passed.
+Ticker accelerometerTicker;
+Ticker gyroscopeTicker;
+Ticker filterTicker;
+Ticker angle_print;
+Ticker debug_leds;
+
+PinDetect motor_switch(p24); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce.
+DigitalOut enable_motor(p21);
+DigitalOut led1(p11);
+DigitalOut led2(p12);
+PwmOut pwm1(p22);
+PwmOut pwm2(p23);
+
+IMUfilter imuFilter(FILTER_RATE, 0.3);
+ADXL345_I2C accelerometer(p28, p27);
+ITG3200 gyroscope(p28,p27);
+
+Point position;
+Point looked_ahead;
+Point line_start;
+Point line_end;
+Point tilt_compensated_position;
+Point yaw_compensated_position;
+
+double distance_to_line;
+//FreePilot parameters
+double look_ahead_time = 2;
+double look_ahead_distance = 5;
+double scale = 1;
+double phaseadv = 50;
+double _Tcenter = 5;
+double filter_gain = 125;
+double avg_pos = -4;
+
+//FreePilot variables
+int timer_enabled;
+int motorspeed;
+int enable_time;
+char* motor_enable_state = 0;
+int motor_enable_tosend = 0;
+double pwm1_speed;
+double pwm2_speed;
+
+// in prevision of PID addition to FreePilot
+double kp = 0;
+double ki = 0;
+double kd = 0;
+
+int msg2_changed = 1;
+char* buffer;
+double meter_lat = 0;
+double meter_lon = 0;
+double antenna_height = 200;
+int antenna_active = 0;//do we have an antenna connected?
+char msg[256]; //GPS line buffer
+char msg2[256];//PC line buffer
+int printing;
+int num_of_gps_sats;
+int print_vtg = 0; //FGPS asked for VTG?
+double decimal_lon;
+float longitude;
+float latitude;
+char ns, ew;
+int lock;
+int flag_gga;
+int reading;
+double decimal_latitude;
+int gps_satellite_quality;
+int day;
+int hour;
+int minute;
+int second;
+int tenths;
+int hundreths;
+char status;
+double track; // track made good . angle
+char magvar_dir;
+double magvar;
+int year;
+int month;
+double speed_km;
+double speed_m_s = 0;
+double velocity; // speed in knot
+int gps_baud = 38400; //default at 115200, but FGPS will pass the real baud-rate.
+int connect_time = 10000; //variable to change the time that the serial output all the strings in order to verify if the command was right.
+int connecting = 0; //are we still in phase of connecting? based on the connect_time value.
+int print_gsa = 0;//FGPS request GSA printing
+int print_gsv = 1;//FGPS request GSV printing.
+int angle_send = 0;
+int correct_rmc = 1;
+double m_lat = 0;
+double m_lon = 0;
+char* degminsec;
+double m_per_deg_lon;
+double m_per_deg_lat;
+double look_ahead_lon;
+double look_ahead_lat;
+int active_AB = 0;
+double compensation_vector;
+char output[256];
+//offsets
+double w_xBias;
+double w_yBias;
+double w_zBias;
+double a_xBias;
+double a_yBias;
+double a_zBias;
+
+double yaw;
+double pitch;
+double roll;
+
+volatile double a_xAccumulator = 0;
+volatile double a_yAccumulator = 0;
+volatile double a_zAccumulator = 0;
+volatile double w_xAccumulator = 0;
+volatile double w_yAccumulator = 0;
+volatile double w_zAccumulator = 0;
+
+volatile double a_x;
+volatile double a_y;
+volatile double a_z;
+volatile double w_x;
+volatile double w_y;
+volatile double w_z;
+
+int readings[3];
+int accelerometerSamples = 0;
+int gyroscopeSamples = 0;
+int print_euler = 1;
+
+double Freepilot_lat;
+double Freepilot_lon;
+double Freepilot_lat1;
+double Freepilot_lon1;
+double Freepilot_bearing;
+//double Freepilot_lon_meter;
+//double Freepilot_lat_meter;
+
+void initializeAcceleromter(void);
+void calibrateAccelerometer(void);
+void sampleAccelerometer(void);
+void initializeGyroscope(void);
+void calibrateGyroscope(void);
+void sampleGyroscope(void);
+void filter(void);
+
+volatile bool newline_detected = false;
+char tx_line[80];
+char rx_line[80];
+
+Point point_add(Point a, Point b)
+{
+ return Point(a.GetX() + b.GetX(), a.GetY() + b.GetY());
+}
+
+Point point_sub(Point a , Point b)
+{
+ return Point(a.GetX() - b.GetX(), a.GetY() - b.GetY());
+}
+
+#define dot(u,v) ((u).GetX() * (v).GetX()+ (u).GetY() * (v).GetY())
+#define norm(v) sqrt(dot(v,v)) // norm = length of vector
+#define d(u,v) norm(point_sub(u,v)) // distance = norm of difference
+
+double dist_Point_to_Line( Point P, Point line_start, Point line_end)
+{
+ //Point v = point_sub(L->point1,L.point0);
+ // Point w = point_sub(P,L.point0);
+ Point v = point_sub(line_end,line_start);
+ Point w = point_sub(P,line_start);
+
+ double c1 = dot(w,v);
+ double c2 = dot(v,v);
+ double b = c1 / c2;
+
+ Point resulting(b * v.GetX(),b*v.GetY());
+ Point Pb = point_add(line_start, resulting);
+ return d(P, Pb);
+}
+
+void initializeAccelerometer(void)
+{
+ accelerometer.setPowerControl(0x00); //Go into standby mode to configure the device.
+ accelerometer.setDataFormatControl(0x0B); //Full resolution, +/-16g, 4mg/LSB.
+ accelerometer.setDataRate(ADXL345_200HZ); //200Hz data rate.
+ accelerometer.setPowerControl(0x08); //Measurement mode.
+ wait_ms(22); //See http://www.analog.com/static/imported-files/application_notes/AN-1077.pdf
+}
+
+void sampleAccelerometer(void)
+{
+ if (accelerometerSamples == SAMPLES)
+ {
+ //Average the samples, remove the bias, and calculate the acceleration
+ //in m/s/s.
+ a_x = ((a_xAccumulator / SAMPLES) - a_xBias) * ACCELEROMETER_GAIN;
+ a_y = ((a_yAccumulator / SAMPLES) - a_yBias) * ACCELEROMETER_GAIN;
+ a_z = ((a_zAccumulator / SAMPLES) - a_zBias) * ACCELEROMETER_GAIN;
+ a_xAccumulator = 0;
+ a_yAccumulator = 0;
+ a_zAccumulator = 0;
+ accelerometerSamples = 0;
+ }
+ else
+ {
+ //Take another sample.
+ accelerometer.getOutput(readings);
+ a_xAccumulator += (int16_t) readings[0];
+ a_yAccumulator += (int16_t) readings[1];
+ a_zAccumulator += (int16_t) readings[2];
+ accelerometerSamples++;
+ }
+}
+
+void calibrateAccelerometer(void)
+{
+ a_xAccumulator = 0;
+ a_yAccumulator = 0;
+ a_zAccumulator = 0;
+ //Take a number of readings and average them
+ //to calculate the zero g offset.
+ for (int i = 0; i < CALIBRATION_SAMPLES; i++)
+ {
+ accelerometer.getOutput(readings);
+ a_xAccumulator += (int16_t) readings[0];
+ a_yAccumulator += (int16_t) readings[1];
+ a_zAccumulator += (int16_t) readings[2];
+ wait(ACC_RATE);
+ }
+
+ a_xAccumulator /= CALIBRATION_SAMPLES;
+ a_yAccumulator /= CALIBRATION_SAMPLES;
+ a_zAccumulator /= CALIBRATION_SAMPLES;
+
+ //At 4mg/LSB, 250 LSBs is 1g.
+ a_xBias = a_xAccumulator;
+ a_yBias = a_yAccumulator;
+ a_zBias = (a_zAccumulator - 250);
+
+ a_xAccumulator = 0;
+ a_yAccumulator = 0;
+ a_zAccumulator = 0;
+}
+
+void initializeGyroscope(void)
+{
+ gyroscope.setLpBandwidth(LPFBW_42HZ);
+ gyroscope.setSampleRateDivider(4);
+}
+
+void calibrateGyroscope(void)
+{
+
+ w_xAccumulator = 0;
+ w_yAccumulator = 0;
+ w_zAccumulator = 0;
+
+ //Take a number of readings and average them
+ //to calculate the gyroscope bias offset.
+ for (int i = 0; i < CALIBRATION_SAMPLES; i++)
+ {
+ w_xAccumulator += gyroscope.getGyroX();
+ w_yAccumulator += gyroscope.getGyroY();
+ w_zAccumulator += gyroscope.getGyroZ();
+ wait(GYRO_RATE);
+ }
+ //Average the samples.
+ w_xAccumulator /= CALIBRATION_SAMPLES;
+ w_yAccumulator /= CALIBRATION_SAMPLES;
+ w_zAccumulator /= CALIBRATION_SAMPLES;
+
+ w_xBias = w_xAccumulator;
+ w_yBias = w_yAccumulator;
+ w_zBias = w_zAccumulator;
+
+ w_xAccumulator = 0;
+ w_yAccumulator = 0;
+ w_zAccumulator = 0;
+}
+
+void sampleGyroscope(void)
+{
+ if (gyroscopeSamples == SAMPLES)
+ {
+ //Average the samples, remove the bias, and calculate the angular
+ //velocity in rad/s.
+ w_x = toRadians(((w_xAccumulator / SAMPLES) - w_xBias) * GYROSCOPE_GAIN);
+ w_y = toRadians(((w_yAccumulator / SAMPLES) - w_yBias) * GYROSCOPE_GAIN);
+ w_z = toRadians(((w_zAccumulator / SAMPLES) - w_zBias) * GYROSCOPE_GAIN);
+
+ w_xAccumulator = 0;
+ w_yAccumulator = 0;
+ w_zAccumulator = 0;
+ gyroscopeSamples = 0;
+ }
+ else
+ {
+ w_xAccumulator += gyroscope.getGyroX();
+ w_yAccumulator += gyroscope.getGyroY();
+ w_zAccumulator += gyroscope.getGyroZ();
+ gyroscopeSamples++;
+ }
+}
+
+void filter(void)
+{
+ imuFilter.updateFilter(w_y, w_x, w_z, a_y, a_x, a_z); //Update the filter variables.
+ imuFilter.computeEuler(); //Calculate the new Euler angles.
+}
+
+void activate_antenna()
+{
+b.baud(gps_baud);
+ antenna_active = 1;
+}
+
+float Round_digits(float x, int numdigits)
+{
+ // return ceil(x * pow(10,numdigits))/pow(10,numdigits);
+ return ceil(x);
+}
+
+char* dec_deg_to_degminsec(double d_lat)
+{
+ double coord = d_lat;
+ int sec = (int)Round_digits(coord * 3600,0);
+ int deg = sec / 3600;
+ sec = abs (sec % 3600);
+ int min = sec / 60;
+ sec %= 60;
+
+ sprintf(degminsec,"%i%i%i",deg,min,sec);
+ return degminsec;
+}
+
+double decimal_to_meters_lat(double lat)
+{
+ m_per_deg_lat = 111.111;
+ m_lat = m_per_deg_lat * lat;
+ return m_lat;
+}
+
+double decimal_to_meters_lon(double lon, double lat)
+{
+ m_per_deg_lon = 111.111 * cos(lat);
+ double m_lon = m_per_deg_lon * lon;
+ return m_lon;
+}
+
+double m_lat_to_dec_deg(double lat)
+{
+ m_per_deg_lon = 111.111;
+ decimal_latitude = decimal_latitude / m_per_deg_lat;
+ return decimal_latitude;
+}
+
+double lat_to_deg(char *s, char north_south)
+{
+ int deg, min, sec;
+ double fsec, val;
+
+ deg = ( (s[0] - '0') * 10) + s[1] - '0';
+ min = ( (s[2] - '0') * 10) + s[3] - '0';
+ sec = ( ((s[5] - '0') * 1000) + ((s[6] - '0') * 100) + ((s[7] - '0') * 10) + (s[8] - '0'));
+ fsec = (double)((double)sec /10000.0);
+ val = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
+ if (north_south == 'S')
+ {
+ val *= -1.0;
+ }
+ decimal_latitude = val;
+ return val;
+}
+
+double lon_to_deg(char *s, char east_west)
+{
+ int deg, min, sec;
+ double fsec, val;
+ deg = ( (s[0] - '0') * 100) + ((s[1] - '0') * 10) + (s[2] - '0');
+ min = ( (s[3] - '0') * 10) + s[4] - '0';
+ sec = ( ((s[6] - '0') * 1000) + ((s[7] - '0') * 100) + ((s[8] - '0') * 10) + (s[9] - '0'));
+ fsec = (double)((double)sec /10000.0);
+ val = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
+ if (east_west == 'W')
+ {
+ val *= -1.0;
+ }
+ decimal_lon = val;
+ return val;
+}
+
+void nmea_gga(char *s)
+{
+ char *token;
+ int token_counter = 0;
+ char *latitude = (char *)NULL;
+ char *longitude = (char *)NULL;
+ char *lat_dir = (char *)NULL;
+ char *lon_dir = (char *)NULL;
+ char *qual = (char *)NULL;
+ char *altitude = (char *)NULL;
+ char *sats = (char *)NULL;
+
+ token = strtok(s, ",");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 2:
+ latitude = token;
+ break;
+ case 4:
+ longitude = token;
+ break;
+ case 3:
+ lat_dir = token;
+ break;
+ case 5:
+ lon_dir = token;
+ break;
+ case 6:
+ qual = token;
+ break;
+ case 7:
+ sats = token;
+ break;
+ case 9:
+ altitude = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+
+ if (latitude && longitude && altitude && sats)
+ {
+ decimal_latitude = lat_to_deg(latitude, lat_dir[0]);
+ decimal_lon = lon_to_deg(longitude, lon_dir[0]);
+ num_of_gps_sats = atoi(sats);
+ gps_satellite_quality = atoi(qual);
+ }
+ else
+ {
+ gps_satellite_quality = 0;
+ }
+}
+
+//from farmerGPS code
+void get_latlon_byangle(double lat1, double lon1, double distance,double angle, double &lon2, double &lat2)
+{
+ double ydist = 0;
+ double xdist = 0;
+ angle = angle + 180;
+ double radiant = angle * 3.14159265359 / 180;
+ double sinr = sin(radiant);
+ double cosr = cos(radiant);
+ xdist = cosr * distance;
+ ydist = sinr * distance;
+ lat2 = lat1 + (ydist / (69.09 * -1609.344));
+ lon2 = lon1 - (xdist / (69.09 * 1609.344 * cos(lat1/57.295779513)));
+ return;
+}
+
+Point compensation;
+double compensation_angle;
+//antenna compensation in cm
+void tilt_compensate()
+{
+ roll = imuFilter.getRoll();
+ compensation_vector = antenna_height * sin(roll);
+ compensation.SetX(compensation_vector * cos((toDegrees(imuFilter.getYaw()) * -1 - 90)/57.295779513));
+ compensation.SetY(compensation_vector * sin((toDegrees(imuFilter.getYaw()) * -1 - 90)/57.295779513));
+}
+
+void yaw_compensate()
+{
+ yaw = imuFilter.getYaw();
+
+}
+
+void modify_rmc()
+{
+
+}
+
+void process_GPSHEIGHT(char* height_string)
+{
+ char *token;
+ int token_counter = 0;
+ char *height = (char *)NULL;
+ token = strtok(height_string, ",");
+ while (token)
+ {
+
+ switch (token_counter)
+ {
+ case 1:
+ height = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if ( height )
+ {
+ antenna_height = atof(height);
+ }
+}
+
+void process_cs(char* cs_string)
+{
+ sprintf(output, "$cs: %s , %02X\r\n",cs_string, checksumm);
+ pc.puts(output);
+ char *token;
+ int token_counter = 0;
+ char *cs = (char *)NULL;
+ token = strtok(cs_string, "*");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ sprintf(output, "$cs:%s , %02X\r\n",token, checksumm);
+ pc.puts(token);
+ break;
+ }
+ }
+}
+
+void nmea_rmc(char *s)
+{
+ char *token;
+ int token_counter = 0;
+ char *time = (char *)NULL;
+ char *date = (char *)NULL;
+ char *stat = (char *)NULL;
+ char *vel = (char *)NULL;
+ char *trk = (char *)NULL;
+ char *magv = (char *)NULL;
+ char *magd = (char *)NULL;
+ char *latitude = (char *)NULL;
+ char *longitude = (char *)NULL;
+ char *lat_dir = (char *)NULL;
+ char *lon_dir = (char *)NULL;
+
+ token = strtok(s, ",*");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 9:
+ date = token;
+ break;
+ case 1:
+ time = token;
+ break;
+ case 2:
+ stat = token;
+ break;
+ case 7:
+ vel = token;
+ break;
+ case 8:
+ trk = token;
+ break;
+ case 10:
+ magv = token;
+ break;
+ case 11:
+ magd = token;
+ break;
+ case 3:
+ latitude = token;
+ break;
+ case 5:
+ longitude = token;
+ break;
+ case 4:
+ lat_dir = token;
+ break;
+ case 6:
+ lon_dir = token;
+ break;
+ /* case 11:
+ process_cs(token);*/
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if (stat && date && time)
+ {
+ hour = (char)((time[0] - '0') * 10) + (time[1] - '0');
+ minute = (char)((time[2] - '0') * 10) + (time[3] - '0');
+ second = (char)((time[4] - '0') * 10) + (time[5] - '0');
+ day = (char)((date[0] - '0') * 10) + (date[1] - '0');
+ month = (char)((date[2] - '0') * 10) + (date[3] - '0');
+ year = (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
+ status = stat[0];
+ velocity = atof(vel);
+ speed_km = velocity * 1.852;
+ speed_m_s = speed_km * 3600.0 / 1000.0;
+ //speed_m_s = 5;
+ track = atof(trk);
+ magvar = atof(magv);
+ magvar_dir = magd[0];
+ }
+ decimal_latitude = lat_to_deg(latitude, lat_dir[0]);
+ decimal_lon = lon_to_deg(longitude, lon_dir[0]);
+ position.SetX(decimal_latitude);
+ position.SetY(decimal_lon);
+ cm_per_deg_lat = 111111;
+ cm_per_deg_lon = 111111 * cos(decimal_latitude);
+ tilt_compensate(); //in centimeters
+ compensation.SetY(compensation.GetY() / cm_per_deg_lon);
+ compensation.SetX(compensation.GetX() / cm_per_deg_lat);
+
+ // yaw_compensate();
+ position = point_add(position,compensation);
+ modify_rmc();
+ look_ahead_distance = look_ahead_time * speed_m_s;
+
+ get_latlon_byangle(position.GetX(),position.GetY(),look_ahead_distance,track,look_ahead_lon,look_ahead_lat);
+ looked_ahead.SetX(look_ahead_lat);
+ looked_ahead.SetY(look_ahead_lon);
+ double filtering = 111.111 / 2.0 + 111.111 * cos(decimal_latitude)/2.0;
+ distance_to_line = dist_Point_to_Line( looked_ahead,line_start,line_end);
+
+ sprintf(output,"$DIST_TO_LINE: % .12f\r\n\0",distance_to_line * filtering);
+ pc.puts(output);
+
+}
+
+void process_FGPSAB(char* ab)
+{
+ char *token;
+ int token_counter = 0;
+ char *line_lat = (char *)NULL;
+ char *line_lon = (char *)NULL;
+ char *line_lat1 = (char *)NULL;
+ char *line_lon1 = (char *)NULL;
+ char *bearing = (char *)NULL;
+ token = strtok(ab, ",");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ line_lat = token;
+ break;
+ case 2:
+ line_lon = token;
+ break;
+ case 3:
+ line_lat1 = token;
+ break;
+ case 4:
+ line_lon1 = token;
+ break;
+ case 5:
+ bearing = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ Freepilot_lon = atof(line_lon);
+ Freepilot_lat = atof(line_lat);
+ Freepilot_lon1 = atof(line_lon1);
+ Freepilot_lat1 = atof(line_lat1);
+ Freepilot_bearing = atof(bearing);
+ line_start.SetX(Freepilot_lat);
+ line_start.SetY(Freepilot_lon);
+ line_end.SetX(Freepilot_lat1);
+ line_end.SetY(Freepilot_lon1);
+ active_AB = 1;
+
+ sprintf(output, "$ABLINE:%f , %f, %f, %f\r\n",line_start.GetX(),line_start.GetY(),line_end.GetX(),line_end.GetY());
+ pc.puts(output);
+}
+
+void autosteer_done()
+{
+ //kill the autosteer once the timeout reech
+ enable_motor = 0;
+}
+
+void process_FGPSAUTO(char* FGPSAUTO)
+{
+ char *token;
+ int token_counter = 0;
+ char *ahead = (char *)NULL;
+ char *center = (char *)NULL;
+ char *phase = (char *)NULL;
+ char *scl = (char *)NULL;
+ char *avg = (char *)NULL;
+ char *_kp = (char *)NULL;
+ char *_ki = (char *)NULL;
+ char *_kd = (char *)NULL;
+
+ token = strtok(FGPSAUTO, ",");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ phase = token;
+ break;
+ case 2:
+ center = token;
+ break;
+ case 4:
+ scl = token;
+ break;
+ case 5:
+ ahead = token;
+ break;
+ case 6:
+ avg = token;
+ break;
+ case 7:
+ _kp = token;
+ break;
+ case 8:
+ _ki = token;
+ break;
+ case 9:
+ _kd = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if ( _kp && _ki && _kd )
+ {
+ kp = atof(_kp);
+ ki = atof(_ki);
+ kd = atof(_kd);
+ }
+ if ( phase && center && scl && avg && ahead )
+ {
+ look_ahead_time = atof(ahead);
+ scale = atof(scl);
+ phaseadv = atof(phase);
+ avg_pos = atof(avg);
+ _Tcenter = atof(center);
+ sprintf(output, "$SETTINGS:%f\r\n", look_ahead_time);
+ pc.puts(output);
+ }
+}
+
+void process_ASTEER(char* asteer)
+{
+ char *token;
+ int token_counter = 0;
+ char *asteer_speed = (char *)NULL;
+ char *asteer_time = (char *)NULL;
+
+ token = strtok(asteer, ",");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ asteer_speed = token;
+ break;
+ case 2:
+ asteer_time = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if ( asteer_speed && asteer_time )
+ {
+ motorspeed = atof(asteer_speed);
+ enable_time = atof(asteer_time);
+ autosteer_timeout.attach(autosteer_done,(double)enable_time / (double)1000);
+ if ( motorspeed > 127 )
+ {
+ pwm2_speed = 0;
+ pwm1_speed = ((double)motorspeed - (double)127) / 127;
+ enable_motor = 1;
+ }
+ else if ( motorspeed < 127 )
+ {
+ pwm2_speed = ((double)motorspeed / 127 );
+ pwm1_speed = 0;
+ enable_motor = 1;
+ }
+ else
+ {
+ pwm1_speed = 0;
+ pwm2_speed = 0;
+ enable_motor = 0;
+ }
+ pwm1 = pwm1_speed;
+ pwm2 = pwm2_speed;
+ }
+}
+
+void process_initstring(char* init)
+{
+ char *token;
+ int token_counter = 0;
+ char *init_string = (char *)NULL;
+ token = strtok(init, "$");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ init_string = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if ( init_string )
+ {
+ if ( antenna_active == 1 )
+ {
+ while(!b.writeable()) {} //disable uart3 interrupt (p9,p10)
+ sprintf(output,"$%s",init_string);
+ b.puts(output);
+ gps_connecting.start();
+ gps_connecting.reset();
+ connecting = 1;
+ }
+ }
+}
+
+void process_GPSBAUD(char* gpsbaud)
+{
+ char *token;
+ int token_counter = 0;
+ char *baud = (char *)NULL;
+ token = strtok(gpsbaud, ",");
+ while (token)
+ {
+ switch (token_counter)
+ {
+ case 1:
+ baud = token;
+ break;
+ }
+ token = strtok((char *)NULL, ",");
+ token_counter++;
+ }
+ if ( baud )
+ {
+ gps_baud = atoi(baud);
+ }
+ activate_antenna();
+}
+
+void pc_analyse(char* pc_string)
+{
+ if (!strncmp(pc_string, "$ASTEER", 7))
+ {
+ process_ASTEER(pc_string);
+ }
+ else if (!strncmp(pc_string, "$GPS-BAUD",9))
+ {
+ process_GPSBAUD(pc_string);
+ sprintf(output,"%s\r\n",pc_string);
+ bluetooth.puts(output);
+ }
+ else if (!strncmp(pc_string, "$FGPS,",6))
+ {
+ process_initstring(pc_string);
+ sprintf(output,"%s\r\n",pc_string);
+ bluetooth.puts(output);
+ }
+ else if (!strncmp(pc_string, "$PRINT_VTG=0",12))
+ {
+ print_vtg = 0;
+ }
+ else if (!strncmp(pc_string, "$PRINT_VTG=1",12))
+ {
+ print_vtg = 1;
+ }
+ else if (!strncmp(pc_string, "$PRINT_GSV=0",12))
+ {
+ print_gsv = 0;
+ }
+ else if (!strncmp(pc_string, "$PRINT_GSV=1",12))
+ {
+ print_gsv = 1;
+ }
+ else if (!strncmp(pc_string, "$PRINT_GSA=0",12))
+ {
+ print_gsa = 0;
+ }
+ else if (!strncmp(pc_string, "$PRINT_GSA=1",12))
+ {
+ print_gsa = 1;
+ }
+ else if (!strncmp(pc_string, "$PRINT_EULER=1",14))
+ {
+ print_euler = 1;
+ }
+ else if (!strncmp(pc_string, "$PRINT_EULER=0",14))
+ {
+ print_euler = 0;
+ }
+ else if (!strncmp(pc_string, "$GPS-HEIGHT",11))
+ {
+ process_GPSHEIGHT(pc_string);
+ sprintf(output,"%s\r\n",pc_string);
+ bluetooth.puts(output);
+ }
+ else if (!strncmp(pc_string, "$CORRECT_RMC=1",14))
+ {
+ correct_rmc = 1;
+ }
+ else if (!strncmp(pc_string, "$CORRECT_RMC=0",14))
+ {
+ correct_rmc = 0;
+ }
+ else if (!strncmp(pc_string, "$FGPSAUTO",9))
+ {
+ process_FGPSAUTO(pc_string);
+ sprintf(output,"%s\r\n",pc_string);
+ bluetooth.puts(output);
+ }
+ else if (!strncmp(pc_string, "$FGPSAB",7))
+ {
+ sprintf(output,"%s\r\n",pc_string);
+ // bluetooth.puts(output);
+ pc.puts(output);
+ process_FGPSAB(pc_string);
+
+ }
+ else
+ {
+ }
+}
+
+void gps_analyse(char* gps_string)
+{
+ if ( connecting == 1 )
+ {
+ if ( gps_connecting.read_ms() < connect_time && reading == 0 )
+ {
+ if ( bluetooth.writeable() > 0 )
+ {
+ bluetooth.puts(gps_string);
+ }
+ }
+ else
+ {
+ connecting = 0;
+ gps_connecting.stop();
+ }
+ }
+ if (!strncmp(gps_string, "$GPRMC", 6))
+ {
+ // if ( connecting == 0 )// && correct_rmc == 1 )
+ // {
+ bluetooth.puts(gps_string);
+ // }
+ nmea_rmc(gps_string); //analyse and decompose the rmc string
+ }
+ else if (!strncmp(gps_string, "$GPGGA", 6))
+ {
+ // if ( connecting == 0 )
+ // {
+ bluetooth.puts(gps_string);
+ // }
+ //nmea_gga(gps_string);//analyse and decompose the gga string
+ }
+ else if (!strncmp(gps_string, "$GPVTG", 6))
+ {
+ // if ( print_vtg == 1 && connecting == 0 )
+ // {
+ bluetooth.puts(gps_string);
+ // }
+ }
+ else if (!strncmp(gps_string, "$GPGSV", 6))
+ {
+ if ( print_gsv == 1 && connecting == 0 )
+ {
+ bluetooth.puts(gps_string);
+ }
+ }
+ else if (!strncmp(gps_string, "$GPGSA", 6))
+ {
+ if ( print_gsa == 1 && connecting == 0 )
+ {
+ bluetooth.puts(gps_string);
+ }
+ }
+ else
+ {
+ }
+}
+
+/*void rxCallback(MODSERIAL_IRQ_INFO *q)
+{
+ if ( bluetooth.rxGetLastChar() == '\n')
+ {
+ newline_detected = true;
+ }
+}*/
+
+void getline2()
+{
+ for (int i = 0; i<126; i++)
+ {
+ msg2[i] = bluetooth.getc();
+ if (msg2[i] == '\n')
+ {
+ msg2[i+1] = 0;
+ dont = 0;
+ return;
+ }
+ }
+}
+
+void getline()
+{
+ while (b.getc() != '$');
+ msg[0] = '$'; // wait for the start of a line
+ for (int i=1; i<256; i++)
+ {
+ msg[i] = b.getc();
+ if (msg[i] == '\n')
+ {
+ msg[i+1] = 0;
+ return;
+ }
+ }
+}
+
+int sample()
+{
+ while (1)
+ {
+ getline();
+ return 1;
+ }
+}
+
+int samplepc()
+{
+ while (1)
+ {
+ getline2();
+ return 1;
+ }
+}
+
+void keyPressedHeld( void )
+{
+ motor_enable_state = "$ENABLE=1\r\n";
+ motor_enable_tosend = 1;
+}
+
+void keyReleasedHeld( void )
+{
+ motor_enable_state = "$ENABLE=0\r\n";
+ motor_enable_tosend = 1;
+}
+
+void toprint()
+{
+ angle_send = 1;
+}
+
+void debugging_leds( void )
+{
+}
+
+int getCheckSum(char *string) {
+int i;
+int XOR;
+int c;
+// Calculate checksum ignoring any $'s in the string
+for (XOR = 0, i = 0; i < strlen(string); i++) {
+c = (unsigned char)string[i];
+if (c == '*') break;
+if (c != '$') XOR ^= c;
+}
+return XOR;
+}
+
+int main()
+{
+ bluetooth.baud(38400);
+ b.baud(38400);
+pc.baud(38400);
+ motor_switch.setSampleFrequency(10000);
+ motor_switch.attach_asserted_held( &keyPressedHeld );
+ motor_switch.attach_deasserted_held( &keyReleasedHeld );
+initializeAccelerometer();
+calibrateAccelerometer();
+ initializeGyroscope();
+ calibrateGyroscope();
+accelerometerTicker.attach(&sampleAccelerometer, 0.005);
+//debug_leds.atatch(&debugging_leds,2);
+gyroscopeTicker.attach(&sampleGyroscope, 0.005);
+filterTicker.attach(&filter, FILTER_RATE);
+angle_print.attach(&toprint,0.2);
+ activate_antenna();
+ while(1)
+ {
+ if ( antenna_active == 1 )
+ {
+ if ( b.readable())
+ {
+ if (sample())
+ {
+ checksumm = getCheckSum(msg);
+ if ( pc.writeable())
+ {
+ sprintf(output,"%s\r\n\0",msg);
+ pc.puts(output);
+ }
+ gps_analyse(msg);
+ }
+ }
+ }
+
+ if ( bluetooth.readable())
+ {
+ if (samplepc())
+ {
+ trim(msg2,"\r");
+ trim(msg2,"\n");
+ trim(msg2,"\0");
+ trim(msg2," ");
+ sprintf(output,"%s\0",msg2);
+ pc.puts(output);
+ pc_analyse(msg2);
+ }
+ }
+ if ( motor_enable_tosend == 1 && reading == 0 )
+ {
+ bluetooth.puts(motor_enable_state);
+ motor_enable_tosend = 0;
+ }
+ /* if ( print_euler == 1 && angle_send == 1 && reading == 0)
+ {
+ sprintf(output,"$EULER,%f,%f,%f\r\n",toDegrees(imuFilter.getRoll()),toDegrees(imuFilter.getPitch()),toDegrees(imuFilter.getYaw()));
+ pc.puts(output);
+ bluetooth.puts(output);
+ angle_send = 0;
+ }*/
+ }
+}
\ No newline at end of file
