Help with using objects in lists to display in a `text` node

I'm programming up for my new project. (Parts still to arrive)

I am making a project with a 20 x 4 LCD display and buttons for input.

I'm not sure what type of buttons or how many. Which doesn't help I know.

What I am wanting to do is get the mechanics of it working for now.

One sticking point is menus, or maybe better: lists.

I'm also stuck how to get the object built, but I'll get to that soon.

So, going a bit macro, I have a list of options which can be scrolled with an up/down button and selected with a select. An exit option in case I go into a selection by mistake, maybe. That's another sticky point.

Going on from there, I am stuck how to do what I just said.
I have played with thing like this, but that was more for a display and it used a node which created a list from the inputs. So that is probably a bit too high level for what I want/need.

I'll start with just 3 buttons for now: up; down; select.
up and down move which part of the object is sent to the text node.
That is to get that part working. Ultimately it will go to the LCD. But at this level, it doesn't matter.
select will send a message with the displayed message ...... to a debug node when pressed.

Yes: I know this is beyond my skill set. But I won't learn if I don't try. So I don't want to be spoon fed the answer. Helped would be more appreciated.

(And this virus is getting serious here again. So I want to keep busy doing stuff I like.)

This is an example of what the source object is:

["option 1","option 2","option 3","option 4"]

Just to be obvious. :wink:

So I press a button (up/down) and it scrolls through the options.
It may be nice if it wrapped when it gets to either end.

This is a flow which kinda works.

[{"id":"49547ff4.9d7028","type":"function","z":"6ccc3cee.3fcb2c","name":"","func":"//msg = {\n//    menu1:\n//    [\"Show clock@2,0\",\"Show/edit alarms@2,1\",\"Edit time@2,2\",\"Something else@2,3\"],\n\n\n\n\nmsg = {\n    options:\n    [\"option 1\",\"option 2\",\"option 3\",\"option 4\"]\n}\n\nflow.set(\"options\",msg.options);\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":1960,"wires":[["4a8a915a.21af18"]]},{"id":"35476e0e.c06e72","type":"inject","z":"6ccc3cee.3fcb2c","name":"","topic":"","payload":"press","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":1960,"wires":[["49547ff4.9d7028"]]},{"id":"4a8a915a.21af18","type":"debug","z":"6ccc3cee.3fcb2c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":580,"y":1960,"wires":[]},{"id":"5512487e.fc3698","type":"function","z":"6ccc3cee.3fcb2c","name":"","func":"var p = context.get(\"pointer\") || 0;\n\nif (msg.payload == \"up\")\n{\n    //  up\n    p = p + 1;\n    context.set(\"pointer\",p);\n}\nif (msg.payload == \"down\")\n{\n    //  down\n    p = p - 1;\n    context.set(\"pointer\",p);\n}\n\nvar t = flow.get(\"options\");\n//node.warn(\"T is set to \" + t);\n\nmsg.payload = t[p];\n\n\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":2090,"wires":[["9a55827c.a9b6e","5010ea80.105aec"]]},{"id":"5010ea80.105aec","type":"debug","z":"6ccc3cee.3fcb2c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":650,"y":2130,"wires":[]},{"id":"f334bfcb.c29ce8","type":"inject","z":"6ccc3cee.3fcb2c","name":"","topic":"","payload":"up","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":330,"y":2030,"wires":[["5512487e.fc3698"]]},{"id":"d0da956a.05ed18","type":"inject","z":"6ccc3cee.3fcb2c","name":"","topic":"","payload":"down","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":330,"y":2160,"wires":[["5512487e.fc3698"]]},{"id":"76321458.07a88c","type":"inject","z":"6ccc3cee.3fcb2c","name":"","topic":"","payload":"start","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":2090,"wires":[["5512487e.fc3698"]]}]

It doesn't have wrapping.

OK - i went through this in the old days with Arduino's and LCDs

As a high level description

  1. Build an array of Lines to show in the menu - one line per option
  2. Build an array that reflects each line your display (in your case) 0-3 (or 1-4)

Label a button as Up and one as down

When you press a button you cycle through the array that reflects your lines on the screen and then offset the lines that are currently displayed by 1 (or -1)

You then enter your display routine and put the appropriate starting array element onto the screen starting from the top

So as an example you start off with

DL = Display Line
ML = Menu Line

DL(1) = ML(1)
DL(2) = ML(2)
DL(3) = ML(3)
DL(4) = ML(4)

(or you might want to Keep Line 4 as a Menu control line etc)

You press the up button and

DL(1) = ML(2)
DL(2) = ML(3)
DL(3) = ML(4)
DL(4) = ML(5)

Press it again and

DL(1) = ML(3)
DL(2) = ML(4)
DL(3) = ML(5)
DL(4) = ML(6)

(You can handle menu wrapping logic etc that way quite easily as well)

Craig

Thanks Craig.

But I am doing all this in Node-Red, rather than Arduino. My head is not enjoying it as much as I would like. :wink:

Yep - sorry i was just showing you the high level logic - i no longer use Arduino and LCDs etc

Craig

I just edited the function node to this:

var p = context.get("pointer") || 0;

if (msg.payload == "up")
{
    //  up
    p = (p + 1) % 3;
    context.set("pointer",p);
}
if (msg.payload == "down")
{
    //  down
    p = (p + 3 - 1) % 3;
    context.set("pointer",p);
}

var t = flow.get("options");
//node.warn("T is set to " + t);

msg.payload = t[p];

return msg;

And it wraps.

Problem:
Variable object lengths.

So what I could do is stick the length at the end.
The first is possible, but please indulge me.

How do I get the last element in an array?
I am sure I have seen it somewhere.

I will go and search, but while I am here.... Though I would ask.

Oh, that's a shame.

I would nearly do this project with a teensy, but as an excuse to keep my hand in Node-Red I am doing the back end with Node-Red.

I do like my Arduino alarm clock though. It is still going good.

This is another bit of code in the function node:

var t = flow.get("options");
var l = (t.length) - 2;

//node.warn(l);
//node.warn("T is set to " + t);

var p = context.get("pointer") || 0;

if (msg.payload == "up")
{
    //  up
    p = (p + 1) % l;
    context.set("pointer",p);
}
if (msg.payload == "down")
{
    //  down
    p = (p + 3 - 1) % l;
    context.set("pointer",p);
}

msg.payload = t[p];

return msg;

Like i said - use array objects (each of which is a string)

You know your max line length is 20 so you do not need to worry about lines longer than this (as you will not store them)

You do not reference the individual objects (characters) in each line - you just retrieve and display the full lines

Craig

So would you mind having a peep at the code I posted and import the latest code for the function node.

I believe that is working.

So that being a working thing: before I call (use) this routine, I would copy the object into the flow.options object.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.