естественно первым делом и открывал документацию, иначе откуда мне брать команды управления ПЧ?
А если бы велосипет не изобретал, щитал бы так
Ну вот так значит читаешь документацию, раз за место того что бы взять готовое от производителя ,по форумам лазишь и методы расчетов CRC непонятные оттуда берешь.
так я из децтва (avr) уже вырос, на столе RP2040 и ESP32 )))
Видать, нет.
тебе видней, но этой библиотеки в esp32 и rp2040 нет, ну или я не нашёл, где она там зарыта
всем спасибо, задача решена. еще реализовал чтение ответа от ПЧ, при ошибке ответа выполняется повторная отправка пакета через рекурсию с подсчетом количества попыток. проверил в симуляции протеус и виртуальным com портом соединил с прогой docklight, все робит
в конце отправил незаписанную команду в docklight и произведена повторная отправка 15 раз рекурсивно
методы отправки и чтения
uint64_t t = 0;
void modbus_query(uint8_t index, uint8_t counter_send){
//if index >= _LAYER_STOP_SET_SPEED need calculate CRC16
bool send = false;
if(index >= _LAYER_STOP_SET_SPEED){
uint8_t len = query_sizes[index]-2;
uint8_t buf[len];
for(uint8_t n = 0; n < len; n++){
buf[n] = query[index][n];
}
//calculate CRC16 value
uint16_t crc = GetCrc16Simple(buf, len);
//update CRC
query[index][len] = (crc >> 8) & 0xFF;
query[index][len+1] = crc & 0xFF;
}
while(!send){
if(micros() - t >= T240){
for(uint8_t i = 0; i < query_sizes[index]; i++){
Serial.write(query[index][i]);
}
Serial.flush();
send = true;
t = micros();
}
}
uint8_t status = modbus_poll(index);
debug.println(status);
if(status != 0 && counter_send < MAX_TRY_COUNT){
modbus_query(index, ++counter_send);
}
}
uint8_t modbus_poll(uint8_t index){
uint8_t buffer[16];
bool read = false;
//wait answer from slave device
if(micros() - t >= (T35 + INTERVAL)){
if(!Serial.available()){ //no answer error
return 3;
}
read = true;
t = micros(); //reset timer
}
if(read){
uint8_t i = 0;
while(Serial.available() > 0){ //read data while buffer not empty
buffer[i] = Serial.read();
i++;
}
if(!crc16_check(index, buffer)){
return 2;
}
return 0;
}
return 4;
}
bool crc16_check(uint8_t index, uint8_t buffer[]){
uint8_t crc_lo_index = query_sizes[index] - 1;
uint8_t crc_hi_index = crc_lo_index - 1;
if(buffer[crc_lo_index] != query[index][crc_lo_index] ||
buffer[crc_hi_index] != query[index][crc_hi_index]){
return false;
}
return true;
}
uint16_t GetCrc16Simple(uint8_t bufferArray[], uint8_t length){
unsigned int temp, temp2, flag;
temp = 0xFFFF;
for (unsigned char i = 0; i < length; i++)
{
temp = temp ^ bufferArray[i];
for (unsigned char j = 1; j <= 8; j++)
{
flag = temp & 0x0001;
temp >>= 1;
if (flag) temp ^= 0xA001;
}
}
temp2 = temp >> 8;
temp = (temp << 8) | temp2;
temp &= 0xFFFF;
return temp;
}
команды для отправки записываются в массив
uint8_t* query[8] = {
STOP_ALL, //0
START_ALL_CW, //1
START_ALL_CCW, //2
LAYER_START_MAX_CW, //3
LAYER_START_MAX_CCW, //4
LAYER_STOP_SET_SPEED, //5
LAYER_SET_SPEED, //6
REEL_SET_SPEED //7
};
extern const uint8_t query_sizes[8] = {
sizeof(STOP_ALL),
sizeof(START_ALL_CW),
sizeof(START_ALL_CCW),
sizeof(LAYER_START_MAX_CW),
sizeof(LAYER_START_MAX_CCW),
sizeof(LAYER_STOP_SET_SPEED),
sizeof(LAYER_SET_SPEED),
sizeof(REEL_SET_SPEED)
};
вы уверены, что в этом массиве у вас именно размеры команд?
Говонокодом пахнет
да пришлось создать отдельный массив содержащий длину каждого, поскольку длина команд разная. У меня не получилось получить длину одной команды через массив query, поэтому такой костыль. размеры команд в массиве верные.