Как читать и анализировать данные UART с радарного датчика присутствия человека
Я работаю над проектом и купил 24 ГГц "Человеческое существование/присутствие" мм Волновой датчик от micradar, R24DVD1. Выход модуля представляет собой последовательные данные различной длины и структуры, показанной ниже;
Элемент данных потока может достигать 5 байтов, и, как показано, каждый пакет заканчивается кодом 0x54 0x43. Мое намерение состоит в том, чтобы мой Arduino Uno считывал данные для дальнейшей обработки. Поскольку я использую Arduino Uno, который имеет только один физический последовательный порт, я чувствовал, что использование его для чтения данных датчика может оказаться проблематичным, поскольку компьютер в равной степени подключен к этой последовательной линии через USB. Поэтому я решил использовать SoftwareSerial для чтения данных с сенсора, а затем переслать их на компьютер, и я написал для этого следующий код:
#include <SoftwareSerial.h>
const int txpin = 3;
int const rxpin = 2;
SoftwareSerial mySerial(rxpin,txpin);
const unsigned int PACK_SIZE = 14;
int inByte1;
int inByte2;
unsigned int recvdByte = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
mySerial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
if (mySerial.available() > 0){
int pack[PACK_SIZE];
inByte1 = mySerial.read();
inByte2 = mySerial.read();
if(inByte1 != 84 && inByte2 != 67){
pack[recvdByte] = inByte1;
pack[recvdByte+1] = inByte2;
recvdByte += 2;
}
else{
pack[recvdByte] = inByte1;
pack[recvdByte+1] = inByte2;
recvdByte = 0;
}
for(int i = 0; i < PACK_SIZE; i++)
{
Serial.print(pack[i],HEX);
}
Serial.println();
}
}
Я хотел бы знать, правилен ли мой мыслительный процесс при чтении и анализе данных, потому что вывод совершенно не соответствует тому, что я ожидаю
@obatala, 👍1
Обсуждение1 ответ
Во-первых, я бы не советовал вам использовать SoftwareSerial
,
особенно при такой высокой скорости передачи данных: это прямой путь к проблемам. С
Вы, кажется, используете ссылку на компьютер только для письма, и
ссылка на датчик только для чтения, можно аппаратный серийник
порт для обоих. Подключите TX датчика к Arduino RX, и вы
иметь возможность считывать данные датчика с помощью Serial.read()
. не подключаться
RX датчика, и вы сможете использовать Serial.print()
для последовательного
контролировать, не нарушая датчик.
Далее вы должны знать, что последовательные данные принимаются по одному байту за раз. Если вы ждали, пока у вас не будет полного пакета в последовательном буфере, то вы можете прочитать и обработать весь пакет сразу. Это, однако, сложно, потому что вы не можете знать длину пакета до начинаю читать.
Я бы рекомендовал вместо этого обрабатывать один входящий байт за раз, и вы выполняете необходимые проверки работоспособности в процессе. Вот как я сделает это (предупреждение: непроверенный код):
const unsigned int MAX_PACKET_SIZE = 14;
const unsigned char char start_signature[] = {0x53, 0x59};
const unsigned char char end_signature[] = {0x54, 0x43};
unsigned char packet[MAX_PACKET_SIZE];
int recvdByte = 0; // количество байтов, полученных и буферизованных на данный момент
int dataLength = 0; // длина поля данных
void processPacket(); // определено в другом месте
// Обработка одного входного байта.
void processInputByte(unsigned char inByte) {
if (recvdByte < 2) { // проверяем стартовую подпись
if (inByte != start_signature[recvdByte]) { // неправильная подпись?
recvdByte = 0; // отбрасываем пакет
return;
}
} else if (recvdByte == 4) { // получаем длину данных
dataLength = inByte;
if (dataLength > MAX_PACKET_SIZE - 9) { // слишком длинный пакет?
recvdByte = 0; // отбрасываем пакет
dataLength = 0;
return;
}
} else if (recvdByte == 5) { // проверяем вторую длину данных
if (dataLength != inByte) { // не совпадает?
recvdByte = 0; // отбрасываем пакет
dataLength = 0;
return;
}
} else if (recvdByte == 6 + dataLength) { // контрольная сумма
// TODO: Посмотрите таблицу данных, чтобы узнать, как контролировать это
// контрольная сумма верна. Отбросьте пакет, если это не так.
} else if (recvdByte >= 7 + dataLength) { // проверка конечной подписи
if (inByte != end_signature[recvdByte - (7 + dataLength)]) {
recvdByte = 0; // отбрасываем пакет
dataLength = 0;
return;
}
}
// Пока все правильно, мы можем буферизовать входящий байт.
packet[recvdByte++] = inByte;
// Если теперь у нас есть полный пакет, обработать его.
if (recvdByte == 9 + dataLength) {
processPacket();
recvdByte = 0; // сброс для следующего пакета
dataLength = 0;
}
}
Вы можете использовать несколько Serial.println()
здесь и там для
тестирование и отладка. Их можно удалить, как только все заработает
ожидается.
Затем в основном цикле вам просто нужно:
void loop() {
if (Serial.available() > 0) {
processInputByte(Serial.read());
}
}
Спасибо миллион Эдгар. Это с небольшой модификацией помогает в большинстве случаев. Я буду продолжать работать над этим, чтобы увидеть, смогу ли я заставить его работать лучше, @obatala
- Использование YS-IRTM с Arduino Uno
- SIM800L не отвечает на AT-команды
- Проблема последовательной связи с общей землей SIM800L
- Связь UART - серийный номер всегда пуст
- Последовательная связь между nodemcu и Arduino Uno
- AT-команда не отвечает на последовательный монитор
- Какова работа pulseIn?
- Сколько датчиков может поддерживать один модуль Arduino?
вы читаете два байта, если доступен только один, @Juraj
Мой мыслительный процесс заключался в том, чтобы прочитать два байта, чтобы я мог сравнить, если два последовательных байта равны 0x54 и 0x43, тогда я знаю, что это конец кадра данных. Любое предложение о том, как это сделать? @Juraj, @obatala