Work in progress...
Dependencies: ESC FreeIMU mbed-rtos mbed
Experiment - work in progress...
Diff: main.cpp
- Revision:
- 3:5e7476bca25f
- Parent:
- 2:7439607ccd51
- Child:
- 4:46f3c3dd5977
--- a/main.cpp Tue Oct 15 18:30:46 2013 +0000 +++ b/main.cpp Sun Oct 27 01:05:35 2013 +0000 @@ -1,16 +1,57 @@ #include "math.h" #include "mbed.h" #include "rtos.h" -//#include "EthernetInterface.h" -//#include "RefRX.h" +#include "EthernetInterface.h" #include "esc.h" +#include "PID.h" +#include "MPU6050.h" +#include "IMUfilter.h" +#include <string> + + +//Author: Matteo Terruzzi + +//Target differential of time in seconds, for the various program cycles: + //timings as for main cycle: +#define TARGET_IMU_DT 0.002 //every 1 step: 100% +#define TARGET_MAIN_DT 0.016 //every 8 steps: 12.5% + 2 step start delay +#define TARGET_TX_DT 0.040 //every 20 steps: 5% + 1 step start delay +#define TARGET_RX_DT 0.040 //with previous + +//For the various dt, "average" is computed using a sort of low-pass filter of the actual value. +//The formula (recurrence equation) is: +// a(t) = x(t) * k - a(t-1) * k with a(0) = 0 +//where: +// x(t) is the actual value at the time t; +// a(t) is the average at the timepoint t; +// a(t-1) is the average at the previous timepoint; +// k is AVERAGE_DT_K_GAIN (macro defined below). +// +//So, here is the meaning of AVERAGE_DT_K_GAIN, or k: the higher it is, the higher is the cut-frequency. +//If k == 1, then a(t) == x(t). +//If k == 0, then a(t) == target value (the actual value is totaly ignored). +//A good value may be k = 1/8 = 0.125. +#define AVERAGE_DT_K_GAIN 0.0125 + +//Blinking status leds +#define LED_ESC LED1 +#define LED_IMU LED2 +#define LED_TXRX LED3 +#define LED_RX LED4 + + #include "state.h" #include "TXRX.h" -#include "IMU.h" -#include "PID.h" int main() { + + Serial pc(USBTX,USBRX); + + + //INITIALIZATION + //------------------------------------------------------------------------------- + //Setup ESCs ESC esc1(p23); ESC esc2(p24); @@ -18,98 +59,155 @@ ESC esc4(p26); //Setup status leds - DigitalOut led1(LED1); led1 = 1; //esc - DigitalOut led4(LED4); led4 = 0; //signal - //DigitalOut led3(LED3); led3 = 0; //tmp signal send - //DigitalOut led2(LED2); led2 = 0;//moved to IMU.h + DigitalOut led_esc(LED_ESC); led_esc = 1; //flip at esc update (fixed 0 means that the ESCs was not been initiated--the program is stucked before this point) + DigitalOut led_imu(LED_IMU); led_imu = 0; //flip at imu computations done (fixed 0 means that the imu sensors don't respond) + DigitalOut led_txrx(LED_TXRX); led_txrx = 0; //flip at remote signal exchange done (fixed 0 means that the TXRX_thread has not been started) //Setup Ethernet - //EthernetInterface interface; - //interface.init("192.168.1.16","255.255.255.0","192.168.1.1"); - //interface.connect(); + EthernetInterface interface; + interface.init("192.168.1.16","255.255.255.0","192.168.1.1"); + interface.connect(); - //Setup RefRX static class for remote control - //Thread RefRX_thread (RefRX::worker); - //RefRX::init(2222, 2223, RefRX_thread); - //Serial pc(USBTX, USBRX); - //pc.baud(115200); - //pc.printf("Serial setted up\r\n"); + //Setup remote control Thread TXRX_thread (TXRX_thread_routine); - led4 = 1; - //Thread::wait(0.5); - - //Setup FreeIMU - //FreeIMU freeIMU; - //freeIMU.init(); - Thread IMU_thread (IMU_thread_routine); - //pc.printf("IMU thread started\r\n"); + led_txrx = 1; //Setup state QuadState mainQuadState; mainQuadState.reset(); QuadState rxQuadState; rxQuadState.reset(); QuadState txQuadState; txQuadState.reset(); - //pc.printf("Main and rx states setted up\r\n"); + + //Setup FreeIMU + IMUfilter IMU_filter(TARGET_IMU_DT,40); + MPU6050 IMU_sensor(p28, p27); + IMU_sensor.setGyroRange(MPU6050_GYRO_RANGE_250); + IMU_sensor.setAcceleroRange(MPU6050_ACCELERO_RANGE_4G); + led_imu = 1; + + + - //Prepare controll loop - //float ref1=0, ref2=0, ref3=0, ref4=0; - double dt=0.001; //will be measured - Timer dt_t; - dt_t.start(); - //unsigned int state_read_i=0; - //unsigned int state_send_i=0; + //MAIN CONTROL CYCLE PREPARATION + //------------------------------------------------------------------------------- + + unsigned short int step = 0; + + //Just a moment... Let the other threads begin! + Thread::wait(2000 /*ms*/); + Thread::yield(); + //just made sure the other threads had time to begin. + + + //Setup timers + Timer IMU_dt_timer; IMU_dt_timer.reset(); IMU_dt_timer.start(); + Timer dt_timer; dt_timer.reset(); dt_timer.start(); + Thread::wait(1000.0 * min(mainQuadState.target_imu_dt,mainQuadState.target_main_dt)); //pid PID targetRoll_pid(0.1,0.0001,0.5, 0.020); targetRoll_pid.setInputLimits(-3.15/4,3.15/4); targetRoll_pid.setOutputLimits(0,0.5); - - //pc.printf("Now going to start main loop...\r\n"); - - led1 = !led1; - //Begins main control loop + + + + //MAIN CONTROL CYCLE + //=================================================================================== while(1) { - //retrive refs - //led4 ^= RefRX::get(ref1,ref2,ref3,ref4); //flip-flop-flip-flop! - /* - if(pc.readable()){ - *((unsigned char *)(&rxQuadState) + state_read_i) = pc.getc(); - ++state_read_i; - if(state_read_i >= sizeof(QuadState)) - state_read_i = 0; - led4 = 1; + + + //IMU INPUT + //------------------------------------------------------------------------------- + + //Measure time + QUAD_STATE_READ_ACTUAL_DT(mainQuadState,imu,IMU_dt_timer) + QUAD_STATE_WAIT_DT_TARGET(mainQuadState.actual_imu_dt,mainQuadState.target_imu_dt) + QUAD_STATE_UPDATE_DT(mainQuadState,imu,IMU_dt_timer) + + + led_imu = 1; + + //Retrieve inertial values from sensors + { + float a[3], g[3]; + IMU_sensor.getAccelero(a); + IMU_sensor.getGyro(g); + + //Compute IMU filters + IMU_filter.updateFilter(g[0], g[1], g[2], a[0], a[1], a[2]); } - else - led4 = 0; - */ - unsigned int rx_delta, rx_wait; - if(TXRX_stateExchange(txQuadState,rxQuadState)) - if(rxQuadState.actual_rx_delta_ms >= 5000 || rxQuadState.actual_rx_wait_ms >= 5000) - mainQuadState.ZERO_ALL_MOTORS_NOW__DANGER = true; //experiments only ////NOTE: FIXME: THAT'S ABSOLUTELY UNSAFE WHILE FLYING!!! + if(mainQuadState.actual_imu_dt >= 100.0 * mainQuadState.target_imu_dt) + mainQuadState.ZERO_MEANS_ZERO_ALL_MOTORS_NOW__DANGER = 0; //experiments only ////NOTE: FIXME: THAT'S ABSOLUTELY UNSAFE WHILE FLYING!!! + + + led_imu = 0; + + + + +if(step % 20 == 2){ +//5% frequency; step%20==2 + + + + //REMOTE INPUT + //------------------------------------------------------------------------------- + led_txrx = 1; + + //Remote signal exchange + txQuadState = mainQuadState; //send info back + if(TXRX_stateExchange(txQuadState,rxQuadState)){ + mainQuadState.average_rx_dt = rxQuadState.average_rx_dt; + mainQuadState.actual_rx_dt = rxQuadState.actual_rx_dt; + if(mainQuadState.actual_rx_dt >= 100.0 * mainQuadState.target_rx_dt) + mainQuadState.ZERO_MEANS_ZERO_ALL_MOTORS_NOW__DANGER = 0; //experiments only ////NOTE: FIXME: THAT'S ABSOLUTELY UNSAFE WHILE FLYING!!! + } + + + /*if(step % 640 == 2){ - //retrive inertial values - IMU_filter_getYawPitchRoll( - mainQuadState.estimated_rotation_y, - mainQuadState.estimated_rotation_p, - mainQuadState.estimated_rotation_r ); + //Other tasks + + if(pc.writeable()){ + pc.printf("%s \r\n", mainQuadState.getJSON().c_str()); //the message is long => it slows down a lot! + } + }*/ + + led_txrx = 0; + + + +//end of 5% frequency; step%20==2 +} +if(step % 8 == 3){ +//12.5% frequency; step%8==3 + - //calc dt - dt_t.stop(); - dt = (double) (1.0/1000000.0) * dt_t.read_us(); - dt_t.reset(); dt_t.start(); - mainQuadState.average_throttle_dt += dt * mainQuadState.average_throttle_dt_k; - mainQuadState.average_throttle_dt -= mainQuadState.average_throttle_dt * mainQuadState.average_throttle_dt_k; - mainQuadState.actual_throttle_dt = dt; + led_esc = 1; + + + //ELABORATION + //------------------------------------------------------------------------------- + + //Measure time + QUAD_STATE_UPDATE_DT(mainQuadState,main,dt_timer) - //elaborate signals - if(mainQuadState.ZERO_ALL_MOTORS_NOW__DANGER){ + //Estimate rotation + IMU_filter.computeEuler(); + mainQuadState.estimated_rotation_y = IMU_filter.getYaw(); + mainQuadState.estimated_rotation_p = IMU_filter.getPitch(); + mainQuadState.estimated_rotation_r = IMU_filter.getRoll(); + + //Elaborate inputs to determinate outputs + if(mainQuadState.ZERO_MEANS_ZERO_ALL_MOTORS_NOW__DANGER == 0 + || rxQuadState.ZERO_MEANS_ZERO_ALL_MOTORS_NOW__DANGER == 0){ mainQuadState.actual_throttle_1 = 0; mainQuadState.actual_throttle_2 = 0; mainQuadState.actual_throttle_3 = 0; mainQuadState.actual_throttle_4 = 0; }else{ - mainQuadState.actual_rx_delta_ms = rxQuadState.actual_rx_delta_ms; - mainQuadState.actual_rx_wait_ms = rxQuadState.actual_rx_wait_ms; + mainQuadState.actual_rx_dt = rxQuadState.actual_rx_dt; + mainQuadState.average_rx_dt = rxQuadState.average_rx_dt; mainQuadState.target_rotation_r = rxQuadState.target_rotation_r; mainQuadState.target_rotation_r_isRequired = rxQuadState.target_rotation_r_isRequired; @@ -117,7 +215,7 @@ float roll = 0; if(mainQuadState.target_rotation_r_isRequired){ targetRoll_pid.setSetPoint(mainQuadState.target_rotation_r); - targetRoll_pid.setInterval(mainQuadState.average_throttle_dt); + targetRoll_pid.setInterval(mainQuadState.average_main_dt); targetRoll_pid.setProcessValue(mainQuadState.estimated_rotation_r); roll = targetRoll_pid.compute(); }else{ @@ -131,6 +229,7 @@ out -= roll; mainQuadState.actual_throttle_1 = out; } + if(rxQuadState.requested_throttle_2 >= 0 && rxQuadState.requested_throttle_2 <=1) mainQuadState.actual_throttle_2 = rxQuadState.requested_throttle_2; else{ @@ -150,52 +249,35 @@ } } - //compute new ESC values.. + + + //OUTPUT + //------------------------------------------------------------------------------- + + //set new ESC values. esc1 = mainQuadState.actual_throttle_1; esc2 = mainQuadState.actual_throttle_2; esc3 = mainQuadState.actual_throttle_3; esc4 = mainQuadState.actual_throttle_4; - //finally output to ESCs + //effectively output to ESCs esc1(); esc2(); esc3(); esc4(); - led1 = !led1; - uint32_t w = 20-dt; - if(w<5) w=5; - else if(w>19) w=19; - Thread::wait(w /*ms*/); + led_esc = 0; + +//end of 12.5% frequency; step%8==3 +} - //send info back - txQuadState = mainQuadState; - /* - for(int i=0; i<sizeof(QuadState); ++i){ - while(!pc.writeable()) - led3=0; - pc.putc((int) *((unsigned char *) (&mainQuadState) + i)); - }*/ - /* - if(state_send_i >= 7){ - state_send_i = 0; - time_t sec = time(NULL); - pc.printf("\033[2J\033[1;1H"); - pc.printf("Time: %s", ctime(&sec)); - pc.printf("Actual thrust: \t\t %8.2f %8.2f %8.2f %8.2f\n", - mainQuadState.actual_throttle_1, mainQuadState.actual_throttle_2, - mainQuadState.actual_throttle_3, mainQuadState.actual_throttle_4 ); - pc.printf("IMU yaw pitch roll: \t %10.1f° %10.1f° %10.1f°\n", mainQuadState.estimated_rotation_y*180.0/3.141592653589793, - mainQuadState.estimated_rotation_p*180.0/3.141592653589793, mainQuadState.estimated_rotation_r*180.0/3.141592653589793 ); - pc.printf("Avg/actual delta time: \t %10.2f ms %10.2f ms \n", mainQuadState.average_throttle_dt*1000.0, mainQuadState.actual_throttle_dt*1000.0); - led3=pc.writeable(); - } - ++state_send_i;*/ - } + ++step; + }//End of main control loop + //It must not get here. return 0; }