library for controlling tv remote with gestures
Dependencies: HCSR04 SI1143 command mbed-rtos mbed
main.cpp
- Committer:
- cardenb
- Date:
- 2015-12-08
- Revision:
- 0:35878487eafe
File content as of revision 0:35878487eafe:
#define DIST_MAX 40 // Maximum distance in cm, anything above is ignored. // Threshold for up/down commands. // If higher, command is "up". If lower, "down". #define DIST_THRES 20 #include "mbed.h" #include "rtos.h" #include "hcsr04.h" #include "SI1143.h" #include "command.h" Serial pc(USBTX, USBRX); // tx, rx HCSR04 usensor(p7, p6); SI1143 sensor(p28, p27); DigitalOut l1(LED1); DigitalOut l2(LED2); DigitalOut l3(LED3); DigitalOut l4(LED4); int value; unsigned int dist; int sense1, sense2, sense3; const float period = 1.0; const float power_execute_count = 3.0 / period; float power_count = 0; Mutex led_mut; Mutex ir_mut; bool flag = false; const int num_commands = 5; enum COMMANDS { POWER_COM, CHANNEL_UP, CHANNEL_DOWN, VOLUME_UP, VOLUME_DOWN, NONE, }; const string com_names[num_commands] = {"power", "channel up", "channel down", "volume up", "volume down"}; Command coms[num_commands]; Ticker power_ticker; enum MODE { NO_MODE = 0, CHANNEL = 1, POWER = 2, VOLUME = 3, }; enum DIRECTION { NO_DIR, UP, DOWN, }; DIRECTION dir = NO_DIR; MODE mode = NO_MODE; void set_led(uint8_t led_vals) { led_mut.lock(); l1 = led_vals & 1; led_vals = led_vals >> 1; l2 = led_vals & 1; led_vals = led_vals >> 1; l3 = led_vals & 1; led_vals = led_vals >> 1; l4 = led_vals & 1; led_mut.unlock(); } void ExecutePowerCommand() { ir_mut.lock(); coms[POWER_COM].TransmitCommand(); ir_mut.unlock(); mode = NO_MODE; } void CheckForPower() { if (mode == POWER) { if (power_count == power_execute_count) { ExecutePowerCommand(); } ++power_count; } else { power_count = 0; set_led(0); } } int handleDist(int dist) { if (dist > DIST_THRES) { return 1; } else { return -1; } } void parallax_thread(void const *args) { int sen = 50; while (true) { sense1 = sensor.get_ps1(1); sense2 = sensor.get_ps2(1); sense3 = sensor.get_ps3(1); if (sense1 > sen || sense2 > sen || sense3 > sen) { if (sense1 > sense2 && sense1 > sense3) { set_led(1); mode = CHANNEL; } else if (sense2 > sense1 && sense2 > sense3) { mode = POWER; set_led(3); } else if (sense3 > sense1 && sense3 > sense2) { set_led(2); mode = VOLUME; } } else { if( mode == POWER) { mode = NO_MODE; } } Thread::wait(300); } } void ultrasound_thread(void const *args) { while (true) { usensor.start(); dist = usensor.get_dist_cm(); if (dist < DIST_MAX) { int d = 500; // first delay is longer for single volume change while (dist < DIST_MAX) { value = handleDist(dist); // is up or down? // doIR(CONTROL_VOL, value); // fire off IR signal if (value == 1) { set_led(8); dir = UP; Thread::wait(100); set_led(0); } else { set_led(4); dir = DOWN; Thread::wait(100); set_led(0); } usensor.start(); Thread::wait(d); // wait dist = usensor.get_dist_cm(); // check for hand again d = 100; // delays are shorter for quick multiple volume adjustment } // this stops accidental channel change after volume adjustment Thread::wait(500); } else { dir = NO_DIR; } Thread::wait(50); // Short enough to detect all swipes. } } void transmit_thread(const void* args) { while(true) { COMMANDS com = NONE; if(mode == VOLUME && dir == UP) { com = VOLUME_UP; } else if(mode == VOLUME && dir == DOWN) { com = VOLUME_DOWN; } else if(mode == CHANNEL && dir == UP) { com = CHANNEL_UP; } else if(mode == CHANNEL && dir == DOWN) { com = CHANNEL_DOWN; } else { com = NONE; } if(com != NONE) { ir_mut.lock(); coms[com].TransmitCommand(); ir_mut.unlock(); } Thread::wait(10); } } void setup(void) { // Serial.begin(9600); // device.baud(2400); pc.printf("Ready to decode IR!\r\n"); for( int i = 0; i < num_commands; ++i) { coms[i] = Command(com_names[i]); coms[i].LearnCommand(pc); } // Setup the baseline sensor.bias(1, 5); wait(1); } int main() { setup(); power_ticker.attach(&CheckForPower, period); set_led(0); Thread mode_checker(parallax_thread); Thread range_checker(ultrasound_thread); Thread transmit_checker(transmit_thread); while (1) { // spin. } }