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
main.cpp
- Committer:
- maximbolduc
- Date:
- 2015-03-06
- Revision:
- 40:a68cc1a1a1e7
- Parent:
- 39:6767d4c840f9
- Child:
- 41:a26acd346c2f
File content as of revision 40:a68cc1a1a1e7:
#include "mbed.h" #include "PinDetect.h" #include "Point.h" #include <vector> #include "Line.h" #include "stringUtils.h" #include "base.h" #include "Config.h" #include "imu_functions.h" #include "atoh.h" #include "checksum.h" #include <string.h> #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 char *version="FreePilot V2.11 Jtan 20, 2015\r\n"; long lastsend_version=0; Timer vTimer; //this timer is int based! Max is 30 minutes int checksumm; double distance_from_line; double cm_per_deg_lon; double cm_per_deg_lat; //all timing objects Timer gps_connecting; Timer autosteer_time; Timer 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; //Motor PinDetect motor_switch(p16); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce. DigitalOut enable_motor(p7); PwmOut pwm1(p21); PwmOut pwm2(p22); //equipment switches PinDetect boom1(p20,PullUp); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce. PinDetect boom2(p19); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce. PinDetect boom3(p18); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce. PinDetect boom4(p17); //pinDetect is close to digitalIn, althought, it can detect holds and detect the debounce. char boom18; //1 byte char lastboom18; //1 byte char boomstate[8]= {'$','F','B','S',0,13,10,0 }; double filterg = 100; Point position; Point looked_ahead; Point line_start; Point line_end; Point tilt_compensated_position; Point yaw_compensated_position; extern int gyro_pos; double distance_to_line; //FreePilot variables int timer_enabled; double motorspeed; int enable_time; char* motor_enable_state = 0; int motor_enable = 0; int lastmotor_enable = 1; double pwm1_speed; double pwm2_speed; long lastsend_motorstate=0; Timer motTimer; //this timer is int based! Max is 30 minutes Timer btTimer; //measure time for Bluetooth communication long lastgetBT=0; int msg2_changed = 1; char* buffer; double meter_lat = 0; double meter_lon = 0; char msg[256]; //GPS line buffer char msg2[256];//PC line buffer int printing; int num_of_gps_sats; 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 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 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]; double yaw; double pitch; double roll; double a_x; double a_y; double a_z; double w_x; double w_y; double w_z; int readings[3]; double Freepilot_bearing; int time_till_stop = 200; volatile bool newline_detected = false; 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()); } double get_yaw() { double yaw_angle = imuFilter.getYaw() * -1 ; // *-1 to reverse polarity as gyro is up-side-down return yaw_angle; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //PID ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*double outMin_ = 0.0; double outMax_ = 510.0; double inMin_ = 0.0; double inMax_ = 10.0; double prevControllerOutput_ = 5.0; double accError_ = 0.0; double prevProcessVariable_ = 5.0; double pParam_; double iParam_; double dParam_; double tSample_ = 0.2; double Kc_ ; double tauR_ ; double tauD_ ; bool inAuto = true; double bias_ = 0.0; bool usingFeedForward = true; double processVariable_ = 5.0; void setTunings(float Kc, float tauI, float tauD) { //Verify that the tunings make sense. if (Kc == 0.0 || tauI < 0.0 || tauD < 0.0) { return; } //Store raw values to hand back to user on request. pParam_ = Kc; iParam_ = tauI; dParam_ = tauD; float tempTauR; if (tauI == 0.0) { tempTauR = 0.0; } else { tempTauR = (1.0 / tauI) * tSample_; } //For "bumpless transfer" we need to rescale the accumulated error. if (inAuto) { if (tempTauR == 0.0) { accError_ = 0.0; } else { accError_ *= (Kc_ * tauR_) / (Kc * tempTauR); } } Kc_ = Kc; tauR_ = tempTauR; tauD_ = tauD / tSample_; } void reset(void) { double outSpan_ = outMax_ - outMin_; double inSpan_ = inMax_ - inMin_; float scaledBias = 0.0; // if (usingFeedForward) { scaledBias = (bias_ - outMin_) / outSpan_; prevControllerOutput_ = scaledBias; prevProcessVariable_ = (processVariable_ - inMin_) / inSpan_; //Clear any error in the integral. accError_ = 0; } float compute(double setPoint_) { double outSpan_ = outMax_ - outMin_; double inSpan_ = inMax_ - inMin_; //Pull in the input and setpoint, and scale them into percent span. float scaledPV = (processVariable_ - inMin_) / inSpan_; if (scaledPV > 1.0) { scaledPV = 1.0; } else if (scaledPV < 0.0) { scaledPV = 0.0; } float scaledSP = (setPoint_ - inMin_) / inSpan_; if (scaledSP > 1.0) { scaledSP = 1; } else if (scaledSP < 0.0) { scaledSP = 0; } float error = scaledSP - scaledPV; //Check and see if the output is pegged at a limit and only //integrate if it is not. This is to prevent reset-windup. if (!(prevControllerOutput_ >= 1 && error > 0) && !(prevControllerOutput_ <= 0 && error < 0)) { accError_ += error; } //Compute the current slope of the input signal. float dMeas = (scaledPV - prevProcessVariable_) / tSample_; float scaledBias = 0.0; if (usingFeedForward) { scaledBias = (bias_ - outMin_) / outSpan_; } //Perform the PID calculation. double controllerOutput_ = scaledBias + Kc_ * (error + (tauR_ * accError_) - (tauD_ * dMeas)); //Make sure the computed output is within output constraints. if (controllerOutput_ < 0.0) { controllerOutput_ = 0.0; } else if (controllerOutput_ > 1.0) { controllerOutput_ = 1.0; } //Remember this output for the windup check next time. prevControllerOutput_ = controllerOutput_; //Remember the input for the derivative calculation next time. prevProcessVariable_ = scaledPV; //Scale the output from percent span back out to a real world number. return ((controllerOutput_ * outSpan_) + outMin_); }*/ double get_roll() { double roll_angle = 0; if ( gyro_pos == 0 ) { roll_angle = imuFilter.getRoll(); } else if ( gyro_pos == 1 ) { roll_angle = imuFilter.getRoll() * -1; } else if( gyro_pos == 2 ) { roll_angle = imuFilter.getPitch() * -1; } else if ( gyro_pos == 3 ) { roll_angle = imuFilter.getPitch(); } return roll_angle; } double get_pitch() { double pitch_angle = 0; if ( gyro_pos == 0 ) { pitch_angle = imuFilter.getPitch(); } else if ( gyro_pos == 1 ) { pitch_angle = imuFilter.getPitch() * -1; } else if( gyro_pos == 2 ) { pitch_angle = imuFilter.getRoll(); } else if ( gyro_pos == 3 ) { pitch_angle = imuFilter.getRoll() * -1; } return pitch_angle; } double dist_Point_to_Line( Point P, Point line_start, Point line_end) { 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); } 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; } return val; } // isLeft(): test if a point is Left|On|Right of an infinite 2D line. // Input: three points P0, P1, and P2 // Return: >0 for P2 left of the line through P0 to P1 // =0 for P2 on the line // <0 for P2 right of the line int isLeft( Point P0, Point P1, Point P2 ) { double isleft = ( (P1.GetY() - P0.GetY()) * (P2.GetX() - P0.GetX()) - (P2.GetY() - P0.GetY()) * (P1.GetX() - P0.GetX())); if ( isleft > 0 ) { isleft = 1; } else { isleft = -1; } return (int)isleft; } 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; } 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; } } void autosteer_done() { enable_motor = 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))); } Point compensation; void yaw_compensate() { yaw = get_yaw(); } void pitch_and_roll(double real_bearing) { pitch = get_pitch(); roll = get_roll(); compensation.SetX(antennaheight * tan(roll) * sin(real_bearing/ 57.295779513)-antennaheight * tan(pitch) * cos(real_bearing/ 57.295779513)); compensation.SetY(antennaheight * tan(roll) * cos(real_bearing/ 57.295779513)-antennaheight * tan(pitch) * sin(real_bearing/ 57.295779513)); } 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 ) { antennaheight = atof(height); Config_Save(); } } char dms[128]; char* To_DMS(double dec_deg) { dec_deg = abs(dec_deg); int d = (int)(dec_deg); sprintf(dms,"%0.2i\0",d); double m = (double)(((double)dec_deg - (double)d) * 60.0); if (m < 10 ) { sprintf(dms,"%s0%0.9f\0",dms,m); } else { sprintf(dms,"%s%0.9f\0",dms,m); } return dms; } char* To_DMS_lon(double dec_deg) { dec_deg = abs(dec_deg); int d = (int)(dec_deg); sprintf(dms,"%0.3i\0",d); double m = (double)(((double)dec_deg - (double)d) * 60.0); if (m < 10 ) { sprintf(dms,"%s0%0.9f\0",dms,m); } else { sprintf(dms,"%s%0.9f\0",dms,m); } return dms; } //sets pwm1 and pwm2 and enable_motor 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.reset(); time_till_stop = atoi(asteer_time); if ( motor_enable == 0 ) { } else { if ( motorspeed > 127.0 ) { pwm2_speed = 0.0; pwm1_speed = ((double)motorspeed - (double)127.0) / 128.0; } else if ( motorspeed < 127.0 ) { pwm1_speed = 0.0; pwm2_speed = ( ((double)127-(double)motorspeed) / 128.0 ); } else { pwm1_speed = 0; pwm2_speed = 0; enable_motor = 0; } // if(Authenticated) // { pwm1 = pwm1_speed; pwm2 = pwm2_speed; enable_motor = 1; //} } } } double lastval = 0; //gets the motor value between -255 and 255 (- means left, positive means right) //distance in meters, always positive //angle in degrees //Points in lat/lon format int freepilot(Point current, Point target, double heading_err, double dist_line, double scale, double filter_g, double phase_adv, double center, double filtering)//dist in meters { dist_line = abs(dist_line); double error = 1; int position_sign = isLeft( line_start, line_end, current); int forward_sign = isLeft(line_start,line_end, target); double position_dist = abs(dist_Point_to_Line( current,line_start,line_end) * filtering); if ( forward_sign == -1 ) { error = error * -1; } else if ( forward_sign == 1 ) { error = error; } //if ( abs(position_dist) < 0.5 ) { if ( forward_sign == position_sign ) { if ( position_dist > dist_line ) { // && abs(position_dist) < // error = error * (dist_line * filter_g - (position_dist * phase_adv)); // error = 0; } else { // error = error * (dist_line * filter_g - (position_dist * phase_adv)*0.8); error = error * dist_line * filter_g; } } else { // error = (error * ((dist_line * filter_g) - (position_dist * phase_adv)))*0.8;//.8 in order to come back less on line than we came on it } //} else { //target coming back at 15-20 degrees on the line error = error;// + heading_err * 2 ; //} error = error * scale; if ( error > 0 ) { error = error + center; } else if (error < 0 ) { error = error - center; } if ( error > 255 ) { error = 255; } else if ( error < -255 ) { error = -255; } error = error + 255; error = (int)(error / 2); return (int)error; } char *strsep(char **stringp, char *delim) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } Point old_position; //char rmc_cpy[256]; 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 *latit = ""; char *longit = ""; char *latitude = (char *)NULL; char *longitude = (char *)NULL; char *lat_dir = (char *)NULL; char *lon_dir = (char *)NULL; while ((token = strsep(&s, ",")) != NULL) { switch (token_counter) { case 1: time = token; break; case 2: stat = token; break; case 3: if ( token ) { latit = token; latitude = token; } break; case 4: lat_dir = token; break; case 5: longit = token; longitude = token; break; case 6: lon_dir = token; break; case 7: vel = token; break; case 8: trk = token; break; case 9: date = token; break; case 10: magv = token; break; case 11: magd = token; break; } token_counter++; } if (stat!= '\0' && date!= '\0' && time!= '\0') { 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; track = atof(trk); magvar = atof(magv); } double angle = ((int)((track-90 )* -1 + 360) + 180) % 360 - 180; double diff_angle = Freepilot_bearing - angle; diff_angle = ((int)diff_angle + 180) % 360 - 180; // pc.printf("%f %f %f\r\n",diff_angle, Freepilot_bearing, (track - 90) * -1); if ( abs(diff_angle) > 90 ) { if ( (abs(360 - diff_angle)) > 90 ) { Point temp = line_end; line_end = line_start; line_start = temp; Freepilot_bearing = ((int) Freepilot_bearing + 360) % 360 - 180; } } if ( longit != '\0' && latit != '\0' ) { old_position = position; position.SetX(lat_to_deg(latitude, lat_dir[0])); position.SetY(lon_to_deg(longitude, lon_dir[0])); cm_per_deg_lat = 11054000; cm_per_deg_lon = 11132000 * cos(decimal_latitude); // pitch_and_roll((track-90)*-1);// as to be real bearing compensation.SetY(compensation.GetY() / cm_per_deg_lon); compensation.SetX(compensation.GetX() / cm_per_deg_lat); position = point_add(position,compensation); double lookaheaddistance = lookaheadtime * speed_m_s; get_latlon_byangle(position.GetX(),position.GetY(),lookaheaddistance,(track-90)*-1,look_ahead_lon,look_ahead_lat); looked_ahead.SetX(look_ahead_lat); looked_ahead.SetY(look_ahead_lon); double filtering = sqrt(111111.0*111111.0 + 111111.0 * cos(decimal_latitude/57.295779513)*111111.0 * cos(decimal_latitude/57.295779513)); distance_to_line = dist_Point_to_Line( looked_ahead,line_start,line_end) * isLeft( line_start,line_end,looked_ahead) * filtering; int val = freepilot(position, looked_ahead, diff_angle, distance_to_line, scale, filterg , phaseadv,tcenter ,filtering); char command[128]; sprintf(command,"$ASTEER,%i,%i\r\n",val,250); //(int)((((val/2)-127)/scale)+127),500); pc.puts(command); process_ASTEER(command); } string rmc = ""; if(time!= '\0') { rmc = "$GPRMC,"; rmc += string(time) + ","; } else { rmc = "$GPRMC,,"; } if(stat!= '\0') { rmc +=(string(stat) + ","); } else { rmc += ","; } if ( latit != '\0' && lat_dir!= '\0') { rmc +=( string(To_DMS(position.GetX())) + "," + string(lat_dir) +","); } else { rmc += ",,"; } if ( longit != '\0' && lon_dir!= '\0' ) { rmc += (string(To_DMS_lon(position.GetY())) + "," + string(lon_dir) + ","); } else { rmc += ","; rmc += ","; } if (vel!= '\0') { rmc += (string(vel) + ","); } else { rmc += ","; } if ((trk)!= '\0') { rmc += string(trk) + ","; } else { rmc += ","; } if (date!= '\0') { rmc += string(date) + ","; } else { rmc += ","; } if (magv!= '\0') { rmc += string(magv) + ","; } else { rmc += ","; } if (magd!= '\0') { rmc += string(magd) + ",W"; } else { rmc += ",W"; } char test[256]; sprintf(test,"%s*\0",rmc.c_str()); sprintf(output,"%s*%02X\r\n\0",rmc.c_str(),getCheckSum(test)); bluetooth.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; string bearing = ""; 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: for (int n=0; n < sizeof(token); n++) { if ( token[n] == '*' ) { break; } else { bearing += token[n]; } } break; } token = strtok((char *)NULL, ","); token_counter++; } double Freepilot_lon = atof(line_lon); double Freepilot_lat = atof(line_lat); double Freepilot_lon1 = atof(line_lon1); double Freepilot_lat1 = atof(line_lat1); Freepilot_bearing = atof(bearing.c_str()) + 360; Freepilot_bearing = ((int)Freepilot_bearing+ 180) % 360 - 180; 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, %f\r\n",line_start.GetX(),line_start.GetY(),line_end.GetX(),line_end.GetY(),Freepilot_bearing); pc.puts(output); } 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 *fg = (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 3: fg = 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 ) { lookaheadtime = atof(ahead); scale = atof(scl); /////////////////////////////////////////////////////////////////////////////// phaseadv = atof(phase); avgpos = atof(avg); tcenter = atof(center); filterg = atof(fg); scale = scale * -1; } } void pc_analyse(char* pc_string) { if (!strncmp(pc_string, "$ASTEER", 7)) { //stop sending when already exists } else if (!strncmp(pc_string, "$BANY",5)) { _ID = Config_GetID(); Config_Save(); } else if (!strncmp(pc_string, "$GPSBAUD",8)) { string mystring = pc_string; string baud = pc_string; if ( mystring.find('*') > 0 ) { string baud = mystring.substr(0,mystring.find('*')); } process_GPSBAUD((char*)baud.c_str()); Config_Save(); sprintf(output,"%s %d\r\n",pc_string,gps_baud); // pc.puts(output); } else if (!strncmp(pc_string, "$FGPSAUTO",9)) { process_FGPSAUTO(pc_string); sprintf(output,"%s\r\n",pc_string); bluetooth.puts(output); Config_Save(); } else if (!strncmp(pc_string, "$FGPS,",6)) { int i=5; char c=pc_string[i]; while (c!=0) { i++; if (i>255) break; //protect msg buffer! c=pc_string[i]; gps.putc(c); pc.putc(c); } } else if (!strncmp(pc_string, "$GPSHEIGHT",10)) { process_GPSHEIGHT(pc_string); sprintf(output,"%s\r\n",pc_string); bluetooth.puts(output); Config_Save(); } else if (!strncmp(pc_string, "$FGPSAB",7)) { process_FGPSAB(pc_string); } else if (!strncmp(pc_string, "$CALIBRATEACCEL",15)) { calibrateGyroscope(); calibrateAccelerometer(); Config_Save(); } else if (!strncmp(pc_string, "$POSITION",9)) { char* pointer; char* Data[5]; int index = 0; //Split data at commas pointer = strtok(pc_string, ","); if(pointer == NULL) Data[0] = pc_string; while(pointer != NULL) { Data[index] = pointer; pointer = strtok(NULL, ","); index++; } gyro_pos = atoi(Data[1]); Config_Save(); } else { } } void gps_analyse(char* gps_string) { if (!strncmp(gps_string, "$GPRMC", 6)) { nmea_rmc(gps_string); //analyse and decompose the rmc string } else { bluetooth.puts(gps_string); } } int i2 = 0; bool end2 = false; bool start2 = false; bool getline2() { int gotstring=false; while (1) { if( !bluetooth.readable() ) { break; } char c = bluetooth.getc(); if (c == 36 ) { start2=true; end2 = false; i2 = 0; } if ((start2) && (c == 10)) { end2=true; start2 = false; } if (start2) { msg2[i2]=c; i2++; if (i2>255) break; //protect msg buffer! } if (end2) { msg2[i2]=c; msg2[i2+1] = 0; start2 = false; gotstring = true; end2=false; i2=0; break; } } return gotstring; } int i=0; bool start=false; bool end=false; bool getline(bool forward) { while (1) { if( !gps.readable() ) { break; } char c = gps.getc(); if (forward) { //simply forward all to Bluetooth bluetooth.putc(c); } if (c == 36 ) { start=true; end = false; i = 0; } if ((start) && (c == 10)) { end=true; start = false; } if (start) { msg[i]=c; i++; if (i>255) break; //protect msg buffer! } if (end) { msg[i]=c; msg[i+1] = 0; i=0; start = false; end = true; break; } } return end; } void keyPressedHeld( void ) { motor_enable_state = "$ENABLE,0\r\n"; motor_enable = 0; pwm1 = 0.0; pwm2 = 0.0; ledGREEN=1; //show green for being ready to steer } void keyReleasedHeld( void ) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// motor_enable_state = "$ENABLE,1\r\n"; motor_enable = 1; pwm1 = 0.0; pwm2 = 0.0; ledGREEN=0; } void boom1PressedHeld( void ) { // ledGREEN=1; boom18=boom18 & 0xFE; } void boom1ReleasedHeld( void ) { //ledGREEN=0; boom18=boom18 | 0x01; } void boom2PressedHeld( void ) { boom18=boom18 & 0xFD; } void boom2ReleasedHeld( void ) { boom18=boom18 | 0x02; } void boom3PressedHeld( void ) { boom18=boom18 & 0xFB; } void boom3ReleasedHeld( void ) { boom18=boom18 | 0x04; } void boom4PressedHeld( void ) { boom18=boom18 & 0xF7; } void boom4ReleasedHeld( void ) { boom18=boom18 | 0x08; } void toprint() { angle_send = 1; } double last_yaw = 0; int counter = 0; bool bear = false; double lastroll = 0; double lastpitch = 0; int main() { bluetooth.baud(115200); gps.baud(38400); pc.baud(38400); //JH prepare and send version info vTimer.start(); vTimer.reset(); motTimer.start(); motTimer.reset(); lastsend_motorstate=motTimer.read_ms()-6500; //should trigger in 5s motor_enable_state = "$ENABLE,1\r\n"; btTimer.start(); btTimer.reset(); lastgetBT= btTimer.read_ms(); bluetooth.puts(version); lastsend_version=vTimer.read_ms()-18000; // pc.puts("test\r\n"); /* Config_Startup(); _ID = Config_GetID(); Config_Save(); */ boom1.attach_asserted_held( &boom1PressedHeld ); boom1.attach_deasserted_held( &boom1ReleasedHeld ); boom1.setSampleFrequency(); //default = 20 ms boom1.setSamplesTillAssert(5); boom1.setSamplesTillHeld(5); boom2.attach_asserted_held( &boom2PressedHeld ); boom2.attach_deasserted_held( &boom2ReleasedHeld ); boom2.setSamplesTillAssert(5); boom2.setSamplesTillHeld(5); boom2.setSampleFrequency(); boom3.attach_asserted_held( &boom3PressedHeld ); boom3.attach_deasserted_held( &boom3ReleasedHeld ); boom3.setSamplesTillAssert(5); boom3.setSamplesTillHeld(5); boom3.setSampleFrequency(); boom4.attach_asserted_held( &boom4PressedHeld ); boom4.attach_deasserted_held( &boom4ReleasedHeld ); boom4.setSamplesTillAssert(5); boom4.setSamplesTillHeld(5); boom4.setSampleFrequency(); 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); gyroscopeTicker.attach(&sampleGyroscope, 0.005); filterTicker.attach(&filter, FILTER_RATE); angle_print.attach(&toprint,0.2); activate_antenna(); autosteer_timeout.start(); //setTunings(0.25, 5, 1); while(1) { //JH send version information every 10 seconds to keep Bluetooth alive if ((vTimer.read_ms()-lastsend_version)>25000) { pc.puts(version); bluetooth.puts(version); vTimer.reset(); lastsend_version=vTimer.read_ms(); } if ( autosteer_timeout.read_ms() > 5000 || autosteer_timeout.read_ms() > time_till_stop ) { autosteer_timeout.reset(); enable_motor = 0; } if ( antenna_active == 1 && gps.readable()) { if (getline(false)) { if ( validate_checksum(msg)) { //pc.puts(msg); gps_analyse(msg); } else { pc.puts("INVALID!!!!\r\n"); } } } if ( bluetooth.readable()) { if (getline2()) { btTimer.reset(); lastgetBT= btTimer.read_ms(); // pc.puts(msg2); pc_analyse(msg2); } } if ( btTimer.read_ms()-lastgetBT>1000) { //we did not get any commands over BT ledRED=1; //turn red } else ledRED=0; if ( ((motTimer.read_ms()-lastsend_motorstate)>8000) || (motor_enable!=lastmotor_enable)) { bluetooth.puts(motor_enable_state); // pc.puts(motor_enable_state); motTimer.reset(); lastsend_motorstate=motTimer.read_ms(); lastmotor_enable=motor_enable; } if (boom18!=lastboom18) { boomstate[4]=boom18 | 0x80; // bluetooth.puts(boomstate); // pc.puts(boomstate); lastboom18=boom18; } if ( print_euler == 1 && angle_send == 1 ) { //&& reading == 0){ lastpitch = 0.8*lastpitch + 0.2 * (toDegrees(get_pitch()*3.5)); lastroll = 0.8 * lastroll + 0.2 * toDegrees(get_roll()*3.5); double dps = - last_yaw; last_yaw =toDegrees( imuFilter.getYaw()) * -1; dps = (dps + last_yaw) * 5; // update every 200 ms, so for dps need *5 sprintf(output,"$EULER,%f,%f,%f\r\n",lastroll,lastpitch,dps); bluetooth.puts(output); angle_send = 0; counter++; if ( bear == false && counter > 3 ) { //reinitialise the gyro after 600ms for the reference to be changed. imuFilter.reset(); bear = true; } } } }