Send array of byte data from Nextion to Arduino

How we can send array of byte from nextion to arduino.

byte msg [] = {1, 1, 1, 3}; // Sender add,Receiver add, Button, status

Project detail

I build home automation system run with Nick Gammon Rs485 non blocking library. Current communication protocol is event based. Each event generate byte of array which contained address,command etc.. like

 byte msg [] = {1, 1, 1, 3}; // Sender add,Receiver add, Button, status

Receiver side code

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) {    // 3 confirm the reply msg for ON
      LED_state1 = 1;
    }
    if (buf [0] == 1 && buf [1] == 1 && buf [2] == 0 && buf [3] == 4) { //  confirm the reply msg for OFF
      LED_state1 = 0;
    }

Now I want to add nextion display in existing setup. I try to send button release event

printh 01 01 01 03

but didn’t succeed. I am looking support to send predefined formate data and process in arduino gammon library.

Full code would help understand what you mean but remember that the Nextion appends its default end-of-command bytes (0xFF 0xFF 0xFF) to the payload

Is it possible that your RS485 protocol does not expect them, so the buffer contains more than 4 bytes and your receiver code gets out of sync quickly (after the first message) and your comparisons fail ?

RS485 protocol can Handles "packets" of between 1 and 255 bytes. (below link of library)

Nick Gammon non blocking library

I think issue is here: (Referance from library page)

  • Uses a "begin packet" character (Start of Text, STX, 0x02) to reliably indicate that a packet is starting.

  • Uses an "end packet" character (End of Text, ETX, 0x03) to reliably indicate that a packet is ending.

  • Each data byte (other than STX/ETX) is sent in a "doubled/inverted" form. That is, each nibble (4 bits) is sent twice, once normally, and once inverted. Thus the only valid values for each nibble are:

STX and ETX should add with

printh 0x02 01 01 01 03 0x03

Please explain what you mean by adding a leading zero to your values 01 01 ...?
This leading zero notation is reserved for octal numbers. It's doesn't matter for number between 0-7, but for 8 and above the result will be syntax error or incorrect number.
For example, the constant "010" will be interpreted as 8 in decimal rather than 10.

what I meant is that if you use printh 01 01 01 03 in a Nextion event, the bytes actually sent on the serial line are 0x01, 0x01, 0x01, 0x03 followed by the three standard end-of-command bytes 0xFF, 0xFF, 0xFF.

So the full sequence on the UART is 0x01 0x01 0x01 0x03 0xFF 0xFF 0xFF

As we don't see your code, I don't know what you really mean and what your setup is, but if your code is reading in some ways the incoming bytes, you should expect and handle the end-of-command bytes.

in Nextion Editor the printh command uses the hexadecimal notation without the 0x, so 01 01 01 03 is interpreted as four raw bytes with values 0x01, 0x01, 0x01, 0x03.

I think to remember that the leading 0 is not mandatory in Nextion printh commands. You can write printh 1 1 1 3 and it will send the same bytes 0x01, 0x01, 0x01, 0x03. The leading zero is just a common convention to indicate a hexadecimal byte

Are you trying to connect the Nextion display using RS485 and expecting it to be compatible with the data format used by the Nick Gammon RS485 library?

1 Like

Yes Exactly, I am looking that.

Insted of poling in Gammon library I use event base ptotocol and my msg is like:

byte msg [] = {1, 1, 1, 3}; // Sender add,Receiver add, Button, status

So I want to send this command from nextion to arduino.

Is this a specific to Nextion interface?

this is specific to their development tool (Nextion Editor), the printh command expects hex values without the 0x notation.

that's what the doc states

PS: looking at the doc now, I now don't think the 0xFF are added automatically

I don't think there is any way you can get the Nextion display to send data in the format used by the Nick Gammon RS485 library, if that is what you are wanting to do.

I hope I will get some solution through this forum.

If not possible than, I will try to add interface Nextion –> Arduino–> RS485 bus

actually after reading again the printh command description, I think it can be used to send an arbitrary binary payload

As long as the Gammon library can ignore the ending 0xff bytes from the Nextion display, then it may work. The data would just need to be encoded properly.

that was my point, I did think it was automatically added to events, but it does not seem to be the case (reading the doc).

it would appear printh sends only the exact bytes you specify in hexadecimal and nothing else, even if triggered by a touch event. So printh 01 01 01 03 sends exactly 0x01 0x01 0x01 0x03, with no extra bytes.

Would be worth trying with what nick's library really expected.

Each data byte (other than STX/ETX) is sent in a "doubled/inverted" form. That is, each nibble (4 bits) is sent twice, once normally, and once inverted.

It then says that the only valid values are

0F, 1E, 2D, 3C, 4B, 5A, 69, 78, 87, 96, A5, B4, C3, D2, E1, F0

Then there is a crc, and I haven't looked at the library to see what method is used.

byte msg [] = {1, 1, 1, 3};

With out the stx,etx and crc, I think the printh statement to send 01 01 01 03 should be

0f f0 01 10 0f f0 01 10 0f f0 01 10 0f f0 03 30

I guess it would be easy to write a sample code with Nick Gammon Rs485 non blocking library to send 1,1,1,3 and write a small piece of code just printing out the bytes as they come on the other side

sender:

#include <RS485_non_blocking.h>

size_t fWrite (const byte what) {
  return Serial.write(what);
}

RS485 myChannel (NULL, NULL, fWrite, 0);

void setup() {
  Serial.begin(115200);
  myChannel.begin();
}

const byte msg[] = {0x1, 0x1, 0x1, 0x3};

void loop() {
  myChannel.sendMsg(msg, sizeof msg);
  delay(1000);
}

and on the receiving end, we just print the bytes as they come in, may be something like this (totally untested, typed here)

unsigned long lastByteTime = 0;

void setup() {
  Serial.begin(115200);
}

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(' ');
  }
}

then we would know :slight_smile:

Its actually a lot simpler than that. Since the library can use hardware Serial, all that is needed is to replace the contents of the fWrite() function to print out the hex value instead of writing the hex value directly.

#include "RS485_protocol.h"

// callback routines

void fWrite (const byte what) {
  if (what < 0x10) Serial.print('0');
  Serial.print(what, HEX);
  Serial.print(' ');
}

int fAvailable () {
  return Serial.available ();
}

int fRead () {
  return Serial.read ();
}

void setup()
{
  Serial.begin (9600);
  delay(500);
  Serial.println(F("\n\nstartup"));
  // assemble message
  byte msg [] = {0x01, 0x01, 0x01, 0x03};
  // send to slave
  sendMsg (fWrite, msg, sizeof msg);
  Serial.println(F("\nend of code"));
}


void loop() {
}

This give the following result:

startup
02 0F 1E 0F 1E 0F 1E 0F 3C 03 0F 2D 
end of code

Each byte is broken into two nibbles, the upper nibble being sent first.

1 Like

Nice

Sender Side code:

#include <RS485_non_blocking.h>
byte buf [20];
// callbacks for the non-blocking RS485 library
size_t fWrite (const byte what)
{
  return Serial.write (what);
}
int fAvailable ()
{
  return Serial.available ();
}
int fRead ()
{
  return Serial.read ();
}
// RS485 library instance
RS485 myChannel (fRead, fAvailable, fWrite, 20);
void setup() {
  Serial.begin (9600);
  myChannel.begin ();
}
void loop() {
     byte msg [] = {1, 1, 1, 3};
      myChannel.sendMsg (msg, sizeof (msg));
delay(5000);
}

Receiver side:

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(' ');
  }
}

Out put of this msg is:

0x02 0x0F 0x1E 0x0F 0x1E 0x0F 0x1E 0x0F 0x3C 0x03 0x0F 0x2D