Start a new topic

Another look at Radio Buttons

Hi,

First up, I'm not a programmer or computer expert, just a hobbyist with a project that involves a Nextion connected to an ESP8266.

On one of my Nextion pages I have a group of 10 selection buttons. For indication purposes, the selected choice should change color, much like a group of Radio buttons. I'm using ordinary buttons for this, as I don't need the sofistication of dual state or other refinements. All that is easy enough to do.

I'm posting this just in case others would like to use the idea, but also to ask which of the 2 methods (question for the MCU guru's) is the most efficient.

I actually have 3 methods, but one of them is a bit of code back on the ESP, similar to page 1 in the attached HMI. And that is the least efficient as we need to use the Serial lines.

So on page 0 we have the quick and dirty method, just a bunch of catch all writes.

Page 1 the refined method, but we have Variables, nested 'ifs', reads and writes.

Over to you guys.

Cheers indev2

HMI

Perhaps this was addressed in the Nextion Gallery v38 Radio Buttons - How to do a workaround ?

In looking at the HMI and keeping in what you stated sending it over serial is least efficient

- efficiency has several meanings.  You are hardly about to run out of resources in the K3.5".


So how do you want to measure the efficiency?



@Patrick


Indeed it was and thanks for that. But like others frustrated before the addition, I used a method that swapped out the colours back on the ESP.


This is my method, very simple


byte ter2 [3] = {0xff, 0xff, 0xff};//Terminating characters


void toggleButtonColor() {  

  NexSerial.print("b");

  NexSerial.print(activeButton); //Gives the button number

  NexSerial.print(".bco=65248");

  NexSerial.write(ter2, 3);

  NexSerial.print("ref b");

  NexSerial.print(activeButton);

  NexSerial.write(ter2, 3);

  NexSerial.print("b");

  NexSerial.print(lastActiveButton); Gives last button number

  NexSerial.print(".bco=33800");

  NexSerial.write(ter2, 3);

  NexSerial.print("ref b");

  NexSerial.print(lastActiveButton);

  NexSerial.write(ter2, 3);

}


Later I was looking for the most efficient method on the Nextion with what we had at the time.


And BTW my app requires all off at default start.

The question was, which is most efficient 

Page 0 or page 1 ?


Sorry Patrick crossed post,


Efficient processing, the best code for the job.

And I am interested to play here - so lets attempt a few things and see.

The most efficient is where neither the Nextion and the MCU are waiting on each other.


The serial is going to slow things down, but is the job for the MCU to flash options to the user as in the game Wack-A-Mole and the user plays to attempt to hit it while it is selected, or is the job to have the user select something and then inform the MCU for the MCU to respond.


Mostly you want to use the Nextion to pre-process what it can without the need of the MCU - then inform.  You do not want to have to constantly poll, or be constantly receiving data so prints are used sparingly.


The difficulty in several buttons is as a radio button is having all the code in each button.  When it comes time to update or find where an offending code is - there is a lot of "user code" to go through and find.  If we can group this code in one spot - we save time when maintenance comes. (It also will consume less TFT file space as well).


The most efficient is to use the radio button and it indicates the user choice to the user

But for the sake of a button type example .. let me play.  Now it does depend on what the button does (if it goes to another page - another approach is needed)


So here I have 10 text Components to do the job of buttons

- I use the sys0, sys1, and sys2 built in variables.

    - sys0 - print over serial or not

    - sys1 - track precious choice to put color to unselected

    - sys2 - track current choice to put color as selected

- each text Touch Press Event contains

    sys2=1 // sys2=x where x is the component id

    click m0,1

- one hotspot size 5x5 tucked between 0 and 1 contains

    b[sys1].bco=50712

    ref b[sys1]

    sys1=sys2

    b[sys2].bco=1024

    ref b[sys2]

    if(sys0==1)

    {

       sys2=sys2*256+66

       print sys2

       sys2=sys2%256

    }

- page0 PostInitialize Event sets sys1=1  // initialized to first button component id

- font is n.zi which contains 0-9 and space.


So overall my attempt uses a reduced font size

uses sys0,sys1,sys2 reducing time to process and as they are built in doesn't require extra space

reduces the output while informing which was selected if it was needed

provides an option to not send over serial

and puts the maintenance code in a single location


comparisons 

- 269 bytes for your page1 can be reduced to 128

- 175084 tft filesize can be reduced to 148901


I attached the HMI if you want to look.  Perhaps some of it may be useful - but it is just another idea.


zi
(2.22 KB)
HMI
(14.5 KB)

Also on the enhanced Nextion you could probably toggle GPIO IO1 using

pio1=1-pio1

pio1=1-pio1

and have your MCU respond to the pin toggle cutting serial down even further.


Now Gerhard Kropf could probably come by and cut mine down even further.

Thank you so much Patrick,


As I'm only a coding student of 8 months standing (though somewhat older and longer of tooth ;) I'll need a little time to digest. What I wanted to learn was best coding practice, not just anything will do because we have acres of SRAM and faster cores these days.


Briefly, the buttons select model railway locomotives (throttle slots) on an Arduino DCC system.

So it's not a time critical application. I'm working on a 10 channel duplex wifi throttle and there are at least 5 mcu's in the loop if one includes the network router.


As you so rightly point out keeping the serial traffic to a minimum should be the goal.


I'll be back later 


Thanks again,


Steve.

@Patrick,


Wow thank you Sir,


That's real neat, I had wondered if you could drop in a single routine like that.

In fact it would be very useful if it became an additional component to the Editor.

In much the same way as we have hidden Variables one could have methods that don't have to be part of the 'surface'. Then use something like a 'call' event rather than 'click'. We would then be moving toward a more traditional approach to programming. Guess someone like yourself has already requested.


All the same, that is a really cool workaround, thanks for enlightening me.


Kind Regards.


Steve.


Two points.  It should matter not whether or not it is called "call" or "click", but rather that we note the behaviour is a simplistic user defined procedure.  Second, with acres of SRAM and plenty of resources normally, there are limits in MCUs that are like no other.  If the GD32 chip on the back of that Nextion has more than 96K of SRAM I would be surprised.  So even though one could toss a 32GB microSD to expand their MCU, there are still limits that challenge - and that is where Good Practices comes in.


For fun I put together a 10 track slider expanding upon the last example.

In the theme of a ten track locomotive concept


Here each of the sliders have a value 0 to 100 and its Touch Release Event contains

   sys2=10  //  sys2=x where x is the component id

   click m0,1

Beside each slider is a numeric value for the slider.

Each slider also shows which is the currently selected slider.


If there was to be ten locomotives in play at the same time, it may be tedious to adjust each locomotive jumping back and forth, so it is intuitive to add a +/- 5 value so that all increase or decrease at once.  It would probably be prudent to have a kill switch.


The +5 contains a basic

  click m1,0

The -5 contains a basic

   click m1,1


For the kill switch we have a checkbox and a label, and to tap exactly on the checkbox - painful, so tapping the label also toggles the checkbox.  It is here that it gets a bit more complex.  If the kill switch is off - does the MCU need to be notified (probably not) - but if you are issuing the kill switch then the MCU certainly needs to know to kill the power to all the locomotives.  Also, if the power is off, does it make sense to send the slider change?  No.  But it would be important to ensure the display represents this to the user by resetting the slider back to zero.


There are four procedures: hotspot m0 and m1 - Touch Pressed and Touch Release.

   m0 touch  -> adjust individual track

   m0 release ->

   m1 touch -> +5 for all

   m1 release -> -5 for all


sys0 still allows for serial to be used or not - in this case hard to control locomotives if the speed isn't sent out of the nextion over serial, so sys0=1 is located in the page0 PostInitialize Event.


So what is Good Coding Practices?


It occurs when you have coded for and against all contingincies that could occur.  Keeping the code simple to follow, clear to the user, clear for the machine (especially when maintenance time arrives) and code should be documented - and note that mine is not.  (Not a good practice).


You might notice that rather than creating a new variable, sometimes I used one of the existing sysX variables as my temp and then reset it after borrowing it ... this again is probably NOT good practice.


However, the interface has a simple 4 byte communication system 0x42 0xAA 0xBB 0x00

The first byte is always 0x42 ... letting you know this is track controls coming in

The second byte 0xAA is for either track or system

    When it is a track - the track number 1 (top) to 10 (bottom) is the second number

    -- and the third byte 0xBB will be the speed from 0 to 100

    When it is system - the byte is 0x00

    -- If the third byte is 0x00 - the kill switch was pressed (MCU should turn each locomotive off)

    -- If the third byte is 0x01 - the -5 was issued (MCU should decrease each locomotive by 5)

    -- If the third byte is 0x02 - the +5 was issued (MCU should increase each locomotive by 5)

The fourth byte is always 0x00 zero.


Now as the user plays with the interface and is seeking a particular value, each release is sending the track command over the serial - so it could be improved by decreasing the serial traffic and allow the user to see the slider value without them having to release and try again - sending more data over serial before they are satisfied.  So by adding another hotspot m2 and adding

   sys2=2

   click m2,1

into the Touch Move event for each slider, we can then have m2's hotspot code update a corresponding  numeric component before the user lets go of the slider -- which triggers the serial.  But only IF the kill switch is off.  So now there are five user procedures.


Hope you find this example interesting and helpful.


BTW: Where did you find the reference to being able to call the components via the b[x] array?


HMI
(34.1 KB)

@Patrick,

"Hope you find this example interesting and helpful."

I did indeed and thank you for your time.

"So now there are five user procedures."

And as I've found out on my journey, quite a few more.

"BTW: Where did you find the reference to being able to call the components via the b[x] array?"

Well as you've already found out and put to very good use, I was scratching my head thinking surely the syntax is a little more evolved than the very basic stuff that is documented.

And looking for a better way to code the method for the original topic of this thread, I just started playing around until something compiled. This was only yesterday I might add. So you could say I just dropped on it by being persistent.

Who knows what else is lurking under the hood ?

My suck it see approach comes from trying to learn Html/javscript and C/C++ all at the same time. Prior to February this year, I knew nothing other than memories of a few lines of Basic going back to my 1970's days at high school.

An Arduino running the blink sketch is a very recent development for me :)

On the off chance you're even remotely interested in what I'm up to, the whole project is pretty much open source, save for my current stuff that I'm working on right now.

This link goes to a shot of my first attempt at getting something to work with my brand new shiny Nextion back in July.

http://www.trainboard.com/highball/index.php?threads/dcc-hardware-throttles.90315/page-10


The large Rotary Encoder ? Well that's another story....


Regards

Steve.


hey Steve


what are the 9 functions? 

I am peaking at your project 12.HMI

how many addresses?  is this the up to 10?

Is this one address per train (symbolic or "address")


rotary contains the "kill switch" ?

Is there a location that contains the complete DCC++ spec?


I am not sure about getting trains or building an ghost town

but I am interested to see what I could do on the Nextion side




Hi Patrick,


Oh no, like me will you ever be able to put it down ?

What started as new hobby for me looking into the digital electronics of model railways (with a view to building something later - I don't own a layout either !) has become quite a time consuming passion this last eight months.

Call it the engineer in me - the logic is quite intriguing.

OK, you're on the right track (pun intended) but not the right project.

Another member, Mr. Dave Bodnar (trainelectronics.com), upon seeing the potential of the Nextion, shortly after I made the announcement that the above link relates, went off to write something is his own style. Let's call it something of a valid, but lesser device than mine. Still with me ?

Now let's not get tied up trying to reinvent the wheel.

Prior to Nextion displays, I'd already been down the WebApp route. I wrote a rather nice page that you can run on modern mobile devices, in an ordinary browser.

I never got to finalising the javascript, but to me anyway, it represents a valid solution and in the main it works quite well.

But, here's the caveat (and I can appreciate folks comments on this), an all touchscreen solution does't have that ergonomic twiddly control factor. So enter the Rotary Encoder.

From a graphic design point of view, Html5 wins hands down.

This is one of my later efforts and is in the public domain.

The full DCC++ spec (the one I'm trying to work to) is here.

https://github.com/DccPlusPlus/BaseStation/wiki/Commands-for-DCCpp-BaseStation

Gregg Berman, The guy who wrote the system, and kindly open sourced for all, has the main repo here.

https://github.com/DccPlusPlus?tab=repositories

It all fit's on an Uno, very cheap...

His Controller app is the standard to reference for Throttle design.

The functions ? There are 29 of them, I've recently been working on solution for them.

Funny you mentioned Wack-a-Mole, here's a demo at post #304 on this page,

http://www.trainboard.com/highball/index.php?threads/dcc-hardware-throttles.90315/page-16

Enough for now

Steve


Let's see.  It was shortly after I built a model railway station as a child and my brother had us play "Wild-Wild-West" with his pellet gun - well let's say Dad never let us touch his train set.  So I would need to just get a few confirmations


So let me see if I have some of this correct. 

  • Connection goes to connect to the BASE Station (more than one?)
  • Up to ten trains on the tracks controlled via the BASE
  • The power switch there is your kill switch
  • <s> ?? not sure
  • Forward/Reverse and All Stop
  • If active then <T5 76 1> status line?
  • The 29 Functions are user add ins (a bell, light, switch, sensor) that can vary for every user?

The layout above 
  • concept of every function quickly tapped - is very handy - so perhaps how to squeeze everything above into a Nexion most efficiently?

I would think that it would be cool if the F25 showed an icon for what it was for - and since you found the b component array and I found the indexed font structure, the two could merge to have a set of icons that changes color when on/off for each function slot (if my understanding of the 29 functions is correct)

Patrick,


"Connection goes to connect to the BASE Station (more than one?)"

Connect does set up a connection to Base Station. In this case it's a WebSocket connection, a fast duplex, always on used by Webpages mainly..

.

"Up to ten trains on the tracks controlled via the BASE"

Yes,the Base does the command interpretation of the throttles output strings.

.

"The power switch there is your kill switch"

That switch kills the whole layout

.

"<s> ?? not sure"

A request to send current running loco status and other stuff.

Great for testing the connection and synchronising the throttle, there can be more that one throttle instance at the same time.

.

"Forward/Reverse and All Stop"

Just applies to the currently selected loco.

.

"If active then <T5 76 1> status line?"

Return data from Base Station, either from this or other throttles. All must be stored and acted upon.

And constantly updated.

.

"The 29 Functions are user add ins (a bell, light, switch, sensor) that can vary for every user?"

Broadly speaking yes.


Functions are a rather secondary consideration, save for folks who have complex sound and other little niceties on their trains. The first group F0 - F4 is used quite often.


I have a current solution for function keys, did you catch the short video ?


Overall the best format for Nextion would be multiple pages.

Least, that is the route I've taken.


So far I've a Serial Terminal on the front Start/Connect/Sync page,

Main throttle on page 2, and functions on 3.

Was thinking CV programming on 4.


Login or Signup to post a comment