mirror of
https://github.com/DashyFox/StackSport.git
synced 2025-05-04 15:20:16 +00:00
window clip variant
This commit is contained in:
parent
2ef50d8b07
commit
953593d32a
@ -3,10 +3,13 @@
|
|||||||
#ifndef INC_EEPROM_H_
|
#ifndef INC_EEPROM_H_
|
||||||
#define INC_EEPROM_H_
|
#define INC_EEPROM_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define AT24C_ADRESS 0x50 // i2c slave adress EEPROM
|
#define AT24C_ADRESS 0x50 // i2c slave adress EEPROM
|
||||||
|
|
||||||
#define START_ADR_STAT 0x0000 //00000
|
#define START_ADR_STAT 0x0000 //00000
|
||||||
#define STAT_BLOCKSIZE sizeof(InfoBlock)
|
|
||||||
|
#define STAT_BLOCKSIZE 128
|
||||||
|
|
||||||
#define START_ADR_SHOT (START_ADR_STAT+STAT_BLOCKSIZE)
|
#define START_ADR_SHOT (START_ADR_STAT+STAT_BLOCKSIZE)
|
||||||
#define SHOT_BLOCKSIZE 10
|
#define SHOT_BLOCKSIZE 10
|
||||||
@ -34,7 +37,7 @@ typedef enum MemoryStatus {
|
|||||||
EEPROM_OK
|
EEPROM_OK
|
||||||
} MemoryStatus;
|
} MemoryStatus;
|
||||||
|
|
||||||
typedef struct Shot {
|
typedef struct __attribute__((packed)) {
|
||||||
unsigned char isExist;
|
unsigned char isExist;
|
||||||
unsigned char countRepeatShot; // 0 = inf
|
unsigned char countRepeatShot; // 0 = inf
|
||||||
unsigned char speedRollerTop; // 0 .. 100 .. 200
|
unsigned char speedRollerTop; // 0 .. 100 .. 200
|
||||||
@ -45,50 +48,50 @@ typedef struct Shot {
|
|||||||
unsigned char rotationVertical; // 0 .. 90 .. 180
|
unsigned char rotationVertical; // 0 .. 90 .. 180
|
||||||
} Shot;
|
} Shot;
|
||||||
|
|
||||||
typedef struct ProgramHeader {
|
typedef struct __attribute__((packed)) {
|
||||||
unsigned char isExist;
|
unsigned char isExist;
|
||||||
unsigned char countRepeat;
|
unsigned char countRepeat;
|
||||||
unsigned char options;
|
unsigned char options;
|
||||||
} ProgramHeader;
|
} ProgramHeader;
|
||||||
|
|
||||||
typedef struct ProgramShot {
|
typedef struct __attribute__((packed)) {
|
||||||
unsigned char id;
|
unsigned char id;
|
||||||
unsigned char speedScrew;
|
unsigned char speedScrew;
|
||||||
} ProgramShot;
|
} ProgramShot;
|
||||||
|
|
||||||
typedef struct Program {
|
typedef struct __attribute__((packed)) {
|
||||||
ProgramHeader header;
|
ProgramHeader header;
|
||||||
ProgramShot shots[MAX_SHOT_COUNT_IN_PROGRAMS];
|
ProgramShot shots[MAX_SHOT_COUNT_IN_PROGRAMS];
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
typedef struct MacroHeader {
|
typedef struct __attribute__((packed)) {
|
||||||
unsigned char isExist;
|
unsigned char isExist;
|
||||||
} MacroHeader;
|
} MacroHeader;
|
||||||
|
|
||||||
typedef struct MacroProgram {
|
typedef struct __attribute__((packed)) {
|
||||||
unsigned char id;
|
unsigned char id;
|
||||||
unsigned char speedScrew;
|
unsigned char speedScrew;
|
||||||
unsigned char countRepeat;
|
unsigned char countRepeat;
|
||||||
unsigned char options;
|
unsigned char options;
|
||||||
} MacroProgram;
|
} MacroProgram;
|
||||||
|
|
||||||
typedef struct Macro {
|
typedef struct __attribute__((packed)) {
|
||||||
MacroHeader header;
|
MacroHeader header;
|
||||||
MacroProgram programs[MAX_PROGRAM_COUNT_IN_MACRO];
|
MacroProgram programs[MAX_PROGRAM_COUNT_IN_MACRO];
|
||||||
} Macro;
|
} Macro;
|
||||||
|
|
||||||
typedef struct ServoSetting {
|
typedef struct __attribute__((packed)) {
|
||||||
uint8_t invert;
|
uint8_t invert;
|
||||||
uint16_t min;
|
uint16_t min;
|
||||||
uint16_t def;
|
uint16_t def;
|
||||||
uint16_t max;
|
uint16_t max;
|
||||||
} ServoSetting;
|
} ServoSetting;
|
||||||
|
|
||||||
typedef struct DelayTimes{
|
typedef struct __attribute__((packed)) {
|
||||||
uint16_t preRun;
|
uint16_t preRun;
|
||||||
} DelayTimes;
|
} DelayTimes;
|
||||||
|
|
||||||
typedef struct Motors{
|
typedef struct __attribute__((packed)) {
|
||||||
uint16_t speed_Rollers_min;
|
uint16_t speed_Rollers_min;
|
||||||
// uint16_t speed_Rollers_max;
|
// uint16_t speed_Rollers_max;
|
||||||
|
|
||||||
@ -96,32 +99,36 @@ typedef struct Motors{
|
|||||||
// uint16_t speed_Screw_max;
|
// uint16_t speed_Screw_max;
|
||||||
} Motors;
|
} Motors;
|
||||||
|
|
||||||
typedef struct HardwareInit_t{
|
typedef struct __attribute__((packed)) {
|
||||||
DelayTimes timings;
|
DelayTimes timings;
|
||||||
ServoSetting servos[3];
|
ServoSetting servos[3];
|
||||||
Motors motors;
|
Motors motors;
|
||||||
} HardwareInit_t;
|
} HardwareInit_t;
|
||||||
|
|
||||||
typedef struct Statistics{
|
typedef struct __attribute__((packed)) {
|
||||||
uint32_t totalShots;
|
uint32_t totalShots;
|
||||||
uint32_t totalPrograms;
|
uint32_t totalPrograms;
|
||||||
uint32_t totalMacros;
|
uint32_t totalMacros;
|
||||||
} Statistics;
|
} Statistics;
|
||||||
|
|
||||||
typedef struct InfoBlock{
|
typedef struct __attribute__((packed)) {
|
||||||
char init_uid[11];
|
char init_uid[11];
|
||||||
HardwareInit_t hwInfo;
|
HardwareInit_t hwInfo;
|
||||||
Statistics statInfo;
|
Statistics statInfo;
|
||||||
} InfoBlock;
|
} InfoBlock;
|
||||||
|
_Static_assert(sizeof(InfoBlock) <= STAT_BLOCKSIZE, "Error: InfoBlock size exceeds 128 bytes.");
|
||||||
|
|
||||||
extern InfoBlock infoBlock;
|
extern InfoBlock infoBlock;
|
||||||
|
|
||||||
|
// read from EEPROM infoBlock
|
||||||
|
// or write to EEPROM default infoBlock
|
||||||
MemoryStatus EEPROM_INIT();
|
MemoryStatus EEPROM_INIT();
|
||||||
MemoryStatus EEPROM_EARSE();
|
MemoryStatus EEPROM_EARSE();
|
||||||
|
|
||||||
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number, uint8_t *writeData, uint16_t dataSize);
|
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number,
|
||||||
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number, uint8_t *readData, uint16_t dataSize);
|
uint8_t *writeData, uint16_t dataSize);
|
||||||
|
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number,
|
||||||
|
uint8_t *readData, uint16_t dataSize);
|
||||||
|
|
||||||
MemoryStatus saveShot(unsigned char number, Shot *shot);
|
MemoryStatus saveShot(unsigned char number, Shot *shot);
|
||||||
MemoryStatus getShot(unsigned char number, Shot *shot);
|
MemoryStatus getShot(unsigned char number, Shot *shot);
|
||||||
@ -132,7 +139,7 @@ MemoryStatus getProg(unsigned char number, Program *prog);
|
|||||||
MemoryStatus saveMacro(unsigned char number, Macro *macro);
|
MemoryStatus saveMacro(unsigned char number, Macro *macro);
|
||||||
MemoryStatus getMacro(unsigned char number, Macro *macro);
|
MemoryStatus getMacro(unsigned char number, Macro *macro);
|
||||||
|
|
||||||
MemoryStatus saveInfoBlock(InfoBlock *infoBlock);
|
MemoryStatus saveInfoBlock();
|
||||||
MemoryStatus getInfoBlock(InfoBlock *infoBlock);
|
MemoryStatus getInfoBlock();
|
||||||
|
|
||||||
#endif /* INC_EEPROM_H_ */
|
#endif /* INC_EEPROM_H_ */
|
||||||
|
@ -51,6 +51,7 @@ typedef struct CurrentInfo {
|
|||||||
CurrentMacro macro;
|
CurrentMacro macro;
|
||||||
} CurrentInfo;
|
} CurrentInfo;
|
||||||
|
|
||||||
|
void Robot_INIT();
|
||||||
|
|
||||||
void doShot(Shot*);
|
void doShot(Shot*);
|
||||||
void doShotForever(uint8_t number);
|
void doShotForever(uint8_t number);
|
||||||
@ -60,11 +61,13 @@ uint8_t prepareShot(uint8_t number);
|
|||||||
void startShooting();
|
void startShooting();
|
||||||
void stopShooting();
|
void stopShooting();
|
||||||
|
|
||||||
|
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min,
|
||||||
|
int16_t out_max);
|
||||||
|
|
||||||
void setPos(uint8_t axial, uint8_t horizontal, uint8_t vertical);
|
void setPos(uint8_t axial, uint8_t horizontal, uint8_t vertical);
|
||||||
void setPosSingle(ServoMap servo, uint8_t value);
|
void setPosSingle(ServoMap servo, uint8_t value);
|
||||||
void setPosDefault();
|
void setPosDefault();
|
||||||
|
void setPosDefaultSingle(ServoMap servo);
|
||||||
|
|
||||||
// 0 .. 100
|
// 0 .. 100
|
||||||
void setScrewkSpeed(uint8_t speed);
|
void setScrewkSpeed(uint8_t speed);
|
||||||
|
@ -26,6 +26,8 @@ void UART3_SetServoOffset(uint8_t *dataPtr, uint8_t len);
|
|||||||
void UART3_GetServoOffset(uint8_t *dataPtr, uint8_t len);
|
void UART3_GetServoOffset(uint8_t *dataPtr, uint8_t len);
|
||||||
void UART3_SetServoMaxAngle(uint8_t *dataPtr, uint8_t len);
|
void UART3_SetServoMaxAngle(uint8_t *dataPtr, uint8_t len);
|
||||||
void UART3_GetServoMaxAngle(uint8_t *dataPtr, uint8_t len);
|
void UART3_GetServoMaxAngle(uint8_t *dataPtr, uint8_t len);
|
||||||
|
void UART3_SetServoMinAngle(uint8_t *dataPtr, uint8_t len);
|
||||||
|
void UART3_GetServoMinAngle(uint8_t *dataPtr, uint8_t len);
|
||||||
void UART3_MoveServoToInitialPosition(uint8_t *dataPtr, uint8_t len);
|
void UART3_MoveServoToInitialPosition(uint8_t *dataPtr, uint8_t len);
|
||||||
void UART3_SetStartupDelay(uint8_t *dataPtr, uint8_t len);
|
void UART3_SetStartupDelay(uint8_t *dataPtr, uint8_t len);
|
||||||
void UART3_GetStartupDelay(uint8_t *dataPtr, uint8_t len);
|
void UART3_GetStartupDelay(uint8_t *dataPtr, uint8_t len);
|
||||||
|
@ -6,123 +6,7 @@
|
|||||||
|
|
||||||
InfoBlock infoBlock;
|
InfoBlock infoBlock;
|
||||||
|
|
||||||
MemoryStatus saveInfoBlock(InfoBlock *infoBlock) {
|
//*********************** EEPROM_INIT ********************************//
|
||||||
return FLASH_WriteBlock(START_ADR_STAT, 0, (uint8_t*) infoBlock,
|
|
||||||
sizeof(InfoBlock));
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus getInfoBlock(InfoBlock *infoBlock) {
|
|
||||||
MemoryStatus status = FLASH_ReadBlock(START_ADR_STAT, 0,
|
|
||||||
(uint8_t*) infoBlock, sizeof(InfoBlock));
|
|
||||||
|
|
||||||
if (status != EEPROM_OK) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus saveShot(unsigned char number, Shot *shot) {
|
|
||||||
if (FLASH_WriteBlock(START_ADR_SHOT, number, (uint8_t*) shot,
|
|
||||||
SHOT_BLOCKSIZE) == EEPROM_OK) {
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus getShot(unsigned char number, Shot *shot) {
|
|
||||||
if (FLASH_ReadBlock(START_ADR_SHOT, number, (uint8_t*) shot, SHOT_BLOCKSIZE)
|
|
||||||
!= EEPROM_OK) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
if (!shot->isExist) {
|
|
||||||
return EEPROM_MISSING_ELEMENT;
|
|
||||||
}
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus saveProg(unsigned char number, Program *prog) {
|
|
||||||
MemoryStatus result = EEPROM_OK;
|
|
||||||
for (uint16_t i = 0; i < MAX_SHOT_COUNT_IN_PROGRAMS; ++i) {
|
|
||||||
Shot shot;
|
|
||||||
MemoryStatus stat = getShot(prog->shots[i].id, &shot);
|
|
||||||
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
if (!shot.isExist) {
|
|
||||||
// todo: добавить в запросы для загрузки снимков
|
|
||||||
result = EEPROM_MISSING_ELEMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*) prog,
|
|
||||||
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus getProg(unsigned char number, Program *prog) {
|
|
||||||
if (FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*) prog,
|
|
||||||
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!prog->header.isExist) {
|
|
||||||
return EEPROM_MISSING_ELEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus saveMacro(unsigned char number, Macro *macro) {
|
|
||||||
MemoryStatus result = EEPROM_OK;
|
|
||||||
for (uint16_t i = 0; i < MAX_PROGRAM_COUNT_IN_MACRO; ++i) {
|
|
||||||
Program prog;
|
|
||||||
MemoryStatus stat = getProg(macro->programs[i].id, &prog);
|
|
||||||
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
if (!prog.header.isExist) {
|
|
||||||
result = EEPROM_MISSING_ELEMENT;
|
|
||||||
// todo: добавить в запросы для загрузки программ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_MACRO, number, (uint8_t*) macro,
|
|
||||||
MACRO_BLOCKSIZE) != EEPROM_OK) {
|
|
||||||
return EEPROM_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!macro->header.isExist) {
|
|
||||||
return EEPROM_MISSING_ELEMENT;
|
|
||||||
}
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus EEPROM_EARSE() {
|
|
||||||
uint16_t addr = 0;
|
|
||||||
uint16_t old_addr = 0;
|
|
||||||
do {
|
|
||||||
uint8_t Buf[255];
|
|
||||||
memset(Buf, 0xFF, sizeof(Buf));
|
|
||||||
FLASH_WriteBlock(addr, 0, Buf, (uint8_t) sizeof(Buf));
|
|
||||||
old_addr = addr;
|
|
||||||
addr += sizeof(Buf);
|
|
||||||
} while (old_addr <= addr);
|
|
||||||
|
|
||||||
return EEPROM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryStatus EEPROM_INIT() {
|
MemoryStatus EEPROM_INIT() {
|
||||||
memset(&infoBlock, 0x00, sizeof(infoBlock));
|
memset(&infoBlock, 0x00, sizeof(infoBlock));
|
||||||
MemoryStatus status = getInfoBlock(&infoBlock);
|
MemoryStatus status = getInfoBlock(&infoBlock);
|
||||||
@ -241,6 +125,125 @@ MemoryStatus EEPROM_INIT() {
|
|||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
//************************************************************//
|
||||||
|
|
||||||
|
|
||||||
|
MemoryStatus saveInfoBlock() {
|
||||||
|
return FLASH_WriteBlock(START_ADR_STAT, 0, (uint8_t*) &infoBlock,
|
||||||
|
sizeof(InfoBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus getInfoBlock() {
|
||||||
|
MemoryStatus status = FLASH_ReadBlock(START_ADR_STAT, 0,
|
||||||
|
(uint8_t*) &infoBlock, sizeof(InfoBlock));
|
||||||
|
|
||||||
|
if (status != EEPROM_OK) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus saveShot(unsigned char number, Shot *shot) {
|
||||||
|
if (FLASH_WriteBlock(START_ADR_SHOT, number, (uint8_t*) shot,
|
||||||
|
SHOT_BLOCKSIZE) == EEPROM_OK) {
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus getShot(unsigned char number, Shot *shot) {
|
||||||
|
if (FLASH_ReadBlock(START_ADR_SHOT, number, (uint8_t*) shot, SHOT_BLOCKSIZE)
|
||||||
|
!= EEPROM_OK) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
if (!shot->isExist) {
|
||||||
|
return EEPROM_MISSING_ELEMENT;
|
||||||
|
}
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus saveProg(unsigned char number, Program *prog) {
|
||||||
|
MemoryStatus result = EEPROM_OK;
|
||||||
|
for (uint16_t i = 0; i < MAX_SHOT_COUNT_IN_PROGRAMS; ++i) {
|
||||||
|
Shot shot;
|
||||||
|
MemoryStatus stat = getShot(prog->shots[i].id, &shot);
|
||||||
|
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
if (!shot.isExist) {
|
||||||
|
// todo: добавить в запросы для загрузки снимков
|
||||||
|
result = EEPROM_MISSING_ELEMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*) prog,
|
||||||
|
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus getProg(unsigned char number, Program *prog) {
|
||||||
|
if (FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*) prog,
|
||||||
|
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prog->header.isExist) {
|
||||||
|
return EEPROM_MISSING_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus saveMacro(unsigned char number, Macro *macro) {
|
||||||
|
MemoryStatus result = EEPROM_OK;
|
||||||
|
for (uint16_t i = 0; i < MAX_PROGRAM_COUNT_IN_MACRO; ++i) {
|
||||||
|
Program prog;
|
||||||
|
MemoryStatus stat = getProg(macro->programs[i].id, &prog);
|
||||||
|
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
if (!prog.header.isExist) {
|
||||||
|
result = EEPROM_MISSING_ELEMENT;
|
||||||
|
// todo: добавить в запросы для загрузки программ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_MACRO, number, (uint8_t*) macro,
|
||||||
|
MACRO_BLOCKSIZE) != EEPROM_OK) {
|
||||||
|
return EEPROM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!macro->header.isExist) {
|
||||||
|
return EEPROM_MISSING_ELEMENT;
|
||||||
|
}
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStatus EEPROM_EARSE() {
|
||||||
|
uint16_t addr = 0;
|
||||||
|
uint16_t old_addr = 0;
|
||||||
|
do {
|
||||||
|
uint8_t Buf[255];
|
||||||
|
memset(Buf, 0xFF, sizeof(Buf));
|
||||||
|
FLASH_WriteBlock(addr, 0, Buf, (uint8_t) sizeof(Buf));
|
||||||
|
old_addr = addr;
|
||||||
|
addr += sizeof(Buf);
|
||||||
|
} while (old_addr <= addr);
|
||||||
|
|
||||||
|
return EEPROM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number,
|
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number,
|
||||||
uint8_t *writeData, uint16_t dataSize) {
|
uint8_t *writeData, uint16_t dataSize) {
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RobotFunctions.h"
|
#include "RobotFunctions.h"
|
||||||
|
#include "pca9685.h"
|
||||||
|
#include "UART3_Handler.h"
|
||||||
#include "EEPROM.h"
|
#include "EEPROM.h"
|
||||||
|
#include "ShiftReg.h"
|
||||||
#include "Print.h"
|
#include "Print.h"
|
||||||
|
|
||||||
uint8_t isPause = 0;
|
uint8_t isPause = 0;
|
||||||
@ -14,19 +17,84 @@ uint8_t isShooting = 0;
|
|||||||
|
|
||||||
CurrentInfo currentInfo;
|
CurrentInfo currentInfo;
|
||||||
|
|
||||||
HardwareInit_t hwSettings = {
|
|
||||||
/*DelayTimes*/{
|
|
||||||
/*preRun*/0 },
|
|
||||||
/*ServoSetting*/{ { 0, 0, 90, 180 }, { 0, 0, 90, 180 }, { 0, 0, 90, 180 } },
|
|
||||||
/*Motors*/{ 0, 0 } };
|
|
||||||
|
|
||||||
extern int16_t Vz1;
|
extern int16_t Vz1;
|
||||||
extern int16_t Vz2;
|
extern int16_t Vz2;
|
||||||
|
unsigned char Shiftreg[3];
|
||||||
|
|
||||||
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min,
|
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min,
|
||||||
int16_t out_max) {
|
int16_t out_max) {
|
||||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
}
|
}
|
||||||
|
void Robot_INIT() {
|
||||||
|
memset(¤tInfo, 0x00, sizeof(currentInfo));
|
||||||
|
// NULL
|
||||||
|
currentInfo.shot.index = 0xFF;
|
||||||
|
currentInfo.program.index = 0xFF;
|
||||||
|
currentInfo.macro.index = 0xFF;
|
||||||
|
initPCA9685();
|
||||||
|
EEPROM_INIT();
|
||||||
|
UART3_START();
|
||||||
|
|
||||||
|
setPosDefault();
|
||||||
|
Shiftreg[0] = 0x00;
|
||||||
|
Shiftreg[1] = 0x44;
|
||||||
|
Shiftreg[2] = 0x00;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x00;
|
||||||
|
Shiftreg[1] = 0x66;
|
||||||
|
Shiftreg[2] = 0x00;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x00;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x00;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x01;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x01;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x03;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x03;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x07;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x07;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x0F;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x0F;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x1F;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x1F;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x3F;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x3F;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x7F;
|
||||||
|
Shiftreg[1] = 0x77;
|
||||||
|
Shiftreg[2] = 0x7F;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
Shiftreg[0] = 0x00;
|
||||||
|
Shiftreg[1] = 0x00;
|
||||||
|
Shiftreg[2] = 0x00;
|
||||||
|
SetShiftReg(Shiftreg);
|
||||||
|
HAL_Delay(10);
|
||||||
|
|
||||||
|
//testing
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void doShot(Shot *shot) {
|
void doShot(Shot *shot) {
|
||||||
SetServo(0, shot->rotationHorizontal);
|
SetServo(0, shot->rotationHorizontal);
|
||||||
@ -106,21 +174,45 @@ uint8_t prepareShot(uint8_t number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setPosSingle(ServoMap servo, uint8_t value) {
|
void setPosSingle(ServoMap servo, uint8_t value) {
|
||||||
if (hwSettings.servos[servo].invert)
|
ServoSetting* currentServo = &infoBlock.hwInfo.servos[servo];
|
||||||
|
uint8_t inv = currentServo->invert;
|
||||||
|
if (servo == SERVO_AXIAL)
|
||||||
|
inv = !inv;
|
||||||
|
|
||||||
|
uint8_t deviationToMax = currentServo->max > currentServo->def
|
||||||
|
? currentServo->max - currentServo->def
|
||||||
|
: currentServo->def - currentServo->max;
|
||||||
|
|
||||||
|
uint8_t deviationToMin = currentServo->def > currentServo->min
|
||||||
|
? currentServo->def - currentServo->min
|
||||||
|
: currentServo->min - currentServo->def;
|
||||||
|
|
||||||
|
uint8_t maxDeviation = (deviationToMax > deviationToMin) ? deviationToMax : deviationToMin;
|
||||||
|
uint8_t minLimit = (currentServo->def >= maxDeviation) ? currentServo->def - maxDeviation : 0;
|
||||||
|
uint8_t maxLimit = (currentServo->def + maxDeviation <= 180) ? currentServo->def + maxDeviation : 180;
|
||||||
|
if (value > maxLimit) {
|
||||||
|
value = maxLimit;
|
||||||
|
} else if (value < minLimit) {
|
||||||
|
value = minLimit;
|
||||||
|
}
|
||||||
|
if (inv)
|
||||||
value = 180 - value;
|
value = 180 - value;
|
||||||
SetServo(servo, value);
|
SetServo(servo, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setPos(uint8_t axial, uint8_t horizontal, uint8_t vertical) {
|
void setPos(uint8_t axial, uint8_t horizontal, uint8_t vertical) {
|
||||||
setPosSingle(SERVO_AXIAL, axial);
|
setPosSingle(SERVO_AXIAL, axial);
|
||||||
setPosSingle(SERVO_HORIZONTAL, horizontal);
|
setPosSingle(SERVO_HORIZONTAL, horizontal);
|
||||||
setPosSingle(SERVO_VERTICAL, vertical);
|
setPosSingle(SERVO_VERTICAL, vertical);
|
||||||
}
|
}
|
||||||
void setPosDefault() {
|
void setPosDefault() {
|
||||||
setPos(
|
setPos(infoBlock.hwInfo.servos[SERVO_AXIAL].def,
|
||||||
hwSettings.servos[SERVO_AXIAL].def,
|
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].def,
|
||||||
hwSettings.servos[SERVO_HORIZONTAL].def,
|
infoBlock.hwInfo.servos[SERVO_VERTICAL].def);
|
||||||
hwSettings.servos[SERVO_VERTICAL].def
|
}
|
||||||
);
|
void setPosDefaultSingle(ServoMap servo) {
|
||||||
|
setPosSingle(servo, infoBlock.hwInfo.servos[servo].def);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 .. 100
|
// 0 .. 100
|
||||||
@ -130,7 +222,9 @@ void setScrewkSpeed(uint8_t speed) {
|
|||||||
if (speed > 100)
|
if (speed > 100)
|
||||||
speed = 100;
|
speed = 100;
|
||||||
|
|
||||||
speed = map(speed, 0, 100, hwSettings.motors.speed_Screw_min, 100);
|
// speed = map(speed, 0, 100, infoBlock.hwInfo.motors.speed_Screw_min, 100);
|
||||||
|
if (speed && speed < infoBlock.hwInfo.motors.speed_Screw_min)
|
||||||
|
speed = infoBlock.hwInfo.motors.speed_Screw_min;
|
||||||
|
|
||||||
TIM1->CCR1 = 0;
|
TIM1->CCR1 = 0;
|
||||||
TIM1->CCR2 = (uint16_t) (40 * speed);
|
TIM1->CCR2 = (uint16_t) (40 * speed);
|
||||||
@ -140,15 +234,23 @@ void setScrewkSpeed(uint8_t speed) {
|
|||||||
void setRollersSpeed(uint8_t up, uint8_t down) {
|
void setRollersSpeed(uint8_t up, uint8_t down) {
|
||||||
|
|
||||||
if (up < 100) {
|
if (up < 100) {
|
||||||
up = map(up, 0, 100, 0, 100 - hwSettings.motors.speed_Screw_min);
|
// up = map(up, 0, 100, 0, 100 - infoBlock.hwInfo.motors.speed_Screw_min);
|
||||||
|
// if (100 - up < min_speed) {
|
||||||
|
// up = 100 - min_speed;
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
up = map(up, 0, 100, 0, 100 + hwSettings.motors.speed_Screw_min);
|
// up = map(up, 0, 100, 0, 100 + infoBlock.hwInfo.motors.speed_Screw_min);
|
||||||
|
// if (up - 100 < min_speed) { // Ограничиваем положительную скорость минимальной
|
||||||
|
// up = 100 + min_speed;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (down < 100) {
|
if (down < 100) {
|
||||||
map(down, 0, 100, 0, 100 - hwSettings.motors.speed_Screw_min);
|
// map(down, 0, 100, 0, 100 - infoBlock.hwInfo.motors.speed_Screw_min);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
map(down, 0, 100, 0, 100 + hwSettings.motors.speed_Screw_min);
|
// map(down, 0, 100, 0, 100 + infoBlock.hwInfo.motors.speed_Screw_min);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vz1 = 200 - up; // invert
|
Vz1 = 200 - up; // invert
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#define HIGHBIT(b) (((b)>>8)&0xff)
|
#define HIGHBIT(b) (((b)>>8)&0xff)
|
||||||
#define LOWBIT(b) ((b)&0xff)
|
#define LOWBIT(b) ((b)&0xff)
|
||||||
|
|
||||||
|
|
||||||
extern CurrentInfo currentInfo;
|
extern CurrentInfo currentInfo;
|
||||||
extern InfoBlock infoBlock;
|
extern InfoBlock infoBlock;
|
||||||
|
|
||||||
@ -33,10 +32,20 @@ uint8_t checkLen(uint8_t cmd, uint8_t current_length, uint8_t required_length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UART3_SaveShot(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SaveShot(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 8;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
uint8_t shotIndx = dataPtr[1];
|
||||||
|
|
||||||
|
Shot shot;
|
||||||
|
shot.countRepeatShot = dataPtr[2];
|
||||||
|
shot.speedRollerTop = dataPtr[3]+100;
|
||||||
|
shot.speedRollerBottom = dataPtr[4]+100;
|
||||||
|
shot.speedScrew = map(dataPtr[6], 0, 120, 0, 100);
|
||||||
|
shot.rotationAxial = map(dataPtr[5], -99, 99, 0, 180);
|
||||||
|
shot.rotationHorizontal = map(dataPtr[6], -99, 99, 90-45, 90+45);
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,78 +121,160 @@ void UART3_DeleteMacro(uint8_t *dataPtr, uint8_t len) {
|
|||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//120
|
||||||
void UART3_DeleteAllData(uint8_t *dataPtr, uint8_t len) {
|
void UART3_DeleteAllData(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
EEPROM_EARSE();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//180
|
||||||
void UART3_GetDeviceStatus(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetDeviceStatus(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
uint8_t res = currentInfo.state.isShooting;
|
||||||
|
|
||||||
|
SendResponse(dataPtr[0], 0, &res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//200
|
||||||
void UART3_SetServoOffset(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetServoOffset(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 3;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ServoMap servo = dataPtr[1];
|
||||||
|
ServoSetting *currentServo = &infoBlock.hwInfo.servos[servo];
|
||||||
|
int16_t newDef = (dataPtr[2] << 8) | dataPtr[3];
|
||||||
|
newDef+=90; // from center
|
||||||
|
|
||||||
|
if (newDef < 0) newDef = 0;
|
||||||
|
if (newDef > 180) newDef = 180;
|
||||||
|
|
||||||
|
int16_t maxDeviation = (currentServo->max > currentServo->def)
|
||||||
|
? currentServo->max - currentServo->def
|
||||||
|
: currentServo->def - currentServo->min;
|
||||||
|
|
||||||
|
currentServo->def = newDef;
|
||||||
|
int16_t newMax = currentServo->def + maxDeviation;
|
||||||
|
int16_t newMin = currentServo->def - maxDeviation;
|
||||||
|
if (newMax > 180) newMax = 180;
|
||||||
|
if (newMin < 0) newMin = 0;
|
||||||
|
currentServo->max = newMax;
|
||||||
|
currentServo->min = newMin;
|
||||||
|
saveInfoBlock();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//204
|
||||||
void UART3_GetServoOffset(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetServoOffset(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 1;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
ServoMap servo = dataPtr[1];
|
||||||
|
ServoSetting *currentServo = &infoBlock.hwInfo.servos[servo];
|
||||||
|
|
||||||
|
int16_t def = currentServo->def - 90; // offset from center
|
||||||
|
|
||||||
|
uint8_t res[2];
|
||||||
|
res[0] = HIGHBIT(def);
|
||||||
|
res[1] = LOWBIT(def);
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//201
|
||||||
void UART3_SetServoMaxAngle(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetServoMaxAngle(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 3;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ServoMap servo = dataPtr[1];
|
||||||
|
uint16_t maxAngl = (dataPtr[2] << 8) | dataPtr[3];
|
||||||
|
ServoSetting *currentServo = &infoBlock.hwInfo.servos[servo];
|
||||||
|
int16_t newMax = currentServo->def + maxAngl;
|
||||||
|
int16_t newMin = currentServo->def - maxAngl;
|
||||||
|
if (newMax > 180) newMax = 180;
|
||||||
|
if (newMin < 0) newMin = 0;
|
||||||
|
currentServo->max = newMax;
|
||||||
|
currentServo->min = newMin;
|
||||||
|
saveInfoBlock();
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//202
|
||||||
void UART3_GetServoMaxAngle(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetServoMaxAngle(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 1;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
ServoMap servo = dataPtr[1];
|
||||||
|
ServoSetting *currentServo = &infoBlock.hwInfo.servos[servo];
|
||||||
|
|
||||||
|
uint8_t deviationToMax = currentServo->max > currentServo->def
|
||||||
|
? currentServo->max - currentServo->def
|
||||||
|
: currentServo->def - currentServo->max;
|
||||||
|
|
||||||
|
uint8_t deviationToMin = currentServo->def > currentServo->min
|
||||||
|
? currentServo->def - currentServo->min
|
||||||
|
: currentServo->min - currentServo->def;
|
||||||
|
|
||||||
|
uint8_t maxAngl = (deviationToMax > deviationToMin) ? deviationToMax : deviationToMin;
|
||||||
|
|
||||||
|
uint8_t res[2];
|
||||||
|
res[0] = HIGHBIT(maxAngl);
|
||||||
|
res[1] = LOWBIT(maxAngl);
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//203
|
||||||
void UART3_MoveServoToInitialPosition(uint8_t *dataPtr, uint8_t len) {
|
void UART3_MoveServoToInitialPosition(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 1;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
setPosDefaultSingle(dataPtr[1]);
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//206
|
||||||
void UART3_SetStartupDelay(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetStartupDelay(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 2;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
infoBlock.hwInfo.timings.preRun = (dataPtr[1] << 8) | dataPtr[2];
|
||||||
|
saveInfoBlock();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//207
|
||||||
void UART3_GetStartupDelay(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetStartupDelay(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
uint8_t res[2];
|
||||||
|
|
||||||
|
res[0] = HIGHBIT(infoBlock.hwInfo.timings.preRun);
|
||||||
|
res[1] = LOWBIT(infoBlock.hwInfo.timings.preRun);
|
||||||
|
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//210 !!!!!!!!
|
||||||
void UART3_SetMinRollerSpeed(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetMinRollerSpeed(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
@ -192,46 +283,75 @@ void UART3_SetMinRollerSpeed(uint8_t *dataPtr, uint8_t len) {
|
|||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//211 !!!!!!!!!!!
|
||||||
void UART3_GetMinRollerSpeed(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetMinRollerSpeed(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
uint8_t res[1];
|
||||||
|
// res[0] = ;
|
||||||
|
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//212
|
||||||
void UART3_SetMinScrewSpeed(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetMinScrewSpeed(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 1;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
infoBlock.hwInfo.motors.speed_Screw_min = dataPtr[1];
|
||||||
|
saveInfoBlock();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//215
|
||||||
void UART3_GetMinScrewSpeed(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetMinScrewSpeed(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
uint8_t res[1];
|
||||||
|
res[0] = infoBlock.hwInfo.motors.speed_Screw_min;
|
||||||
|
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//214
|
||||||
void UART3_SetServoInvertFlag(uint8_t *dataPtr, uint8_t len) {
|
void UART3_SetServoInvertFlag(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 1;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
uint8_t inv = dataPtr[1];
|
||||||
|
|
||||||
|
infoBlock.hwInfo.servos[SERVO_AXIAL].invert = inv;
|
||||||
|
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].invert = inv;
|
||||||
|
infoBlock.hwInfo.servos[SERVO_VERTICAL].invert = inv;
|
||||||
|
|
||||||
|
saveInfoBlock();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//215
|
||||||
void UART3_GetServoInvertFlag(uint8_t *dataPtr, uint8_t len) {
|
void UART3_GetServoInvertFlag(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
uint8_t res[1];
|
||||||
|
|
||||||
|
res[0] = (infoBlock.hwInfo.servos[SERVO_AXIAL].invert
|
||||||
|
|| infoBlock.hwInfo.servos[SERVO_HORIZONTAL].invert
|
||||||
|
|| infoBlock.hwInfo.servos[SERVO_VERTICAL].invert);
|
||||||
|
|
||||||
|
SendResponse(dataPtr[0], 0, res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 181
|
||||||
void UART3_ReadStatistics(uint8_t *dataPtr, uint8_t len) {
|
void UART3_ReadStatistics(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
@ -252,7 +372,7 @@ void UART3_ReadStatistics(uint8_t *dataPtr, uint8_t len) {
|
|||||||
|
|
||||||
StatusStruct res;
|
StatusStruct res;
|
||||||
|
|
||||||
res.status = currentInfo.state.isShooting && !currentInfo.state.isPause;
|
res.status = currentInfo.state.isShooting;
|
||||||
res.shot_number = currentInfo.shot.index;
|
res.shot_number = currentInfo.shot.index;
|
||||||
res.program_number = currentInfo.program.index;
|
res.program_number = currentInfo.program.index;
|
||||||
res.macro_number = currentInfo.macro.index;
|
res.macro_number = currentInfo.macro.index;
|
||||||
@ -269,11 +389,15 @@ void UART3_ReadStatistics(uint8_t *dataPtr, uint8_t len) {
|
|||||||
SendResponse(dataPtr[0], 0, (uint8_t*) &res, sizeof(res));
|
SendResponse(dataPtr[0], 0, (uint8_t*) &res, sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 121
|
||||||
void UART3_ResetStatistics(uint8_t *dataPtr, uint8_t len) {
|
void UART3_ResetStatistics(uint8_t *dataPtr, uint8_t len) {
|
||||||
const uint8_t MIN_PARAM_LENGTH = 0;
|
const uint8_t MIN_PARAM_LENGTH = 0;
|
||||||
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
if (!checkLen(dataPtr[0], len, MIN_PARAM_LENGTH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
memset(&infoBlock.statInfo, 0x00, sizeof(infoBlock.statInfo));
|
||||||
|
saveInfoBlock();
|
||||||
|
|
||||||
SendResponse(dataPtr[0], 0, NULL, 0);
|
SendResponse(dataPtr[0], 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ void handle_rx_complete(uint8_t *data, uint16_t len)
|
|||||||
// CDC_Transmit_FS((uint8_t*) byte_info, strlen(byte_info));
|
// CDC_Transmit_FS((uint8_t*) byte_info, strlen(byte_info));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Проверка правильности пакета (первый байт должен быть 0xF0)
|
// Проверка 0xF0
|
||||||
if (data[0] != 0xF0) {
|
if (data[0] != 0xF0) {
|
||||||
char error_msg[64];
|
char error_msg[64];
|
||||||
snprintf(error_msg, sizeof(error_msg),
|
snprintf(error_msg, sizeof(error_msg),
|
||||||
@ -89,7 +89,6 @@ void handle_rx_complete(uint8_t *data, uint16_t len)
|
|||||||
|
|
||||||
// CDC_Transmit_FS((uint8_t*)"\n\n", 2);
|
// CDC_Transmit_FS((uint8_t*)"\n\n", 2);
|
||||||
|
|
||||||
// Если пакет корректен, передать управление обработчику команд
|
|
||||||
uint8_t *data_ptr = &data[2];
|
uint8_t *data_ptr = &data[2];
|
||||||
UART3_CMD_Handler(data_ptr, length);
|
UART3_CMD_Handler(data_ptr, length);
|
||||||
}
|
}
|
||||||
|
186
Core/Src/main.c
186
Core/Src/main.c
@ -68,8 +68,6 @@ uint8_t velosety[600];
|
|||||||
uint8_t rxcomlite = 0;
|
uint8_t rxcomlite = 0;
|
||||||
uint8_t initcomlete = 0;
|
uint8_t initcomlete = 0;
|
||||||
|
|
||||||
unsigned char Shiftreg[3];
|
|
||||||
|
|
||||||
uint8_t rejim[60]; // 0 - chislo rejimov, 1-6 - rejim1, 7-12 - rejim2...
|
uint8_t rejim[60]; // 0 - chislo rejimov, 1-6 - rejim1, 7-12 - rejim2...
|
||||||
uint8_t avto = 0; // vkl/otkl avtomaticheskoi raboti
|
uint8_t avto = 0; // vkl/otkl avtomaticheskoi raboti
|
||||||
uint8_t rejim_number = 1; // nomer tekyshego rejima
|
uint8_t rejim_number = 1; // nomer tekyshego rejima
|
||||||
@ -108,8 +106,7 @@ static void MX_USART3_UART_Init(void);
|
|||||||
* @brief The application entry point.
|
* @brief The application entry point.
|
||||||
* @retval int
|
* @retval int
|
||||||
*/
|
*/
|
||||||
int main(void)
|
int main(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN 1 */
|
/* USER CODE BEGIN 1 */
|
||||||
|
|
||||||
@ -128,11 +125,8 @@ int main(void)
|
|||||||
SystemClock_Config();
|
SystemClock_Config();
|
||||||
|
|
||||||
/* USER CODE BEGIN SysInit */
|
/* USER CODE BEGIN SysInit */
|
||||||
// Установка приоритета прерывания
|
|
||||||
// NVIC_SetPriority(SysTick_IRQn, 0);
|
SysTick->LOAD = 479999;
|
||||||
// Настройка SysTick таймера на 1 мс
|
|
||||||
SysTick->LOAD = 479999; // 1ms Sys timer
|
|
||||||
// SysTick_Config(SystemCoreClock / 1000);
|
|
||||||
|
|
||||||
__HAL_RCC_USB_FORCE_RESET();
|
__HAL_RCC_USB_FORCE_RESET();
|
||||||
HAL_Delay(10);
|
HAL_Delay(10);
|
||||||
@ -150,11 +144,9 @@ int main(void)
|
|||||||
MX_TIM3_Init();
|
MX_TIM3_Init();
|
||||||
MX_USART3_UART_Init();
|
MX_USART3_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
HAL_Delay(10);
|
|
||||||
__HAL_RCC_USART3_CLK_ENABLE();
|
__HAL_RCC_USART3_CLK_ENABLE();
|
||||||
HAL_Delay(10);
|
|
||||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||||
HAL_Delay(10);
|
|
||||||
|
|
||||||
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //PA8
|
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //PA8
|
||||||
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); //PA9
|
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); //PA9
|
||||||
@ -163,56 +155,22 @@ int main(void)
|
|||||||
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); //PA2
|
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); //PA2
|
||||||
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); //PA3
|
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); //PA3
|
||||||
|
|
||||||
initPCA9685();
|
Robot_INIT();
|
||||||
|
|
||||||
Shiftreg[0] = 0x00; Shiftreg[1] = 0x44; Shiftreg[2] = 0x00; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x00; Shiftreg[1] = 0x66; Shiftreg[2] = 0x00; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x00; Shiftreg[1] = 0x77; Shiftreg[2] = 0x00; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
EEPROM_INIT();
|
|
||||||
Shiftreg[0] = 0x01; Shiftreg[1] = 0x77; Shiftreg[2] = 0x01; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x03; Shiftreg[1] = 0x77; Shiftreg[2] = 0x03; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x07; Shiftreg[1] = 0x77; Shiftreg[2] = 0x07; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x0F; Shiftreg[1] = 0x77; Shiftreg[2] = 0x0F; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x1F; Shiftreg[1] = 0x77; Shiftreg[2] = 0x1F; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x3F; Shiftreg[1] = 0x77; Shiftreg[2] = 0x3F; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x7F; Shiftreg[1] = 0x77; Shiftreg[2] = 0x7F; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
Shiftreg[0] = 0x00; Shiftreg[1] = 0x00; Shiftreg[2] = 0x00; SetShiftReg(Shiftreg); HAL_Delay(10);
|
|
||||||
|
|
||||||
initcomlete = 1;
|
initcomlete = 1;
|
||||||
|
|
||||||
|
|
||||||
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 <20>6 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> PA0 PA1
|
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 <20>6 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> PA0 PA1
|
||||||
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
|
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
|
||||||
|
|
||||||
HAL_TIM_Base_Start_IT(&htim3);
|
HAL_TIM_Base_Start_IT(&htim3);
|
||||||
HAL_NVIC_EnableIRQ(TIM3_IRQn);
|
HAL_NVIC_EnableIRQ(TIM3_IRQn);
|
||||||
UART3_START();
|
|
||||||
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
/* USER CODE BEGIN WHILE */
|
/* USER CODE BEGIN WHILE */
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
Shot testShot;
|
|
||||||
memset(&testShot, 0x00, sizeof(Shot));
|
|
||||||
getShot(3, &testShot);
|
|
||||||
|
|
||||||
if(!testShot.isExist){
|
|
||||||
testShot.countRepeatShot = 1;
|
|
||||||
testShot.speedRollerTop = 200;
|
|
||||||
testShot.speedRollerBottom = 200;
|
|
||||||
testShot.speedScrew = 100;
|
|
||||||
testShot.rotationAxial = 90;
|
|
||||||
testShot.rotationHorizontal = 90;
|
|
||||||
testShot.rotationVertical = 90;
|
|
||||||
|
|
||||||
saveShot(3, &testShot);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
|
|
||||||
IR_CMD_Handler();
|
IR_CMD_Handler();
|
||||||
UART3_Handler();
|
UART3_Handler();
|
||||||
@ -224,6 +182,20 @@ initcomlete = 1;
|
|||||||
// unsigned char text[] = "Hello\n";
|
// unsigned char text[] = "Hello\n";
|
||||||
// printNumber(SysTick->LOAD);
|
// printNumber(SysTick->LOAD);
|
||||||
// CDC_Transmit_FS(text, sizeof(text));
|
// CDC_Transmit_FS(text, sizeof(text));
|
||||||
|
|
||||||
|
// char buffer[100]; // Буфер для формата строки
|
||||||
|
|
||||||
|
// extern uint32_t vsk1;
|
||||||
|
// extern uint32_t vsk2;
|
||||||
|
// extern uint16_t timing1;
|
||||||
|
// extern uint16_t timing2;
|
||||||
|
// // Форматируем строку для вывода timing1, timing2, vsk1, vsk2
|
||||||
|
// sprintf(buffer,
|
||||||
|
// "timing1: %u ms, timing2: %u ms, vsk1: %u RPM, vsk2: %u RPM\n",
|
||||||
|
// timing1, timing2, vsk1, vsk2);
|
||||||
|
//
|
||||||
|
// // Отправляем строку через CDC (USB)
|
||||||
|
// CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE END WHILE */
|
/* USER CODE END WHILE */
|
||||||
@ -237,8 +209,7 @@ initcomlete = 1;
|
|||||||
* @brief System Clock Configuration
|
* @brief System Clock Configuration
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void SystemClock_Config(void)
|
void SystemClock_Config(void) {
|
||||||
{
|
|
||||||
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
|
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
|
||||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
|
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
|
||||||
RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
|
RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
|
||||||
@ -253,8 +224,7 @@ void SystemClock_Config(void)
|
|||||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||||
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
|
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
|
||||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,14 +237,12 @@ void SystemClock_Config(void)
|
|||||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
||||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||||
|
|
||||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
|
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
|
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
|
||||||
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL;
|
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL;
|
||||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
|
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,8 +252,7 @@ void SystemClock_Config(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_I2C1_Init(void)
|
static void MX_I2C1_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN I2C1_Init 0 */
|
/* USER CODE BEGIN I2C1_Init 0 */
|
||||||
|
|
||||||
@ -303,8 +270,7 @@ static void MX_I2C1_Init(void)
|
|||||||
hi2c1.Init.OwnAddress2 = 0;
|
hi2c1.Init.OwnAddress2 = 0;
|
||||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||||
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
|
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
/* USER CODE BEGIN I2C1_Init 2 */
|
/* USER CODE BEGIN I2C1_Init 2 */
|
||||||
@ -318,8 +284,7 @@ static void MX_I2C1_Init(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_TIM1_Init(void)
|
static void MX_TIM1_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN TIM1_Init 0 */
|
/* USER CODE BEGIN TIM1_Init 0 */
|
||||||
|
|
||||||
@ -340,23 +305,20 @@ static void MX_TIM1_Init(void)
|
|||||||
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
htim1.Init.RepetitionCounter = 0;
|
htim1.Init.RepetitionCounter = 0;
|
||||||
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
|
if (HAL_TIM_Base_Init(&htim1) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||||
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
|
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
|
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
|
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||||
@ -366,12 +328,12 @@ static void MX_TIM1_Init(void)
|
|||||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||||
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
|
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
|
||||||
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
|
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
|
||||||
@ -381,8 +343,8 @@ static void MX_TIM1_Init(void)
|
|||||||
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
|
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
|
||||||
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
|
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
|
||||||
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
|
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
|
||||||
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
|
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
/* USER CODE BEGIN TIM1_Init 2 */
|
/* USER CODE BEGIN TIM1_Init 2 */
|
||||||
@ -397,8 +359,7 @@ static void MX_TIM1_Init(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_TIM2_Init(void)
|
static void MX_TIM2_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN TIM2_Init 0 */
|
/* USER CODE BEGIN TIM2_Init 0 */
|
||||||
|
|
||||||
@ -417,43 +378,40 @@ static void MX_TIM2_Init(void)
|
|||||||
htim2.Init.Period = 4000;
|
htim2.Init.Period = 4000;
|
||||||
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
|
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||||
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
|
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
|
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
|
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||||
sConfigOC.Pulse = 0;
|
sConfigOC.Pulse = 0;
|
||||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
|
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
/* USER CODE BEGIN TIM2_Init 2 */
|
/* USER CODE BEGIN TIM2_Init 2 */
|
||||||
@ -468,8 +426,7 @@ static void MX_TIM2_Init(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_TIM3_Init(void)
|
static void MX_TIM3_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN TIM3_Init 0 */
|
/* USER CODE BEGIN TIM3_Init 0 */
|
||||||
__HAL_RCC_TIM3_CLK_ENABLE();
|
__HAL_RCC_TIM3_CLK_ENABLE();
|
||||||
@ -488,35 +445,30 @@ static void MX_TIM3_Init(void)
|
|||||||
htim3.Init.Period = 65000;
|
htim3.Init.Period = 65000;
|
||||||
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||||
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
|
if (HAL_TIM_Base_Init(&htim3) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||||
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
|
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
|
if (HAL_TIM_IC_Init(&htim3) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
|
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig)
|
||||||
{
|
!= HAL_OK) {
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
|
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
|
||||||
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
|
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
|
||||||
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
|
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
|
||||||
sConfigIC.ICFilter = 0;
|
sConfigIC.ICFilter = 0;
|
||||||
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
|
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
|
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
/* USER CODE BEGIN TIM3_Init 2 */
|
/* USER CODE BEGIN TIM3_Init 2 */
|
||||||
@ -530,8 +482,7 @@ static void MX_TIM3_Init(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_USART3_UART_Init(void)
|
static void MX_USART3_UART_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* USER CODE BEGIN USART3_Init 0 */
|
/* USER CODE BEGIN USART3_Init 0 */
|
||||||
|
|
||||||
@ -548,8 +499,7 @@ static void MX_USART3_UART_Init(void)
|
|||||||
huart3.Init.Mode = UART_MODE_TX_RX;
|
huart3.Init.Mode = UART_MODE_TX_RX;
|
||||||
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||||
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
|
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||||
if (HAL_UART_Init(&huart3) != HAL_OK)
|
if (HAL_UART_Init(&huart3) != HAL_OK) {
|
||||||
{
|
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
/* USER CODE BEGIN USART3_Init 2 */
|
/* USER CODE BEGIN USART3_Init 2 */
|
||||||
@ -564,8 +514,7 @@ static void MX_USART3_UART_Init(void)
|
|||||||
/**
|
/**
|
||||||
* Enable DMA controller clock
|
* Enable DMA controller clock
|
||||||
*/
|
*/
|
||||||
static void MX_DMA_Init(void)
|
static void MX_DMA_Init(void) {
|
||||||
{
|
|
||||||
|
|
||||||
/* DMA controller clock enable */
|
/* DMA controller clock enable */
|
||||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||||
@ -582,8 +531,7 @@ static void MX_DMA_Init(void)
|
|||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void MX_GPIO_Init(void)
|
static void MX_GPIO_Init(void) {
|
||||||
{
|
|
||||||
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
||||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||||
/* USER CODE END MX_GPIO_Init_1 */
|
/* USER CODE END MX_GPIO_Init_1 */
|
||||||
@ -645,14 +593,12 @@ static void MX_GPIO_Init(void)
|
|||||||
* @brief This function is executed in case of error occurrence.
|
* @brief This function is executed in case of error occurrence.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void Error_Handler(void)
|
void Error_Handler(void) {
|
||||||
{
|
|
||||||
/* USER CODE BEGIN Error_Handler_Debug */
|
/* USER CODE BEGIN Error_Handler_Debug */
|
||||||
/* User can add his own implementation to report the HAL error return state */
|
/* User can add his own implementation to report the HAL error return state */
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
// GPIOC->ODR &= ~GPIO_PIN_13;
|
// GPIOC->ODR &= ~GPIO_PIN_13;
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
/* USER CODE END Error_Handler_Debug */
|
/* USER CODE END Error_Handler_Debug */
|
||||||
}
|
}
|
||||||
|
12
TODO.md
12
TODO.md
@ -1,3 +1,12 @@
|
|||||||
|
Логика:
|
||||||
|
Ограничение скорости роликов!
|
||||||
|
Ограничение углов сервы
|
||||||
|
Уточнить, в ТЗ только обработка 201 команды и учитывается только макс угол
|
||||||
|
Начальное смещение:
|
||||||
|
Корректировать макс углы ?
|
||||||
|
Не корректировать углы ?
|
||||||
|
|
||||||
|
|
||||||
Работа с памятью:
|
Работа с памятью:
|
||||||
V Припаять i2c!!!
|
V Припаять i2c!!!
|
||||||
Сохранение выстрела
|
Сохранение выстрела
|
||||||
@ -28,6 +37,7 @@ IR:
|
|||||||
Функция отображения скорости
|
Функция отображения скорости
|
||||||
Обратный отсчёт
|
Обратный отсчёт
|
||||||
Индикация ошибок
|
Индикация ошибок
|
||||||
|
Процесс удаления
|
||||||
|
|
||||||
Звук:
|
Звук:
|
||||||
Звук приёма IR
|
Звук приёма IR
|
||||||
@ -37,5 +47,5 @@ IR:
|
|||||||
|
|
||||||
|
|
||||||
Ошибки:
|
Ошибки:
|
||||||
В некоторый момент PID регулятор выдаёт 0 и двигатель не запускается не зависимо от входного значенияPWM
|
V В некоторый момент PID регулятор выдаёт 0 и двигатель не запускается не зависимо от входного значенияPWM
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user