Hi, I've ordered a new card, perhaps mine was faulty or I broke it. I'll write in this forum about the results....
hi thanks for sharing info .. can u please also share your hardware details , all the hardware items you used
Hi, esp32 nodeMCU, ILI9341 2.8" tft display (no touch), LD2451 and for testing 18650 battery via dc-dc boost, and of course some wires. The LD2451 is now mounted in a box and because it has smd's on it a piece plastic was used as a space and also so there was no "air gap" between the sensor and case (ie rather than stand offs) This is my phase 1 testing finished and now working on phase 2 which is to get the tft info (just speed and distance) to display on my DVR using ONVIF protocol. So far 8 AI's have failed to code for the ONVIF protocol so still work in progress. Once finished the speed info will appear as if it was a camera and show the info next to the camera that is recording the car.
Hope this is helpful, don't seem to be able to upload videos.
It may be a silly question but have you tried swapping the RT/TX lines RX of the sensor goes to the TX assigned pin on the esp? Do you get anything on the serial monitor?
Hi, yes: I've tried to swap. Also if I connect just a serial to USB converter I get weird data. Perhaps mine were faulty. Waiting for new units.
Weird data often means the baud rate is incorrect, try some diffenert ones, should be 115200, the fact you get something is the important thing. Connect the sensor to you pc with usb TTL adaptor and run a program called "Realterm" you are looking for data like F8F7F600F4F3F2F1 and it should repeat about 5 time (once for each possible target) Make sure it is set to "HEX" in the display tab.
No, I've tried the setup @115200, the problem was that the init was OK but the sequence was not "closed"
Anyway: thanks for your help.
Hi, I have now somethingh that is "more or less" working. In the next message the code, I hope that will be useful for someone. So far it appears to be quite unreliable in readings, perhaps is the plastic cover I've used.
#include <HardwareSerial.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define RXD2 16
#define TXD2 17
HardwareSerial mySerial(2);
#define TFT_CS 5
#define TFT_RST 22
#define TFT_DC 15
#define TFT_SCLK 18
#define TFT_MOSI 23
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
int dataPosition = 120;
byte allBytes_OLD[9]={000000000};
byte allBytes[9]={111111111};
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("LD2451 Test");
mySerial.begin(115200, SERIAL_8N1, RXD2, TXD2);
delay(100);
// Initialize TFT display
tft.initR() ;
tft.setRotation(3); // Adjust rotation as needed
tft.invertDisplay(1);
tft.fillScreen(ST7735_BLACK); // Clear TFT screen
tft.setTextSize(3);
tft.setCursor(20, 40);
tft.setTextColor(ST7735_YELLOW);
tft.print("BAT BOY");
delay(6000);
tft.fillScreen(ST7735_BLACK); // Clear TFT screen
tft.invertDisplay(0);
}
// ... tutte le #include e definizioni rimangono uguali fino al loop()
void loop() {
while (mySerial.available() >= 4) {
byte startMarker[4];
mySerial.readBytes(startMarker, 4);
if (startMarker[0] == 0xF4 && startMarker[1] == 0xF3 && startMarker[2] == 0xF2 && startMarker[3] == 0xF1) {
Serial.println("marker");
if (mySerial.available() >= 1) {
byte dataLength;
mySerial.readBytes(&dataLength, 1);
Serial.println("serial avail ");
Serial.println(dataLength);
if (dataLength != 0) {
if (mySerial.available() >= 9) {
mySerial.readBytes(allBytes, 9);
tft.setTextWrap(true);
tft.setTextSize(1);
// Byte after F1
if (allBytes[0] != allBytes_OLD[0]) {
tft.setCursor(0, 0);
tft.setTextColor(ST7735_WHITE);
tft.print("Byte after F1: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 0);
tft.print(allBytes_OLD[0]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 0);
tft.print(allBytes[0]);
Serial.print("Byte after F1: ");
Serial.println(allBytes[0]);
}
// Target Detected
if (allBytes[1] != allBytes_OLD[1]) {
tft.setCursor(0, 15);
tft.setTextColor(ST7735_WHITE);
tft.print("1=Target Detected: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 15);
tft.print(allBytes_OLD[1]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 15);
tft.print(allBytes[1]);
Serial.print("1=Target Detected: ");
Serial.println(allBytes[1]);
}
// Num Targets
if (allBytes[2] != allBytes_OLD[2]) {
tft.setCursor(0, 30);
tft.setTextColor(ST7735_WHITE);
tft.print("Num Targets: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 30);
tft.print(allBytes_OLD[2]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 30);
tft.print(allBytes[2]);
Serial.print("Num Targets: ");
Serial.println(allBytes[2]);
}
// Angle
if (allBytes[3] != allBytes_OLD[3]) {
tft.setCursor(0, 45);
tft.setTextColor(ST7735_WHITE);
tft.print("Angle: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 45);
tft.print(allBytes_OLD[3]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 45);
tft.print(allBytes[3]);
Serial.print("Angle: ");
Serial.println(allBytes[3]);
}
// Distance
if (allBytes[4] != allBytes_OLD[4]) {
tft.setTextSize(2);
tft.setCursor(0, 60);
tft.setTextColor(ST7735_GREEN);
tft.print("Distance: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition + 5, 60);
tft.print(allBytes_OLD[4]);
tft.setTextColor(ST7735_GREEN);
tft.setCursor(dataPosition + 5, 60);
tft.print(allBytes[4]);
Serial.print("Distance (m): ");
Serial.println(allBytes[4]);
tft.setTextSize(1); // torna a dimensione standard
}
// Approach/Recede
if (allBytes[5] != allBytes_OLD[5]) {
tft.setCursor(0, 80);
tft.setTextColor(ST7735_WHITE);
tft.print("1=Approach 0=Recede: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition + 10, 80);
tft.print(allBytes_OLD[5]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition + 10, 80);
tft.print(allBytes[5]);
Serial.print("1=Approach 0=Recede: ");
Serial.println(allBytes[5]);
}
// Speed km
if (allBytes[6] != allBytes_OLD[6]) {
tft.setTextSize(2);
tft.setCursor(0, 95);
tft.setTextColor(ST7735_GREEN);
tft.print("Speed km: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 95);
tft.print(allBytes_OLD[6]);
tft.setTextColor(ST7735_GREEN);
tft.setCursor(dataPosition, 95);
tft.print(allBytes[6]);
Serial.print("Speed km: ");
Serial.println(allBytes[6]);
tft.setTextSize(1); // torna a dimensione standard
}
// Salva i nuovi dati
memcpy(allBytes_OLD, allBytes, sizeof(allBytes));
}
}
}
}
}
delay(50);
}`Use code tags to format code for the forum`
Please edit your post to add code tags.
Is better now ? Cheers, Alex.
Too many delays will make it useless and slow, delay (6000) and other delay (100) is excessive.
Hi, what is the maximum detection distance you've archived ? I cannot go beyond 30 meters.
Speed instead seems (relatively) accurate.
Cheers, Alex.
BTW, Actually the only delay during normal activity is 50 .
So far just at "hand hold" height, best distance is 50 to 70 meters. It is recommended by the manufacturer it be mounted at a height of 2 meters and it makes a difference if the sensor is mounted horizontal or vertical, mine is being used in the horizontal position as shown in my past photo.
Try uploading some photos so others can see what you are doing. Now that we have some good working code for the LD2451, others will be more interested. Of course the REAL question is what is the highest SPEED you have detected hehe.
Hi, yes: as soon as I can run a "road test". BTW, I've updated the code so parameters are loaded each time, if they don't reach the radar an error is displayed. Code follows.
#include <HardwareSerial.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define RXD2 16
#define TXD2 17
HardwareSerial mySerial(2);
#define TFT_CS 5
#define TFT_RST 22
#define TFT_DC 15
#define TFT_SCLK 18
#define TFT_MOSI 23
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
int dataPosition = 120;
byte allBytes_OLD[9]={000000000};
byte allBytes[9]={111111111};
////
unsigned long timeout = 1000; //one second timeout on response receive
char cmdStartConfig[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 4, 3, 2, 1}; //command header, data, trailer
char cmdEndConfig[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xFE, 0x00, 4, 3, 2, 1}; //command header, data, trailer
char cmdSensitivity[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x06, 0x00, 0x03, 0x00, 0x02, 0x04, 0x00, 0x00, 4, 3, 2, 1}; //command header, data, trailer
char cmdDistancedir[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x06, 0x00, 0x02, 0x00, 0x64, 0x02, 0x01, 0x00, 4, 3, 2, 1}; //command header, data, trailer. Sets max distance and bidirectional
char cmdFactoryReset[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xA2, 0x00, 4, 3, 2, 1};
char cmdBluetoothOn[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xA4, 0x00, 0x01, 0x00, 4, 3, 2, 1}; //from HLK-LD2410B serial protocol manual
char cmdBluetoothOff[] = {0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xA4, 0x00, 0x00, 0x00, 4, 3, 2, 1};
char data[20]; //response message buffer
int dataSize = 20;
int returnValue = 0;
bool config_sensitivity=false;
bool config_distance=false;
////
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("LD2451 Test");
mySerial.begin(115200, SERIAL_8N1, RXD2, TXD2);
delay(2000);
//clear input buffer
while (mySerial.available()) {
Serial.print(mySerial.read(), HEX);
}
Serial.println("");
Serial.println("Set config mode");
mySerial.write(cmdStartConfig, sizeof cmdStartConfig);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
delay(10);
Serial.println("Set sensitivity trigger = 2, S/N = 4");
cmdSensitivity[8] = 2; //set number of triggers
cmdSensitivity[9] = 3; //set minimimum SNR
mySerial.write(cmdSensitivity, sizeof cmdSensitivity);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
if (returnValue == 0) {config_sensitivity=true;}
delay(10);
Serial.println("Set speed direction distance = 100 m , direction = 2 min speed= 1 delay=0");
//cmdSensitivity[8] = 2; //set number of triggers
//cmdSensitivity[9] = 4; //set minimimum SNR
mySerial.write(cmdDistancedir, sizeof cmdDistancedir);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
if (returnValue == 0) {config_distance=true;}
delay(10);
/*
//Bluetooth off
Serial.println("BT off");
mySerial.write(cmdBluetoothOff, sizeof cmdBluetoothOff);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
delay(10000); //check for BT off
*/
//Bluetooth on
Serial.println("BT on");
mySerial.write(cmdBluetoothOn, sizeof cmdBluetoothOn);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
Serial.println("End config mode");
mySerial.write(cmdEndConfig, sizeof cmdEndConfig);
delay(10);
returnValue = getResponse();
Serial.println((returnValue == 0) ? "OK" : "Failed");
Serial.println("Done with configuration");
// Initialize TFT display
tft.initR() ;
tft.setRotation(3); // Adjust rotation as needed
tft.invertDisplay(1);
tft.fillScreen(ST7735_BLACK); // Clear TFT screen
tft.setTextSize(3);
tft.setCursor(20, 20);
tft.setTextColor(ST7735_YELLOW);
tft.print("BAT BOY");
tft.setTextSize(2);
tft.setCursor(10, 70);
tft.setTextColor(ST7735_WHITE);
if (config_distance){
tft.print("Dist. OK SET");}else {tft.print("Dist. NO SET");}
tft.setTextSize(2);
tft.setCursor(10, 90);
tft.setTextColor(ST7735_WHITE);
if (config_sensitivity){ tft.print("Sens. OK SET");}else {tft.print("Sens. NO SET");}
delay(5000);
tft.fillScreen(ST7735_BLACK); // Clear TFT screen
tft.invertDisplay(0);
}
// ... tutte le #include e definizioni rimangono uguali fino al loop()
void loop() {
while (mySerial.available() >= 4) {
byte startMarker[4];
mySerial.readBytes(startMarker, 4);
if (startMarker[0] == 0xF4 && startMarker[1] == 0xF3 && startMarker[2] == 0xF2 && startMarker[3] == 0xF1) {
//Serial.println("marker");
if (mySerial.available() >= 1) {
byte dataLength;
mySerial.readBytes(&dataLength, 1);
// Serial.println("serial avail ");
Serial.println(dataLength);
if (dataLength != 0) {
if (mySerial.available() >= 9) {
mySerial.readBytes(allBytes, 9);
tft.setTextWrap(true);
tft.setTextSize(1);
// Byte after F1
if (allBytes[0] != allBytes_OLD[0]) {
tft.setCursor(0, 0);
tft.setTextColor(ST7735_WHITE);
tft.print("Byte after F1: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 0);
tft.print(allBytes_OLD[0]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 0);
tft.print(allBytes[0]);
// Serial.print("Byte after F1: ");
// Serial.println(allBytes[0]);
}
// Target Detected
if (allBytes[1] != allBytes_OLD[1]) {
tft.setCursor(0, 15);
tft.setTextColor(ST7735_WHITE);
tft.print("1=Target Detected: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 15);
tft.print(allBytes_OLD[1]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 15);
tft.print(allBytes[1]);
// Serial.print("1=Target Detected: ");
// Serial.println(allBytes[1]);
}
// Num Targets
if (allBytes[2] != allBytes_OLD[2]) {
tft.setCursor(0, 30);
tft.setTextColor(ST7735_WHITE);
tft.print("Num Targets: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 30);
tft.print(allBytes_OLD[2]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 30);
tft.print(allBytes[2]);
// Serial.print("Num Targets: ");
// Serial.println(allBytes[2]);
}
// Angle
if (allBytes[3] != allBytes_OLD[3]) {
tft.setCursor(0, 45);
tft.setTextColor(ST7735_WHITE);
tft.print("Angle: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 45);
tft.print(allBytes_OLD[3]);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(dataPosition, 45);
tft.print(allBytes[3]);
// Serial.print("Angle: ");
// Serial.println(allBytes[3]);
}
// Distance
if (allBytes[4] != allBytes_OLD[4]) {
tft.setTextSize(2);
tft.setCursor(0, 60);
tft.setTextColor(ST7735_GREEN);
tft.print("Distance: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition , 60);
tft.print(allBytes_OLD[4]);
tft.setTextColor(ST7735_GREEN);
tft.setCursor(dataPosition , 60);
tft.print(allBytes[4]);
// Serial.print("Distance (m): ");
// Serial.println(allBytes[4]);
}
// Speed km
if (allBytes[6] != allBytes_OLD[6]) {
tft.setTextSize(2);
tft.setCursor(0, 85);
tft.setTextColor(ST7735_GREEN);
tft.print("Speed km: ");
tft.setTextColor(ST7735_BLACK);
tft.setCursor(dataPosition, 85);
tft.print(allBytes_OLD[6]);
tft.setTextColor(ST7735_GREEN);
tft.setCursor(dataPosition, 85);
tft.print(allBytes[6]);
// Serial.print("Speed km: ");
// Serial.println(allBytes[6]);
}
// Approach/Recede
if (allBytes[5] != allBytes_OLD[5]) {
tft.setTextSize(2);
tft.setCursor(0, 108);
tft.setTextColor(ST7735_BLACK);
if (allBytes_OLD[5] == 1)
{
tft.print("Approach");
}
else
{
tft.print("Recedes");
}
tft.setCursor(0, 108);
if (allBytes[5]==1)
{
tft.setTextColor(ST7735_BLUE);
tft.print("Approach");
}
else
{
tft.setTextColor(ST7735_YELLOW);
tft.print("Recedes");
}
// Serial.print("1=Approach 0=Recede: ");
// Serial.println(allBytes[5]);
}
// Salva i nuovi dati
memcpy(allBytes_OLD, allBytes, sizeof(allBytes));
}
}
}
}
}
delay(50);
}
//return value 0 = success, 1=failure
int getResponse() {
unsigned long startTime = millis();
int state = 0, count = 0, indx = 0, messageSize = 0;
char c;
while (millis() - startTime < timeout) {
if (mySerial.available()) {
c = mySerial.read();
//debug response
if (c < 0x10) Serial.print('0'); //if debug
Serial.print(c, HEX); //if debug
Serial.print(' '); //if debug
switch (state) {
case 0:
if (c != cmdStartConfig[count])
{ //header doesn't match
return 1;
}
else {
count++;
if (count > 3) //have the 4 message startbytes.
state = 1; //get message size
indx = 0;
}
break;
case 1: //get message size
messageSize = c; //The next 2 bytes tells the size in bytes of the dataframe that follows
state = 2;
break;
case 2: //high byte of size
messageSize += (c << 8);
state = 3;
if (messageSize == 0) state = 4; //no message
break;
case 3: //get data, if any
if (indx < dataSize) data[indx] = c; //buffer overflow check
indx++;
messageSize--;
if (messageSize == 0)
state = 4; //get frame end markers
break;
case 4:
count--; //ignore four end markers
if (count == 0) {
Serial.println(); //if debug
return data[2]; //low byte of second data word, 0=OK, 1=failure
}
}
}
}//end while timeout
Serial.println("response timeout");
return 1;
}
After buying one of these sensors found this discussion.
Using the code from here as a starting place created a library for use on ESP32 boards - GitHub - Madproforg/HLK_LD2451: ESP32 only Library for the HighLink LD2451 Vehicle detection radar sensor
probably some questionable code in it - this is just a side hobby for me - modify it to your hearts content
I do use PlatformIO rather than the Arduino IDE but don't see why it shouldn't work
small example of usage
#include <Arduino.h>
#include <HardwareSerial.h>
#include <HLK_LD2451.h>
// which uart to use for the sensor
HardwareSerial uart2(2);
// sensor initial config
HLK_LD2451 ld2451_sensor(uart2);
void setup() {
Serial.begin(115200);
// wait for serial to init
while (!Serial) vTaskDelay(10);
// send sensor debugging output to Serial monitor
ld2451_sensor.debugOutput(&Serial);
// begin sensor reading with defaults pins 15 for RX 16 for TX
ld2451_sensor.begin();
// begin sensor reading with custome serial paramaters
//ld2451_sensor.begin(115200, SERIAL_8N1, 15, 16);
}
void loop() {
// wait 1 second for a detection event
if (ld2451_sensor.waitForDetection(1000)) {
// detected vehicles are in a vector - no manual memory management
std::vector<LD2451::vehicleTarget_t> detected = ld2451_sensor.getTargets();
// output all detected items to serial monitor
Serial.println("--------------------");
Serial.printf("%d vehicles detected\r\n", detected.capacity());
uint8_t vehicleNumber = 1;
for (LD2451::vehicleTarget_t singleTarget : detected) {
Serial.printf("vehicle #%d\r\n", vehicleNumber);
Serial.printf("Distance: %dm\r\n", singleTarget.distance);
Serial.printf("@angle: %d°\r\n", singleTarget.angle);
Serial.printf("Heading %s\r\n", singleTarget.direction==0 ? "Away" : "Towards");
Serial.printf("With a speed of %d km/h\r\n", singleTarget.speed);
Serial.printf("SNR: %d\r\n", singleTarget.snr);
Serial.println("-----");
vehicleNumber++;
}
}
}
For those of you still playing with this sensor, great, I have now adapted my code to connect to the LD2451 using bluetooth (actually more AI Grok3's code) but it works well and reliably. There is a lot of debug lines I have left in for future tinkering but they are commented out and may be of some help for others to get it working.
// Grok3 AI and his master Gary Durey April 2025
#include <ArduinoBLE.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// TFT connections
#define TFT_CS 5
#define TFT_RST 4
#define TFT_DC 2
#define TFT_MOSI 23
#define TFT_SCK 18
int dataPosition = 260;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);
// Bluetooth specifics
const char* deviceAddress = "40:02:be:4d:6f:24";
const char* serviceUUID = "fff0";
const char* charUUID = "fff1";
BLEDevice peripheral;
BLEService sensorService(serviceUUID);
BLECharacteristic sensorChar;
static uint8_t dataBuffer[256];
static int dataIndex = 0;
static boolean connected = false;
unsigned long lastCheck = 0;
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("LD2451 BLE Test - Setup Start");
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
// Commented out TFT debug
// tft.setCursor(0, 0);
// tft.setTextColor(ILI9341_WHITE);
// tft.setTextSize(2);
// tft.println("TFT Init OK");
Serial.println("TFT Initialized");
delay(1000);
if (!BLE.begin()) {
Serial.println("Starting BLE failed!");
tft.fillScreen(ILI9341_RED);
tft.setCursor(0, 0);
tft.println("BLE Failed");
while (1);
}
BLE.setLocalName("ESP32_LD2451");
Serial.println("Scanning for device...");
}
void loop() {
if (!connected) {
connectToPeripheral();
return;
}
if (!sensorChar) {
Serial.println("Error: sensorChar is invalid");
tft.fillScreen(ILI9341_RED);
tft.setCursor(0, 0);
tft.println("Char Invalid");
connected = false;
peripheral.disconnect();
return;
}
if (millis() - lastCheck >= 5000) {
Serial.println("Checking for data...");
lastCheck = millis();
}
if (sensorChar.valueUpdated()) {
uint8_t tempBuffer[32];
int len = sensorChar.readValue(tempBuffer, sizeof(tempBuffer));
Serial.print("Raw Data Received (len=");
Serial.print(len);
Serial.print("): ");
for (int i = 0; i < len; i++) {
Serial.print(tempBuffer[i], HEX);
Serial.print(" ");
dataBuffer[dataIndex++] = tempBuffer[i];
if (dataIndex >= 256) dataIndex = 0;
}
Serial.println();
// Commented out TFT raw data debug
// tft.fillScreen(ILI9341_BLACK);
// tft.setCursor(0, 0);
// tft.setTextSize(2);
// tft.print("Raw Data (");
// tft.print(len);
// tft.println("):");
// for (int i = 0; i < len; i++) {
// tft.setCursor(0, 20 + i * 20);
// tft.print("Byte ");
// tft.print(i);
// tft.print(": ");
// tft.fillRect(dataPosition, 20 + i * 20, 100, 16, ILI9341_BLACK);
// tft.setCursor(dataPosition, 20 + i * 20);
// tft.print(tempBuffer[i], HEX);
// }
}
while (dataIndex >= 4) {
if (dataBuffer[0] == 0xF4 && dataBuffer[1] == 0xF3 && dataBuffer[2] == 0xF2 && dataBuffer[3] == 0xF1) {
if (dataIndex >= 5) {
byte dataLength = dataBuffer[4];
if (dataLength == 0) {
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(4);
tft.setCursor(0, 200);
tft.setTextColor(ILI9341_RED);
tft.println("No Target");
Serial.println("No Target");
memmove(dataBuffer, dataBuffer + 5, dataIndex - 5);
dataIndex -= 5;
} else if (dataIndex >= 14) {
byte allBytes[9];
memcpy(allBytes, dataBuffer + 5, 9);
displayData(allBytes);
memmove(dataBuffer, dataBuffer + 14, dataIndex - 14);
dataIndex -= 14;
} else {
break;
}
} else {
break;
}
} else {
memmove(dataBuffer, dataBuffer + 1, dataIndex - 1);
dataIndex--;
}
}
if (!peripheral.connected()) {
connected = false;
Serial.println("Disconnected.");
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.println("Disconnected");
}
delay(200);
}
void connectToPeripheral() {
Serial.println("Scanning...");
// Commented out TFT debug
// tft.fillScreen(ILI9341_BLACK);
// tft.setCursor(0, 0);
// tft.println("Scanning...");
BLE.scanForAddress(deviceAddress);
peripheral = BLE.available();
if (peripheral) {
Serial.println("Device found");
// tft.setCursor(0, 20);
// tft.println("Device Found");
BLE.stopScan();
if (peripheral.connect()) {
Serial.println("Connected!");
// tft.setCursor(0, 40);
// tft.println("Connected");
if (peripheral.discoverAttributes()) {
BLEService genericService("1800");
BLECharacteristic nameChar = peripheral.service("1800").characteristic("2a00");
if (nameChar) {
uint8_t nameBuffer[32];
int len = nameChar.readValue(nameBuffer, sizeof(nameBuffer));
Serial.print("Device Name: ");
for (int i = 0; i < len; i++) Serial.write(nameBuffer[i]);
Serial.println();
}
sensorService = peripheral.service(serviceUUID);
if (sensorService) {
sensorChar = sensorService.characteristic(charUUID);
if (sensorChar && sensorChar.canSubscribe()) {
sensorChar.subscribe();
connected = true;
Serial.println("Subscribed to characteristic");
// tft.setCursor(0, 60);
// tft.println("Subscribed");
} else {
Serial.println("Failed to subscribe or find characteristic");
peripheral.disconnect();
}
} else {
Serial.println("Service not found");
peripheral.disconnect();
}
} else {
Serial.println("Attribute discovery failed");
peripheral.disconnect();
}
} else {
Serial.println("Connection failed");
}
}
delay(2000);
}
void displayData(byte* allBytes) {
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setTextWrap(true);
tft.setCursor(0, 0);
tft.print("Byte after F1: ");
tft.fillRect(dataPosition, 0, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 0);
tft.print(allBytes[0]);
Serial.print("Byte after F1: ");
Serial.println(allBytes[0]);
tft.setCursor(0, 20);
tft.print("1=Target Detected: ");
tft.fillRect(dataPosition, 20, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 20);
tft.print(allBytes[1]);
Serial.print("1=Target Detected: ");
Serial.println(allBytes[1]);
tft.setCursor(0, 40);
tft.print("Num Targets: ");
tft.fillRect(dataPosition, 40, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 40);
tft.print(allBytes[2]);
Serial.print("Num Targets: ");
Serial.println(allBytes[2]);
tft.setCursor(0, 60);
tft.print("Angle: ");
tft.fillRect(dataPosition, 60, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 60);
tft.print(allBytes[3]);
Serial.print("Angle: ");
Serial.println(allBytes[3]);
tft.setCursor(0, 80);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(3);
tft.print("Distance (m): ");
tft.fillRect(dataPosition, 80, 100, 18, ILI9341_BLACK);
tft.setCursor(dataPosition, 80);
tft.print(allBytes[4]);
Serial.print("Distance (m): ");
Serial.println(allBytes[4]);
tft.setCursor(0, 120);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("1=Approach 0=Recede: ");
tft.fillRect(dataPosition, 120, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 120);
tft.print(allBytes[5]);
Serial.print("1=Approach 0=Recede: ");
Serial.println(allBytes[5]);
tft.setCursor(0, 150);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(3);
tft.print("Speed km: ");
tft.fillRect(dataPosition, 150, 100, 18, ILI9341_BLACK);
tft.setCursor(dataPosition, 150);
tft.print(allBytes[6]);
Serial.print("Speed km: ");
Serial.println(allBytes[6]);
tft.setCursor(0, 180);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Signal/Noise: ");
tft.fillRect(dataPosition, 180, 100, 16, ILI9341_BLACK);
tft.setCursor(dataPosition, 180);
tft.print(allBytes[7]);
Serial.print("Signal/Noise: ");
Serial.println(allBytes[7]);
}
Good luck. (I'm still working on a version that will feed the data into my DVR but ONVIF and RTSP stuff is proving extremely difficult for AI to code hehe)
OH and of course you will need to replace the "deviceAddress" with your own. I have a script that you can run to discover it if anyone wants it let me know.
Thanks, I;ll test it.