Open bytelabsco opened 3 years ago
I've made a little progress, but I'm still not confident that this is the right path. Here's some trimmed down code for where I am currently:
int highThreshold = 1023;
int currentPotReading = 0;
result setThresholdHigh() {
highThreshold = currentPotReading;
return proceed;
}
class highThresholdPrompt : public prompt {
public:
String promptVal = "";
highThresholdPrompt(constMEM promptShadow& p) : prompt(p) {}
Used printTo(navRoot &root, bool sel, menuOut& out, idx_t idx, idx_t len, idx_t) override {
promptVal = "Set High: ";
promptVal += highThreshold;
out.print(promptVal);
}
};
MENU(thresholdSubMenu, "Threshold Settings", doNothing, anyEvent, noStyle,
altOP(highThresholdPrompt, "", setThresholdHigh, enterEvent),
EXIT("Back")
);
// Nav Definition, Setup, Loop and Potentiometer reading, and low threshold code omitted for clarity
How this is currently working is the user will navigate through the menu to the Threshold Settings menu. The custom prompt will then display "Set High: {{Current highThreshold value}}" (eg: Set High: 1023). The user can then adjust the potentiometer to where the max should be, and then select the Set HIgh... menu item with the rotary encoder. That then triggers the enterEvent, and the setThresholdHigh function is called, which sets the highThreshold variable to the current reading of the potentiometer.
There are a couple issues I'm still facing.
1) Once that highThreshold value has changed, the custom prompt is not actually updated until the user interacts with the menu again. I tried to force a refresh by calling nav.printMenu(), but that didn't seem to force a redraw.
2) I would really love for this to behave more like a field. So the user would use the rotary encoder, and selected "Set High: {{current highThreshold value}}" to 'Activate' it. The prompt would then look like "Set High: {{current currentPotReading value}}". The user would then adjust the potentiometer to the desired max, and then click the rotary encoder again to set highThreshold equal to currentPotReading.
Do I just need to use a custom field instead of prompt, and then override the same printTo function? If I go that route, how do I ignore the defined inputs for the values while stepping/tuning, and instead just use the currentPotReading value?
the navigation should be automatic
prompts do not have self updates, on the contrary they have minimal draw to avoid flick. So, only when user interacts they will be forced to draw. However fields do, please derive from field
but notice that we already have fields to change values within a range or from an enumerated list of values
I'm trying to force the redraw of a readonly-field, is that posible? @neu-rah could you please Pointe where to find information about how to derive from field,
Currently my menu looks like this:
MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
//v--this one--v
,altFIELD(decPlaces<1>::menuField,input,"Sensor:","\xb0" "C",0,MAX_TEMP,1,0,doNothing,noEvent,noStyle)
,altFIELD(decPlaces<1>::menuField,setPoint,"Temp:","\xb0" "C",0,MAX_TEMP,1,0,setTempEvent,exitEvent,wrapStyle)
,SUBMENU(setHeat)
,FIELD(speed,"Speed:","%",-MAX_SPEED,MAX_SPEED,1,0,setSpeedEvent,exitEvent,wrapStyle)
,SUBMENU(setMotor)
,EXIT("<Back")
);
The one bellow the comment "this one" needs to be updated each time the input
variable changes but that doesn't seem to be the case.
hi, even read-only fields should self update when the original variable value changes, so just change the value, they are read-only just for the menu system (unless you made it const, that would also be for c++, ofcoz)
input=x//<-some value here
this project makes a very nice use of it https://github.com/jarkman/ServoBox
@neu-rah thanks for your quick reply. I'm not sure why but only after adding mainMenu[0].dirty = true;
I was able to update by hand the field. Also, it seems better that way, since I'm able to check the precision, for instance to update the field only when it changes in one whole unit or include up to an arbitrary number of decimal places.
Hello,
I'm new to Arduino development, so forgive me if these are questions with obvious answers.
I've been able to use the excellent PCF8574 example to put together a small program where I'm able to navigate through a menu using a rotary encoder, and then toggle the LCD backlight on and off. Now I would like to add a potentiometer to the circuit, and add menu options to set an upper and lower threshold for the values. I would like to set those threshold values using the potentiometer itself.
So that interaction would be using the rotary encoder to navigate through the menus to the set upper threshold and set lower threshold options. So that submenu may look like:
Upper [1023] Lower [0] Back
You would then select which threshold to set (by clicking the rotary encoder), and a the display would show something like:
Set Upper: ####
where #### is the current value of the potentiometer. Then, instead of using the rotary encoder (or other defined inputs) to set that threshold value, I want to use the potentiometer. I would turn it to the position that is Upper or Lower, while displaying the value output from the potentiometer. Once the user has the potentiometer where they want it, they would then click the rotary encoder to set that value as the new threshold, and then take them back to the threshold menu.
Initially, I thought a Field might solve my problems:
FIELD(lowerThreshold, "Set Lower","", 0, 1023, 10, 1, doNothing, noEvent, noStyle)
But I'm not sure how I can limit the menu system to only listen to the button click from the rotary encoder to "Lock in" the value (exitEvent?) and the potentiometer to set the range between 0 and 1023. Additionally, I don't want to "Step" the values, I just want whatever value the pot is returning.
Then I thought about using a customField, so I checked out that example, but that seems way over my head.
Can you offer any guidance on this, or point me to an example I may have overlooked -- or is custom field the right path, and I just need to commit more time to understanding it?