Need to write and then read from serial device

Hi,

I have a serial device hooked up to my Arduino (ESP32 WROOM). I'm not a serial expert but I have at least some stuff working. The manual is chinese (or at least, very broken english) and I'm trying to make sense of it.

The device needs to be configured as such:

  • Baud rate: 115200
  • Word width: 8bit
  • Stop bit: 1
  • Parity: None
  • Flow control: none (no idea what that is?)
  • Receive/send settings: ASCII

I would assume that is done by doing: (it's on RX2/TX2)

MMWave.begin(115200, SERIAL_8N1, 16, 17);

When I try the following code I get the output from the device as expected:

#include <Arduino.h>

HardwareSerial MMWave(1);
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
bool newData = false;

void setup() {
    Serial.begin(115200);
    MMWave.begin(115200, SERIAL_8N1, 16, 17);
}

bool sent = false;

void loop() {
    byte index = 0;
    while(MMWave.available() > 0) {
        char rc = MMWave.read();
        receivedChars[index] = rc;
        index++;

        if (rc == '\n') {
            Serial.print(receivedChars);
            index = 0;
            delay(1000);
        }
    }
}

The output is exactly as in the manual:

mov, dis=2.95
mov, dis=2.83
mov, dis=2.83

Now comes the problem, I can write parameters to the device as well. They say to send/receive data in ASCII in the manual and that when I write the command "get_all" to the device I should get a response returning all the current configuration parameters.

If I do not get the feedback from the device the manual tell me to make sure that the command is sent "with a carriage return and line feed".

I would expect that when I:

MMWave.write("get_all");
MMWave.write('\r');
MMWave.write('\n');

And then use the above code to read again...I would get the output from the command. But instead it keeps outputing the mov lines (default output) and it doesn't respond at all to my command. I also tried to:

MMWave.println("get_all");

And

MMWave.print("get_all\r\n");

Nothing seems to work. Any advice would be greatly appreciated. I have read alot of serial introduction stuff but I can't seem to match the correct info to my use case.

Thank you guys in advance!

Please also post the entire faulty sketch. Also a link to the manual.

the' broken english' manual would be 'better-that-nothing' info as well! :wink:

You are right, I wasnt sure about posting links in my first post. Here it is: Manual

The sketch I will upload as soon as I get home, though 90% is in my opening post haha.

Okay, is that a link to something you uploaded to the cloud or a manufacturer upload? Please add it as an attachment if the forum software will allow you to do it.

This all may seem pedantic to you, but we need all the information in the right format to facilitate efficient help.

The 90% you posted is working code according to you. So it's only partially useful.

It says I am a new user and cannot upload an attachment.

I uploaded it here: HLK-LD1125H-24G应用手册.zh-CN.en.pdf | DocDroid

You can just view it online then.

So, I got back and somehow it "started" working after I unplugged it and plugged it.

The messages return somehow jumbled up though, after I send "get_all" it returns this:

received message: get_all
test_mode is 0
: get_all
rmax is 6.00

: get_all
mth1_mov is 80
: get_all
mth2_mov is 50
: get_all
mth3_mov is 20
: get_all
mth1_occ is 60
: get_all
mth2_occ is 55
: get_all
mth3_occ is 20
: get_all
eff_th is 20

: get_all
accu_num is 10
: get_all
mov, dis=1.60

: get_all
mov, dis=1.63

: get_all
mov, dis=0.70

: get_all
mov, dis=1.13

: get_all
1.33
is=1.13

After that the normal flow is constantly interupted by ": get_all":

: get_all
mov, dis=0.67

: get_all
mov, dis=0.75

: get_all
mov, dis=0.75

: get_all

Here is my full program:

#include <Arduino.h>

HardwareSerial MMWave(1);
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
bool newData = false;

void setup() {
    Serial.begin(115200);
    MMWave.begin(115200, SERIAL_8N1, 16, 17);
}

bool sent = false;

void loop() {
    if (!sent) {
        while(!MMWave.availableForWrite()) {
            Serial.println("Cant write waiting...");
            delay(500);
        }
        MMWave.write("get_all");
        MMWave.write('\r');
        MMWave.write('\n');
        Serial.println("Written");
        sent = true;
    }

    byte index = 0;
    Serial.println("Reading...");
    while(MMWave.available() > 0) {
        char rc = MMWave.read();
        receivedChars[index] = rc;
        index++;

        if (rc == '\n') {
            Serial.print(receivedChars);
            index = 0;
            delay(1000);
        }
    }

    delay(1000);
}

It's just so strange, I changed my program to do the following:

#include <Arduino.h>

HardwareSerial MMWave(1);


void setup() {
    Serial.begin(115200);
    MMWave.begin(115200, SERIAL_8N1, 16, 17);
}

bool sent = false;
int count = 0;
void loop() {
    count++;
    Serial.println(MMWave.readStringUntil('\n'));

    if (count == 3) {
        Serial.println("Writing get_all");
        MMWave.write("get_all");
        MMWave.write('\r');
        MMWave.write('\n');
    }

    delay(200);
}

Then the output becomes:

mov, dis=1.05
mov, dis=1.17
mov, dis=1.17
Writing get_all
mov, dis=1.20
mov, dis=1.38
mov, dis=1.35
mov, dis=1.17
mov, dis=1.17
mov, dis=1.35
mov, dis=1.17
mov, dis=1.00
mov, dis=1.00
mov, dis=1.05
mov, dis=1.05
mov, dis=1.23
mov, dis=1.35
mov, dis=1.35
mov, dis=1.35
mov, dis=1.35
received message: ���mov, dis��get_all
mov, dis=1.63
mov, dis=1.63
mov, dis=1.60
mov, dis=1.58
mov, dis=1.55
mov, dis=1.45
0
mov, dis=0.98
mov, dis=0.95
mov, dis=0.95
mov, dis=0.95
mov, dis=0.95
mov, dis=0.98
mov, dis=1.10
is=1.40

So it seems for a long time it doesn't respond to get_all. Then it says: received message:...and the data get's all messed up. Am I doing something wrong or am I dealing with a broken device?

Also tried the code below (changed it out for Serial2). Still only reads the data, doesn't output get_all return data.

#include <Arduino.h>

String readSerial() {
    String message = "";
    while (Serial2.available()) {
        char incomingChar = Serial2.read();
        if (incomingChar == '\n') {
            break;
        }
        message += incomingChar;
    }
    return message;
}

void SendCommand(String cmd) {
    cmd += '\r';
    cmd += '\n';
    Serial.print("Writing command: "+cmd);
    Serial2.print(cmd);
}

void setup() {
    Serial.begin(115200);
    Serial2.begin(115200, SERIAL_8N1);
}

int count = 0;
void loop() {
    SendCommand("get_all");
    Serial.println(readSerial());
    delay(1000);
}

I have posted the manual!

I have posted all my code and some more tries!

Something I discovered is that when I just keep pushing the get_all message (or any message for that matter) it will eventually start outputing the data.

Is there something in the communication that I'm doing wrong? Sometimes it takes 5 tries but then the response isn't always good or complete, but it is definitely returning something.

Could this be like a voltage problem or something? I measure 5.04V on USB and the device as well. Everything seems to work normally.

Did you ever get a working sketch? I just got one of the LD1125H modules that I would like to use.

HLK-LD1125H-24GApplication.Manual.pdf (1.4 MB)

Hi @b03tz, some of the issues you are having might be from your use of delay() functions in your main loop. You should use timers/counters instead so that Serial and anything else can continue in the background. The loop() function loops faster than a full/complete Serial string, hence why you gotta process it in chunks and look for the \n to determine when you've captured a complete string.

I've started a test script for the LD1125H sensor, that sends motion and occupancy state as boolean values over mqtt ~ kind of like Tasmota. I may even look into seeing if I can use tasmota with serial when I need these for production. But for now I'm just debugging with a simple script.

My outgoing mqtt topics, and payloads are:
tele/{{ device id }}/mov, true|false.
tele/{{ device id }}/occ, true|false.
stat/{{ device id }}/cmnd, ok.

My incoming mqtt topics are (but haven't done anything with yet):
cmnd/{{ device id }}/max Set max distance value
cmnd/{{ device id }}/mov Set motion range sensitivity values
cmnd/{{ device id }}/occ Set occupancy range sensitivity values
cmnd/{{ device id }}/save Save sensitivity values to LD1125H

#include <ESP8266WiFi.h>
#include <PubSubClient.h>


// Wifi, and MQTT server
const char* SSID = "***";
const char* PASSWORD = "***";
const char* SERVER = "***.***.***.***";

// Serial vars
String serial_buff;
bool serial_new = false;
char serial_char;

// Sensor vars
bool mov_snr = false;
bool occ_snr = false;
unsigned long mov_timer = 0;
unsigned long occ_timer = 0;

// Init Wifi and MQTT
WiFiClient esp_client;
PubSubClient mqtt_client(esp_client);


// Init script
void setup()
{
    Serial.begin(115200);

    delay(10);

    WiFi.mode(WIFI_STA);
    WiFi.begin(SSID, PASSWORD);

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
    }

    mqtt_client.setServer(SERVER, 1883);
    mqtt_client.setCallback(mqttCallBack);
}


// Main loop
void loop()
{
    if (!mqtt_client.connected())
    {
        mqttReconnect();
    }

    mqtt_client.loop();

    readSerial();
    processSerial();
}


// Fetch serial payload
void readSerial()
{
    while (Serial.available() > 0 && !serial_new)
    {
        serial_char = Serial.read();

        if (serial_char == '\r' || serial_char == '\n')
        {
            serial_new = true;
        }

        if (!serial_new)
        {
            serial_buff += serial_char;
        }
    }
}


// Process serial payload
void processSerial()
{
    // Trigger motion `false` mqtt payload
    if (!serial_new && mov_snr && (millis() - mov_timer) > 1000)
    {
        mov_snr = false;
        teleSend("mov", "false");
    }

    // Trigger occupancy `false` mqtt payload
    if (!serial_new && occ_snr && (millis() - occ_timer) > 1000)
    {
        occ_snr = false;
        teleSend("occ", "false");
    }
    
    // Exit early, nothing to process
    if (!serial_new) return;

    // Process `mov` serial payload
    if (serial_buff.substring(0, 3).equals("mov"))
    {
        // Trigger motion `true` mqtt payload
        if (!mov_snr)
        {
            teleSend("mov", "true");
        }

        mov_snr = true;
        mov_timer = millis();
    }
    // Process `occ` serial payload
    else if (serial_buff.substring(0, 3).equals("occ"))
    {
        // Trigger occupancy `true` mqtt payload
        if (!occ_snr)
        {
            teleSend("occ", "true");
        }

        occ_snr = true;
        occ_timer = millis();
    }
    // Process `received` serial payload, todo...
    else if (serial_buff.substring(0, 3).equals("rec"))
    {
        statSend("cmnd", "ok");
    }

    // Reset serial string
    serial_buff = "";
    serial_new = false;
}


// Handle incoming MQTT payloads
void mqttCallBack(char* topic, byte* payload, unsigned int length)
{
    // TODO: process setting sensitivity values
}


// Handle reconnecting to MQTT broker
void mqttReconnect()
{
    while (!mqtt_client.connected())
    {
        char buffer [25];

        if (mqtt_client.connect(WiFi.macAddress().c_str()))
        {
            sprintf(buffer, "cmnd/%s/max", WiFi.macAddress().c_str());
            mqtt_client.subscribe(buffer);

            sprintf(buffer, "cmnd/%s/mov", WiFi.macAddress().c_str());
            mqtt_client.subscribe(buffer);

            sprintf(buffer, "cmnd/%s/occ", WiFi.macAddress().c_str());
            mqtt_client.subscribe(buffer);

            sprintf(buffer, "cmnd/%s/save", WiFi.macAddress().c_str());
            mqtt_client.subscribe(buffer);
        }
        else
        {
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}


// Format `tele` topic and send mqtt payload
void teleSend(char * topic, char * payload)
{
    char buffer [25];
    sprintf(buffer, "tele/%s/%s", WiFi.macAddress().c_str(), topic);
    mqtt_client.publish(buffer, payload);
}


// Format `stat` topic and send mqtt payload
void statSend(char * topic, char * payload)
{
    char buffer [25];
    sprintf(buffer, "stat/%s/%s", WiFi.macAddress().c_str(), topic);
    mqtt_client.publish(buffer, payload);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.