Using GetValue with the MLPUI Message Processor

Support forum for MegunoLink
Post Reply
LEDesign
Posts: 2
Joined: Mon Jun 15, 2020 1:13 pm

Wed Jun 17, 2020 1:05 pm

Goal: read the UI NumericUpDown values to initialise the variables in Arduino Code

The NumericUpDown buttons allow an initial value to be set. The Properties:Communications allow a serial command to be sent, that sets a variable value on the Arduino. When the mouse is used to change the UI value, this value is then updated on the Arduino.
After power on, the code is uploaded to the Arduino, this would require all the UI values to be mouse clicked to initialise the variables to the UI. Otherwise, they would all have to be hard coded (where I am pre MegUnoLink)). Since the initial values can be saved to a project or even to file, it should be possible to have a method to update the Arduino variables from the UI at power-on.

I've not found a simple solution, but I suspect there is one! I've tried 3 approaches, still not quite there so I've picked up the white flag and admitted defeat.

First, the neat solution should be to use the Message Processor to 'GET' the value. The problem is the response. For example: {UI:SetUp|set|origin.Value=18}. The value I want is 18. Reading the documentation, this is the correct serial response, but the next step to grab the response and pull out the value requested is missing. Having a red serial response is very nice, but it doesn't complete the request to GET the value into the variable. That's what the command is all about, isn't it? This must be possible.

A modification of this was to add the Message Library and set-up the same serial command used by the NumericUpDown Communications:OnValueChange. The black command confirmation appeared, for example, {UI|CMD|GetOrigin}. The name 'GetOrigin ' is linked to the command '!Setorigin [origin.DoubleValue]\r\n'. This is the same command that works when the mouse changes the UI value. However, no change is seen to the value of the variable 'origin' when printed to the monitor.

The final approach was really banging a nail into the UI and setting up a Button with multiple commands, one for each NumericUpDown button. Once the default length had been increased to accommodate the total length sent to the Command Handler, this allows a single mouse click to set-up the default values for several variables. This works, but it's not really a solution as it relies on people like me remembering to do it! Better to find a clean solution.

Reference flow…...
(1)https://www.megunolink.com/documentatio ... r-library/:
This library lets you:
Set the value of a control on the interface panel
**Get the value of a control on the interface panel**
Invoke a message from the MessageLibrary component attached to the MLPUIMessageProcessor

(2)<https://www.megunolink.com/documentatio ... /#GetValue>
GetValue(ControlName, PropertyName)
Returns the value of a serial message property for the named control. The format used for the message return is described in the Message Processor Reference.
(3)https://www.megunolink.com/documentatio ... processor/
Response
When a GET command is received by a message processor, it returns the information requested using the MegunoLink Pro message format. The general format of the message returned is:
 {UI:ChannelName|set|ControlName.Property=CurrentValue} 

(4)<MISSING info> how to get the CurrentValue from this message?

Your feedback would be appreciated,
Nick.
philr
Posts: 446
Joined: Mon May 26, 2014 10:58 am

Thu Jun 18, 2020 9:06 am

Hi Nick, you are correct you would need to find a way to parse the response. Your second suggestion should work, the arduino can call some commands to return the initial values when it boots up. The best example for this is here
https://www.megunolink.com/documentatio ... egunolink/

It shows how to call a command so megunolink sends a timesync message but you can get it to send values from your number controls. I think the bit you are missing is adding the MLPUIMessageProcessor and pointing that to the MessageLibrary.

We also have the SerialConnection object found in the toolbox of the interface panel designer. It allows you to send a message automatically whenever a serial connection is established. This could trigger the arduino to send the command which retrieves the initial values.



Another random idea could be to use a timer and just periodically send out the initial values whenever the interface loads. Then when the connection is made the arduino could process the initial values and instruct the timer to be disabled ceasing the initial value messages. Its a bit hacky but might get the job done.

Further option, is it better to store the values in the arduino end and use that to restore the current values in the UI whenever it boots up?

Cheers
Phil
LEDesign
Posts: 2
Joined: Mon Jun 15, 2020 1:13 pm

Tue Jul 07, 2020 4:01 pm

Thanks Phil,
I looked at parsing the serial response. This works with the Arduino Serial.parseInt() command:

Turtle.GetValue(F("numTurtles"), F("Value")); // value of selected item
nn = Serial.parseInt();

The integer value returned in the variable nn. I've never had a reason to do this before so I've no experience on the pros and cons. As this Serial.parseInt() command is needed but not included in your examples, is it not recommended? I decided not to continue with this as I would rather use the structure provided by the MUL environment and not extra code.

The second suggestion also worked, as you noted, when I linked the channel to the Message Library (Ohps!). There is a BUT…

As the examples are presented, the UI is updated during the main loop() in the Arduino sketch. This doesn't help as the global variables need to be set before entering the main loop(). It didn't take long to realise this was not going to work. Fortunately, the solution was - eventually - quite simple. It involves creating a pre-sketch in the main setup() part of the sketch. The flow is as follows:

A. Headers & Definitions
a. CommandHandler<> SerialCommandHandler;
B. Setup() {
Serial.Begin(115200)
SerialCommandHandler.AddVariable(F("Tname"), Avariable);
SerialCommandHandler.AddCommand(F("Tcommand "), Aroutine);
Etc.
StartMegUnoLink(); // here is the pre-sketch
Everything else here………..to setup the system
Etc.
} // END setup()
C. loop() {
SerialCommandHandler.Process();
Etc.
} // END loop()
D. void StartMegUnoLink() {
// local setup here : initialise the UI
do {
SerialCommandHandler.Process();
} while (ButtonStart == false);
} // END StartMegUnoLink

The do….while loop in routine StartMegUnoLink() is ended when ButtonStart = true. This is set by a mouse click on a button on the UI. While this button is not pressed (clicked) the operation remains inside the empty loop. This allows all the setup of the UI and parameter transfer to be completed before proceeding to the rest of the setup and the main loop() in the sketch. It just needs one extra button on the UI.
The transfer of the global variables to the Arduino by isolating this process in the pre-sketch makes the UI complement the sketch and not consuming the sketch when used as part of the normal sketch setup() coding. This now makes the UI setup independent of the main Arduino sketch, but allows full interaction with the UI during normal operation.

Nick.
Post Reply