diff --git a/platformio.ini b/platformio.ini index 7294854..700d09c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,4 +17,5 @@ lib_deps = adafruit/Adafruit NeoPixel@^1.10.1 gitlab-simple-serial-protocol/SimpleSerialProtocol@^2.4.0 ivanseidel/LinkedList@0.0.0-alpha+sha.dac3874d28 + thomasfredericks/Bounce2@^2.70 src_filter = +<*> -<.git/> -<.svn/> - - - - - diff --git a/src/main.cpp b/src/main.cpp index 854ffc3..c4e161f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,19 +10,19 @@ /*-------- Pin definitions --------*/ // Vertical motor top -#define VERT_UP_PWM 3 -#define VERT_UP_AIN2 4 -#define VERT_UP_AIN1 5 +#define VERT_UP_PWM 3 +#define VERT_UP_AIN2 4 +#define VERT_UP_AIN1 5 // Vertical motor bottom -#define VERT_DOWN_PWM 9 -#define VERT_DOWN_AIN2 7 -#define VERT_DOWN_AIN1 8 +#define VERT_DOWN_PWM 9 +#define VERT_DOWN_AIN2 7 +#define VERT_DOWN_AIN1 8 // Horizontal motor left -#define HORZ_LEFT_PWM 24 -#define HORZ_LEFT_AIN2 25 -#define HORZ_LEFT_AIN1 26 +#define HORZ_LEFT_PWM 24 +#define HORZ_LEFT_AIN2 25 +#define HORZ_LEFT_AIN1 26 // Horizontal motor right #define HORZ_RIGHT_PWM 29 @@ -41,11 +42,21 @@ #define HORZ_CNT_OUTER 35 // Lights -#define LED_FRONT 41 +#define LED_FRONT 41 #define LED_COUNT_FRONT 26 -#define LED_BACK 14 -#define LED_COUNT_BACK 72 +#define LED_BACK 14 +#define LED_COUNT_BACK 72 + +// Buttons +#define BTN_LED_BLUE 21 +#define BTN_BLUE 20 +#define BTN_LED_RED 17 +#define BTN_RED 16 +#define BTN_LED_GREEN 23 +#define BTN_GREEN 22 +#define BTN_LED_YELLOW 19 +#define BTN_YELLOW 18 /*-------- Constants --------*/ @@ -79,15 +90,16 @@ State* S40 = sm.addState(&state_serial_com); State* SER = sm.addState(&state_error); // Heartbeat blink interval constants -#define WAIT_ON_MS 200 // Blink when waiting for Serial -#define WAIT_OFF_MS 1800 +#define WAIT_ON_MS 200 // Blink when waiting for Serial +#define WAIT_OFF_MS 1800 -#define ERROR_ON_MS 1000 // Blink when in error state -#define ERROR_OFF_MS 500 +#define ERROR_ON_MS 1000 // Blink when in error state +#define ERROR_OFF_MS 500 /*-------- Variables --------*/ // Heartbeat blinker timer elapsedMillis blink_time; +bool blink_status; // boolean to hold led status (needed to let more than one led blink) // Statemachine booleans bool handshake_complete; @@ -111,6 +123,12 @@ Motor horz_right(HORZ_RIGHT_PWM, HORZ_RIGHT_AIN1, HORZ_RIGHT_AIN2); Adafruit_NeoPixel led_front(LED_COUNT_FRONT, LED_FRONT, NEO_GBRW + NEO_KHZ800); Adafruit_NeoPixel led_back(LED_COUNT_BACK, LED_BACK, NEO_GBRW + NEO_KHZ800); +// Buttons +Bounce2::Button btn_blue = Bounce2::Button(); +Bounce2::Button btn_red = Bounce2::Button(); +Bounce2::Button btn_yellow = Bounce2::Button(); +Bounce2::Button btn_green = Bounce2::Button(); + /*-------- Serial Communication --------*/ // Error handler void serial_on_error(uint8_t errorNum); @@ -169,15 +187,20 @@ void vert_count() { * @param on_interval time LED stays on in millis * @param off_interval time LED is off in millis */ -void blink_builtin(uint32_t on_interval, uint32_t off_interval) { - if (digitalRead(LED_BUILTIN)) { +template +void blink(int (&led_pin)[N], uint32_t on_interval, uint32_t off_interval) { + if (blink_status) { if (blink_time >= on_interval) { - digitalWrite(LED_BUILTIN, LOW); + blink_status = false; + for (const int &led : led_pin) + digitalWrite(led, LOW); blink_time = blink_time - on_interval; } } else { if (blink_time >= off_interval) { - digitalWrite(LED_BUILTIN, HIGH); + blink_status = true; + for (const int &led : led_pin) + digitalWrite(led, HIGH); blink_time = blink_time - off_interval; } } @@ -249,6 +272,12 @@ void serial_received() { ssp.writeEot(); } +void serial_received(uint8_t response) { + ssp.writeCommand(RECEIVED); + ssp.writeUnsignedInt8(response); + ssp.writeEot(); +} + /** * @brief Helper function to calculate transition between two colors * @@ -290,11 +319,10 @@ void serial_led_fade(Adafruit_NeoPixel &led) { Serial.printf("r = %i, g = %i, b = %i, w = %i \n", from_R, from_G, from_B, from_W); - uint32_t start_time = millis(); - uint32_t end_time = start_time + time_ms; + elapsedMillis t = 0; - while (millis() < end_time) { - float_t perc = (float) (millis() - start_time) / (float) time_ms; + while (t < time_ms) { + float_t perc = (float) t / (float) time_ms; uint32_t color = led.Color(color_value(from_R, to_R, perc), color_value(from_G, to_G, perc), color_value(from_B, to_B, perc), @@ -435,8 +463,30 @@ void serial_motor_h() { * */ void serial_record() { + uint32_t timeout = ssp.readUnsignedInt32(); ssp.readEot(); - Serial.println("Received RECORD"); + Serial.printf("Received RECORD, timeout %d\n", timeout); + + elapsedMillis time = 0; + + // TODO reset leds + digitalWrite(LED_BUILTIN, HIGH); + blink_status = true; + + while (time < timeout) { + // do nothing until t - 5s + btn_red.update(); + + if (btn_red.isPressed()) + break; + + if ((timeout - time) < 5000) { + int leds[] = { LED_BUILTIN }; + blink(leds, 500, 500); + } + } + digitalWrite(LED_BUILTIN, LOW); + serial_received(); } @@ -448,6 +498,7 @@ void serial_rewind() { ssp.readEot(); Serial.println("Received REWIND"); zero_motor(vert_up, vert_down, VERT_END_INNER, VERT_END_OUTER); + // TODO enable zero_motor(hor_left, hor_right, HOR_END_OUTER, HOR_END_INTER); serial_received(); } @@ -456,9 +507,49 @@ void serial_rewind() { * */ void serial_userinteract() { + char bt = ssp.readByte(); + uint32_t timeout = ssp.readUnsignedInt32(); ssp.readEot(); Serial.println("Received USER_INTERACT"); - serial_received(); + + u_int8_t blue = (bt & 0x1); + u_int8_t red = (bt & 0x2) >> 1; + u_int8_t yellow = (bt & 0x4) >> 2; + u_int8_t green = (bt & 0x8) >> 3; + + Serial.printf("Blink byte: B=%d, R=%d, Y=%d, G=%d; Timeout=%d\n", blue, red, yellow, green, timeout); + elapsedMillis t = 0; + const u_int8_t n_leds = blue + red + yellow + green; + int leds[n_leds]; + + // TODO add leds + // for (int i = 0; i < n_leds; i++) { + // leds[i] = + // } + // {LED_BUILTIN, BTN_LED_BLUE, BTN_LED_RED, BTN_LED_YELLOW, BTN_LED_GREEN}; + // for (const int &led : leds) { + // digitalWrite(led, LOW); + // } + + uint8_t btn_pressed = 0; + while (t < timeout) + { + // blink(leds, 500, 500); + // TODO use bitmask + btn_blue.update(); + btn_red.update(); + btn_yellow.update(); + btn_green.update(); + + btn_pressed = (blue && btn_blue.pressed() ? 0x1 : 0) | + (red && btn_red.pressed() ? 0x2 : 0) | + (yellow && btn_yellow.pressed() ? 0x4 : 0) | + (green && btn_green.pressed() ? 0x8 : 0); + + if (btn_pressed > 0) break; + } + + serial_received(btn_pressed); } /** @@ -498,12 +589,28 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); + btn_blue.attach(BTN_BLUE, INPUT_PULLUP); + btn_red.attach(BTN_RED, INPUT_PULLUP); + btn_yellow.attach(BTN_YELLOW, INPUT_PULLUP); + btn_green.attach(BTN_GREEN, INPUT_PULLUP); + + btn_blue.interval(5); + btn_red.interval(5); + btn_yellow.interval(5); + btn_green.interval(5); + + btn_blue.setPressedState(LOW); + btn_red.setPressedState(LOW); + btn_yellow.setPressedState(LOW); + btn_green.setPressedState(LOW); + hor_pos = 0; vert_pos = 0; hor_lastchange = 0; vert_lastchange = 0; blink_time = 0; + blink_status = false; vert_up.setup(); vert_down.setup(); @@ -606,9 +713,11 @@ void state_wait_serial() { Serial.println("State Waiting for Serial Handshake."); digitalWrite(LED_BUILTIN, LOW); + blink_status = false; } - blink_builtin(WAIT_ON_MS, WAIT_OFF_MS); + int leds[] = {LED_BUILTIN}; + blink(leds, WAIT_ON_MS, WAIT_OFF_MS); ssp.loop(); } @@ -632,9 +741,11 @@ void state_serial_com() { void state_error() { if (sm.executeOnce) { Serial.println("State Error."); + blink_status = digitalRead(LED_BUILTIN); } - blink_builtin(ERROR_ON_MS, ERROR_OFF_MS); + int leds[] = { LED_BUILTIN }; + blink(leds, ERROR_ON_MS, ERROR_OFF_MS); } /**