library for controlling tv remote with gestures

Dependencies:   HCSR04 SI1143 command mbed-rtos mbed

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?

UserRevisionLine numberNew 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 }