From 6c3af6fbb541d13183843c30e40ba09a0fcf837d Mon Sep 17 00:00:00 2001 From: DashyFox Date: Mon, 30 Sep 2024 00:26:00 +0300 Subject: [PATCH] led and rc --- .cproject | 4 +- Core/Inc/IR_CMD_Handler.h | 2 +- Core/Inc/Indicator.h | 18 +- Core/Inc/RobotFunctions.h | 9 +- Core/Inc/ShiftReg.h | 10 + Core/Src/EEPROM.c | 10 +- Core/Src/IR_CMD_HandlerLogic.c | 300 +++++++++++--------- Core/Src/IR_CMD_Wrapper.c | 19 ++ Core/Src/Indicator.c | 391 ++++++++++++++++++++++----- Core/Src/RobotFunctions.c | 45 ++- Core/Src/UART3_CMD_Handler.c | 32 +++ Core/Src/main.c | 2 +- Core/Src/stm32f1xx_hal_msp.c | 2 +- Core/Startup/startup_stm32f103c8tx.s | 3 +- StackSport.ioc | 8 +- 15 files changed, 634 insertions(+), 221 deletions(-) diff --git a/.cproject b/.cproject index bb6126b..a2128c8 100644 --- a/.cproject +++ b/.cproject @@ -79,8 +79,8 @@ - + @@ -159,8 +159,8 @@ - + diff --git a/Core/Inc/IR_CMD_Handler.h b/Core/Inc/IR_CMD_Handler.h index 55a8bb1..f2406f2 100644 --- a/Core/Inc/IR_CMD_Handler.h +++ b/Core/Inc/IR_CMD_Handler.h @@ -31,7 +31,7 @@ enum IR_CMD_LIST { IR_NUM_9 = 8, IR_NUM_0 = 9, IR_DEBUG = 29, // -/-- - IR_PAUSE = 43, + IR_PAUSE = 43, // . IR_STOP = 116, IR_START = 124, IR_F_BTN = 23, diff --git a/Core/Inc/Indicator.h b/Core/Inc/Indicator.h index e3a3b20..2e529fb 100644 --- a/Core/Inc/Indicator.h +++ b/Core/Inc/Indicator.h @@ -38,6 +38,7 @@ **/ #define INDICATORS_COUNT 2 +#define LED_IDLE_TIMEOUT 1000 typedef struct LedMap_element { uint8_t byteIndx; @@ -59,9 +60,24 @@ void led_show(); void led_tick(); void led_writeMirror(uint8_t number, uint8_t state); -void led_write(LedMap_element led, uint8_t state); +void led_write(uint8_t number, uint8_t state); void led_blink(LedMap_element led, uint16_t period, uint16_t count); void led_blink_num(uint8_t ledNum, uint16_t period, uint16_t count); + +void led_progressbar(uint8_t fromLed, uint8_t toLed ,uint8_t progress); +void led_progressbarMirror(uint8_t fromLed, uint8_t toLed ,uint8_t progress); +//void led_setOnDone(void (*callback)()); +//void led_resetOnDone(); + +void led_PingPong_start(uint8_t fromLed, uint8_t toLed); +void led_PingPong_startMirror(uint8_t fromLed, uint8_t toLed); +void led_PingPong_next(); + +void led_showSpeed(uint8_t progressUP, uint8_t progressDOWN); + +void led_setIdleCallback(void(*callback)()); +void led_resetIdleCallback(); + uint8_t led_getState(LedMap_element led); void led_clear(); diff --git a/Core/Inc/RobotFunctions.h b/Core/Inc/RobotFunctions.h index 0a0422a..7091501 100644 --- a/Core/Inc/RobotFunctions.h +++ b/Core/Inc/RobotFunctions.h @@ -22,7 +22,7 @@ typedef enum ServoMap{ SERVO_VERTICAL = 2 }ServoMap; -typedef enum CurrentMode { +typedef enum Mode { NoneMode, ShotMode, ProgramMode, MacroMode, } Mode; @@ -58,11 +58,6 @@ typedef struct CurrentMacro { uint16_t doneCount; } CurrentMacro; -//typedef struct CurrentState { -// uint8_t isPause; -// uint8_t isShooting; -//} CurrentState; - typedef struct CurrentInfo { Mode mode; State state; @@ -72,6 +67,8 @@ typedef struct CurrentInfo { uint32_t startDelay; } CurrentInfo; +extern CurrentInfo currentInfo; + void Robot_INIT(); void shotApply(CurrentShot*); diff --git a/Core/Inc/ShiftReg.h b/Core/Inc/ShiftReg.h index f9911f9..50ed7df 100644 --- a/Core/Inc/ShiftReg.h +++ b/Core/Inc/ShiftReg.h @@ -12,6 +12,16 @@ #define NUMLEDS 10 +#define SHIFT_REG_DATA_PORT GPIOA +#define SHIFT_REG_DATA_PIN GPIO_PIN_4 + +#define SHIFT_REG_CLOCK_PORT GPIOA +#define SHIFT_REG_CLOCK_PIN GPIO_PIN_5 + +// Минимальные задержки для правильной работы +#define DATA_SETUP_TIME 20 // Время установки данных в нс +#define CLOCK_PULSE_WIDTH 20 // Длительность импульса тактирования в нс + void SetShiftReg_inline (unsigned char b1, unsigned char b2, unsigned char b3); void SetShiftReg (unsigned char shiftreg[3]); diff --git a/Core/Src/EEPROM.c b/Core/Src/EEPROM.c index 9903992..cba8bf1 100644 --- a/Core/Src/EEPROM.c +++ b/Core/Src/EEPROM.c @@ -3,6 +3,7 @@ #include "usbd_cdc_if.h" #include "Print.h" #include "RobotFunctions.h" +#include "Indicator.h" InfoBlock infoBlock; extern IWDG_HandleTypeDef hiwdg; @@ -265,16 +266,23 @@ MemoryStatus delMacro(unsigned char number) { MemoryStatus EEPROM_EARSE() { uint16_t addr = 0; const uint16_t EEPROM_MAX_ADDR = 1024*32; + led_PingPong_start(7, 12); do { uint8_t Buf[64]; HAL_IWDG_Refresh(&hiwdg); memset(Buf, 0x00, sizeof(Buf)); - HAL_IWDG_Refresh(&hiwdg); FLASH_WriteBlock(addr, 0, Buf, sizeof(Buf), sizeof(Buf)); + HAL_IWDG_Refresh(&hiwdg); + led_PingPong_next(); + uint8_t progress = (addr * 100) / EEPROM_MAX_ADDR; + led_progressbar(00, 06, progress<50 ? 100 : 100-(progress-50)*2); + led_progressbar(13, 19, progress<50 ? 100-progress*2 : 0); + addr += sizeof(Buf); } while (addr < EEPROM_MAX_ADDR); + led_clear(); return EEPROM_OK; } diff --git a/Core/Src/IR_CMD_HandlerLogic.c b/Core/Src/IR_CMD_HandlerLogic.c index 7226236..fef3382 100644 --- a/Core/Src/IR_CMD_HandlerLogic.c +++ b/Core/Src/IR_CMD_HandlerLogic.c @@ -8,6 +8,7 @@ #include "IR.h" #include "ShiftReg.h" #include "RobotFunctions.h" +#include "Indicator.h" #include "Print.h" @@ -30,11 +31,30 @@ extern IRData data; extern void NullFunc(); // null func for paramEnter(NullFunc); extern void paramEnter(void (*onEnter_)()); // setParamFunc for enter -void IR_ShotPrepared(); +void IR_ShootingStart(); void onSelectShot() { if (prepareShot(inputParam)) { - InputHandler = IR_ShotPrepared; + InputHandler = IR_ShootingStart; + } else { + paramEnter(onSelectShot); + print("Shot not found\n"); + // Shot not found + } +} + +void onSelectProgram() { + if (prepareProgramm(inputParam)) { + InputHandler = IR_ShootingStart; + } else { + paramEnter(onSelectShot); + print("Shot not found\n"); + // Shot not found + } +} +void onSelectMacro() { + if (prepareMacro(inputParam)) { + InputHandler = IR_ShootingStart; } else { paramEnter(onSelectShot); print("Shot not found\n"); @@ -50,37 +70,172 @@ uint8_t screwSpeed; uint8_t speedUP = 100; uint8_t speedDown = 100; +// onHoldRepeat = IR_Home_Process; + void IR_Home_Process() { InputHandler = IR_Home_Process; -// SetShiftReg_inline(0xff, 0, 0); switch (data.command) { case IR_SHOT: paramEnter(onSelectShot); break; case IR_PROG: { - SetShiftReg_inline(0, 7, 0); - b1 = b2 = b3 = 0; + paramEnter(onSelectProgram); break; } - case IR_FONT_RIGHT: - SetShiftReg_inline(b1, b2, ++b3); - break; - case IR_FRONT_MID: - SetShiftReg_inline(b1, ++b2, b3); - break; - case IR_FRONT_LEFT: - SetShiftReg_inline(++b1, b2, b3); -// onHoldRepeat = IR_Home_Process; + case IR_MACRO: { + paramEnter(onSelectMacro); break; + } case IR_F_BTN: { - EEPROM_INIT(); + + break; + } + + case IR_PAUSE: + if (currentInfo.state == RUN) { + currentInfo.state = PAUSE; + } + break; + + case IR_START: + if (currentInfo.state == PAUSE) { + currentInfo.state = RUN; + } + break; + + case IR_ESC: { +// if (EEPROM_EARSE() != EEPROM_OK) { +// char errorMsg[] = "Error EEPROM_EARSE\n\n"; +// CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg)); +// } else { +// char doneMsg[] = "EEPROM_EARSE Done\n\n"; +// CDC_Transmit_FS((uint8_t*) doneMsg, strlen(doneMsg)); +// } + break; + } + + case IR_DEBUG: { + + break; + } + + case IR_NUM_1: + + break; + case IR_NUM_2: + break; + case IR_NUM_3: + + break; + + case IR_NUM_7: + break; + case IR_NUM_8: + break; + case IR_NUM_9: + break; + + case IR_NUM_5: + break; + + case IR_STOP: { + speedUP = 100; + speedDown = 100; + screwSpeed = 0; + stopShooting(); + break; + } + + case IR_TEMPO_INC: + if (currentInfo.shot.shot.speedScrew < 100) { + currentInfo.shot.shot.speedScrew++; + shotApply(¤tInfo.shot); +// led_progressbar(10, 19, currentInfo.shot.shot.speedScrew); //todo: led_progressbarTMP + } + onHoldRepeat = IR_Home_Process; + break; + + case IR_TEMPO_DEC: + if (currentInfo.shot.shot.speedScrew > 0) { + currentInfo.shot.shot.speedScrew--; + shotApply(¤tInfo.shot); + } + onHoldRepeat = IR_Home_Process; + break; + + case IR_ENGINE_UP_INC: + if (currentInfo.shot.shot.speedRollerTop < 200) { + currentInfo.shot.shot.speedRollerTop++; + shotApply(¤tInfo.shot); + } + onHoldRepeat = IR_Home_Process; + break; + + case IR_ENGINE_UP_DEC: + if (currentInfo.shot.shot.speedRollerTop > 0) { + currentInfo.shot.shot.speedRollerTop--; + shotApply(¤tInfo.shot); + } + onHoldRepeat = IR_Home_Process; + break; + + case IR_ENGINE_DOWM_INC: + if (currentInfo.shot.shot.speedRollerBottom < 200) { + currentInfo.shot.shot.speedRollerBottom++; + shotApply(¤tInfo.shot); + } + onHoldRepeat = IR_Home_Process; + break; + + case IR_ENGINE_DOWM_DEC: + if (currentInfo.shot.shot.speedRollerBottom > 0) { + currentInfo.shot.shot.speedRollerBottom--; + shotApply(¤tInfo.shot); + } + onHoldRepeat = IR_Home_Process; + break; + +///////////////////////////////////////////////////////// + + case IR_FONT_RIGHT: + for (int i = 0; i <= 100; ++i) { + led_progressbar(0, 19, i); + HAL_Delay(10); + } + led_clear(); + break; + + case IR_FRONT_MID: { + uint8_t i2c_address; + HAL_StatusTypeDef result; + + print("Scan\n"); + + // Перебираем все возможные адреса на шине I2C (7 бит, от 0x08 до 0x77) + for (i2c_address = 0x08; i2c_address <= 0x77; i2c_address++) { + // Отправляем запрос на указанный адрес (HAL_I2C_Master_Transmit без данных) + result = HAL_I2C_IsDeviceReady(&hi2c1, (i2c_address << 1), 1, 100); + + if (result == HAL_OK) { + // Если устройство отвечает, выводим его адрес + print("Found I2C at: "); + printNumber(i2c_address); + print("\n"); + } else { + // Если устройство не отвечает, продолжаем сканирование + print("."); + } + HAL_Delay(10); // Задержка для стабильности сканирования + } + + print("\nScanning completed.\n"); } break; - case IR_PAUSE: { + case IR_FRONT_LEFT: { uint8_t buf[1024]; // Буфер для чтения данных размером 128 байт uint16_t blockAddr16 = START_ADR_MACRO; // Начальный адрес EEPROM uint8_t blockAddr[2] = { (uint8_t) (blockAddr16 >> 8), @@ -131,121 +286,13 @@ void IR_Home_Process() { } break; - case IR_ESC: { - - if (EEPROM_EARSE() != EEPROM_OK) { - char errorMsg[] = "Error EEPROM_EARSE\n\n"; - CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg)); - } else { - char doneMsg[] = "EEPROM_EARSE Done\n\n"; - CDC_Transmit_FS((uint8_t*) doneMsg, strlen(doneMsg)); - } - } - break; - - case IR_DEBUG: { - uint8_t i2c_address; - HAL_StatusTypeDef result; - - print("Scan\n"); - - // Перебираем все возможные адреса на шине I2C (7 бит, от 0x08 до 0x77) - for (i2c_address = 0x08; i2c_address <= 0x77; i2c_address++) { - // Отправляем запрос на указанный адрес (HAL_I2C_Master_Transmit без данных) - result = HAL_I2C_IsDeviceReady(&hi2c1, (i2c_address << 1), 1, 100); - - if (result == HAL_OK) { - // Если устройство отвечает, выводим его адрес - print("Found I2C at: "); - printNumber(i2c_address); - print("\n"); - } else { - // Если устройство не отвечает, продолжаем сканирование - print("."); - } - HAL_Delay(10); // Задержка для стабильности сканирования - } - - print("\nScanning completed.\n"); - } - break; - - case IR_NUM_1: - - break; - case IR_NUM_2: - break; - case IR_NUM_3: - - break; - - case IR_NUM_7: - break; - case IR_NUM_8: - break; - case IR_NUM_9: - break; - - case IR_NUM_5: - break; - - case IR_STOP: - speedUP = 100; - speedDown = 100; - screwSpeed = 0; - stopShooting(); - break; - - case IR_TEMPO_INC: - if (screwSpeed < 100) { - setScrewkSpeed(++screwSpeed); - } - onHoldRepeat = IR_Home_Process; - break; - - case IR_TEMPO_DEC: - if (screwSpeed > 0) { - setScrewkSpeed(--screwSpeed); - } - onHoldRepeat = IR_Home_Process; - break; - - case IR_ENGINE_UP_INC: - if (speedUP < 200) { - setRollersSpeed(++speedUP, speedDown); - } - onHoldRepeat = IR_Home_Process; - break; - - case IR_ENGINE_UP_DEC: - if (speedUP > 0) { - setRollersSpeed(--speedUP, speedDown); - } - onHoldRepeat = IR_Home_Process; - break; - - case IR_ENGINE_DOWM_INC: - if (speedDown < 200) { - setRollersSpeed(speedUP, ++speedDown); - } - onHoldRepeat = IR_Home_Process; - break; - - case IR_ENGINE_DOWM_DEC: - if (speedDown > 0) { - setRollersSpeed(speedUP, --speedDown); - } - onHoldRepeat = IR_Home_Process; - break; - default: break; } - } -void IR_ShotPrepared() { - InputHandler = IR_ShotPrepared; +void IR_ShootingStart() { + InputHandler = IR_ShootingStart; switch (data.command) { case IR_START: startShooting(infoBlock.hwInfo.timings.preRun); @@ -255,3 +302,4 @@ void IR_ShotPrepared() { break; } } + diff --git a/Core/Src/IR_CMD_Wrapper.c b/Core/Src/IR_CMD_Wrapper.c index 877ef4f..75137b2 100644 --- a/Core/Src/IR_CMD_Wrapper.c +++ b/Core/Src/IR_CMD_Wrapper.c @@ -3,6 +3,7 @@ #include "SimpleTimer.h" #include "ShiftReg.h" #include "Print.h" +#include "Indicator.h" #define IR_Timeout 137 #define ResetInputProgerss_Timeout 2500 @@ -62,6 +63,12 @@ void IR_CMD_Handler() { } if (inputInProgerss && (millis() - inputInProgerss_timer > ResetInputProgerss_Timeout)) { IR_CMD_Clear(); + + uint8_t blinkPeriod = 25; + for (int i = 9; i <= 10; ++i) { + led_blink_num(i, blinkPeriod, 4); + } + } // cmd handler @@ -80,6 +87,14 @@ void IR_CMD_Handler() { holdStartTime = millis(); // Запоминаем время начала удержания lastRepeatTime = holdStartTime; // Инициализируем таймер повторного вызова currentRepeatTime = InitialRepeatTime; // Сбрасываем интервал повторного вызова + + uint8_t blinkPeriod = 75; + led_blink_num(19, blinkPeriod, 1); + led_blink_num(18, blinkPeriod, 1); + led_blink_num(17, blinkPeriod, 1); + led_blink_num(2, blinkPeriod, 1); + led_blink_num(1, blinkPeriod, 1); + led_blink_num(0, blinkPeriod, 1); } memcpy(&old_data, &data, sizeof(IRData)); } else { @@ -87,6 +102,10 @@ void IR_CMD_Handler() { if (millis() - holdStartTime > HoldTime) { // Если кнопка удерживается дольше HoldTime if (millis() - lastRepeatTime > currentRepeatTime) { // Если прошло достаточно времени для повторного вызова lastRepeatTime = millis(); // Обновляем время последнего вызова +// uint8_t blinkPeriod = 10; + led_writeMirror(9, 1); + + onHoldRepeat(); // Вызываем функцию при удержании // Уменьшаем интервал до минимального значения diff --git a/Core/Src/Indicator.c b/Core/Src/Indicator.c index 202d511..21abe0d 100644 --- a/Core/Src/Indicator.c +++ b/Core/Src/Indicator.c @@ -8,70 +8,35 @@ #include "Indicator.h" #include "ShiftReg.h" #include "SimpleTimer.h" +#include "Print.h" + #include const LedMap ledMap = { // ALL - DOWN[0] TO UP[19] - { - {0, 0b01000000}, - {0, 0b00100000}, - {0, 0b00010000}, - {0, 0b00001000}, - {0, 0b00000100}, - {0, 0b00000010}, - {0, 0b00000001}, - {1, 0b00000001}, - {1, 0b00000010}, - {1, 0b00000100}, + { { 0, 0b01000000 }, { 0, 0b00100000 }, { 0, 0b00010000 }, { 0, + 0b00001000 }, { 0, 0b00000100 }, { 0, 0b00000010 }, { 0, + 0b00000001 }, { 1, 0b00000001 }, { 1, 0b00000010 }, { 1, + 0b00000100 }, - {1, 0b01000000}, - {1, 0b00100000}, - {1, 0b00010000}, - {2, 0b00000001}, - {2, 0b00000010}, - {2, 0b00000100}, - {2, 0b00001000}, - {2, 0b00010000}, - {2, 0b00100000}, - {2, 0b01000000}, - }, + { 1, 0b01000000 }, { 1, 0b00100000 }, { 1, 0b00010000 }, + { 2, 0b00000001 }, { 2, 0b00000010 }, { 2, 0b00000100 }, { 2, + 0b00001000 }, { 2, 0b00010000 }, { 2, 0b00100000 }, { 2, + 0b01000000 }, }, // UP - DOWN[0] TO UP[9] - { - {1, 0b01000000}, - {1, 0b00100000}, - {1, 0b00010000}, - {2, 0b00000001}, - {2, 0b00000010}, - {2, 0b00000100}, - {2, 0b00001000}, - {2, 0b00010000}, - {2, 0b00100000}, - {2, 0b01000000}, - }, + { { 1, 0b01000000 }, { 1, 0b00100000 }, { 1, 0b00010000 }, { 2, + 0b00000001 }, { 2, 0b00000010 }, { 2, 0b00000100 }, { 2, + 0b00001000 }, { 2, 0b00010000 }, { 2, 0b00100000 }, { 2, + 0b01000000 }, }, // DOWN - DOWN[0] TO UP[9] - { - {0, 0b01000000}, - {0, 0b00100000}, - {0, 0b00010000}, - {0, 0b00001000}, - {0, 0b00000100}, - {0, 0b00000010}, - {0, 0b00000001}, - {1, 0b00000001}, - {1, 0b00000010}, - {1, 0b00000100}, - }, + { { 0, 0b01000000 }, { 0, 0b00100000 }, { 0, 0b00010000 }, { 0, + 0b00001000 }, { 0, 0b00000100 }, { 0, 0b00000010 }, { 0, + 0b00000001 }, { 1, 0b00000001 }, { 1, 0b00000010 }, { 1, + 0b00000100 }, }, // RED - DOWN[0] TO UP[5] - { - {1, 0b00000001}, - {1, 0b00000010}, - {1, 0b00000100}, + { { 1, 0b00000001 }, { 1, 0b00000010 }, { 1, 0b00000100 }, - {1, 0b01000000}, - {1, 0b00100000}, - {1, 0b00010000}, - } -}; + { 1, 0b01000000 }, { 1, 0b00100000 }, { 1, 0b00010000 }, } }; static uint8_t ledBuf[3] = { 0, 0, 0 }; @@ -80,35 +45,91 @@ typedef struct { uint16_t count; uint32_t timer; } LedBlinkInfo; +typedef struct { + + uint8_t start; + uint8_t end; + uint32_t ledCurrent; + uint8_t globalDir; + uint8_t dir; + void (*writeCallback)(uint8_t ledNum, uint8_t state); +} LedPingPongInfo; + static LedBlinkInfo ledBlinkInfo[NUMLEDS * INDICATORS_COUNT]; +static LedPingPongInfo ledPingPongInfo; + +static uint32_t idle_timer; +static void NULL_FUNC(){}; +static void (*onLedIdle_Callback)() = NULL_FUNC; +//static void (*onDone_Callback)() = NULL_FUNC; +static void led_PingPong_start_(uint8_t fromLed, uint8_t toLed); +static void led_progressbar_(uint8_t fromLed, uint8_t toLed, uint8_t progress, void (*led_writeFunc)(uint8_t, uint8_t)); + +//void led_setOnDone(void (*callback)()){ +// onDone_Callback = callback; +//} + +//void led_resetOnDone(){ +// onDone_Callback = NULL_FUNC; +//} + +static long map(long x, long in_min, long in_max, long out_min, long out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} static void blinkHandler() { for (int i = 0; i < sizeof(ledBlinkInfo) / sizeof(ledBlinkInfo[0]); ++i) { - if(!ledBlinkInfo[i].count || !ledBlinkInfo[i].period){ + if (!ledBlinkInfo[i].count || !ledBlinkInfo[i].period) { continue; } - if(millis() - ledBlinkInfo[i].timer > ledBlinkInfo[i].period){ + if (millis() - ledBlinkInfo[i].timer > ledBlinkInfo[i].period) { ledBlinkInfo[i].timer = millis(); - led_write(ledMap.ALL[i], (ledBlinkInfo[i].count & 1) != 1); - ledBlinkInfo[i].count--; + if(ledBlinkInfo[i].count != 0xFFFF){ + led_write(i, (ledBlinkInfo[i].count & 1) != 1); + ledBlinkInfo[i].count--; + } else { + led_write(i, !led_getState(ledMap.ALL[i])); + } } } } -void led_init(){ +void led_setIdleCallback(void(*callback)()){ + onLedIdle_Callback = callback; +} +void led_resetIdleCallback(){ + onLedIdle_Callback = NULL_FUNC; +} + +void led_init() { memset(ledBlinkInfo, 0x00, sizeof(ledBlinkInfo)); + memset(&ledPingPongInfo, 0x00, sizeof(ledPingPongInfo)); + ledPingPongInfo.writeCallback = led_write; } void led_show() { + idle_timer = millis(); SetShiftReg(ledBuf); } void led_tick() { blinkHandler(); + if(onLedIdle_Callback != NULL_FUNC && millis() - idle_timer > LED_IDLE_TIMEOUT){ + onLedIdle_Callback(); + led_resetIdleCallback(); + } } -void led_write(LedMap_element led, uint8_t state) { +void led_write(uint8_t number, uint8_t state) { + if(number >= sizeof(ledMap.ALL)/sizeof(ledMap.ALL[0])) + return; + + LedMap_element led = ledMap.ALL[number]; + + if(led_getState(led) == state) + return; + if (state) { ledBuf[led.byteIndx] |= led.offsetMask; } else { @@ -117,7 +138,7 @@ void led_write(LedMap_element led, uint8_t state) { led_show(); } -uint8_t led_getState(LedMap_element led){ +uint8_t led_getState(LedMap_element led) { return (ledBuf[led.byteIndx] & led.offsetMask) != 0; } @@ -126,31 +147,259 @@ void led_writeMirror(uint8_t number, uint8_t state) { if (number >= 10) { number = 9; } + number+=10; - led_write(ledMap.UP[number], state); - led_write(ledMap.DOWN[9 - number], state); - - led_show(); + led_write(number, state); + led_write(19 - number, state); } -void led_blink_num(uint8_t ledNum, uint16_t period, uint16_t count){ - if(ledNum>=sizeof(ledBlinkInfo)/sizeof(ledBlinkInfo[0])) +void led_blink_num(uint8_t ledNum, uint16_t period, uint16_t count) { + if (ledNum >= sizeof(ledBlinkInfo) / sizeof(ledBlinkInfo[0])) return; - ledBlinkInfo[ledNum].count = count*2; + if(count == 0xFFFF){ + ledBlinkInfo[ledNum].count = count; + } else { + ledBlinkInfo[ledNum].count = count * 2; + } ledBlinkInfo[ledNum].period = period; ledBlinkInfo[ledNum].timer = 0; // run immediately } void led_blink(LedMap_element led, uint16_t period, uint16_t count) { - for (int i = 0; i < sizeof(ledMap.ALL)/sizeof(ledMap.ALL[0]); ++i) { - if(memcmp(&led, &ledMap.ALL[i], sizeof(LedMap_element)) == 0){ + for (int i = 0; i < sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0]); ++i) { + if (memcmp(&led, &ledMap.ALL[i], sizeof(LedMap_element)) == 0) { led_blink_num(i, period, count); return; } } } +// Общая функция для управления прогрессбаром +void led_progressbar_(uint8_t fromLed, uint8_t toLed, uint8_t progress, void (*led_writeFunc)(uint8_t, uint8_t)) { + if (progress > 100) { + progress = 100; + } + + // Проверка на выход за границы массива ledMap.ALL + if (fromLed >= sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0]) + || toLed >= sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0])) { + return; + } + + // Инициализация переменных в зависимости от направления + int8_t dir; + uint8_t start; + uint8_t end; + uint8_t numLeds; + if (fromLed < toLed) { + start = fromLed; + end = toLed; + dir = 1; // Заполнение снизу вверх + } else { + start = toLed; + end = fromLed; + dir = -1; // Заполнение сверху вниз + } + + // Количество светодиодов в прогрессбаре (включая последний светодиод) + numLeds = end - start + 1; + + // Рассчитываем, сколько светодиодов нужно включить + uint8_t ledsToLight = map(progress, 0, 100, 0, numLeds); + + // Корректировка включения для первого и последнего светодиода + if (progress > 0 && ledsToLight == 0) { + ledsToLight = 1; // Включаем первый светодиод при любом положительном прогрессе + } + if (progress == 100) { + ledsToLight = numLeds; // Включаем последний светодиод только при прогрессе 100% + } + + print("progress "); + printNumber(progress); + print(" led "); + printNumber(ledsToLight); + print("\n"); + + for (int i = 0; i < numLeds; ++i) { + int ledIndex = fromLed + i * dir; + + // Сброс счетчика мигания для включенных светодиодов + ledBlinkInfo[ledIndex].count = 0; + + if (i < ledsToLight) { + // Включаем светодиод, если он не включен + if (!led_getState(ledMap.ALL[ledIndex])) { + led_writeFunc(ledIndex, 1); // Используем переданную функцию для включения + } + } else { + // Выключаем светодиод, если он включен + if (led_getState(ledMap.ALL[ledIndex])) { + led_writeFunc(ledIndex, 0); // Используем переданную функцию для выключения + } + } + } +} + +// Оригинальная функция, использующая led_write +void led_progressbar(uint8_t fromLed, uint8_t toLed, uint8_t progress) { + led_progressbar_(fromLed, toLed, progress, led_write); +} + +// Новая функция, использующая led_writeMirror +void led_progressbarMirror(uint8_t fromLed, uint8_t toLed, uint8_t progress) { + led_progressbar_(fromLed, toLed, progress, led_writeMirror); +} + + +void led_PingPong_startMirror(uint8_t fromLed, uint8_t toLed){ + uint8_t half_ledMap_size = (sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0]))/2; + if (fromLed >= half_ledMap_size + || toLed >= half_ledMap_size) { + return; + } + ledPingPongInfo.writeCallback = led_writeMirror; + led_PingPong_start_(fromLed, toLed); +} + +void led_PingPong_start(uint8_t fromLed, uint8_t toLed) { + if (fromLed >= sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0]) + || toLed >= sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0])) { + return; + } + ledPingPongInfo.writeCallback = led_write; + led_PingPong_start_(fromLed, toLed); +} +void led_PingPong_start_(uint8_t fromLed, uint8_t toLed){ + if (fromLed < toLed) { + ledPingPongInfo.start = fromLed; + ledPingPongInfo.end = toLed; + ledPingPongInfo.globalDir = 1; + } else { + ledPingPongInfo.start = toLed; + ledPingPongInfo.end = fromLed; + ledPingPongInfo.globalDir = 0; + } + ledPingPongInfo.dir = 1; + ledPingPongInfo.ledCurrent = ledPingPongInfo.start; + + for (uint8_t i = ledPingPongInfo.start; i <= ledPingPongInfo.end; i++) { + ledBlinkInfo[i].count = 0; + if (led_getState(ledMap.ALL[i])) + ledPingPongInfo.writeCallback(i, 0); + } + if(!led_getState(ledMap.ALL[ledPingPongInfo.start])) + ledPingPongInfo.writeCallback(ledPingPongInfo.start, 1); +} + +void led_PingPong_next() { + // Проверка на выход за границы массива + uint8_t ledCount = sizeof(ledMap.ALL) / sizeof(ledMap.ALL[0]); + + // Обработка движения "туда-обратно" + if (ledPingPongInfo.globalDir) { + // Двигаемся от начала к концу + if (ledPingPongInfo.dir) { + // Если не дошли до конца и не выходим за границы массива + if (ledPingPongInfo.ledCurrent + 1 < ledCount && ledPingPongInfo.ledCurrent + 1 <= ledPingPongInfo.end) { + // Включаем следующий светодиод и выключаем текущий + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent + 1, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 0); + ledPingPongInfo.ledCurrent++; + } else { + // Достигли конца — сразу меняем направление и двигаемся обратно + ledPingPongInfo.dir = 0; + ledPingPongInfo.ledCurrent--; + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent + 1, 0); + } + } else { + // Двигаемся от конца к началу + if (ledPingPongInfo.ledCurrent > ledPingPongInfo.start) { + // Включаем предыдущий светодиод и выключаем текущий + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent - 1, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 0); + ledPingPongInfo.ledCurrent--; + } else { + // Достигли начала — сразу меняем направление и двигаемся вперед + ledPingPongInfo.dir = 1; + ledPingPongInfo.ledCurrent++; + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent - 1, 0); + } + } + } else { + // Двигаемся от конца к началу (начальное обратное направление) + if (ledPingPongInfo.dir) { + // Если не дошли до начала и не выходим за границы массива + if (ledPingPongInfo.ledCurrent > ledPingPongInfo.start) { + // Включаем предыдущий светодиод и выключаем текущий + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent - 1, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 0); + ledPingPongInfo.ledCurrent--; + } else { + // Достигли начала — сразу меняем направление и двигаемся обратно + ledPingPongInfo.dir = 0; + ledPingPongInfo.ledCurrent++; + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent - 1, 0); + } + } else { + // Двигаемся от начала к концу (обратное направление) + if (ledPingPongInfo.ledCurrent + 1 < ledCount && ledPingPongInfo.ledCurrent + 1 <= ledPingPongInfo.end) { + // Включаем следующий светодиод и выключаем текущий + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent + 1, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 0); + ledPingPongInfo.ledCurrent++; + } else { + // Достигли конца — сразу меняем направление и двигаемся обратно + ledPingPongInfo.dir = 1; + ledPingPongInfo.ledCurrent--; + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent, 1); + ledPingPongInfo.writeCallback(ledPingPongInfo.ledCurrent + 1, 0); + } + } + } +} + +void led_showSpeed(uint8_t progressUP, uint8_t progressDOWN){ + memset(ledBlinkInfo, 0x00, sizeof(ledBlinkInfo)); + if (progressUP < 70 && progressUP) + progressUP = 70; + + if (progressUP > 100) { + progressUP = map(progressUP, 100, 199, 0, 100); + led_progressbar(13, 19, progressUP); + led_progressbar(12, 10, 0); + } else if (progressUP < 100) { + progressUP = map((100 - progressUP), 0, 30, 0, 100); + led_progressbar(13, 19, 0); + led_progressbar(12, 10, progressUP); + } else { + led_progressbar(13, 19, 0); + led_progressbar(12, 10, 0); + } + + if (progressDOWN < 70 && progressDOWN) + progressDOWN = 70; + + if (progressDOWN > 100) { + progressDOWN = map(progressDOWN, 100, 199, 0, 100); + led_progressbar(7, 0, progressDOWN); + led_progressbar(9, 7, 0); + } else if (progressDOWN < 100) { + progressDOWN = map((100 - progressDOWN), 0, 30, 0, 100); + led_progressbar(7, 0, 0); + led_progressbar(9, 7, progressDOWN); + } else { + led_progressbar(7, 0, 0); + led_progressbar(9, 7, 0); + } +} + + void led_clear() { memset(ledBuf, 0x00, sizeof(ledBuf)); + memset(ledBlinkInfo, 0x00, sizeof(ledBlinkInfo)); led_show(); } diff --git a/Core/Src/RobotFunctions.c b/Core/Src/RobotFunctions.c index 5fd7f2e..954049e 100644 --- a/Core/Src/RobotFunctions.c +++ b/Core/Src/RobotFunctions.c @@ -60,6 +60,7 @@ void robotStateStop() { long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } + float calculatePeriod(int pwm_value) { // Функция для расчета периода вылета мяча на основе ШИМ // Коэффициенты из аппроксимации float a = 100382.255; @@ -72,6 +73,8 @@ float calculatePeriod(int pwm_value) { // Функция для расчета } void Robot_INIT() { + led_init(); +// led_PingPong_start(7, 12); memset(¤tInfo, 0x00, sizeof(currentInfo)); // NULL currentInfo.shot.indexGlobal = 0xFF; @@ -79,8 +82,8 @@ void Robot_INIT() { currentInfo.macro.indexGlobal = 0xFF; initPCA9685(); EEPROM_INIT(); + setPosDefault(); UART3_START(); - led_init(); for (int i = 0; i < 10; ++i) { // if ((i&1U)!=1 || i > 4) for test @@ -90,10 +93,15 @@ void Robot_INIT() { } } led_clear(); + HAL_Delay(100); - for (int i = 7; i < 13; ++i) { - led_blink_num(i, 100, 15); - } +// for (int i = 9; i <= 9; ++i) { +// led_blink_num(i, 100, 15); +// } +// for (int i = 0; i <= 100; ++i) { +// led_progressbar(0, 19, i); +// HAL_Delay(10); +// } } @@ -109,6 +117,11 @@ void RobotTick() { // No Ball Handler if (currentInfo.state == RUN && millis() - noBallTimer > noBallTimeout) { robotStateStop(); + led_clear(); + for (int i = 7; i <= 12; ++i) { + led_blink_num(i, 250, 0xFFFF-1); + } + isDelayTimerRun = 0; setScrewkSpeed(0); setRollersSpeed(100, 100); setPos(infoBlock.hwInfo.servos[SERVO_AXIAL].def, @@ -131,8 +144,16 @@ void RobotTick() { uint32_t intervalStep = currentInfo.startDelay / NUMLEDS; if (elapsedTime - lastIndicationTime >= intervalStep) { lastIndicationTime = elapsedTime; - uint8_t progress = (elapsedTime * 100) / currentInfo.startDelay; -// indicate(progress); + uint8_t progress = 100 - (elapsedTime * 100) / currentInfo.startDelay; + + uint8_t ledProgress = map(progress, 0, 70, 0, 100); + if (ledProgress > 30) { + led_progressbar(9, 0, progress); + led_progressbar(10, 19, progress); + } else { + led_progressbar(9, 0, 100); + led_progressbar(10, 19, 100); + } print("delay: "); printNumber(progress); print("\n"); @@ -142,6 +163,7 @@ void RobotTick() { } uint8_t prepareShot(uint8_t number) { + stopShooting(); Shot shot; memset(&shot, 0x00, sizeof(shot)); getShot(number, &shot); @@ -157,6 +179,7 @@ uint8_t prepareShot(uint8_t number) { } } uint8_t prepareProgramm(uint8_t number) { + stopShooting(); Program program; memset(&program, 0x00, sizeof(program)); getProg(number, &program); @@ -173,6 +196,7 @@ uint8_t prepareProgramm(uint8_t number) { } uint8_t prepareMacro(uint8_t number) { + stopShooting(); Macro macro; memset(¯o, 0x00, sizeof(macro)); getMacro(number, ¯o); @@ -478,6 +502,9 @@ void startShooting(uint32_t delayTime) { } void stopShooting() { + led_clear(); + + isDelayTimerRun = 0; robotStateStop(); setScrewkSpeed(0); setRollersSpeed(100, 100); @@ -494,6 +521,12 @@ void shotApply(CurrentShot *currentShot) { calculatePeriod( shot->speedScrew) * NOBALL_TIMEOUT_MULTIPLIER, 30000); noBallTimer = millis(); + +////////////////////////// LED //////////////////////////////////////// + led_clear(); + led_showSpeed(shot->speedRollerTop, shot->speedRollerBottom); +///////////////////////////////////////////////////////////////////////////// + print("Global indx "); printNumber(currentShot->indexGlobal); print("\nisExist "); diff --git a/Core/Src/UART3_CMD_Handler.c b/Core/Src/UART3_CMD_Handler.c index f60ef6f..9c15562 100644 --- a/Core/Src/UART3_CMD_Handler.c +++ b/Core/Src/UART3_CMD_Handler.c @@ -9,6 +9,7 @@ #include "Print.h" #include "RobotFunctions.h" #include "EEPROM.h" +#include "Indicator.h" #define HIGHBIT(b) (((b)>>8)&0xff) #define LOWBIT(b) ((b)&0xff) @@ -31,6 +32,31 @@ uint8_t checkLen(uint8_t cmd, uint8_t current_length, uint8_t required_length) { return 1; } +static void NULL_FUNC(){}; +static void (*onSave)() = NULL_FUNC; +static void resetOnSave(){onSave = NULL_FUNC;}; +uint8_t isSyncFirstSave; +static void onLedIdle(){ + isSyncFirstSave = 0; + for (int i = 0; i < 9; ++i) { + led_writeMirror(i, 1); + } + HAL_Delay(25); + led_clear(); + resetOnSave(); +} +static void onSaveCallback(){ + if(isSyncFirstSave){ + isSyncFirstSave = 0; + led_PingPong_startMirror(3, 9); + for (int i = 0; i < 3; ++i) { + led_writeMirror(i, 1); + } + } + led_PingPong_next(); +} + + // 10 void UART3_SaveShot(uint8_t *dataPtr, uint8_t len) { const uint8_t MIN_PARAM_LENGTH = 8; @@ -50,6 +76,7 @@ void UART3_SaveShot(uint8_t *dataPtr, uint8_t len) { shot.rotationVertical = 180 - (int8_t) dataPtr[8] - 90; saveShot(shotIndx, &shot); + onSaveCallback(); SendResponse(dataPtr[0], 0, NULL, 0); } @@ -77,6 +104,7 @@ void UART3_SaveProgram(uint8_t *dataPtr, uint8_t len) { } saveProg(progIndx, &prog); + onSaveCallback(); SendResponse(dataPtr[0], 0, NULL, 0); } @@ -106,6 +134,7 @@ void UART3_SaveMacro(uint8_t *dataPtr, uint8_t len) { } else { delMacro(macroIndx); } + onSaveCallback(); SendResponse(dataPtr[0], 0, NULL, 0); } @@ -201,6 +230,9 @@ void UART3_DeleteAllData(uint8_t *dataPtr, uint8_t len) { const uint8_t MIN_PARAM_LENGTH = 0; if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH)) return; + isSyncFirstSave = 1; + led_setIdleCallback(onLedIdle); + onSave = onSaveCallback; getInfoBlock(); EEPROM_EARSE(); diff --git a/Core/Src/main.c b/Core/Src/main.c index c9972e7..4fe4e05 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -618,7 +618,7 @@ static void MX_GPIO_Init(void) GPIO_InitStruct.Pin = LED_DATA_Pin|LED_CLK_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : BALL_EXT_Pin */ diff --git a/Core/Src/stm32f1xx_hal_msp.c b/Core/Src/stm32f1xx_hal_msp.c index 54601fd..cfcbe37 100644 --- a/Core/Src/stm32f1xx_hal_msp.c +++ b/Core/Src/stm32f1xx_hal_msp.c @@ -367,7 +367,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) __HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx); /* USART3 interrupt Init */ - HAL_NVIC_SetPriority(USART3_IRQn, 0, 0); + HAL_NVIC_SetPriority(USART3_IRQn, 3, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ diff --git a/Core/Startup/startup_stm32f103c8tx.s b/Core/Startup/startup_stm32f103c8tx.s index 7614285..3bb314b 100644 --- a/Core/Startup/startup_stm32f103c8tx.s +++ b/Core/Startup/startup_stm32f103c8tx.s @@ -60,8 +60,7 @@ defined in linker script */ .type Reset_Handler, %function Reset_Handler: -/* Call the clock system initialization function.*/ - bl SystemInit +/* Call the clock system initialization function.*/ bl SystemInit /* Copy the data segment initializers from flash to SRAM */ ldr r0, =_sdata diff --git a/StackSport.ioc b/StackSport.ioc index f9f033a..6e67818 100644 --- a/StackSport.ioc +++ b/StackSport.ioc @@ -115,12 +115,14 @@ PA3.GPIOParameters=GPIO_Speed,GPIO_Label PA3.GPIO_Label=LPWM_DOWN PA3.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PA3.Signal=S_TIM2_CH4 -PA4.GPIOParameters=GPIO_Label +PA4.GPIOParameters=GPIO_Speed,GPIO_Label PA4.GPIO_Label=LED_DATA +PA4.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PA4.Locked=true PA4.Signal=GPIO_Output -PA5.GPIOParameters=GPIO_Label +PA5.GPIOParameters=GPIO_Speed,GPIO_Label PA5.GPIO_Label=LED_CLK +PA5.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PA5.Locked=true PA5.Signal=GPIO_Output PA6.GPIOParameters=GPIO_PuPd,GPIO_Label @@ -205,7 +207,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM2_Init-TIM2-false-HAL-true,8-MX_TIM3_Init-TIM3-false-HAL-true,9-MX_USART3_UART_Init-USART3-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM2_Init-TIM2-false-HAL-true,8-MX_TIM3_Init-TIM3-false-HAL-true,9-MX_USART3_UART_Init-USART3-false-HAL-true,10-MX_IWDG_Init-IWDG-false-HAL-true RCC.ADCFreqValue=24000000 RCC.AHBFreq_Value=48000000 RCC.APB1CLKDivider=RCC_HCLK_DIV2