
library for controlling tv remote with gestures
Dependencies: HCSR04 SI1143 command mbed-rtos mbed
main.cpp@0:35878487eafe, 2015-12-08 (annotated)
- Committer:
- cardenb
- Date:
- Tue Dec 08 03:10:08 2015 +0000
- Revision:
- 0:35878487eafe
library for controlling tv remote with mbed and gesture sensors
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
cardenb | 0:35878487eafe | 1 | #define DIST_MAX 40 // Maximum distance in cm, anything above is ignored. |
cardenb | 0:35878487eafe | 2 | // Threshold for up/down commands. |
cardenb | 0:35878487eafe | 3 | // If higher, command is "up". If lower, "down". |
cardenb | 0:35878487eafe | 4 | #define DIST_THRES 20 |
cardenb | 0:35878487eafe | 5 | |
cardenb | 0:35878487eafe | 6 | #include "mbed.h" |
cardenb | 0:35878487eafe | 7 | #include "rtos.h" |
cardenb | 0:35878487eafe | 8 | #include "hcsr04.h" |
cardenb | 0:35878487eafe | 9 | #include "SI1143.h" |
cardenb | 0:35878487eafe | 10 | #include "command.h" |
cardenb | 0:35878487eafe | 11 | |
cardenb | 0:35878487eafe | 12 | Serial pc(USBTX, USBRX); // tx, rx |
cardenb | 0:35878487eafe | 13 | HCSR04 usensor(p7, p6); |
cardenb | 0:35878487eafe | 14 | SI1143 sensor(p28, p27); |
cardenb | 0:35878487eafe | 15 | |
cardenb | 0:35878487eafe | 16 | DigitalOut l1(LED1); |
cardenb | 0:35878487eafe | 17 | DigitalOut l2(LED2); |
cardenb | 0:35878487eafe | 18 | DigitalOut l3(LED3); |
cardenb | 0:35878487eafe | 19 | DigitalOut l4(LED4); |
cardenb | 0:35878487eafe | 20 | |
cardenb | 0:35878487eafe | 21 | int value; |
cardenb | 0:35878487eafe | 22 | |
cardenb | 0:35878487eafe | 23 | unsigned int dist; |
cardenb | 0:35878487eafe | 24 | int sense1, sense2, sense3; |
cardenb | 0:35878487eafe | 25 | |
cardenb | 0:35878487eafe | 26 | const float period = 1.0; |
cardenb | 0:35878487eafe | 27 | const float power_execute_count = 3.0 / period; |
cardenb | 0:35878487eafe | 28 | float power_count = 0; |
cardenb | 0:35878487eafe | 29 | Mutex led_mut; |
cardenb | 0:35878487eafe | 30 | Mutex ir_mut; |
cardenb | 0:35878487eafe | 31 | |
cardenb | 0:35878487eafe | 32 | bool flag = false; |
cardenb | 0:35878487eafe | 33 | |
cardenb | 0:35878487eafe | 34 | const int num_commands = 5; |
cardenb | 0:35878487eafe | 35 | enum COMMANDS { |
cardenb | 0:35878487eafe | 36 | POWER_COM, |
cardenb | 0:35878487eafe | 37 | CHANNEL_UP, |
cardenb | 0:35878487eafe | 38 | CHANNEL_DOWN, |
cardenb | 0:35878487eafe | 39 | VOLUME_UP, |
cardenb | 0:35878487eafe | 40 | VOLUME_DOWN, |
cardenb | 0:35878487eafe | 41 | NONE, |
cardenb | 0:35878487eafe | 42 | }; |
cardenb | 0:35878487eafe | 43 | const string com_names[num_commands] = {"power", "channel up", "channel down", |
cardenb | 0:35878487eafe | 44 | "volume up", "volume down"}; |
cardenb | 0:35878487eafe | 45 | |
cardenb | 0:35878487eafe | 46 | Command coms[num_commands]; |
cardenb | 0:35878487eafe | 47 | |
cardenb | 0:35878487eafe | 48 | Ticker power_ticker; |
cardenb | 0:35878487eafe | 49 | enum MODE { |
cardenb | 0:35878487eafe | 50 | NO_MODE = 0, |
cardenb | 0:35878487eafe | 51 | CHANNEL = 1, |
cardenb | 0:35878487eafe | 52 | POWER = 2, |
cardenb | 0:35878487eafe | 53 | VOLUME = 3, |
cardenb | 0:35878487eafe | 54 | |
cardenb | 0:35878487eafe | 55 | }; |
cardenb | 0:35878487eafe | 56 | |
cardenb | 0:35878487eafe | 57 | enum DIRECTION { |
cardenb | 0:35878487eafe | 58 | NO_DIR, |
cardenb | 0:35878487eafe | 59 | UP, |
cardenb | 0:35878487eafe | 60 | DOWN, |
cardenb | 0:35878487eafe | 61 | }; |
cardenb | 0:35878487eafe | 62 | DIRECTION dir = NO_DIR; |
cardenb | 0:35878487eafe | 63 | MODE mode = NO_MODE; |
cardenb | 0:35878487eafe | 64 | |
cardenb | 0:35878487eafe | 65 | void set_led(uint8_t led_vals) { |
cardenb | 0:35878487eafe | 66 | led_mut.lock(); |
cardenb | 0:35878487eafe | 67 | l1 = led_vals & 1; |
cardenb | 0:35878487eafe | 68 | led_vals = led_vals >> 1; |
cardenb | 0:35878487eafe | 69 | l2 = led_vals & 1; |
cardenb | 0:35878487eafe | 70 | led_vals = led_vals >> 1; |
cardenb | 0:35878487eafe | 71 | l3 = led_vals & 1; |
cardenb | 0:35878487eafe | 72 | led_vals = led_vals >> 1; |
cardenb | 0:35878487eafe | 73 | l4 = led_vals & 1; |
cardenb | 0:35878487eafe | 74 | led_mut.unlock(); |
cardenb | 0:35878487eafe | 75 | } |
cardenb | 0:35878487eafe | 76 | |
cardenb | 0:35878487eafe | 77 | void ExecutePowerCommand() { |
cardenb | 0:35878487eafe | 78 | ir_mut.lock(); |
cardenb | 0:35878487eafe | 79 | coms[POWER_COM].TransmitCommand(); |
cardenb | 0:35878487eafe | 80 | ir_mut.unlock(); |
cardenb | 0:35878487eafe | 81 | mode = NO_MODE; |
cardenb | 0:35878487eafe | 82 | } |
cardenb | 0:35878487eafe | 83 | |
cardenb | 0:35878487eafe | 84 | void CheckForPower() { |
cardenb | 0:35878487eafe | 85 | if (mode == POWER) { |
cardenb | 0:35878487eafe | 86 | if (power_count == power_execute_count) { |
cardenb | 0:35878487eafe | 87 | ExecutePowerCommand(); |
cardenb | 0:35878487eafe | 88 | } |
cardenb | 0:35878487eafe | 89 | ++power_count; |
cardenb | 0:35878487eafe | 90 | } else { |
cardenb | 0:35878487eafe | 91 | power_count = 0; |
cardenb | 0:35878487eafe | 92 | set_led(0); |
cardenb | 0:35878487eafe | 93 | } |
cardenb | 0:35878487eafe | 94 | } |
cardenb | 0:35878487eafe | 95 | |
cardenb | 0:35878487eafe | 96 | int handleDist(int dist) { |
cardenb | 0:35878487eafe | 97 | if (dist > DIST_THRES) { |
cardenb | 0:35878487eafe | 98 | return 1; |
cardenb | 0:35878487eafe | 99 | } else { |
cardenb | 0:35878487eafe | 100 | return -1; |
cardenb | 0:35878487eafe | 101 | } |
cardenb | 0:35878487eafe | 102 | } |
cardenb | 0:35878487eafe | 103 | |
cardenb | 0:35878487eafe | 104 | void parallax_thread(void const *args) { |
cardenb | 0:35878487eafe | 105 | int sen = 50; |
cardenb | 0:35878487eafe | 106 | while (true) { |
cardenb | 0:35878487eafe | 107 | sense1 = sensor.get_ps1(1); |
cardenb | 0:35878487eafe | 108 | sense2 = sensor.get_ps2(1); |
cardenb | 0:35878487eafe | 109 | sense3 = sensor.get_ps3(1); |
cardenb | 0:35878487eafe | 110 | |
cardenb | 0:35878487eafe | 111 | |
cardenb | 0:35878487eafe | 112 | if (sense1 > sen || sense2 > sen || sense3 > sen) { |
cardenb | 0:35878487eafe | 113 | if (sense1 > sense2 && sense1 > sense3) { |
cardenb | 0:35878487eafe | 114 | set_led(1); |
cardenb | 0:35878487eafe | 115 | mode = CHANNEL; |
cardenb | 0:35878487eafe | 116 | } |
cardenb | 0:35878487eafe | 117 | |
cardenb | 0:35878487eafe | 118 | else if (sense2 > sense1 && sense2 > sense3) { |
cardenb | 0:35878487eafe | 119 | mode = POWER; |
cardenb | 0:35878487eafe | 120 | set_led(3); |
cardenb | 0:35878487eafe | 121 | } |
cardenb | 0:35878487eafe | 122 | |
cardenb | 0:35878487eafe | 123 | else if (sense3 > sense1 && sense3 > sense2) { |
cardenb | 0:35878487eafe | 124 | set_led(2); |
cardenb | 0:35878487eafe | 125 | mode = VOLUME; |
cardenb | 0:35878487eafe | 126 | } |
cardenb | 0:35878487eafe | 127 | } else { |
cardenb | 0:35878487eafe | 128 | if( mode == POWER) { |
cardenb | 0:35878487eafe | 129 | mode = NO_MODE; |
cardenb | 0:35878487eafe | 130 | } |
cardenb | 0:35878487eafe | 131 | } |
cardenb | 0:35878487eafe | 132 | Thread::wait(300); |
cardenb | 0:35878487eafe | 133 | } |
cardenb | 0:35878487eafe | 134 | } |
cardenb | 0:35878487eafe | 135 | |
cardenb | 0:35878487eafe | 136 | void ultrasound_thread(void const *args) { |
cardenb | 0:35878487eafe | 137 | while (true) { |
cardenb | 0:35878487eafe | 138 | usensor.start(); |
cardenb | 0:35878487eafe | 139 | dist = usensor.get_dist_cm(); |
cardenb | 0:35878487eafe | 140 | if (dist < DIST_MAX) { |
cardenb | 0:35878487eafe | 141 | int d = 500; // first delay is longer for single volume change |
cardenb | 0:35878487eafe | 142 | |
cardenb | 0:35878487eafe | 143 | while (dist < DIST_MAX) { |
cardenb | 0:35878487eafe | 144 | value = handleDist(dist); // is up or down? |
cardenb | 0:35878487eafe | 145 | // doIR(CONTROL_VOL, value); // fire off IR signal |
cardenb | 0:35878487eafe | 146 | if (value == 1) { |
cardenb | 0:35878487eafe | 147 | set_led(8); |
cardenb | 0:35878487eafe | 148 | dir = UP; |
cardenb | 0:35878487eafe | 149 | Thread::wait(100); |
cardenb | 0:35878487eafe | 150 | set_led(0); |
cardenb | 0:35878487eafe | 151 | } else { |
cardenb | 0:35878487eafe | 152 | set_led(4); |
cardenb | 0:35878487eafe | 153 | dir = DOWN; |
cardenb | 0:35878487eafe | 154 | Thread::wait(100); |
cardenb | 0:35878487eafe | 155 | set_led(0); |
cardenb | 0:35878487eafe | 156 | } |
cardenb | 0:35878487eafe | 157 | usensor.start(); |
cardenb | 0:35878487eafe | 158 | Thread::wait(d); // wait |
cardenb | 0:35878487eafe | 159 | dist = usensor.get_dist_cm(); // check for hand again |
cardenb | 0:35878487eafe | 160 | d = 100; // delays are shorter for quick multiple volume adjustment |
cardenb | 0:35878487eafe | 161 | } |
cardenb | 0:35878487eafe | 162 | // this stops accidental channel change after volume adjustment |
cardenb | 0:35878487eafe | 163 | Thread::wait(500); |
cardenb | 0:35878487eafe | 164 | } else { |
cardenb | 0:35878487eafe | 165 | dir = NO_DIR; |
cardenb | 0:35878487eafe | 166 | } |
cardenb | 0:35878487eafe | 167 | Thread::wait(50); // Short enough to detect all swipes. |
cardenb | 0:35878487eafe | 168 | } |
cardenb | 0:35878487eafe | 169 | } |
cardenb | 0:35878487eafe | 170 | |
cardenb | 0:35878487eafe | 171 | void transmit_thread(const void* args) { |
cardenb | 0:35878487eafe | 172 | while(true) { |
cardenb | 0:35878487eafe | 173 | COMMANDS com = NONE; |
cardenb | 0:35878487eafe | 174 | if(mode == VOLUME && dir == UP) { |
cardenb | 0:35878487eafe | 175 | com = VOLUME_UP; |
cardenb | 0:35878487eafe | 176 | } else if(mode == VOLUME && dir == DOWN) { |
cardenb | 0:35878487eafe | 177 | com = VOLUME_DOWN; |
cardenb | 0:35878487eafe | 178 | } else if(mode == CHANNEL && dir == UP) { |
cardenb | 0:35878487eafe | 179 | com = CHANNEL_UP; |
cardenb | 0:35878487eafe | 180 | } else if(mode == CHANNEL && dir == DOWN) { |
cardenb | 0:35878487eafe | 181 | com = CHANNEL_DOWN; |
cardenb | 0:35878487eafe | 182 | } else { |
cardenb | 0:35878487eafe | 183 | com = NONE; |
cardenb | 0:35878487eafe | 184 | } |
cardenb | 0:35878487eafe | 185 | if(com != NONE) { |
cardenb | 0:35878487eafe | 186 | ir_mut.lock(); |
cardenb | 0:35878487eafe | 187 | coms[com].TransmitCommand(); |
cardenb | 0:35878487eafe | 188 | ir_mut.unlock(); |
cardenb | 0:35878487eafe | 189 | } |
cardenb | 0:35878487eafe | 190 | Thread::wait(10); |
cardenb | 0:35878487eafe | 191 | } |
cardenb | 0:35878487eafe | 192 | } |
cardenb | 0:35878487eafe | 193 | |
cardenb | 0:35878487eafe | 194 | void setup(void) { |
cardenb | 0:35878487eafe | 195 | // Serial.begin(9600); |
cardenb | 0:35878487eafe | 196 | // device.baud(2400); |
cardenb | 0:35878487eafe | 197 | pc.printf("Ready to decode IR!\r\n"); |
cardenb | 0:35878487eafe | 198 | |
cardenb | 0:35878487eafe | 199 | for( int i = 0; i < num_commands; ++i) { |
cardenb | 0:35878487eafe | 200 | coms[i] = Command(com_names[i]); |
cardenb | 0:35878487eafe | 201 | coms[i].LearnCommand(pc); |
cardenb | 0:35878487eafe | 202 | } |
cardenb | 0:35878487eafe | 203 | // Setup the baseline |
cardenb | 0:35878487eafe | 204 | sensor.bias(1, 5); |
cardenb | 0:35878487eafe | 205 | wait(1); |
cardenb | 0:35878487eafe | 206 | } |
cardenb | 0:35878487eafe | 207 | |
cardenb | 0:35878487eafe | 208 | int main() { |
cardenb | 0:35878487eafe | 209 | |
cardenb | 0:35878487eafe | 210 | setup(); |
cardenb | 0:35878487eafe | 211 | power_ticker.attach(&CheckForPower, period); |
cardenb | 0:35878487eafe | 212 | set_led(0); |
cardenb | 0:35878487eafe | 213 | |
cardenb | 0:35878487eafe | 214 | Thread mode_checker(parallax_thread); |
cardenb | 0:35878487eafe | 215 | Thread range_checker(ultrasound_thread); |
cardenb | 0:35878487eafe | 216 | Thread transmit_checker(transmit_thread); |
cardenb | 0:35878487eafe | 217 | |
cardenb | 0:35878487eafe | 218 | while (1) { |
cardenb | 0:35878487eafe | 219 | // spin. |
cardenb | 0:35878487eafe | 220 | } |
cardenb | 0:35878487eafe | 221 | } |