Bluetooth app controlled robot
Dependencies: ESP8266 HALLFX_ENCODER LSM9DS1_Library_cal MotorDriver PID mbed
Fork of ESP8266_pid_redbot_webserver by
main.cpp@3:bf6e71964ceb, 2016-03-16 (annotated)
- Committer:
- ihl396
- Date:
- Wed Mar 16 16:21:56 2016 +0000
- Revision:
- 3:bf6e71964ceb
- Parent:
- 2:3466e9e16c99
commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
electromotivated | 0:11bc7a815367 | 1 | #include "mbed.h" |
electromotivated | 0:11bc7a815367 | 2 | #include "PID.h" |
electromotivated | 1:d4a95e3a8aeb | 3 | #include "HALLFX_ENCODER.h" |
electromotivated | 1:d4a95e3a8aeb | 4 | #include "MotorDriver.h" |
ihl396 | 2:3466e9e16c99 | 5 | #include "LSM9DS1.h" |
electromotivated | 0:11bc7a815367 | 6 | #include <algorithm> |
ihl396 | 2:3466e9e16c99 | 7 | #define PI 3.14159 |
ihl396 | 2:3466e9e16c99 | 8 | #define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA. |
ihl396 | 2:3466e9e16c99 | 9 | #define REFRESH_TIME_MS 1 |
ihl396 | 2:3466e9e16c99 | 10 | #define DEBUG |
electromotivated | 0:11bc7a815367 | 11 | |
ihl396 | 2:3466e9e16c99 | 12 | Serial blue(p28,p27); |
ihl396 | 2:3466e9e16c99 | 13 | BusOut myled(LED1,LED2,LED3,LED4); |
ihl396 | 2:3466e9e16c99 | 14 | Serial pc(USBTX, USBRX); |
ihl396 | 3:bf6e71964ceb | 15 | |
ihl396 | 3:bf6e71964ceb | 16 | // -------- PID Initialization ----------- |
electromotivated | 1:d4a95e3a8aeb | 17 | float kp, ki, kd; // Working gain vars |
electromotivated | 1:d4a95e3a8aeb | 18 | float working_setpoint; // Used for web parsing and updating |
electromotivated | 1:d4a95e3a8aeb | 19 | float setpoint; // This is used by PID objects, because |
electromotivated | 1:d4a95e3a8aeb | 20 | // encoders are not quadrature and |
electromotivated | 1:d4a95e3a8aeb | 21 | // do not have direction information |
electromotivated | 1:d4a95e3a8aeb | 22 | // we use this to store the absolute |
electromotivated | 1:d4a95e3a8aeb | 23 | // value of the working_setpoint. |
electromotivated | 1:d4a95e3a8aeb | 24 | // Specifically setpoint is used only |
electromotivated | 1:d4a95e3a8aeb | 25 | // for PID objects. Refer to |
electromotivated | 1:d4a95e3a8aeb | 26 | // pid_callback() function |
electromotivated | 1:d4a95e3a8aeb | 27 | float feedbackL, outputL; // Should these be volatile? |
electromotivated | 1:d4a95e3a8aeb | 28 | float feedbackR, outputR; // Should these be volatile? |
electromotivated | 1:d4a95e3a8aeb | 29 | const float output_lower_limit = 0.0; |
electromotivated | 0:11bc7a815367 | 30 | const float output_upper_limit = 1.0; |
electromotivated | 1:d4a95e3a8aeb | 31 | const float FEEDBACK_SCALE = 1.0/384.0; // Scale feedback to 1rev/3000cnts |
electromotivated | 0:11bc7a815367 | 32 | // this is encoder specific. |
electromotivated | 0:11bc7a815367 | 33 | const float Ts = 0.04; // 25Hz Sample Freq (40ms Sample Time) |
electromotivated | 0:11bc7a815367 | 34 | const float Ts_PID_CALLBACK = Ts/2.0; // Update Motors and sensers twice as |
electromotivated | 0:11bc7a815367 | 35 | // fast as PID sample rate, ensures |
electromotivated | 0:11bc7a815367 | 36 | // PID feedback is upto date every |
electromotivated | 0:11bc7a815367 | 37 | // time PID calculations run |
electromotivated | 0:11bc7a815367 | 38 | |
electromotivated | 1:d4a95e3a8aeb | 39 | const float kp_init = 0.01; // Good Kp for Speed Control; Start with this |
electromotivated | 1:d4a95e3a8aeb | 40 | const float ki_init= 0.015; // Good Ki for Speed Control; Start with this |
electromotivated | 1:d4a95e3a8aeb | 41 | const float kd_init = 0.0001; // Good Kd for Speed Control; Start with this |
electromotivated | 0:11bc7a815367 | 42 | |
electromotivated | 1:d4a95e3a8aeb | 43 | PID pidL(&setpoint, &feedbackL, &outputL, |
electromotivated | 0:11bc7a815367 | 44 | output_lower_limit, output_upper_limit, |
electromotivated | 1:d4a95e3a8aeb | 45 | kp_init, ki_init, kd_init, Ts); |
electromotivated | 1:d4a95e3a8aeb | 46 | PID pidR(&setpoint, &feedbackR, &outputR, |
electromotivated | 1:d4a95e3a8aeb | 47 | output_lower_limit, output_upper_limit, |
electromotivated | 1:d4a95e3a8aeb | 48 | kp_init, ki_init, kd_init, Ts); |
electromotivated | 1:d4a95e3a8aeb | 49 | MotorDriver mtrR(p20, p19, p25, 10000.0, true); // in1, in2, pwm, pwmFreq, isBrakeable |
electromotivated | 1:d4a95e3a8aeb | 50 | MotorDriver mtrL(p18, p17, p24, 10000.0, true); // in1, in2, pwm, pwmFreq, isBrakeable |
electromotivated | 1:d4a95e3a8aeb | 51 | HALLFX_ENCODER encR(p21); |
electromotivated | 1:d4a95e3a8aeb | 52 | HALLFX_ENCODER encL(p22); |
electromotivated | 0:11bc7a815367 | 53 | void pid_callback(); // Updates encoder feedback and motor output |
ihl396 | 2:3466e9e16c99 | 54 | |
electromotivated | 1:d4a95e3a8aeb | 55 | Ticker motor; // Interrupt for feedback and motor updates |
ihl396 | 2:3466e9e16c99 | 56 | //global variables for main and interrupt routine |
electromotivated | 0:11bc7a815367 | 57 | |
ihl396 | 2:3466e9e16c99 | 58 | char state_num = 0, bnum =0 ; |
ihl396 | 2:3466e9e16c99 | 59 | int dirL = 0, dirR = 0; |
electromotivated | 0:11bc7a815367 | 60 | |
ihl396 | 2:3466e9e16c99 | 61 | //Interrupt routine to parse message with one new character per serial RX interrupt |
electromotivated | 0:11bc7a815367 | 62 | |
electromotivated | 0:11bc7a815367 | 63 | float clip(float value, float lower, float upper); |
electromotivated | 0:11bc7a815367 | 64 | |
ihl396 | 2:3466e9e16c99 | 65 | LSM9DS1 imu(p9, p10, 0xD6, 0x3C); |
ihl396 | 2:3466e9e16c99 | 66 | void calculate_heading(float mx, float my, float mz); |
ihl396 | 2:3466e9e16c99 | 67 | float oldX = 0; |
ihl396 | 2:3466e9e16c99 | 68 | float oldY = 0; |
ihl396 | 2:3466e9e16c99 | 69 | float oldZ = 0; |
ihl396 | 2:3466e9e16c99 | 70 | float x= 0; |
ihl396 | 2:3466e9e16c99 | 71 | float y = 0; |
ihl396 | 2:3466e9e16c99 | 72 | float z = 0; |
ihl396 | 2:3466e9e16c99 | 73 | |
ihl396 | 2:3466e9e16c99 | 74 | float posx = 0; |
ihl396 | 2:3466e9e16c99 | 75 | float velx = 0; |
ihl396 | 2:3466e9e16c99 | 76 | float oldPosx = 0; |
ihl396 | 2:3466e9e16c99 | 77 | float oldVelx = 0; |
ihl396 | 2:3466e9e16c99 | 78 | |
ihl396 | 2:3466e9e16c99 | 79 | float posy = 0; |
ihl396 | 2:3466e9e16c99 | 80 | float vely = 0; |
ihl396 | 2:3466e9e16c99 | 81 | float oldPosy = 0; |
ihl396 | 2:3466e9e16c99 | 82 | float oldVely = 0; |
ihl396 | 2:3466e9e16c99 | 83 | |
ihl396 | 2:3466e9e16c99 | 84 | float posz = 0; |
ihl396 | 2:3466e9e16c99 | 85 | float velz = 0; |
ihl396 | 2:3466e9e16c99 | 86 | float oldPosz = 0; |
ihl396 | 2:3466e9e16c99 | 87 | float oldVelz = 0; |
ihl396 | 2:3466e9e16c99 | 88 | int sample_time = 0; |
ihl396 | 2:3466e9e16c99 | 89 | |
ihl396 | 2:3466e9e16c99 | 90 | float accelx = 0, accely = 0, accelz = 0; |
ihl396 | 2:3466e9e16c99 | 91 | Serial esp(p13, p14); // tx, rx |
ihl396 | 2:3466e9e16c99 | 92 | DigitalOut reset(p26); |
ihl396 | 2:3466e9e16c99 | 93 | |
ihl396 | 2:3466e9e16c99 | 94 | Timer t; |
ihl396 | 2:3466e9e16c99 | 95 | void send_data(float *accelx, float *accely, float *accelz, float *velx, float *vely, float *velz); |
ihl396 | 2:3466e9e16c99 | 96 | int count,ended,timeout; |
ihl396 | 2:3466e9e16c99 | 97 | float heading = 0.0; |
ihl396 | 2:3466e9e16c99 | 98 | char buf[1024]; |
ihl396 | 2:3466e9e16c99 | 99 | char snd[1024]; |
ihl396 | 2:3466e9e16c99 | 100 | char str_buf[80]; |
ihl396 | 2:3466e9e16c99 | 101 | |
ihl396 | 2:3466e9e16c99 | 102 | char ssid[32] = "4180_test"; // enter WiFi router ssid inside the quotes |
ihl396 | 2:3466e9e16c99 | 103 | char pwd [32] = "4180isawesome"; // enter WiFi router password inside the quotes |
ihl396 | 2:3466e9e16c99 | 104 | |
ihl396 | 2:3466e9e16c99 | 105 | void SendCMD(),getreply(),ESPconfig(),ESPsetbaudrate(); |
electromotivated | 0:11bc7a815367 | 106 | int main() |
electromotivated | 0:11bc7a815367 | 107 | { |
ihl396 | 2:3466e9e16c99 | 108 | pc.printf("\f---------- Program Start ----------\r\n\n"); |
ihl396 | 2:3466e9e16c99 | 109 | reset=0; //hardware reset for 8266 |
ihl396 | 2:3466e9e16c99 | 110 | pc.baud(9600); // set what you want here depending on your terminal program speed |
ihl396 | 2:3466e9e16c99 | 111 | pc.printf("\f\n\r-------------ESP8266 Hardware Reset-------------\n\r"); |
ihl396 | 2:3466e9e16c99 | 112 | wait(0.5); |
ihl396 | 2:3466e9e16c99 | 113 | reset=1; |
ihl396 | 2:3466e9e16c99 | 114 | timeout=2; |
ihl396 | 2:3466e9e16c99 | 115 | getreply(); |
electromotivated | 0:11bc7a815367 | 116 | |
ihl396 | 2:3466e9e16c99 | 117 | ESPconfig(); //****************** include Config to set the ESP8266 configuration *********************** |
electromotivated | 0:11bc7a815367 | 118 | |
ihl396 | 2:3466e9e16c99 | 119 | imu.begin(); |
ihl396 | 2:3466e9e16c99 | 120 | if (!imu.begin()) { |
ihl396 | 2:3466e9e16c99 | 121 | pc.printf("Failed to communicate with LSM9DS1.\n"); |
electromotivated | 0:11bc7a815367 | 122 | } |
ihl396 | 2:3466e9e16c99 | 123 | imu.calibrate(1); |
ihl396 | 2:3466e9e16c99 | 124 | imu.calibrateMag(0); |
ihl396 | 2:3466e9e16c99 | 125 | |
ihl396 | 2:3466e9e16c99 | 126 | working_setpoint = 0.0; |
electromotivated | 0:11bc7a815367 | 127 | |
electromotivated | 1:d4a95e3a8aeb | 128 | encL.reset(); |
electromotivated | 1:d4a95e3a8aeb | 129 | encR.reset(); |
electromotivated | 1:d4a95e3a8aeb | 130 | feedbackL = encL.read(); |
electromotivated | 1:d4a95e3a8aeb | 131 | feedbackR = encR.read(); |
electromotivated | 0:11bc7a815367 | 132 | |
electromotivated | 0:11bc7a815367 | 133 | // Update sensors and feedback twice as fast as PID sample time |
electromotivated | 0:11bc7a815367 | 134 | // this makes pid react in real-time avoiding errors due to |
electromotivated | 0:11bc7a815367 | 135 | // missing counts etc. |
ihl396 | 2:3466e9e16c99 | 136 | |
electromotivated | 0:11bc7a815367 | 137 | motor.attach(&pid_callback, Ts_PID_CALLBACK); |
ihl396 | 2:3466e9e16c99 | 138 | |
electromotivated | 0:11bc7a815367 | 139 | // Start PID sampling |
electromotivated | 1:d4a95e3a8aeb | 140 | pidL.start(); |
electromotivated | 1:d4a95e3a8aeb | 141 | pidR.start(); |
ihl396 | 2:3466e9e16c99 | 142 | working_setpoint = 0; |
ihl396 | 2:3466e9e16c99 | 143 | dirL = 1; |
ihl396 | 2:3466e9e16c99 | 144 | dirR = 1; |
ihl396 | 2:3466e9e16c99 | 145 | while(1) |
ihl396 | 2:3466e9e16c99 | 146 | { |
ihl396 | 2:3466e9e16c99 | 147 | if(blue.readable()) |
ihl396 | 2:3466e9e16c99 | 148 | { |
ihl396 | 2:3466e9e16c99 | 149 | if (blue.getc()=='!') |
ihl396 | 2:3466e9e16c99 | 150 | { |
ihl396 | 2:3466e9e16c99 | 151 | if (blue.getc()=='B') //button data |
ihl396 | 2:3466e9e16c99 | 152 | { |
ihl396 | 2:3466e9e16c99 | 153 | bnum = blue.getc(); //button number |
ihl396 | 2:3466e9e16c99 | 154 | if(bnum=='1') { |
ihl396 | 2:3466e9e16c99 | 155 | working_setpoint = 50; |
ihl396 | 2:3466e9e16c99 | 156 | sample_time = 1; |
ihl396 | 2:3466e9e16c99 | 157 | pc.printf("setpoint: %2.0f\r\n", working_setpoint); |
electromotivated | 0:11bc7a815367 | 158 | } |
ihl396 | 2:3466e9e16c99 | 159 | } |
electromotivated | 0:11bc7a815367 | 160 | } |
ihl396 | 2:3466e9e16c99 | 161 | } |
ihl396 | 2:3466e9e16c99 | 162 | while(!imu.accelAvailable()); |
ihl396 | 2:3466e9e16c99 | 163 | imu.readAccel(); |
ihl396 | 3:bf6e71964ceb | 164 | //while(!imu.magAvailable()); |
ihl396 | 2:3466e9e16c99 | 165 | imu.readMag(); |
ihl396 | 2:3466e9e16c99 | 166 | |
ihl396 | 2:3466e9e16c99 | 167 | if( sample_time % 800 == 0) |
ihl396 | 2:3466e9e16c99 | 168 | { |
ihl396 | 2:3466e9e16c99 | 169 | velx = oldVelx + REFRESH_TIME_MS * oldX/1000; |
ihl396 | 2:3466e9e16c99 | 170 | posx = oldPosx + REFRESH_TIME_MS * oldVelx/1000; |
ihl396 | 2:3466e9e16c99 | 171 | |
ihl396 | 2:3466e9e16c99 | 172 | vely = oldVely + REFRESH_TIME_MS * oldY/1000; |
ihl396 | 2:3466e9e16c99 | 173 | posy = oldPosy + REFRESH_TIME_MS * oldVely/1000; |
ihl396 | 2:3466e9e16c99 | 174 | |
ihl396 | 2:3466e9e16c99 | 175 | accelx = imu.calcAccel(imu.ax); |
ihl396 | 2:3466e9e16c99 | 176 | accely = imu.calcAccel(imu.ay); |
ihl396 | 2:3466e9e16c99 | 177 | accelz = imu.calcAccel(imu.az); |
ihl396 | 2:3466e9e16c99 | 178 | calculate_heading(imu.calcMag(imu.mx), imu.calcMag(imu.my), imu.calcMag(imu.mz)); |
ihl396 | 2:3466e9e16c99 | 179 | |
ihl396 | 2:3466e9e16c99 | 180 | #ifdef DEBUG |
ihl396 | 2:3466e9e16c99 | 181 | pc.printf(" X axis Y axis Z axis\n\r"); |
ihl396 | 2:3466e9e16c99 | 182 | pc.printf("accel: %2.2f %2.2f %2.2f in Gs\r\n", imu.calcAccel(imu.ax), imu.calcAccel(imu.ay), imu.calcAccel(imu.az)); |
ihl396 | 2:3466e9e16c99 | 183 | pc.printf("Veloc: %2.2f %2.2f %2.2f in G*s\r\n", velx, vely, velz); |
ihl396 | 2:3466e9e16c99 | 184 | pc.printf("Magnetic heading: %2.2f", heading); |
ihl396 | 2:3466e9e16c99 | 185 | #endif |
ihl396 | 2:3466e9e16c99 | 186 | |
ihl396 | 2:3466e9e16c99 | 187 | oldVelx = velx; |
ihl396 | 2:3466e9e16c99 | 188 | oldPosx = posx; |
ihl396 | 2:3466e9e16c99 | 189 | oldVely = vely; |
ihl396 | 2:3466e9e16c99 | 190 | oldPosy = posy; |
ihl396 | 2:3466e9e16c99 | 191 | oldX = imu.ax; |
ihl396 | 2:3466e9e16c99 | 192 | oldY = imu.ay; |
electromotivated | 0:11bc7a815367 | 193 | } |
ihl396 | 2:3466e9e16c99 | 194 | if(working_setpoint > 0) |
ihl396 | 2:3466e9e16c99 | 195 | { |
ihl396 | 2:3466e9e16c99 | 196 | if(sample_time % 1500 == 0) |
ihl396 | 2:3466e9e16c99 | 197 | { |
ihl396 | 2:3466e9e16c99 | 198 | #ifdef DEBUG |
ihl396 | 2:3466e9e16c99 | 199 | pc.printf("Pushing data to server\r\n"); |
ihl396 | 2:3466e9e16c99 | 200 | #endif |
ihl396 | 2:3466e9e16c99 | 201 | |
ihl396 | 2:3466e9e16c99 | 202 | myled[0] = !myled[0]; |
ihl396 | 2:3466e9e16c99 | 203 | working_setpoint = 0; |
ihl396 | 2:3466e9e16c99 | 204 | |
ihl396 | 2:3466e9e16c99 | 205 | strcpy(snd, "srv:listen(80,function(conn)\r\n"); |
ihl396 | 2:3466e9e16c99 | 206 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 207 | wait(1); |
ihl396 | 2:3466e9e16c99 | 208 | strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n"); |
ihl396 | 2:3466e9e16c99 | 209 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 210 | wait(1); |
ihl396 | 2:3466e9e16c99 | 211 | strcpy(snd, "print(payload)\r\n"); |
ihl396 | 2:3466e9e16c99 | 212 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 213 | wait(1); |
ihl396 | 2:3466e9e16c99 | 214 | strcpy(snd, "conn:send(\"<!DOCTYPE html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 215 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 216 | wait(1); |
ihl396 | 2:3466e9e16c99 | 217 | |
ihl396 | 2:3466e9e16c99 | 218 | strcpy(snd, "conn:send(\"<html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 219 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 220 | wait(1); |
ihl396 | 2:3466e9e16c99 | 221 | sprintf(str_buf,"%2.2f",velx); |
ihl396 | 2:3466e9e16c99 | 222 | strcpy(snd, "conn:send(\"<h1>Velocity x: "); |
ihl396 | 2:3466e9e16c99 | 223 | strcat(snd, str_buf); |
ihl396 | 2:3466e9e16c99 | 224 | strcat(snd, "</h1>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 225 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 226 | wait(1); |
ihl396 | 2:3466e9e16c99 | 227 | |
ihl396 | 2:3466e9e16c99 | 228 | sprintf(str_buf,"%2.2f",vely); |
ihl396 | 2:3466e9e16c99 | 229 | strcpy(snd, "conn:send(\"<h1>Velocity y: "); |
ihl396 | 2:3466e9e16c99 | 230 | strcat(snd, str_buf); |
ihl396 | 2:3466e9e16c99 | 231 | strcat(snd, "</h1>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 232 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 233 | wait(1); |
ihl396 | 2:3466e9e16c99 | 234 | |
ihl396 | 2:3466e9e16c99 | 235 | sprintf(str_buf,"%2.2f",heading); |
ihl396 | 2:3466e9e16c99 | 236 | strcpy(snd, "conn:send(\"<h1>Magnetic Heading: "); |
ihl396 | 2:3466e9e16c99 | 237 | strcat(snd, str_buf); |
ihl396 | 2:3466e9e16c99 | 238 | strcat(snd, "</h1>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 239 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 240 | wait(1); |
ihl396 | 2:3466e9e16c99 | 241 | |
ihl396 | 2:3466e9e16c99 | 242 | strcpy(snd, "conn:send(\"</html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 243 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 244 | wait(1); |
ihl396 | 2:3466e9e16c99 | 245 | |
ihl396 | 2:3466e9e16c99 | 246 | strcpy(snd, "end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 247 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 248 | wait(1); |
ihl396 | 2:3466e9e16c99 | 249 | |
ihl396 | 2:3466e9e16c99 | 250 | strcpy(snd, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 251 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 252 | wait(1); |
ihl396 | 2:3466e9e16c99 | 253 | strcpy(snd, "end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 254 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 255 | wait(1); |
ihl396 | 2:3466e9e16c99 | 256 | timeout=17; |
ihl396 | 2:3466e9e16c99 | 257 | getreply(); |
ihl396 | 2:3466e9e16c99 | 258 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 259 | pc.printf("\r\nDONE"); |
ihl396 | 2:3466e9e16c99 | 260 | } |
ihl396 | 2:3466e9e16c99 | 261 | if(sample_time > 100000) |
ihl396 | 2:3466e9e16c99 | 262 | { |
ihl396 | 2:3466e9e16c99 | 263 | sample_time = 1; |
ihl396 | 2:3466e9e16c99 | 264 | } |
ihl396 | 2:3466e9e16c99 | 265 | sample_time++; |
electromotivated | 0:11bc7a815367 | 266 | } |
electromotivated | 0:11bc7a815367 | 267 | } |
electromotivated | 0:11bc7a815367 | 268 | } |
electromotivated | 0:11bc7a815367 | 269 | |
ihl396 | 2:3466e9e16c99 | 270 | void ESPconfig() |
ihl396 | 2:3466e9e16c99 | 271 | { |
ihl396 | 2:3466e9e16c99 | 272 | wait(5); |
ihl396 | 2:3466e9e16c99 | 273 | pc.printf("\f---------- Starting ESP Config ----------\r\n\n"); |
ihl396 | 2:3466e9e16c99 | 274 | strcpy(snd,".\r\n.\r\n"); |
ihl396 | 2:3466e9e16c99 | 275 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 276 | wait(1); |
ihl396 | 2:3466e9e16c99 | 277 | pc.printf("---------- Reset & get Firmware ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 278 | strcpy(snd,"node.restart()\r\n"); |
ihl396 | 2:3466e9e16c99 | 279 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 280 | timeout=5; |
ihl396 | 2:3466e9e16c99 | 281 | getreply(); |
ihl396 | 2:3466e9e16c99 | 282 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 283 | |
ihl396 | 2:3466e9e16c99 | 284 | wait(2); |
ihl396 | 2:3466e9e16c99 | 285 | |
ihl396 | 2:3466e9e16c99 | 286 | pc.printf("\n---------- Get Version ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 287 | strcpy(snd,"print(node.info())\r\n"); |
ihl396 | 2:3466e9e16c99 | 288 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 289 | timeout=4; |
ihl396 | 2:3466e9e16c99 | 290 | getreply(); |
ihl396 | 2:3466e9e16c99 | 291 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 292 | wait(3); |
ihl396 | 2:3466e9e16c99 | 293 | |
ihl396 | 2:3466e9e16c99 | 294 | // set CWMODE to 1=Station,2=AP,3=BOTH, default mode 1 (Station) |
ihl396 | 2:3466e9e16c99 | 295 | pc.printf("\n---------- Setting Mode ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 296 | strcpy(snd, "wifi.setmode(wifi.STATION)\r\n"); |
ihl396 | 2:3466e9e16c99 | 297 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 298 | timeout=4; |
ihl396 | 2:3466e9e16c99 | 299 | getreply(); |
ihl396 | 2:3466e9e16c99 | 300 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 301 | |
ihl396 | 2:3466e9e16c99 | 302 | wait(2); |
ihl396 | 2:3466e9e16c99 | 303 | |
ihl396 | 2:3466e9e16c99 | 304 | pc.printf("\n---------- Connecting to AP ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 305 | pc.printf("ssid = %s pwd = %s\r\n",ssid,pwd); |
ihl396 | 2:3466e9e16c99 | 306 | strcpy(snd, "wifi.sta.config(\""); |
ihl396 | 2:3466e9e16c99 | 307 | strcat(snd, ssid); |
ihl396 | 2:3466e9e16c99 | 308 | strcat(snd, "\",\""); |
ihl396 | 2:3466e9e16c99 | 309 | strcat(snd, pwd); |
ihl396 | 2:3466e9e16c99 | 310 | strcat(snd, "\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 311 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 312 | timeout=10; |
ihl396 | 2:3466e9e16c99 | 313 | getreply(); |
ihl396 | 2:3466e9e16c99 | 314 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 315 | |
ihl396 | 2:3466e9e16c99 | 316 | wait(5); |
ihl396 | 2:3466e9e16c99 | 317 | |
ihl396 | 2:3466e9e16c99 | 318 | pc.printf("\n---------- Get IP's ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 319 | strcpy(snd, "print(wifi.sta.getip())\r\n"); |
ihl396 | 2:3466e9e16c99 | 320 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 321 | timeout=3; |
ihl396 | 2:3466e9e16c99 | 322 | getreply(); |
ihl396 | 2:3466e9e16c99 | 323 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 324 | |
ihl396 | 2:3466e9e16c99 | 325 | wait(1); |
ihl396 | 2:3466e9e16c99 | 326 | |
ihl396 | 2:3466e9e16c99 | 327 | pc.printf("\n---------- Get Connection Status ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 328 | strcpy(snd, "print(wifi.sta.status())\r\n"); |
ihl396 | 2:3466e9e16c99 | 329 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 330 | timeout=5; |
ihl396 | 2:3466e9e16c99 | 331 | getreply(); |
ihl396 | 2:3466e9e16c99 | 332 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 333 | |
ihl396 | 2:3466e9e16c99 | 334 | pc.printf("\n---------- Setting up http server ----------\r\n"); |
ihl396 | 2:3466e9e16c99 | 335 | strcpy(snd, "srv=net.createServer(net.TCP)\r\n"); |
ihl396 | 2:3466e9e16c99 | 336 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 337 | wait(1); |
ihl396 | 2:3466e9e16c99 | 338 | strcpy(snd, "srv:listen(80,function(conn)\r\n"); |
ihl396 | 2:3466e9e16c99 | 339 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 340 | wait(1); |
ihl396 | 2:3466e9e16c99 | 341 | strcpy(snd, "conn:on(\"receive\",function(conn,payload)\r\n"); |
ihl396 | 2:3466e9e16c99 | 342 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 343 | wait(1); |
ihl396 | 2:3466e9e16c99 | 344 | strcpy(snd, "print(payload)\r\n"); |
ihl396 | 2:3466e9e16c99 | 345 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 346 | wait(1); |
ihl396 | 2:3466e9e16c99 | 347 | strcpy(snd, "conn:send(\"<!DOCTYPE html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 348 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 349 | wait(1); |
electromotivated | 0:11bc7a815367 | 350 | |
ihl396 | 2:3466e9e16c99 | 351 | strcpy(snd, "conn:send(\"<html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 352 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 353 | wait(1); |
electromotivated | 0:11bc7a815367 | 354 | |
ihl396 | 2:3466e9e16c99 | 355 | strcpy(snd, "conn:send(\"<h1>WIFI Monitoring Program</h1>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 356 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 357 | wait(1); |
ihl396 | 2:3466e9e16c99 | 358 | |
ihl396 | 2:3466e9e16c99 | 359 | strcpy(snd, "conn:send(\"</html>\")\r\n"); |
ihl396 | 2:3466e9e16c99 | 360 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 361 | wait(1); |
electromotivated | 0:11bc7a815367 | 362 | |
ihl396 | 2:3466e9e16c99 | 363 | strcpy(snd, "end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 364 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 365 | wait(1); |
electromotivated | 0:11bc7a815367 | 366 | |
ihl396 | 2:3466e9e16c99 | 367 | strcpy(snd, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 368 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 369 | wait(1); |
ihl396 | 2:3466e9e16c99 | 370 | strcpy(snd, "end)\r\n"); |
ihl396 | 2:3466e9e16c99 | 371 | SendCMD(); |
ihl396 | 2:3466e9e16c99 | 372 | wait(1); |
ihl396 | 2:3466e9e16c99 | 373 | timeout=17; |
ihl396 | 2:3466e9e16c99 | 374 | getreply(); |
ihl396 | 2:3466e9e16c99 | 375 | pc.printf(buf); |
ihl396 | 2:3466e9e16c99 | 376 | pc.printf("\r\nDONE"); |
ihl396 | 2:3466e9e16c99 | 377 | |
electromotivated | 0:11bc7a815367 | 378 | } |
electromotivated | 0:11bc7a815367 | 379 | |
ihl396 | 2:3466e9e16c99 | 380 | void SendCMD() |
ihl396 | 2:3466e9e16c99 | 381 | { |
ihl396 | 2:3466e9e16c99 | 382 | esp.printf("%s", snd); |
ihl396 | 2:3466e9e16c99 | 383 | } |
ihl396 | 2:3466e9e16c99 | 384 | |
ihl396 | 2:3466e9e16c99 | 385 | void getreply() |
ihl396 | 2:3466e9e16c99 | 386 | { |
ihl396 | 2:3466e9e16c99 | 387 | memset(buf, '\0', sizeof(buf)); |
ihl396 | 2:3466e9e16c99 | 388 | t.start(); |
ihl396 | 2:3466e9e16c99 | 389 | ended=0; |
ihl396 | 2:3466e9e16c99 | 390 | int count=0; |
ihl396 | 2:3466e9e16c99 | 391 | while(!ended) { |
ihl396 | 2:3466e9e16c99 | 392 | if(esp.readable()) { |
ihl396 | 2:3466e9e16c99 | 393 | buf[count] = esp.getc(); |
ihl396 | 2:3466e9e16c99 | 394 | count++; |
ihl396 | 2:3466e9e16c99 | 395 | } |
ihl396 | 2:3466e9e16c99 | 396 | if(t.read() > timeout) { |
ihl396 | 2:3466e9e16c99 | 397 | ended = 1; |
ihl396 | 2:3466e9e16c99 | 398 | t.stop(); |
ihl396 | 2:3466e9e16c99 | 399 | t.reset(); |
ihl396 | 2:3466e9e16c99 | 400 | } |
electromotivated | 0:11bc7a815367 | 401 | } |
ihl396 | 2:3466e9e16c99 | 402 | } |
ihl396 | 2:3466e9e16c99 | 403 | void calculate_heading(float mx, float my, float mz) |
ihl396 | 2:3466e9e16c99 | 404 | { |
ihl396 | 2:3466e9e16c99 | 405 | |
ihl396 | 2:3466e9e16c99 | 406 | // touchy trig stuff to use arctan to get compass heading (scale is 0..360) |
ihl396 | 2:3466e9e16c99 | 407 | mx = -mx; |
ihl396 | 2:3466e9e16c99 | 408 | if (my == 0.0) |
ihl396 | 2:3466e9e16c99 | 409 | heading = (mx < 0.0) ? 180.0 : 0.0; |
ihl396 | 2:3466e9e16c99 | 410 | else |
ihl396 | 2:3466e9e16c99 | 411 | heading = atan2(mx, my)*360.0/(2.0*PI); |
ihl396 | 2:3466e9e16c99 | 412 | heading -= DECLINATION; //correct for geo location |
ihl396 | 2:3466e9e16c99 | 413 | if(heading>180.0) heading = heading - 360.0; |
ihl396 | 2:3466e9e16c99 | 414 | else if(heading<-180.0) heading = 360.0 + heading; |
ihl396 | 2:3466e9e16c99 | 415 | else if(heading<0.0) heading = 360.0 + heading; |
electromotivated | 0:11bc7a815367 | 416 | |
ihl396 | 2:3466e9e16c99 | 417 | #ifdef DEBUG |
ihl396 | 2:3466e9e16c99 | 418 | pc.printf("Magnetic Heading: %f degress\n\r",heading); |
ihl396 | 2:3466e9e16c99 | 419 | #endif |
electromotivated | 0:11bc7a815367 | 420 | } |
electromotivated | 0:11bc7a815367 | 421 | |
ihl396 | 2:3466e9e16c99 | 422 | void pid_callback() |
ihl396 | 2:3466e9e16c99 | 423 | { |
ihl396 | 2:3466e9e16c99 | 424 | |
ihl396 | 2:3466e9e16c99 | 425 | // Deal with feedback and update motors |
ihl396 | 2:3466e9e16c99 | 426 | // Motor direction based on working setpoint var |
ihl396 | 2:3466e9e16c99 | 427 | |
ihl396 | 2:3466e9e16c99 | 428 | //myled[0] = dirL; |
ihl396 | 2:3466e9e16c99 | 429 | //myled[1] = dirR; |
ihl396 | 2:3466e9e16c99 | 430 | // Setpoint vars used by PID objects are concerned with |
ihl396 | 2:3466e9e16c99 | 431 | // only SPEED not direction. |
ihl396 | 2:3466e9e16c99 | 432 | setpoint = abs(working_setpoint); |
ihl396 | 2:3466e9e16c99 | 433 | |
ihl396 | 2:3466e9e16c99 | 434 | float k = Ts_PID_CALLBACK; // Discrete time, (Ts/2 because this callback is called |
ihl396 | 2:3466e9e16c99 | 435 | // at interval of Ts/2... or twice as fast as pid controller) |
ihl396 | 2:3466e9e16c99 | 436 | static int last_count_L = 0; |
ihl396 | 2:3466e9e16c99 | 437 | static int last_count_R = 0; |
ihl396 | 2:3466e9e16c99 | 438 | int countL = encL.read(); |
ihl396 | 2:3466e9e16c99 | 439 | int countR = encR.read(); |
ihl396 | 2:3466e9e16c99 | 440 | //pc.printf("%d\r\n", countL); |
electromotivated | 1:d4a95e3a8aeb | 441 | |
ihl396 | 2:3466e9e16c99 | 442 | // Because encoders are not quadrature we must handle the sign ourselves, |
ihl396 | 2:3466e9e16c99 | 443 | // i.e. explicitly make calcs based on the direction we have set the motor |
ihl396 | 2:3466e9e16c99 | 444 | float raw_speed_L = ((countL - last_count_L)*FEEDBACK_SCALE) / k; |
ihl396 | 2:3466e9e16c99 | 445 | float rpm_speed_L = raw_speed_L * 60.0; // Convert speed to RPM |
ihl396 | 2:3466e9e16c99 | 446 | |
ihl396 | 2:3466e9e16c99 | 447 | float raw_speed_R = ((countR - last_count_R)*FEEDBACK_SCALE) / k; |
ihl396 | 2:3466e9e16c99 | 448 | float rpm_speed_R = raw_speed_R * 60.0; // Convert speed to RPM |
electromotivated | 1:d4a95e3a8aeb | 449 | |
ihl396 | 2:3466e9e16c99 | 450 | last_count_L = countL; // Save last count |
ihl396 | 2:3466e9e16c99 | 451 | last_count_R = countR; |
ihl396 | 2:3466e9e16c99 | 452 | feedbackL = rpm_speed_L; |
ihl396 | 2:3466e9e16c99 | 453 | feedbackR = rpm_speed_R; |
ihl396 | 2:3466e9e16c99 | 454 | |
ihl396 | 2:3466e9e16c99 | 455 | mtrL.forceSetSpeed(outputL * dirL); |
ihl396 | 2:3466e9e16c99 | 456 | mtrR.forceSetSpeed(outputR * dirR); |
electromotivated | 0:11bc7a815367 | 457 | } |
electromotivated | 0:11bc7a815367 | 458 | |
electromotivated | 0:11bc7a815367 | 459 | /* |
electromotivated | 0:11bc7a815367 | 460 | Clips value to lower/ uppper |
electromotivated | 0:11bc7a815367 | 461 | @param value The value to clip |
electromotivated | 0:11bc7a815367 | 462 | @param lower The mininum allowable value |
electromotivated | 0:11bc7a815367 | 463 | @param upper The maximum allowable value |
electromotivated | 0:11bc7a815367 | 464 | @return The resulting clipped value |
electromotivated | 0:11bc7a815367 | 465 | */ |
electromotivated | 0:11bc7a815367 | 466 | float clip(float value, float lower, float upper){ |
electromotivated | 0:11bc7a815367 | 467 | return std::max(lower, std::min(value, upper)); |
ihl396 | 2:3466e9e16c99 | 468 | } |