Send array of byte data from Nextion to Arduino

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() {}

I try to build this encoding in excel and reached to close last 02 digit 0F 2D, which I belive are CRC. There is some referance in library to calculate crc but I didnot understant. Someone may help to review the library to calculate CRC or clear understanding about 0F 2D.

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