After months of lurking and working. I have hit a stumbling stone that I can't get past and need to ask the community here for help.
Let me start this off by saying that I am not a coder...more like a jack of all master of none experience level. Also would like to say that I have made the "Nextion Instruction Set Wiki," the other itead examples, and reading of the free chat forums here and arduino documentation the foundation for everything I've done thus far.
*Use a touchscreen to send commands to a microcontroller to activate mini relays that will activate the coil circuits of larger relays to control all of the circuits in a project car that I’m building.
Example: touchscreen low beam button press sends a serial command to the microcontroller-->proper microcontroller digital i/o pin changes state and activates a mini relay->mini relay being energized closes the coil circuit of a larger under-hood relay that sends power to the low beam head lights.
*12v/24V to 5V 5A power supply
*qty 3, 8 channel 5V mini relay boards
*arduino mega 2560
*nextion 7" touchscreen, basic model #NX8048T070_11
*relay board power circuit = relay board DC+ terminal to 5V+ terminal on power supply AND relay board DC- terminal to 5V- terminal on power supply
*arduino power circuit = arduino 5V+ terminal to power supply 5V+ terminal AND arduino GND terminal to power supply 5V- terminal.
*Nextion power circuit = nextion +5V terminal to power supply 5V+ terminal AND nextion GND terminal to power supply 5V- terminal
*Nextion TX terminal connected to arduino 0 terminal (RX of hardware serial 1)
*Nextion RX terminal connected to arduino 1 terminal (TX or hardware serial 1)
In other words...common power and ground connections for all of the 5v stuff(nextion, arduino, and mini relay boards)
I have used the arduino controllers for several other projects with success, but this is my first foray into serial communication. I am attempting to write my own very basic serial protocol between the arduino and nextion. Rather than using the large nextion "send component id strings" and itead library, I would like to send 4 digit strings as necessary from the nextion to the arduino whenever a button is pressed or released. There's only 4 pages and approximately 20 buttons total in my HMI file. Trying to keep it simple.
For each button in the nextion hmi file, I am sending:
digit 1 = page id(0 through 3 in my case)
digits 2 and 3 = button id ( roughly 27 through 47 in my case)
digit 4 = active/inactive or pressed/released = 1 or 0 in my case
For example, I have a momentary button(not a dual state button) on page 1 with an id of 27. In the touch event field for that button I have: print "1271" to send 0x31 0x32 0x37 0x31 from the nextion to the arduino. On that same button in the release event section I have: print "1270" to send 0x31 0x32 0x37 0x30 to the arduino. Including the spaces, this is 19 characters that I'm sending telling the nextion to send to the arduino.
I have written an arduino program that is intended to read each of these 19 characters and store them in a 20 character array. It adds the null character "\n" to the 20th position in the array. Once this 20 character array is filled up each time a message comes in to the arduino from the nextion, the arduino program uses if statements with "stringcompare" to see what message was sent from the nextion and then fire the proper outputs to activate the proper mini relays. If things get mixed up and the full 20 character array doesn't match any of the valid commands in the if statements, the arduino just fills the whole array with "q" and one "\n" so that the serial read starts again.
If I run my hmi file in the nextion simulator and press and hold the button programmed to print "1271", the simulator return data field shows 0x31 0x32 0x37 0x31 as it should due to my use of "print" rather than "printh". As soon as I release that button, the simulator return data field shows 0x31 0x32 0x37 0x30 as it should since print "1270" was programmed into the button release event.
If I use the serial monitor on the arduino development environment and send 0x31 0x32 0x37 0x31 over usb from my PC to the arduino, the arduino fires the corresponding output HIGH as it should . If I send 0x31 0x32 0x37 0x30 from my PC to the arduino over usb, the arduino fires the output low as it should. Good!
FYI, whenever I power up and communicate with the arduino and relay boards using my PC and usb, I disconnect the power leads from the power supply to the nextion so I don't send too little juice to the nextion which I read is a great way to fry the good old nextion.
Now, here is where the problem comes in.... I disconnect the usb cable from the arduino. I power up the 12v to 5v power supply with a fresh 12v car battery. This powers up the arduino, nextion, and relay boards. I type in my super cool 9x9 radio button password on the first screen of the hmi and now I have access to the "engine page" which has the button that is programmed to print "1271" which equates to sending 0x31 0x32 0x37 0x31 to arduino on touch event and print "1270" which equates to sending 0x31 0x32 0x37 0x30 to arduino on release event. I press and hold this button and nothing happens. Furthermore, the TX/RX leds on the arduino don't even flash at all when I press and hold this button. I release the button and now the nextion should be sending 0x31 0x32 0x37 0x31 due to the print “1270” on release event and no TX/RX leds flashing on the arduino. Looks like nothing is sent from the nextion to the arduino when using print “ “ on touch and/or release events.
Why can I send this command from my pc to ardunio serially and it works great, but when I try to send this command from nextion to arduino serially, nothing happens?
I'm using iso-8859-1 character encoding on the nextion. I'm not sure if this good/bad/ugly or has any influence on the behavior that I'm seeing.
I'm using the default hardware serial port on the arduino (pin 0 and 1.) I have the nextion disconnected whenever I communicate with the arduino over usb from my pc and I have the usb to pc disconnected whenever I attempt to communicate with the arduino from the nextion through pins 0 and 1. I open serial communication in the setup loop of the arduino at 9600 baud. I use bauds=9600 on the preinitialize event of the password page on the nextion which is the first screen that is displayed when the nextion powers up.
I also read on the nextion instruction set wiki that "0xff 0xff 0xff" is appended on each instruction sent out of the nextion. I have already tried modifying the original serial read block on my arduino program to hold the 14 characters that I spoke of above along with the additional characters for the possible “0xff 0xff 0xff” that could be on the end of each message that the nextion sends and still no worky.
I'm attaching a picture of the main panel so you can see what I'm working with.
I'm also attaching the .hmi file and the two associated font .zi files so you can open it up and see the commands that I'm attempting to send out of the nextion if you feel so inclined.
I'm also attaching the .ino file so you can see the serial read block and message checks that I programmed on the arduino mega.
Much much appreciated!
ZI files not needed to be posted - once included in the HMI, they are embedded.
0xFF 0xFF 0xFF terminators for most commands - print is an exception on output.
0xFF 0xFF 0xFF terminators are still needed for serial command from MCU to Nextion.
The use of print command on Nextion may get rid of the 0xFFs in print command
But Nextion's startup will still send out its startup sequence (Start and Ready)
0x00 0x00 0x00 0xFF 0xFF 0xFF 0x86 0xFF 0xFF 0xFF
So one thing to look at is if you are custom serial communications is accounting for this.
You have put some effort into your project, and for that reason I will help you get things working.
If you would like to change your code by yourself, then in this post I shall just tell you what is wrong.
If you send a literal string "0x31 0x32 0x37 0x31" from the serial monitor, then indeed you are sending 19 characters to your Arduino if that string is not appended with \n\r (newline return).
Your code collects these characters then does the strcmp(), as expected it works.
When using Nextions print "1271" you are sending 4 characters, which I must say is an efficient way of doing things, so well done for doing something outside the rigid Itead library structure.
So all you need do at this stage is change the code to collect 4 characters and add the terminating '\0'. To test from the serial monitor, send the literal string "1271" appended with nothing.
The strcmp() functions would need changing to compare "1271" and so on.
If you run in to further problems then let me know.
Thanks for taking the time to look over my post and offer a response. I appreciate the heads up on the .zi files embedding in the .hmi file as well as clearing up my question about the print command and terminating characters. Also, I did not end up having to write any code into my arduino program looking for the Nextion start and ready signal data packets but still managed to get it to work per indev2's advice. Does the nextion always send out the start and ready packets that you mentioned above? Does the nextion generally need to receive some type of confirmation after it sends these start packets out to the device that it should be communicating with?
Thank you sooooooooooooooooooooooooo much for the direct response! I just changed all of my strcmp() functions to look for the 4 digit literals and now the 3 page Nextion program, Arduino, and all 24 channels of micro relays are responding flawlessly. In my previous post I only attached a truncated version of the arduino program, but that serial read into char array and strcmp block that you analyzed for me is exactly what I'm using in my full Arduino program.
Since you were able to directly offer a solution, I'm guessing you know you're stuff so can I ask why, when the nextion instruction set says this.... [ print "123" //returns the ASCII of string "123":0x31 0x32 0x33 ] do I have to tell the micronctroller to look for the string literal "123" rather than the ascii code 0x31 0x32 and so on? My loop specifically pulls only 4 characters out of the serial buffer and assembles them into a string ie char.
My unfounded/unresearched theories so far are: Does the ascii code 0x31 for example in the serial buffer count as only 1 character of the char data type? Or, does this have to with the fact that I'm using the iso-8895-1 encoding setting on the nextion?
Haha, as you can see I'm not a comp sci guy. Hope you can be patient and try to explain this to me.
@Patrick Martin and @indev2
Regardless, the control system for this project vehicle seems like it will work out very well now and I'm one step closer to getting this car back onto the road and track. Can't thank you enough!
The Nextion always sends out its start sequence on power up and/or reset.
This is a notification, no response or ack required.
But indeed should not start before ready ... lost transmissions for sure.
For whatever reason reset is caused by, taking note of sequence allows you to resync
If Mega did not lose power, then indeed Nextion and Mega are no longer on same page.
Let me try to rephrase back to you what you just said so that you can tell me if I got it straight or not....
The nextion sends out the 0x00 0x00 0x00 0xFF 0xFF 0xFF 0x86 0xFF 0xFF 0xFF start and ready data packets every time it is powered up or restarted. If these packets aren't read from the arduino buffer, before I press any buttons on my nextion screen, then the simple serial read into 4 char arrays that I have the arduino programmed to do every time something is available at its serial port could potentially not be in sync with each 4 char packet from the messages that I'm with each button press of my nextion.
If what I said above is the case, then why can I simply power on the nextion and arduino at the same time, enter my password on the password page that I programmed into the .hmi file of the nextion, navigate to any of the other 3 pages and press any button that sends the 4 char data packet and the arduino processes it and responds properly every time? I'm not saying you're wrong, I'm just trying to convince myself that there is a good reason that those initial data packets from the nextion to the arduino don't seem to be interfering with the successive 4 char packets that I'm sending with each button press on the screen. Care to offer any further details?
Also, I'm trying to answer my own question above about "why do i tell the arduino to look for individual chars when the nextion is actually sending stuff like 0x32 to the arduino." I'm looking at a utf-8 to char conversion table and it looks like 0x32 is the hex code for the character 2, etc, etc. If hex 0x32 shows up at the arduino serial port, how does the arduino know that when it sees 0x32 at the serial port that it's actually looking at the char 2 that I told it to look for? I'm probably phrasing the question to where it seems like this is just theory that isn't worth explaining to someone at my level but if there's any way that you think you could try to give me a little bit more understanding, I would greatly appreciate it.
I am saying these characters leave the nextion TX buffer.
All or some of them will be in the Arduino RX buffer if
- Arduino has booted up and Serial2.begin is ready in time to catch.
- These may indeed effect your first command to be received.
Now perhaps your Arduino is slow at starting and Serial isn't yet
initialized when the Nextion sequence is sent. Serial RX buffer is
merely empty at that point, missing all or part of the transmission.
But such would not be the case when Serial is running but Nextion has
as started, or perhaps reset. Here your Arduino Serial is indeed running
and ready and these 10 will indeed be sent and in your RX buffer.
But more important I would think is when you are travelling down the
road and somewhere, over a bump or pothole, for what ever reason
Nextion restarts but Arduino has not - the two are no longer in sync.
It is then probably valuable to minimal catch the 0x86 0xFF 0xFF 0xFF
a key indicator that Nextion is now at the very beginning of the HMI
while your Arduino is already running but elsewhere in the INO code ...
synchronizing on this 0x86 is so HMI and INO are on the same page .. no?
As far as how characters is known by the MCU - they aren't.
It goes back to ASCII, a byte is translated to mean this or that char.
(byte = 8 bits, single byte char = 8 bits)
Different parts of the world, char dec 248 has different meanings.
This started many code pages to deal with regional characters
Nextion supports several of the iso-8859-X series
1 American, 5 Russian, 6 Greek, 7 Arabic, 8 Hebrew ...
UTF-8 is a multi-byte where 1 byte to maybe 6 bytes defines 1 single char
GB2312 is a two-byte where every char takes 2 bytes to define.
But Nextion is Numeric. Arduino is numeric.
Selecting your HMI encoding when setting up your Device
defines basic character expectations at regionally local keyboard.
So char dec 248 has the proper regional meaning.
This is needed only because you are programming it with a computer
and that computer ... has been regionally divided, based on language
and local regional requirements.
BTW one reason why you can start and passcode works
is your loop() code
- reads in bytes conditionally if available
- acts on stcmp this or strcmp that.
- clear and reset your Bfrs
These are indeed ideal conditions that you are looking to act on
and when they indeed line up, then all will work fine.
So when read in and not 1270, it is lost and reset by your code.
This doesn't mean the notification wasn't made available
but without a catch for bla-bla-blah and trigger
Some useful things like Nextion Ready can and will go unnoticed.
Just like the additional traffic that states an error was made in
a command from your Arduino MCU to Nextion.
As this feature is not turned off in your code, it is available but
would be ignored or lost, but also would fill parts of your buffer,
So if under real not ideal circumstances, you find that a command
you intended skips and wasn't executed as you thought it should
- this explanation may come to mind.