Как читать и анализировать данные 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();

 }
}

Я хотел бы знать, правилен ли мой мыслительный процесс при чтении и анализе данных, потому что вывод совершенно не соответствует тому, что я ожидаю

, 👍1

Обсуждение

вы читаете два байта, если доступен только один, @Juraj

Мой мыслительный процесс заключался в том, чтобы прочитать два байта, чтобы я мог сравнить, если два последовательных байта равны 0x54 и 0x43, тогда я знаю, что это конец кадра данных. Любое предложение о том, как это сделать? @Juraj, @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