RC-car remotely controlled from a computer. A demonstration of the power of Pytelemetry/telemetry. MIT Licensing.
Dependencies: BufferedSerial FRDM-TFC mbed telemetry
Example of the 'Telemetry' library, a portable communication library for embedded devices. The PC-side of this code is hosted a github.com/Overdrivr/telemetry-examples
This code uses the car from the Freescale Cup competition initially dedicated to be a line-following racing car, and turns it into a full-blown radio-controlled car.
It is using a Bluetooth serial module to provide wireless connectivity. See the repository at github.com/Overdrivr/telemetry-examples for complete instructions on wiring everthing together.
Repo : TO BE DONE
main.cpp@1:5a07069e17b6, 2016-02-22 (annotated)
- Committer:
- Overdrivr
- Date:
- Mon Feb 22 21:24:52 2016 +0000
- Revision:
- 1:5a07069e17b6
- Parent:
- 0:c5e974040f21
- Child:
- 2:74d5233b6284
Updated code for new interface + comments and description
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Overdrivr | 0:c5e974040f21 | 1 | #include "mbed.h" |
Overdrivr | 0:c5e974040f21 | 2 | #include "FRDM-TFC/TFC.h" |
Overdrivr | 1:5a07069e17b6 | 3 | #include "telemetry/Telemetry.h" |
Overdrivr | 1:5a07069e17b6 | 4 | |
Overdrivr | 1:5a07069e17b6 | 5 | /* |
Overdrivr | 1:5a07069e17b6 | 6 | Example of the 'Telemetry' library, a portable communication library for embedded devices. |
Overdrivr | 1:5a07069e17b6 | 7 | The PC-side of this code is hosted a github.com/Overdrivr/telemetry-examples |
Overdrivr | 1:5a07069e17b6 | 8 | |
Overdrivr | 1:5a07069e17b6 | 9 | This code uses the car from the Freescale Cup competition initially dedicated to be a |
Overdrivr | 1:5a07069e17b6 | 10 | line-following racing car, and turns it into a full-blown radio-controlled car. |
Overdrivr | 1:5a07069e17b6 | 11 | |
Overdrivr | 1:5a07069e17b6 | 12 | It is using a Bluetooth serial module to provide wireless connectivity. See the repository at |
Overdrivr | 1:5a07069e17b6 | 13 | github.com/Overdrivr/telemetry-examples for complete instructions on wiring everthing together. |
Overdrivr | 1:5a07069e17b6 | 14 | |
Overdrivr | 1:5a07069e17b6 | 15 | Repo : TO BE DONE |
Overdrivr | 1:5a07069e17b6 | 16 | */ |
Overdrivr | 0:c5e974040f21 | 17 | |
Overdrivr | 0:c5e974040f21 | 18 | DigitalOut led(LED1); |
Overdrivr | 0:c5e974040f21 | 19 | |
Overdrivr | 0:c5e974040f21 | 20 | struct TM_state { |
Overdrivr | 0:c5e974040f21 | 21 | float direction; |
Overdrivr | 0:c5e974040f21 | 22 | float throttle; |
Overdrivr | 0:c5e974040f21 | 23 | }; |
Overdrivr | 0:c5e974040f21 | 24 | |
Overdrivr | 1:5a07069e17b6 | 25 | // Definition of the callback function |
Overdrivr | 0:c5e974040f21 | 26 | void process(TM_state* carState, TM_msg* msg); |
Overdrivr | 0:c5e974040f21 | 27 | |
Overdrivr | 0:c5e974040f21 | 28 | int main() |
Overdrivr | 0:c5e974040f21 | 29 | { |
Overdrivr | 1:5a07069e17b6 | 30 | // Create a Telemetry instance, running on uart at 115200 bauds |
Overdrivr | 1:5a07069e17b6 | 31 | Telemetry TM(115200); |
Overdrivr | 1:5a07069e17b6 | 32 | |
Overdrivr | 1:5a07069e17b6 | 33 | // a data structure to hold writeable parameters |
Overdrivr | 1:5a07069e17b6 | 34 | // i.e. the car direction and throttle that will be both be controlled from the laptop |
Overdrivr | 0:c5e974040f21 | 35 | TM_state carState; |
Overdrivr | 0:c5e974040f21 | 36 | carState.direction = 0; |
Overdrivr | 0:c5e974040f21 | 37 | carState.throttle = 0; |
Overdrivr | 1:5a07069e17b6 | 38 | |
Overdrivr | 1:5a07069e17b6 | 39 | // Suscribe our custom processing function (= callback function), and pass the data structure |
Overdrivr | 1:5a07069e17b6 | 40 | // so that we can access it inside |
Overdrivr | 1:5a07069e17b6 | 41 | // This way, everytime a frame is received, Telemetry will call this function for us, |
Overdrivr | 1:5a07069e17b6 | 42 | // and pass the TM_state data structure to it. |
Overdrivr | 1:5a07069e17b6 | 43 | TM.sub(process, &carState); |
Overdrivr | 0:c5e974040f21 | 44 | |
Overdrivr | 0:c5e974040f21 | 45 | led = 1; |
Overdrivr | 1:5a07069e17b6 | 46 | |
Overdrivr | 1:5a07069e17b6 | 47 | // Init the TheFreescaleCup shield |
Overdrivr | 0:c5e974040f21 | 48 | TFC_Init(); |
Overdrivr | 0:c5e974040f21 | 49 | |
Overdrivr | 1:5a07069e17b6 | 50 | // Some timers... for timing :p |
Overdrivr | 0:c5e974040f21 | 51 | Timer servo_timer; |
Overdrivr | 0:c5e974040f21 | 52 | Timer motor_timer; |
Overdrivr | 0:c5e974040f21 | 53 | Timer tm_timer; |
Overdrivr | 0:c5e974040f21 | 54 | Timer print_timer; |
Overdrivr | 0:c5e974040f21 | 55 | |
Overdrivr | 0:c5e974040f21 | 56 | servo_timer.start(); |
Overdrivr | 0:c5e974040f21 | 57 | motor_timer.start(); |
Overdrivr | 0:c5e974040f21 | 58 | tm_timer.start(); |
Overdrivr | 0:c5e974040f21 | 59 | print_timer.start(); |
Overdrivr | 1:5a07069e17b6 | 60 | |
Overdrivr | 1:5a07069e17b6 | 61 | // Activate the engines ! |
Overdrivr | 0:c5e974040f21 | 62 | TFC_HBRIDGE_ENABLE; |
Overdrivr | 1:5a07069e17b6 | 63 | |
Overdrivr | 0:c5e974040f21 | 64 | for(;;) |
Overdrivr | 0:c5e974040f21 | 65 | { |
Overdrivr | 0:c5e974040f21 | 66 | // update telemetry |
Overdrivr | 0:c5e974040f21 | 67 | if(tm_timer.read_ms() > 50) |
Overdrivr | 0:c5e974040f21 | 68 | { |
Overdrivr | 0:c5e974040f21 | 69 | tm_timer.reset(); |
Overdrivr | 0:c5e974040f21 | 70 | TM.update(); |
Overdrivr | 0:c5e974040f21 | 71 | } |
Overdrivr | 0:c5e974040f21 | 72 | |
Overdrivr | 0:c5e974040f21 | 73 | // update servo control |
Overdrivr | 0:c5e974040f21 | 74 | if(servo_timer.read_ms() > 10) |
Overdrivr | 0:c5e974040f21 | 75 | { |
Overdrivr | 0:c5e974040f21 | 76 | servo_timer.reset(); |
Overdrivr | 0:c5e974040f21 | 77 | TFC_SetServo(0, carState.direction); |
Overdrivr | 0:c5e974040f21 | 78 | } |
Overdrivr | 0:c5e974040f21 | 79 | |
Overdrivr | 0:c5e974040f21 | 80 | // update motor control |
Overdrivr | 0:c5e974040f21 | 81 | if(motor_timer.read_ms() > 5) |
Overdrivr | 0:c5e974040f21 | 82 | { |
Overdrivr | 0:c5e974040f21 | 83 | motor_timer.reset(); |
Overdrivr | 0:c5e974040f21 | 84 | TFC_SetMotorPWM(carState.throttle , carState.throttle); |
Overdrivr | 0:c5e974040f21 | 85 | } |
Overdrivr | 0:c5e974040f21 | 86 | |
Overdrivr | 0:c5e974040f21 | 87 | // publish car state & blink a led |
Overdrivr | 0:c5e974040f21 | 88 | if(print_timer.read_ms() > 500) |
Overdrivr | 0:c5e974040f21 | 89 | { |
Overdrivr | 0:c5e974040f21 | 90 | print_timer.reset(); |
Overdrivr | 1:5a07069e17b6 | 91 | // Publish the car parameters, so we can access them from the computer |
Overdrivr | 1:5a07069e17b6 | 92 | TM.pub_f32("direction",carState.direction); |
Overdrivr | 0:c5e974040f21 | 93 | TM.pub_f32("throttle",carState.throttle); |
Overdrivr | 1:5a07069e17b6 | 94 | led = (led == 0) ? 1 : 0; // Toggle the led |
Overdrivr | 0:c5e974040f21 | 95 | } |
Overdrivr | 0:c5e974040f21 | 96 | } |
Overdrivr | 0:c5e974040f21 | 97 | } |
Overdrivr | 0:c5e974040f21 | 98 | |
Overdrivr | 1:5a07069e17b6 | 99 | // This is our processing function called every time a frame is received |
Overdrivr | 1:5a07069e17b6 | 100 | // First parameter is a pointer to the data structure we defined in main |
Overdrivr | 1:5a07069e17b6 | 101 | // Second parameter is a pointer to a data structure containing all info about received frame |
Overdrivr | 0:c5e974040f21 | 102 | void process(TM_state* carState, TM_msg* msg) |
Overdrivr | 0:c5e974040f21 | 103 | { |
Overdrivr | 1:5a07069e17b6 | 104 | // temp variable |
Overdrivr | 0:c5e974040f21 | 105 | float value = 0.f; |
Overdrivr | 1:5a07069e17b6 | 106 | // If received topic == 'direction' |
Overdrivr | 0:c5e974040f21 | 107 | if(strcmp(msg->topic,"direction") == 0) |
Overdrivr | 0:c5e974040f21 | 108 | { |
Overdrivr | 1:5a07069e17b6 | 109 | // If data type matches 'float32' |
Overdrivr | 0:c5e974040f21 | 110 | if(emplace_f32(msg,&value)) |
Overdrivr | 0:c5e974040f21 | 111 | { |
Overdrivr | 1:5a07069e17b6 | 112 | // Check values in order to avoid going beyond servomotor limits |
Overdrivr | 0:c5e974040f21 | 113 | if(value > 1.f) |
Overdrivr | 0:c5e974040f21 | 114 | value = 1.f; |
Overdrivr | 0:c5e974040f21 | 115 | if(value < -1.f) |
Overdrivr | 0:c5e974040f21 | 116 | value = -1.f; |
Overdrivr | 0:c5e974040f21 | 117 | carState->direction = value; |
Overdrivr | 0:c5e974040f21 | 118 | } |
Overdrivr | 0:c5e974040f21 | 119 | } |
Overdrivr | 1:5a07069e17b6 | 120 | // Idem for throttle |
Overdrivr | 0:c5e974040f21 | 121 | else if(strcmp(msg->topic,"throttle") == 0) |
Overdrivr | 0:c5e974040f21 | 122 | { |
Overdrivr | 0:c5e974040f21 | 123 | if(emplace_f32(msg,&value)) |
Overdrivr | 0:c5e974040f21 | 124 | { |
Overdrivr | 0:c5e974040f21 | 125 | if(value > 1.f) |
Overdrivr | 0:c5e974040f21 | 126 | value = 1.f; |
Overdrivr | 0:c5e974040f21 | 127 | if(value < -1.f) |
Overdrivr | 0:c5e974040f21 | 128 | value = -1.f; |
Overdrivr | 0:c5e974040f21 | 129 | carState->throttle = value; |
Overdrivr | 0:c5e974040f21 | 130 | } |
Overdrivr | 0:c5e974040f21 | 131 | } |
Overdrivr | 0:c5e974040f21 | 132 | } |