/* * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv * An IR detector/demodulator must be connected to the input RECV_PIN. * Version 0.1 July, 2009 * Copyright 2009 Ken Shirriff * http://arcfn.com */ #include #include namespace Infared { #define RECV_PIN 2 struct { } ir_map; #define NO_INPUT 0x00 #define ESTOP 0xFFF807 #define STOP 0xFF32CD #define UP 0xFF0AF5 #define LEFT 0xFF22DD #define RIGHT 0xFF1AE5 #define DOWN 0xFFF00F #define UP_LEFT 0xFF12ED #define UP_RIGHT 0xFF2AD5 #define DOWN_LEFT 0xFFE01F #define DOWN_RIGHT 0xFF9A65 #pragma region math inline void lerp(float &from, const float to, const float weight) { from = from + (to - from) * weight; } inline float lerpr(const float from, const float to, const float weight) { return from + (to - from) * weight; } static int clamp(long value, long minv, long maxv) { if (value < minv) return minv; else if (value > maxv) return maxv; return value; } void kinda_round(float &n) { if (n > .9) n = 1; else if (n < -.9) n = -1; else if (n > -.1 and n < .1) n = 0; } inline int8_t mult(const float n) { return round(clamp(n * 100, -100, 100)); } #pragma endregion int8_t motors[2] = {0, 0}; void map(const unsigned long cmd) { static float forces = 0, torque = 0; const float large_weight = .8, weight = .5, low_weight = .3, speed = 1; switch (cmd) { case ESTOP: torque = 0; forces = 0; case NO_INPUT: lerp(forces, 0, large_weight); lerp(torque, 0, large_weight); break; case UP: lerp(forces, +speed, weight); break; case LEFT: lerp(torque, +speed, weight); break; case RIGHT: lerp(torque, -speed, weight); break; case UP_LEFT: lerp(forces, +speed, low_weight); lerp(torque, -speed, low_weight); break; case UP_RIGHT: lerp(forces, +speed, low_weight); lerp(torque, +speed, low_weight); break; case DOWN: lerp(forces, -speed, weight); break; case DOWN_LEFT: lerp(forces, -speed, low_weight); lerp(torque, -speed / 2, low_weight); break; case DOWN_RIGHT: lerp(forces, -speed, low_weight); lerp(torque, +speed / 2, low_weight); break; default: break; } kinda_round(forces); kinda_round(torque); const float turn_amount = abs(torque) / 2.5; const int8_t a = mult(lerpr(forces, torque, turn_amount)), b = mult(lerpr(forces, -torque, turn_amount)); if (forces > 0) { motors[0] = a; motors[1] = b; } else { motors[1] = a; motors[0] = b; } } IRrecv irrecv(RECV_PIN); decode_results results; unsigned long last_result_time = 0, last_real_result = 0; void begin() { Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver } void loop() { if (irrecv.decode(&results)) { if (results.value == REPEAT) results.value = last_real_result; else last_real_result = results.value; map(results.value); last_result_time = millis(); irrecv.resume(); } else if (not(motors[0] == 0 and motors[1] == 0) and millis() - last_result_time > 200) // no results in a while (.2 seconds), lerpit down map(NO_INPUT); } inline int8_t motor_a() { return motors[0]; } inline int8_t motor_b() { return motors[1]; } } // namespace Infared