diff --git a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp index 9c8afac..d170a44 100644 --- a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp +++ b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp @@ -45,7 +45,15 @@ void DFRobot_ST7687S_Widgets::PasDisplay(int value) { print(value); } -void DFRobot_ST7687S_Widgets::Tacho() { +void DFRobot_ST7687S_Widgets::drawNormalTacho() { + Tacho(TACHO_DEFAULT_COLOR); +} + +void DFRobot_ST7687S_Widgets::drawOffRoadTacho() { + Tacho(TACHO_OFFROAD_COLOR); +} + +void DFRobot_ST7687S_Widgets::Tacho( int color) { int i = 0; int j = 0; int i2 = 0; @@ -53,12 +61,12 @@ void DFRobot_ST7687S_Widgets::Tacho() { bool thick_line = true; - fillCircle(0, 0, 3, DISPLAY_CYAN); + fillCircle(0, 0, 3, color); for (int p = TACHO_OPEN; p < TACHO_CLOSE; p++) { i = TACHO_RADIUS * (cos(PI * p / 2000)); j = TACHO_RADIUS * (sin(PI * p / 2000)); - drawPixel(i, j, DISPLAY_CYAN); + drawPixel(i, j, color); } for (int p = TACHO_OPEN; p < TACHO_CLOSE; p = p + 230) { @@ -74,7 +82,7 @@ void DFRobot_ST7687S_Widgets::Tacho() { setLineWidth(1); thick_line = true; } - drawLine(i, j, i2, j2, DISPLAY_CYAN); + drawLine(i, j, i2, j2, color); } } diff --git a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h index f92b715..20359ba 100644 --- a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h +++ b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h @@ -4,7 +4,7 @@ #define TACHO_RADIUS 60 #define TACHO_DEFAULT_COLOR DISPLAY_CYAN -#define TACHO_BOOST_COLOR DISPLAY_RED +#define TACHO_OFFROAD_COLOR DISPLAY_RED #define TACHO_LABEL_COLOR DISPLAY_WHITE #define TACHO_OPEN 1500 #define TACHO_CLOSE TACHO_OPEN + 2995 @@ -13,7 +13,7 @@ #define TACHO_NEEDLE_WIDTH 3 #define TACHO_MAX_SPEED 65 -#define AMPMETER_OPEN 2000 +#define AMPMETER_OPEN 1000 #define AMPMETER_CLOSE TACHO_OPEN + 2000 #define AMPMETER_RADIUS 64 #define AMPMETER_MAX 100 @@ -27,8 +27,9 @@ class DFRobot_ST7687S_Widgets : public DFRobot_ST7687S_Latch { public: DFRobot_ST7687S_Widgets (uint8_t pin_cs, uint8_t pin_cd, uint8_t pin_wr, uint8_t pin_rck); - void Tacho(); void AmpMeter(int value); + void drawNormalTacho(); + void drawOffRoadTacho(); void TachoLabels(); void TachoNeedle(uint8_t speed); void drawLine2(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); @@ -37,6 +38,7 @@ class DFRobot_ST7687S_Widgets : public DFRobot_ST7687S_Latch { private: void labelText(int16_t* pX, int16_t* pY, const char* ch); unsigned int rainbow(byte value); + void Tacho(int color); bool labels_written; int8_t old_needle_pos[]; diff --git a/src/config.h b/src/config.h index 20bf680..a6b5670 100644 --- a/src/config.h +++ b/src/config.h @@ -18,4 +18,11 @@ #define TOUCH_BUTTON 12 #define TOUCH_THRESHOLD 15 +#define BIKE_MODE_NORMAL 1 +#define BIKE_MODE_OFFROAD 2 + +#define TOUCH_CHECK_DURATION 100 +#define STATUS_DURATION 250 +#define OFFROAD_WINDOW 30 + #define BTN_COOLDOWN 50 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fa6587a..c5345b9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "BLEDevice.h" @@ -12,7 +13,15 @@ DFRobot_ST7687S_Widgets tft_right(TFT_RIGHT_PIN_CS, TFT_RIGHT_PIN_RS, TFT_RIGHT_ bool doConnect = false; bool connected = false; bool doScan = false; +bool offroad_deactivated = false; +bool offroad_touch_released = false; + int btn_checked = millis(); +int touch_started = 0; +int init_done = 0; +int last_status = 0; +int bike_mode = BIKE_MODE_NORMAL; + static BLEUUID serviceUUID("0000ffe0-0000-1000-8000-00805f9b34fb"); static BLEUUID charUUID("0000ffe1-0000-1000-8000-00805f9b34fb"); static BLERemoteCharacteristic* pRemoteCharacteristic; @@ -20,13 +29,13 @@ static BLEAdvertisedDevice* myDevice; // TODO: check request length // uint8_t status_request[] = { 0x66, 0x41, 0x02, 0x05, 0x00, 0xAE, 0x00, 0x00, 0x30, 0xDD, 0xFC, 0x3F, 0xF0, 0xDC, 0xFC, 0x3F, 0x66, 0x10, 0x94, 0xEE, 0x13, 0x00, 0x00, 0x00 }; -uint8_t old_speed = 0; +//uint8_t old_speed = 0; uint8_t status_request[] = { 0x66, 0x41, 0x02, 0x05, 0x00, 0xAE }; uint8_t last_bike_status[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t bike_status[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -float calc_speed() { - int rmp = (int) (60.0d / (((double) ((bike_status[2] * 255) + bike_status[3])) / 1000.0d)); +float calc_speed(uint8_t param_0, uint8_t param_1) { + int rmp = (int) (60.0d / (((double) ((param_0 * 255) + param_1)) / 1000.0d)); uint8_t tempSpeed = (int) ((((double) rmp) * ((((double) ((float) 27) / 39.37f)) * 3.141592653589793d) / 1000.0d) * 60.0d); return tempSpeed; } @@ -101,6 +110,43 @@ bool connectToServer() { return true; } +bool check_touch() { + if ( (touchRead(TOUCH_BUTTON) < TOUCH_THRESHOLD) && (touch_started != 0) && millis() - touch_started > TOUCH_CHECK_DURATION ) { + return true; + } + else if ( (touchRead(TOUCH_BUTTON) < TOUCH_THRESHOLD) && touch_started == 0 ) { + touch_started = millis(); + } + else if ( !(touchRead(TOUCH_BUTTON) < TOUCH_THRESHOLD) && touch_started != 0 ) { + touch_started = 0; + } + return false; +} + +void check_buttons() { + if ( (digitalRead(BTN_RIGHT_LOWER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { + btn_checked = millis(); + + if (status_request[3] > 2 ) { + status_request[3]--; + tft_right.PasDisplay((status_request[3]) - 2); + } + } + + else if ( (digitalRead(BTN_RIGHT_CENTER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { + btn_checked = millis(); + } + + else if ( (digitalRead(BTN_RIGHT_HIGHER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { + btn_checked = millis(); + + if (status_request[3] < 5 ) { + status_request[3]++; + tft_right.PasDisplay((status_request[3]) - 2); + } + } +} + void process_status() { // TODO: ERRORS OverVoltage / Undervoltage / BLE_ERROR /* @@ -114,48 +160,82 @@ void process_status() { if( ((last_bike_status[7] >> 0) & 1) != ((bike_status[7] >> 0) & 1) ) { if((bike_status[7] >> 0) & 1) { Serial.println("rbs error"); - tft_right.drawBmp(RegenBrakeFaultBMP, -30, 30, 25, 25, 1, REGENBRAKE_FAULT_COLOR); + tft_right.drawBmp(RegenBrakeFaultBMP, -30, 20, 25, 25, 1, REGENBRAKE_FAULT_COLOR); } else { - tft_right.fillRect(-30, 30, 25, 25, CBC_DISPLAY_BACKCOLOR); + tft_right.fillRect(-30, 20, 25, 25, CBC_DISPLAY_BACKCOLOR); } } if( ((last_bike_status[7] >> 1) & 1) != ((bike_status[7] >> 1) & 1) ) { if((bike_status[7] >> 1) & 1) { - tft_right.drawBmp(ThrottleFaultBMP, 5, 30, 25, 25, 1, THROTTLE_FAULT_COLOR); + tft_right.drawBmp(ThrottleFaultBMP, 5, 20, 25, 25, 1, THROTTLE_FAULT_COLOR); } else { - tft_right.fillRect(5, 30, 25, 25, CBC_DISPLAY_BACKCOLOR); + tft_right.fillRect(5, 20, 25, 25, CBC_DISPLAY_BACKCOLOR); } } + + if ( last_bike_status[3] != bike_status[3] ) { + if (bike_status[3] == 0) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery0BMP, 30, -28, 25, 50, 1, DISPLAY_RED); + } + else if (bike_status[3] == 1) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery1BMP, 30, -28, 25, 50, 1, DISPLAY_RED); + } + else if (bike_status[3] == 2) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery2BMP, 30, -28, 25, 50, 1, DISPLAY_ORANGE); + } + else if (bike_status[3] == 3) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery3BMP, 30, -28, 25, 50, 1, DISPLAY_ORANGE); + } + else if (bike_status[3] == 4) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery4BMP, 30, -28, 25, 50, 1, DISPLAY_GREEN); + } + else if (bike_status[3] == 5) { + tft_right.fillRect(30, -28, 25, 50, CBC_DISPLAY_BACKCOLOR); + tft_right.drawBmp(Battery5BMP, 30, -28, 25, 50, 1, DISPLAY_GREEN); + } + } + if ( (last_bike_status[5] != bike_status[5]) || (last_bike_status[6] != bike_status[6]) ) { + Serial.print("Speed: "); + Serial.println(calc_speed(bike_status[5], bike_status[6])); + tft_left.TachoNeedle((int) calc_speed(bike_status[5], bike_status[6])); + } } void setup() { Serial.begin(115200); + while( !(millis() > (TOUCH_CHECK_DURATION * 2)) ) { + if (check_touch()) { + Serial.println("Offroad not possible"); + offroad_deactivated = true; + } + } + pinMode(BTN_RIGHT_LOWER, INPUT); pinMode(BTN_RIGHT_CENTER, INPUT); pinMode(BTN_RIGHT_HIGHER, INPUT); tft_left.begin(ST7687S_Rotation_270); tft_left.fillScreen(CBC_DISPLAY_BACKCOLOR); - + tft_right.begin(ST7687S_Rotation_90); tft_right.fillScreen(CBC_DISPLAY_BACKCOLOR); tft_right.AmpMeter(50); tft_right.PasDisplay((status_request[3]) - 2); -// tft_right.fillRect(-30, 30, 25, 25, DISPLAY_GREEN); -// tft_right.drawBmp(RegenBrakeFaultBMP, -30, 30, 25, 25, 1, DISPLAY_ORANGE); -// tft_right.fillRect(5, 30, 25, 25, DISPLAY_GREEN); -// tft_right.drawBmp(ThrottleFaultBMP, 5, 30, 25, 25, 1, DISPLAY_ORANGE); - tft_right.drawBmp(Battery5BMP, 30, -28, 25, 50, 1, DISPLAY_GREEN); - tft_left.Tacho(); + + tft_left.drawNormalTacho(); tft_left.TachoLabels(); tft_left.TachoNeedle(35); -// tft_left.drawLine2(0 ,0, -45, -45, DISPLAY_DARKGREY); BLEDevice::init(""); BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); @@ -163,11 +243,28 @@ void setup() { pBLEScan->setWindow(449); pBLEScan->setActiveScan(true); pBLEScan->start(5, false); + + init_done = millis(); } void loop() { - if (touchRead(TOUCH_BUTTON) < TOUCH_THRESHOLD) { - Serial.println("touch detected"); + + if (check_touch()) { + if ( (bike_mode == BIKE_MODE_NORMAL) && ((millis() - init_done) < (OFFROAD_WINDOW * 1000)) && !offroad_deactivated) { + bike_mode = BIKE_MODE_OFFROAD; + tft_left.drawOffRoadTacho(); + Serial.println("switching to offroad"); + } + else if ( (bike_mode == BIKE_MODE_OFFROAD) && offroad_touch_released ) { + offroad_deactivated = true; + bike_mode = BIKE_MODE_NORMAL; + tft_left.drawNormalTacho(); + Serial.println("switching to normal"); + } + } + else if ( (bike_mode == BIKE_MODE_OFFROAD) && !offroad_touch_released ) { + Serial.println("offroad_touch_released"); + offroad_touch_released = true; } if (doConnect == true) { @@ -177,29 +274,12 @@ void loop() { } if (connected) { - pRemoteCharacteristic->writeValue(status_request, sizeof(status_request)); - - if ( (digitalRead(BTN_RIGHT_LOWER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { - btn_checked = millis(); - - if (status_request[3] > 2 ) { - status_request[3]--; - tft_right.PasDisplay((status_request[3]) - 2); - } - } - - else if ( (digitalRead(BTN_RIGHT_CENTER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { - btn_checked = millis(); - } - - else if ( (digitalRead(BTN_RIGHT_HIGHER)) && (millis() - btn_checked > BTN_COOLDOWN) ) { - btn_checked = millis(); - - if (status_request[3] < 5 ) { - status_request[3]++; - tft_right.PasDisplay((status_request[3]) - 2); - } + if ( (millis() - last_status) > STATUS_DURATION) { + last_status = millis(); + Serial.println("sending status_request"); + pRemoteCharacteristic->writeValue(status_request, sizeof(status_request)); } + check_buttons(); process_status(); } @@ -208,5 +288,5 @@ void loop() { // BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino } - delay(250); + delay(10); } \ No newline at end of file