прошу помощи по заполнению и обработке массива
- Войдите на сайт для отправки комментариев
Пнд, 30/03/2020 - 20:55
#include <SoftwareSerial.h>
#define LOOP_DELAY 50
#define SW_SERIAL_BAUD_RATE 9600
#define HW_SERIAL_BAUD_RATE 9600
#define SW_SERIAL_RX_PIN 11
#define SW_SERIAL_TX_PIN 10
SoftwareSerial mySerial(SW_SERIAL_RX_PIN, SW_SERIAL_TX_PIN); // RX, TX
int IBUSreceiveByte = 0; // byte reading from I-BUS
byte IBUSbyte[7] = {0,0,0,0,0,0,0}; // key byte sequence
int Delay = 0; //delay in millisec
int ButtonPressed = 0; //boolean value set 1 if key press detected
int KeyID = 0; // key press number (for easy select case routine)
//hold keys flags
//int N_HOLD_F = 0; //next track hold flag
//int P_HOLD_F = 0; //prev track hold flag
//int V_HOLD_F = 0; // r/t key hold flag
byte PLUS_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x32, 0x11, 0x1F}; // + press button
byte MINUS_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x32, 0x10, 0x1E}; // - press button
byte NEXT_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x01, 0x06}; // > press button
byte NEXT_HOLD[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x11, 0x16}; // > hold button
byte NEXT_REL[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x21, 0x26}; // > release button
byte PREV_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < press button
byte PREV_HOLD[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < hold button
byte PREV_REL[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < release button
byte VOICE_DOWN[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x80, 0x27}; // voice press button
byte VOICE_HOLD[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x90, 0x37}; // voice hold button
byte VOICE_REL[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0xA0, 0x07}; // voice release button
byte RT_DOWN[7] = {0, 0x50, 0xFF, 0x03, 0xC8, 0x01, 0x9A}; // voice release button
void setup()
{
mySerial.begin(9600);
Serial.begin(9600);
}
void loop()
{
if (Serial.available() && ButtonPressed==0){
TryReadIBUSmsg();
}
if (ButtonPressed==1){
mySerial.print(millis());
mySerial.println(" ----------------------------------------------- ");
switch (KeyID){
case 100: //Если клавиша не опознана или какие-то ошибки в шине при чтении
mySerial.print("UNKNOWN KEY: ");
SerialPrintKey();
break;
case 40:
mySerial.print("R/T KEY: ");
SerialPrintKey();
break;
case 1:
mySerial.print("VOL + key: ");
SerialPrintKey();
break;
case 2:
mySerial.print("VOL - key: ");
SerialPrintKey();
break;
case 11:
mySerial.print("NEXT FLAG HOLD=0: ");
SerialPrintKey();
// N_HOLD_F=0;
break;
case 12:
mySerial.print("NEXT FLAG HOLD=1: ");
SerialPrintKey();
// N_HOLD_F=1;
break;
/* case 13:
if (N_HOLD_F==0){
mySerial.print("NEXT TRACK key: ");
SerialPrintKey();
}
else {
mySerial.print("NEXT FOLDER key: ");
SerialPrintKey();
}
break;
*/
case 21:
mySerial.print("PREV FLAG HOLD=0: ");
SerialPrintKey();
// P_HOLD_F=0;
break;
case 22:
mySerial.print("PREV FLAG HOLD=1: ");
SerialPrintKey();
// P_HOLD_F=1;
break;
/* case 23:
if (P_HOLD_F==0){
mySerial.print("PREV TRACK key: ");
SerialPrintKey();
}
else {
mySerial.print("PREV FOLDER key: ");
SerialPrintKey();
}
break;
*/
case 31:
mySerial.print("VOICE FLAG HOLD=0: ");
SerialPrintKey();
// V_HOLD_F=0;
break;
case 32:
mySerial.print("VOICE FLAG HOLD=1: ");
SerialPrintKey();
// V_HOLD_F=1;
break;
/* case 33:
if (V_HOLD_F==0){
mySerial.print("VOICE key press: ");
SerialPrintKey();
}
else {
mySerial.print("Voice key hold: ");
SerialPrintKey();
}
break; */
}
ButtonPressed = 0;
}
}
void TryReadIBUSmsg()
{
IBUSreceiveByte = Serial.read(); //read 1-st byte Если 50 то это начало посылки от рулевых кнопок
if (IBUSreceiveByte==0x50)
{
IBUSbyte[1]=0x50;
for (int i=2; i <= 7; i++){
IBUSbyte[i] = Serial.read(); //read 2,3,4,5,6,7 bytes of data - читаем следующие байты
delay(Delay);
SerialPrintKey();
}
KeyID=100; //Устанавливаем по умолчанию что клавиша не опознана
if(memcmp(IBUSbyte, PLUS_DOWN, 7) == 0 ){KeyID=1;} // и меняем если опознана на соответствующий код
if(memcmp(IBUSbyte, MINUS_DOWN, 7) == 0 ){KeyID=2;}
if(memcmp(IBUSbyte, NEXT_DOWN, 7) == 0 ){KeyID=11;}
if(memcmp(IBUSbyte, NEXT_HOLD, 7) == 0 ){KeyID=12;}
if(memcmp(IBUSbyte, NEXT_REL, 7) == 0 ){KeyID=13;}
if(memcmp(IBUSbyte, PREV_DOWN, 7) == 0 ){KeyID=21;}
if(memcmp(IBUSbyte, PREV_HOLD, 7) == 0 ){KeyID=22;}
if(memcmp(IBUSbyte, PREV_REL, 7) == 0 ){KeyID=23;}
if(memcmp(IBUSbyte, VOICE_DOWN, 7) == 0 ){KeyID=31;}
if(memcmp(IBUSbyte, VOICE_HOLD, 7) == 0 ){KeyID=33;}
if(memcmp(IBUSbyte, VOICE_REL, 7) == 0 ){KeyID=32;}
if(memcmp(IBUSbyte, RT_DOWN, 7) == 0 ){KeyID=40;}
ButtonPressed=1;
}
else
{
ButtonPressed=0;
}
}
void SerialPrintKey() // печать в ком порт посылки
{
for (int x=1; x <= 7; x++){
mySerial.print(IBUSbyte[x], HEX);
mySerial.print(" ");
}
mySerial.println();
}
Здравствуйте все
Нужна помощь новичку.
Прошу подсказки, в чем может быть проблема - пробую переделать найденный скетч для распознавания нажатий кнопок руля.
Не могу понять, почему на месте первого байта массива появляется FF
на картинке ситуация в мониторе порта, после нажатия кнопки руля - первый раз (кстати тоже не могу понять почему одно нажатие выводит две распечатки) - на месте второго байта FF, и соответственно, сравнение массива не успешное. Тут же появляется вторая распечатка - видно как (для меня странно) дублируются байты, смещаясь по мере заполнения. Но при этом посылка уже правильная, 04 вместо FF и таки в конце распознается скетчем.
Собственно, задача более чем тривиальная - принять в порт посылку, и на основании ее содержания (условия строятся на основании определенных байт посылки) - выполнять те или иные действия. Но пока какой-то тотальный бардак с заполнением массива из посылки.
Подскажите, кто знает - где ошибка?
Спасибо!
Знаю есть тут люди с машинами понимающие. Я пока со своей колокольни брякну, может и не поможет, но на мысли какие наведёт. Байты же справа на лево читаться должны, полагаю FF это заполнение не достающих данных, типа нету ничего поэтому по максимуму. Но это я так, со своей колокольни и вообще ничего не понимая брыкнул. Удачи вам!
Спасибо за участие.
У меня есть решение как обойти это - просто "подогнать" строку для сравнения с тем, что приходит на экран. Но это не выход. Я принципиально где-то недопонимаю и ошибаюсь. А очень хочется таки разобраться и сделать как надо.
напал на след этого безобразия.
Вот такой скетч
#include <SoftwareSerial.h> #define LOOP_DELAY 50 #define BUFFER_SIZE 7 #define BUFFER_OFFSET 0 #define SW_SERIAL_BAUD_RATE 9600 #define HW_SERIAL_BAUD_RATE 9600 #define SW_SERIAL_RX_PIN 11 #define SW_SERIAL_TX_PIN 10 SoftwareSerial mySerial(SW_SERIAL_RX_PIN, SW_SERIAL_TX_PIN); // RX, TX uint8_t IBUSbytes[BUFFER_SIZE]; void setup() { mySerial.begin(SW_SERIAL_BAUD_RATE); Serial.begin(HW_SERIAL_BAUD_RATE, SERIAL_8E1); } void loop() { tryReadIBUSmsg(); delay(LOOP_DELAY); } void tryReadIBUSmsg() { if (Serial.available() ) { for (uint8_t index = BUFFER_OFFSET; index < sizeof(IBUSbytes); index++) { IBUSbytes[index] = Serial.read(); } printCode(); } } void printCode() { for (int index = BUFFER_OFFSET; index < sizeof(IBUSbytes); index++) { mySerial.print(IBUSbytes[index], HEX); if (index < sizeof(IBUSbytes) - 1) { mySerial.print(" "); } } mySerial.println(); mySerial.println("income"); }Дает в монитор следующее :
Получается, что если отправить посылку (я с эмулятора вручную пока пробую) длинной равной длине объявленного массива - то ( с горем пополам) посылка в монитора показывается верно. Периодически "пролетает" какой-то мусор (видно на левой части) но, это скорее всего к портам-таймингам вопрос.
А самый главный вопрос - почему вторая часть строки все равно попадает в массив, хотя он ограничен по размеру? Получается, что все, что пришло в порт "загоняется" в массив по кругу.
Как сделать так, чтобы принимались только необходимые мне байты, а остальное просто игнорировалось?
На правой части картинки видно, что все, что отправлено в порт попадает в массив, а мне это не нужно.
Я вижу вариант - через условие, в посылке ведь есть длинна сообщения. Но если кто-то подскажет решение проще - буду благодарен.
Грубо говоря, какой бы длинны не было принято сообщение - в массив записать только 8 байт. Остальное игнорировать.
Спасибо всем!
Почему вы читаете из буфера N байт, не убедившись, что они там есть?
Прошу понять и простить, я начинающий
if(Serial.available() - это не проверка наличия чего-то в буфере?Именно - чего-то. Но считываете вы не чего-то, а 7 байт.
if (Serial.available() > 7)
так?
void tryReadIBUSmsg() { if (Serial.available() >7) { for (uint8_t index = BUFFER_OFFSET; index < sizeof(IBUSbytes); index++) { IBUSbytes[index] = Serial.read(); } printCode(); } }Сделал так. Стало намного лучше. Отсекает "хвост" в 7 байт, если посылка до 14. Если длиннее - получается 7 первых приняло, потом 7 пропустило, и оставшиеся снова приняло.
Я может неправильно понимаю как это работает. Моя расшифровка if (Serial.available() > 7) - если в буфере есть что-то длинной больше 7 байт, то....
Стало быть, по условиям - приняло первые 7, ок. Проверили остаток, и если меньше 7 - то ничего, а если больше, то снова условие выполняется и "остатки" попадают в порт.
Так?
Можно как-то очистить буфер после успешного принятия первых N байт?
Я пробовал втыкнуть flush, но не сработало. Это для отправки, как я понял.
Спасибо
Нельзя очистить то, что ещё не принято. Переходите от парадигмы "данные ждут в массиве" к парадигме "данные придут хрен знает когда": ждете маркера начала пакета, считываете после этого N байт в свой массив (буферизуете), обрабатываете. Потом всё заново.
Благодарю, буду пробовать