This commit is contained in:
DashyFox 2024-09-10 01:09:10 +03:00
parent 8aed06aa9c
commit c85e6aca95
6 changed files with 268 additions and 333 deletions

View File

@ -6,25 +6,25 @@
#define AT24C_ADRESS 0x50 // i2c slave adress EEPROM
#define START_ADR_STAT 0x0000 //00000
#define STAT_BLOCKSIZE 20
#define STAT_BLOCKSIZE sizeof(InfoBlock)
#define START_ADR_SHOT (START_ADR_STAT+STAT_BLOCKSIZE) // 0x0014 = 20
#define START_ADR_SHOT (START_ADR_STAT+STAT_BLOCKSIZE)
#define SHOT_BLOCKSIZE 10
#define MAX_NUMBER_SHOTS 255
#define START_ADR_PROGRAM (START_ADR_SHOT + (SHOT_BLOCKSIZE*MAX_NUMBER_SHOTS)) // 0x0A0A = 2570
#define START_ADR_PROGRAM (START_ADR_SHOT + (SHOT_BLOCKSIZE*MAX_NUMBER_SHOTS))
#define PROGRAM_BLOCKSIZE 203
#define MAX_NUMBER_PROGRAMS 100
#define MAX_NUMBER_SHOTS_IN_PROGRAMS \
(PROGRAM_BLOCKSIZE-sizeof(ProgramHeader)) /sizeof(ProgramShot) // 100
#define START_ADR_MACRO (START_ADR_PROGRAM + (PROGRAM_BLOCKSIZE*MAX_NUMBER_PROGRAMS)) // 0x5956 = 22870
#define START_ADR_MACRO (START_ADR_PROGRAM + (PROGRAM_BLOCKSIZE*MAX_NUMBER_PROGRAMS))
#define MACRO_BLOCKSIZE 81
#define MAX_NUMBER_MACRO 100
#define MAX_NUMBER_PROGRAMS_IN_MACRO \
(MACRO_BLOCKSIZE-sizeof(MacroHeader)) /sizeof(MacroProgram) // 20
#define MEMORY_END (START_ADR_MACRO + (MACRO_BLOCKSIZE*MAX_NUMBER_MACRO)) // 0x78FA = 30970
#define MEMORY_END (START_ADR_MACRO + (MACRO_BLOCKSIZE*MAX_NUMBER_MACRO))
typedef enum MemoryStatus {
EEPROM_FAIL,
@ -103,16 +103,20 @@ typedef struct HardwareInit_t{
}HardwareInit_t;
typedef struct Statistics{
uint16_t totalShots;
uint16_t totalPrograms;
uint16_t totalMacros;
uint32_t totalShots;
uint32_t totalPrograms;
uint32_t totalMacros;
}Statistics;
typedef struct InfoBlock{
HardwareInit_t hwInfo;
Statistics statInfo;
}InfoBlock;
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number, uint8_t *writeData, uint8_t dataSize);
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number, uint8_t *readData, uint8_t dataSize);
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number,
uint8_t *writeData);
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number,
uint8_t *outData);
MemoryStatus saveShot(unsigned char number, Shot *shot);
MemoryStatus getShot(unsigned char number, Shot *shot);

View File

@ -6,7 +6,7 @@
MemoryStatus saveShot(unsigned char number, Shot* shot)
{
if(FLASH_WriteBlock(START_ADR_SHOT, number, (uint8_t*)shot) == EEPROM_OK){
if (FLASH_WriteBlock(START_ADR_SHOT, number, (uint8_t*)shot, SHOT_BLOCKSIZE) == EEPROM_OK) {
return EEPROM_OK;
}
return EEPROM_FAIL;
@ -14,7 +14,7 @@ MemoryStatus saveShot(unsigned char number, Shot* shot)
MemoryStatus getShot(unsigned char number, Shot* shot)
{
if(FLASH_ReadBlock(START_ADR_SHOT, number, (uint8_t*)&shot) != EEPROM_OK){
if (FLASH_ReadBlock(START_ADR_SHOT, number, (uint8_t*)shot, SHOT_BLOCKSIZE) != EEPROM_OK) {
return EEPROM_FAIL;
}
if (!shot->isExist) {
@ -33,11 +33,12 @@ MemoryStatus saveProg(unsigned char number, Program* prog)
return EEPROM_FAIL;
}
if (!shot.isExist) {
//todo: add to shotRequest order
// todo: добавить в запросы для загрузки снимков
result = EEPROM_MISSING_ELEMENT;
}
}
if(FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*)prog) != EEPROM_OK){
if (FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*)prog, PROGRAM_BLOCKSIZE) != EEPROM_OK) {
return EEPROM_FAIL;
}
return result;
@ -45,7 +46,7 @@ MemoryStatus saveProg(unsigned char number, Program* prog)
MemoryStatus getProg(unsigned char number, Program* prog)
{
if(FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*)&prog) != EEPROM_OK){
if (FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*)prog, PROGRAM_BLOCKSIZE) != EEPROM_OK) {
return EEPROM_FAIL;
}
@ -67,20 +68,21 @@ MemoryStatus saveMacro(unsigned char number, Macro* macro)
}
if (!prog.header.isExist) {
result = EEPROM_MISSING_ELEMENT;
//todo: add to programRequest order
// todo: добавить в запросы для загрузки программ
}
}
if(FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*)macro) != EEPROM_OK){
if (FLASH_WriteBlock(START_ADR_MACRO, number, (uint8_t*)macro, MACRO_BLOCKSIZE) != EEPROM_OK) {
return EEPROM_FAIL;
}
return result;
}
MemoryStatus getMacro(unsigned char number, Macro* macro)
{
if(FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*)&macro) != EEPROM_OK){
if (FLASH_ReadBlock(START_ADR_MACRO, number, (uint8_t*)macro, MACRO_BLOCKSIZE) != EEPROM_OK) {
return EEPROM_FAIL;
}
@ -90,34 +92,16 @@ MemoryStatus getMacro( unsigned char number, Macro* macro)
return EEPROM_OK;
}
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number, uint8_t *writeData)
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number, uint8_t *writeData, uint8_t dataSize)
{
HAL_StatusTypeDef result;
uint8_t dataSize;
// protect and select
switch (startAddr) {
case START_ADR_STAT:
number = 0;
dataSize = STAT_BLOCKSIZE;
break;
case START_ADR_SHOT:
dataSize = SHOT_BLOCKSIZE;
if(number > MAX_NUMBER_SHOTS)
// Проверка на корректность входных данных
if ((startAddr == START_ADR_SHOT && number > MAX_NUMBER_SHOTS) ||
(startAddr == START_ADR_PROGRAM && number > MAX_NUMBER_PROGRAMS) ||
(startAddr == START_ADR_MACRO && number > MAX_NUMBER_MACRO)) {
return EEPROM_OUT_OF_RANGE;
break;
case START_ADR_PROGRAM:
dataSize = PROGRAM_BLOCKSIZE;
if(number > MAX_NUMBER_PROGRAMS)
return EEPROM_OUT_OF_RANGE;
break;
case START_ADR_MACRO:
dataSize = MACRO_BLOCKSIZE;
if(number > MAX_NUMBER_MACRO)
return EEPROM_OUT_OF_RANGE;
break;
default:
return EEPROM_WRONG_STARTADDR;
break;
}
uint16_t blockAddr16 = (uint16_t)(startAddr + (uint16_t)(number * dataSize));
@ -128,40 +112,22 @@ MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number, uint8_t *write
Buf[0] = blockAddr[0];
Buf[1] = blockAddr[1];
for( unsigned char i = 0; i < (dataSize); i++ ) Buf[i+2] = writeData[i];
for (unsigned char i = 0; i < dataSize; i++) Buf[i + 2] = writeData[i];
result = HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), Buf, (dataSize + 2), 10);
HAL_Delay(1);
return result;
}
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number, uint8_t *readData){
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number, uint8_t *readData, uint8_t dataSize)
{
HAL_StatusTypeDef result;
uint8_t dataSize;
// protect and select
switch (startAddr) {
case START_ADR_STAT:
number = 0;
dataSize = STAT_BLOCKSIZE;
break;
case START_ADR_SHOT:
dataSize = SHOT_BLOCKSIZE;
if(number > MAX_NUMBER_SHOTS)
// Проверка на корректность входных данных
if ((startAddr == START_ADR_SHOT && number > MAX_NUMBER_SHOTS) ||
(startAddr == START_ADR_PROGRAM && number > MAX_NUMBER_PROGRAMS) ||
(startAddr == START_ADR_MACRO && number > MAX_NUMBER_MACRO)) {
return EEPROM_OUT_OF_RANGE;
break;
case START_ADR_PROGRAM:
dataSize = PROGRAM_BLOCKSIZE;
if(number > MAX_NUMBER_PROGRAMS)
return EEPROM_OUT_OF_RANGE;
break;
case START_ADR_MACRO:
dataSize = MACRO_BLOCKSIZE;
if(number > MAX_NUMBER_MACRO)
return EEPROM_OUT_OF_RANGE;
break;
default:
return EEPROM_WRONG_STARTADDR;
break;
}
memset(readData, 0x00, dataSize);

View File

@ -14,10 +14,7 @@
enum IR_MENU {
IR_MENU_Home,
IR_MENU_SHOT,
IR_MENU_PROGR,
IR_MENU_MACRO,
IR_MENU_,
IR_MENU_SHOT, IR_MENU_PROGR, IR_MENU_MACRO, IR_MENU_,
};
@ -45,8 +42,6 @@ void onSelectShot(){
}
}
unsigned char b1 = 1;
unsigned char b2 = 1;
unsigned char b3 = 1;
@ -97,37 +92,52 @@ void IR_Home_Process() {
case IR_PAUSE:
{
uint8_t buf[32];
uint16_t blockAddr16 = 0; // Начальный адрес блока в EEPROM
uint8_t blockAddr[2] = {HIBYTE(blockAddr16), LOBYTE(blockAddr16)}; // Адрес в формате 2 байта
uint8_t buf[128]; // Буфер для чтения данных размером 128 байт
uint16_t blockAddr16 = 0; // Начальный адрес EEPROM
uint8_t blockAddr[2] = { (uint8_t)(blockAddr16 >> 8), (uint8_t)(blockAddr16 & 0xFF) }; // Адрес в формате 2 байта
int max_attempts = 15; // Максимальное количество попыток для операции
int attempts = 0; // Счетчик попыток
HAL_StatusTypeDef status;
do {
// Отправляем адрес в EEPROM
if (HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), blockAddr, 2, 1000) == HAL_OK) {
status = HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), blockAddr, 2, 1000);
if (status != HAL_OK) {
HAL_Delay(5); // Задержка перед повтором
attempts++;
continue; // Переход к следующей попытке
}
HAL_Delay(1); // Небольшая задержка
// Читаем данные из EEPROM
if (HAL_I2C_Master_Receive(&hi2c1, (AT24C_ADRESS << 1), buf, sizeof(buf), 1000) == HAL_OK) {
// Выводим считанные данные
for (int i = 0; i < sizeof(buf); ++i) {
if (!(i % 8)) print(" ");
if (!(i % 32)) print("\n");
// Читаем 128 байт данных из EEPROM
status = HAL_I2C_Master_Receive(&hi2c1, (AT24C_ADRESS << 1) | 1, buf, sizeof(buf), 1000);
if (status == HAL_OK) {
// Данные успешно считаны, выводим их
char buffer[16];
snprintf(buffer, sizeof(buffer), "%02X ", buf[i]); // Преобразуем байт в шестнадцатеричную строку
for (int i = 0; i < sizeof(buf); ++i) {
if (i % 8 == 0) print(" ");
if (i % 32 == 0) print("\n");
// snprintf(buffer, sizeof(buffer), "%02X ", buf[i]); // Преобразуем байт в шестнадцатеричную строку
CDC_Transmit_FS((uint8_t*)buffer, strlen(buffer));
}
break; // Выход из попыток, если чтение успешно
} else {
print("Read Error EEPROM\n");
HAL_Delay(5); // Задержка перед повтором
attempts++;
}
} else {
print("Address TX Error EEPROM\n");
} while (attempts < max_attempts);
if (status != HAL_OK) {
print("Failed to read EEPROM after multiple attempts\n");
}
}
break;
case IR_DEBUG:
{
case IR_DEBUG: {
uint8_t i2c_address;
HAL_StatusTypeDef result;
@ -155,33 +165,22 @@ void IR_Home_Process() {
break;
case IR_NUM_1:
setRollersSpeed(speedUP+=1, speedDown);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_2:
setScrewkSpeed(screwSpeed+=1);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_3:
setRollersSpeed(speedUP, speedDown+=1);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_7:
setRollersSpeed(speedUP-=1, speedDown);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_8:
setScrewkSpeed(screwSpeed-=1);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_9:
setRollersSpeed(speedUP, speedDown-=1);
onHoldRepeat = IR_Home_Process;
break;
case IR_NUM_5:
setRollersSpeed(100,100);
break;
case IR_STOP:
@ -191,6 +190,48 @@ void IR_Home_Process() {
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;
}

View File

@ -52,6 +52,10 @@ HardwareInit_t hwSettings = {
extern int16_t Vz1;
extern int16_t Vz2;
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void doShot(Shot *shot) {
SetServo(0, shot->rotationHorizontal);
SetServo(1, shot->rotationVertical);
@ -99,13 +103,10 @@ void startShooting() {
void stopShooting() {
isShooting = 0;
isPause = 0;
setScrewkSpeed(0);
setRollersSpeed(100, 100);
setPosDefault();
Vz1 = 100;
Vz2 = 100;
TIM1->CCR1 = 0;
TIM1->CCR2 = 0;
}
void doShotForever(uint8_t number) {
@ -135,16 +136,18 @@ void setPos(uint8_t axial, uint8_t horizontal, uint8_t vertical) {
SetServo(SERVO_VERTICAL, vertical); // Vertical
}
void setPosDefault() {
SetServo(0, 90); // Axial
SetServo(1, 90); // Horizontal
SetServo(2, 90); // Vertical
SetServo(SERVO_AXIAL, hwSettings.servos[SERVO_AXIAL].def); // Axial
SetServo(SERVO_HORIZONTAL, hwSettings.servos[SERVO_HORIZONTAL].def); // Horizontal
SetServo(SERVO_VERTICAL, hwSettings.servos[SERVO_VERTICAL].def); // Vertical
}
// 0 .. 100
void setScrewkSpeed(uint8_t speed) {
if(speed && speed < hwSettings.motors.speed_Screw_min)
speed = hwSettings.motors.speed_Screw_min;
// if(speed < 0) speed = 0;
if(speed > 100) speed = 100;
speed = map(speed, 0, 100, hwSettings.motors.speed_Screw_min, 100);
TIM1->CCR1 = 0;
TIM1->CCR2 = (uint16_t)(40 * speed);
@ -153,6 +156,18 @@ void setScrewkSpeed(uint8_t speed) {
//(-v) 0 .. 100(stop) .. 200(+v)
void setRollersSpeed(uint8_t up, uint8_t down) {
if(up < 100){
up = map(up, 0, 100, 0, 100-hwSettings.motors.speed_Screw_min);
} else {
up = map(up, 0, 100, 0, 100+hwSettings.motors.speed_Screw_min);
}
if(down < 100){
map(down, 0, 100, 0, 100-hwSettings.motors.speed_Screw_min);
} else {
map(down, 0, 100, 0, 100+hwSettings.motors.speed_Screw_min);
}
Vz1 = 200-up; // invert
Vz2 = down;
}

View File

@ -204,7 +204,9 @@ initcomlete = 1;
/* USER CODE BEGIN WHILE */
Shot testShot;
memset(&testShot, 0x00, sizeof(Shot));
getShot(3, &testShot);
if(!testShot.isExist){
testShot.countRepeatShot = 1;
testShot.speedRollerTop = 200;

97
TODO.md
View File

@ -8,7 +8,7 @@ IR:
V Добавить press and hold
Проверка железа:
Проверить все PWM
V Проверить все PWM
Проверить функции управления железом
setRollersSpeed
setScrewkSpeed
@ -17,7 +17,7 @@ IR:
doShot
Логика работы:
Ограничение минимальных скоростей!
V Ограничение минимальных скоростей!
Правильное переключение выстрелов с учётом repeatCount
Переключение выстрелов в программе
Переключение программ в макро
@ -39,96 +39,3 @@ IR:
Ошибки:
В некоторый момент PID регулятор выдаёт 0 и двигатель не запускается не зависимо от входного значенияPWM
uint32_t GetTimerClockFrequency(TIM_TypeDef *TIMx) {
uint32_t clock_frequency = 0;
uint32_t sysclk_frequency = 0;
uint32_t hclk_frequency = 0;
uint32_t apb1_frequency = 0;
uint32_t apb2_frequency = 0;
// Определяем источник системного тактирования (SYSCLK)
switch (RCC->CFGR & RCC_CFGR_SWS) {
case RCC_CFGR_SWS_HSI: // HSI используется как системный клок
sysclk_frequency = 8000000; // HSI - 8 MHz
break;
case RCC_CFGR_SWS_HSE: // HSE используется как системный клок
sysclk_frequency = HSE_VALUE; // Предположим, что значение HSE_VALUE определено
break;
case RCC_CFGR_SWS_PLL: // PLL используется как системный клок
// Получаем значение входного тактового сигнала PLL
if ((RCC->CFGR & RCC_CFGR_PLLSRC) == RCC_CFGR_PLLSRC_HSI_DIV2) {
sysclk_frequency = 4000000; // HSI/2 - 4 MHz
} else {
sysclk_frequency = HSE_VALUE; // HSE_VALUE определено как 8 или 16 MHz
}
// Получаем множитель PLL
uint32_t pll_mul = ((RCC->CFGR & RCC_CFGR_PLLMULL) >> 18) + 2;
sysclk_frequency *= pll_mul;
break;
default:
sysclk_frequency = 8000000; // По умолчанию HSI
break;
}
// Определяем частоту шины AHB (HCLK)
uint32_t ahb_prescaler = (RCC->CFGR & RCC_CFGR_HPRE) >> 4;
if (ahb_prescaler < 8) {
hclk_frequency = sysclk_frequency;
} else {
hclk_frequency = sysclk_frequency >> ((ahb_prescaler - 7));
}
// Определяем частоту шины APB1
uint32_t apb1_prescaler = (RCC->CFGR & RCC_CFGR_PPRE1) >> 8;
if (apb1_prescaler < 4) {
apb1_frequency = hclk_frequency;
} else {
apb1_frequency = hclk_frequency >> ((apb1_prescaler - 3));
}
// Определяем частоту шины APB2
uint32_t apb2_prescaler = (RCC->CFGR & RCC_CFGR_PPRE2) >> 11;
if (apb2_prescaler < 4) {
apb2_frequency = hclk_frequency;
} else {
apb2_frequency = hclk_frequency >> ((apb2_prescaler - 3));
}
// Определяем частоту для конкретного таймера
if (TIMx == TIM1 || TIMx == TIM8) { // Таймеры на шине APB2
clock_frequency = (apb2_prescaler == 0 ? apb2_frequency : apb2_frequency * 2);
} else { // Таймеры на шине APB1
clock_frequency = (apb1_prescaler == 0 ? apb1_frequency : apb1_frequency * 2);
}
return clock_frequency;
}
// Функция для вычисления целевого значения
uint32_t CalculateTargetCount(TIM_TypeDef *TIMx, uint32_t freq) {
// Проверяем, что частота не равна нулю
if (freq == 0) return 0xFFFFFFFF; // Защита от деления на ноль
// Получаем частоту тактового генератора для данного таймера
uint32_t clock_frequency = GetTimerClockFrequency(TIMx);
// Получаем значение предделителя (PSC) и ARR таймера
uint32_t psc = TIMx->PSC;
uint32_t arr = TIMx->ARR;
// Вычисляем частоту работы таймера
uint32_t timer_frequency = clock_frequency / ((psc + 1) * (arr + 1));
// Вычисляем целевое значение счетчика для заданной частоты
uint32_t target_count = timer_frequency / freq;
return target_count;
}