The difficult part would be if you needed to send to the Nextion display, since it would not understand the data format.
Did I understand correct - on receiver you use the same Serial for read from RS485 and for printing on Serial Monitor?
Yes I send this msg from nick nonblocking library
byte msg [] = {1, 1, 1, 3};
and read data on serial monitor with
unsigned long lastByteTime = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
unsigned long now = millis();
if (now - lastByteTime > 750 && lastByteTime != 0) Serial.println();
lastByteTime = now;
byte b = Serial.read();
Serial.print("0x");
if (b < 0x10) Serial.write('0');
Serial.print(b, HEX);
Serial.write(' ');
}
}
So this confirms that
Seems a good candidate for the printh
I send the array of byte through software serial:
#include <SoftwareSerial.h> // Or use HardwareSerial if available
// SoftwareSerial setup (adjust pins as needed)
SoftwareSerial nextionSerial(2, 3); // RX, TX
void setup() {
Serial.begin(9600);
nextionSerial.begin(9600);
}
void loop() {
// Array of bytes to send
byte myData[] = {0x02, 0x0F ,0x1E ,0x0F ,0x1E ,0x0F ,0x1E, 0x0F, 0x3C, 0x03, 0x0F, 0x2D};
int dataSize = sizeof(myData);
nextionSerial.write(myData, dataSize); // The actual data
delay(1000);
}
which pass through Nick gammon RS485 non-blocking library.
//Slave: Receiver
#include <RS485_non_blocking.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12,11); //RX = 2 TX = 3
byte buf [20];
int fAvailable () {
return mySerial.available ();
}
int fRead() {
return mySerial.read ();
}
RS485 myChannel (fRead, fAvailable, NULL, 20);
int Led_1 = 13;
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
myChannel.begin();
pinMode (Led_1, OUTPUT);
} // end of setup
void loop ()
{
if (myChannel.update ())
{
memcpy (buf, myChannel.getData (), myChannel.getLength ()); // make a copy of the data
if (buf [0] == 1 && buf [1] == 1 && buf [2] == 1 && buf [3] == 3)
{
Serial.println ("Led_1 High");
// digitalWrite (Led_1, HIGH);
}}}
Serial Output
Led_1 High
Led_1 High
How we can send or at least receive the same from nation display side
Have you tried the printh ?
From Nextion to arduino pass through nick non-blocking library
printh 02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D
I am looking support to same receive from nick non-blocking library to Nextion display.
There is a very complex procedure called Protocol Reparse Mode which is described in the Instruction Set document and could probably achieve what you want.
I think that an easier procedure would be to set up a text box to receive a text string of
"02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D". What do you want the nextion to do if the text box contains that string?
I have 50+ switch and dimmers in system each switch generate ON / OFF and call back msg like
byte msg [] = {101, 1, 3, 0}; //Sender ID, ReceiverID, Switch ID, Status OFF
byte msg [] = {101, 1, 3, 1}; //Sender ID, ReceiverID, Switch ID, Status ON
and call back function
byte msg [] = {1, 101, 3, 0}; //Sender ID, ReceiverID, Switch ID, Status OFF
Should I run all these msg and generate this code to put in nextion event. or we have some easy way to do that.
02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D
Can you explain some detail for clear understating.
Sorry, I am not very familiar with the Nextion display, someone else will have to provide answers.
Thanks for your time.
My question was how byte msg [] = {1, 1, 1, 3}; become 02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D
In my system 100++ msg for events. Should I send each msg from serial and pass through nick library to generate this code.
That is the simplest way to generate the code for each message.
If your Sender ID/Receiver ID and Switch ID numbers are sequential, then it would be fairly easy to run through all possible combinations with a couple of for loops, printing out the msg and its equivalent code from the library.
That’s the encoding used by the library. The source code is there.
I’m not familiar with nextion (they don’t have a Mac version for the editor so I’m not using their products) but if you have some way of writing a function on the display side, then possibly you could mimic the algorithm and send the right stuff out.
Finally, manage to send command from arduino to nextion with
myNextion.sendCommand("click bt0,1"); // instead of changing the image I use touch event over serial command.
Utilize nextion library with nick Gammon library
Can you help me in below sketch to print like {10,100,1,0}
// Four source arrays to combine
byte array1[] = {10, 11, 12, 13}; //Sender address 1-255
byte array2[] = {100, 101, 102,103}; // receiver 100-255
byte array3[] = {1, 2, 3, 4}; // Component iD 1-255
byte array4[] = {0, 0, 0, 0}; //Status 0 and 1
const size_t total_size = sizeof(array1) + sizeof(array2) + sizeof(array3) + sizeof(array4);
byte combined_message[total_size];
void setup() {
Serial.begin(9600);
while (!Serial);
// Use memcpy to combine the arrays into the combined_message buffer
memcpy(combined_message, array1, sizeof(array1));
memcpy(combined_message + sizeof(array1), array2, sizeof(array2));
memcpy(combined_message + sizeof(array1) + sizeof(array2), array3, sizeof(array3));
memcpy(combined_message + sizeof(array1) + sizeof(array2) + sizeof(array3), array4, sizeof(array4));
Serial.println("Combined message sent over Serial:");
// Send the entire combined message
Serial.write(combined_message, total_size);
// Optional: print the combined message for verification
for (int i = 0; i < total_size; i++) {
if (combined_message[i] < 0x10) Serial.print("0");
Serial.print(combined_message[i], HEX);
Serial.print(" ");
}
Serial.println();
}
void loop() {
// Empty for this example
}
I really do not understand what you are trying to do.
You should use a struct and an array of struct
Something like that (typed here - mind typos)
struct MessagePart {
byte sender;
byte receiver;
byte component;
byte status;
};
MessagePart messages[] = {
{10, 100, 1, 0},
{11, 101, 2, 1},
{12, 102, 3, 0},
{13, 103, 4, 1}
};
const size_t num_messages = sizeof messages / sizeof *messages;
void printByte(byte b) {
if (b < 0x10) Serial.write('0');
Serial.print(b, HEX);
Serial.write(' ');
}
void setup() {
Serial.begin(115200); // ⚠️ changed to 115200 adjust your serial terminal speed
while (!Serial) yield();
Serial.println("Messages:");
for (size_t i = 0; i < num_messages; i++) {
printByte(messages[i].sender);
printByte(messages[i].receiver);
printByte(messages[i].component);
printByte(messages[i].status);
Serial.println();
}
}
void loop() {}
Or with a range based for loops you don’t even need the index
struct MessagePart {
byte sender;
byte receiver;
byte component;
byte status;
};
MessagePart messages[] = {
{10, 100, 1, 0},
{11, 101, 2, 1},
{12, 102, 3, 0},
{13, 103, 4, 1}
};
void printByte(byte b) {
if (b < 0x10) Serial.write('0');
Serial.print(b, HEX);
Serial.write(' ');
}
void setup() {
Serial.begin(115200);
while (!Serial) yield();
Serial.println("Messages:");
for (MessagePart &msg : messages) { // or for (const auto &msg : messages) {
printByte(msg.sender);
printByte(msg.receiver);
printByte(msg.component);
printByte(msg.status);
Serial.println();
}
}
void loop() {}
excel won't let you easily calculate the CRC - you would have to use a function in VB and do bit manipulation which is not what excel is good at.
to go back to the issue at hand : if you look at the library's source code
you can see he sends the start marker STX, the encoded data where each byte is split into two nibbles which are sent in a "doubled/inverted" form, the end marker ETX and then the CRC is calculated over the non encrypted data using the crc8 function.
the source code of this function, as the name indicates, calculates a checksum (CRC-8) for a block of bytes and the CRC is only 1 byte long.
if you are unfamiliar with CRC, a CRC is based on a polynomial whose coefficients are only zeros and ones. For example, the byte 10110010 can be interpreted as the polynomial x⁷ + x⁵ + x⁴ + x¹, where the power position starts at 0 for the least significant bit, and each bit corresponds to the coefficient of x to the power of its position (remember x⁰ is 1). We usually don't use the binary form for the polynomial representation but rather the hexadecimal form and so the same coefficients can be written as the byte 0xB2.
Now looking at this code ➜ simplifying a bit, a common choice for CRC-8 is the polynomial x⁵ + x⁴ + 1 and if you write those coefficients as bits you get 0011 0001, which is 0x31 in hexadecimal.
In nick's code, the algorithm processes each byte starting from the least significant bit and shifts the remainder to the right. Because of that, the representation of the polynomial has to be reversed so that the bits line up with the direction of the shifting. Reversing the bits of 0x31 gives 1000 1100, which is 0x8C. That is why the constant 0x8C appears in the code.
The function then performs a simulated polynomial division with this polynomial, shifting and applying XOR (which is the same as addition or subtraction in a Galois field with two elements, if you want to sound fancy at your next dinner) as required, until the whole message has been consumed. The remainder that is left at the end is the CRC-8 checksum.
instead of trying to get that done in excel, why don't you write a small arduino code to generate the right messages ?
you have the library's source code so you can easily generate the full payload and just iterate over your 100+ messages.
so I had 10 minutes, so here is a code that will take an array of commands and show you the exact transformation
/*
Adapted from RS485_non_blocking library by Nick Gammon
https://github.com/nickgammon/RS485_non_blocking
This sketch encodes 4 bytes messages with STX, ETX, complemented nibbles,
and CRC8 exactly like the library, without using the library itself.
J-M-L for the arduino forum
*/
const byte STX = 0x02;
const byte ETX = 0x03;
byte crc8(const byte *addr, byte len) {
byte crc = 0;
while (len--) {
byte inbyte = *addr++;
for (byte i = 8; i; i--) {
byte mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
void printHexByte(byte b) {
if (b < 16) Serial.write('0');
Serial.print(b, HEX);
Serial.write(' ');
}
byte encodeByte(byte b, byte nibble) {
byte n = (nibble == 0) ? (b >> 4) : (b & 0x0F);
return (n << 4) | (n ^ 0x0F);
}
void printMessage(const byte *data, byte length) {
printHexByte(STX);
for (byte i = 0; i < length; i++) {
printHexByte(encodeByte(data[i], 0));
printHexByte(encodeByte(data[i], 1));
}
printHexByte(ETX);
byte crc = crc8(data, length);
printHexByte(encodeByte(crc, 0));
printHexByte(encodeByte(crc, 1));
Serial.println();
}
const byte msgLength = 4;
byte messages[][msgLength] = {
{1, 1, 1, 3},
{101, 1, 3, 0},
{101, 1, 3, 1},
{1, 101, 3, 0},
};
const byte messagesCnt = sizeof messages / sizeof * messages;
void setup() {
Serial.begin(115200);
for (size_t i = 0; i < messagesCnt; i++) {
Serial.print("message[");
Serial.print(i);
Serial.print("]\t");
printMessage(messages[i], msgLength);
}
}
void loop() {}
this code will take the messages from this array
byte messages[][msgLength] = {
{1, 1, 1, 3},
{101, 1, 3, 0},
{101, 1, 3, 1},
{1, 101, 3, 0},
};
and you'll see in the Serial monitor at 115200 bauds
message[0] 02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D
message[1] 02 69 5A 0F 1E 0F 3C 0F 0F 03 E1 F0
message[2] 02 69 5A 0F 1E 0F 3C 0F 1E 03 B4 1E
message[3] 02 0F 1E 69 5A 0F 3C 0F 0F 03 4B A5
