User Interface (Part 1)
The goal for this user interface is to use the least number of pins from Arduino, leaving as many pins as possible for the application itself.
Taking advandage of my early works on rotary encoders I decided to use this type of control in addition to an LCD display.
This type of combination involves the design of a menu driven application. The principle of operation is fairly simple. A click on the encoder calls the main menu on display: the first line tells about the menu content; the menu items are scrolled with the encoder on the second line. An other click selects the current menu item. And so on. The last scrollable menu item is reserved for the EXIT command for returning to upper menu levels.
For the purpose of testing the interface, I designed a basic blinker application which can be controlled in terms of
- start/stop blinking
- blink cycle duration
- cycle modulation
The critical components from the interface are located in the following routine:
void commandProcessor(void) { int lastCounts; int counts; boolean firstCount = true; if (Encoder.buttonDown()) { // Read push button status (Ground true => 0=down) while (Encoder.buttonDown()); // Do nothing while button is depressed // Display menu LCD.printString(MSG_FCT_SELECT, 1); counts = 0; Encoder.setCounter(counts, 0, 3); firstCount = true; while (!Encoder.buttonDown()) { // While button is not depressed lastCounts = counts; counts = Encoder.getCounter(); // Get counter value if ((lastCounts != counts) || firstCount) { // If counter has changed since last display firstCount = false; LCD.printString(FunctionIndexToString(counts), 2); } } while (Encoder.buttonDown()); // Wait button release switch(counts) { // Run control case 0: LCD.printString(MSG_FCT_RUN_CONTROL, 1); counts = 0; Encoder.setCounter(counts, 0, 1); firstCount = true; while (!Encoder.buttonDown()) { // While button is not depressed lastCounts = counts; counts = Encoder.getCounter(); // Get counter value if ((lastCounts != counts) || firstCount) { // If counter has changed since last display firstCount = false; LCD.printString(RunControlIndexToString(counts), 2); } } while (Encoder.buttonDown()) // Do nothing while button is depressed run_state = counts; break; // Function: cycle duration case 1: LCD.printString(MSG_FCT_DURATION, 1); counts = tim_cycleDuration; Encoder.setCounter(counts, 100, 10000); firstCount = true; while (!Encoder.buttonDown()) { // While button is not depressed lastCounts = counts; counts = Encoder.getCounter(); // Get counter value if ((lastCounts != counts) || firstCount) { // If counter has changed since last display firstCount = false; counts = lastCounts + pow((counts - lastCounts), 3); // Non linear counter (counts booster): Powering to 3 prevents from caring about the sign Encoder.setCounter(counts); // Update counter // Display frequency LCD.eraseBuffer(); LCD.insertInteger(counts, 5); LCD.insertString("ms", 7, true); LCD.printBuffer(2); } delay(50); } while (Encoder.buttonDown()); // Wait for button release tim_cycleDuration = counts; computeDurations(); break; // Function: on/off ratio case 2: LCD.printString(MSG_FCT_ON__OFF_RATIO, 1); counts = tim_onOffRatio; Encoder.setCounter(counts, 1, 99); firstCount = true; while (!Encoder.buttonDown()) { // While button is not depressed lastCounts = counts; counts = Encoder.getCounter(); // Get counter value if ((lastCounts != counts) || firstCount) { // If counter has changed since last display firstCount = false; Encoder.setCounter(counts); // Update counter // Display frequency LCD.eraseBuffer(); LCD.insertInteger(counts, 5); LCD.insertString("%", 7, true); LCD.printBuffer(2); } } while (Encoder.buttonDown()); // Wait for button release tim_onOffRatio = counts; computeDurations(); break; // Exit case 3: break; } LCD.printString(MSG_FIRMWARE, 1); LCD.printString(" ", 2); } }
the
commandProcessor();
command shall be inserted in the loop() routine.
You can download a compatible version of my PlainEncoder Library from here. Any LCD library would work.
Conclusion
This interface uses only 6 I/O ports for the LCD and 3 I/O ports for the encoder, which leaves 8 + 3 I/O Ports (Or even 2 more if you consider using PORTD0:1) for the application. There is surely room for code improvment (e.g. Storing menu item strings in EEPROM instead of RAM), however, it works great for simple applications.
[…] http://arduino.cc/playground/Main/RotaryEncoders http://www.arduinoos.com/?p=643 Gefällt mir:Gefällt mirBe the first to like this. Dieser Beitrag wurde unter Arduino, Hardware […]
Hi, great site! sorry, but where i found de PlainEncoder Library? The above link say “ERROR 404 – NOT FOUND”.
Thanks!
Thanks for notifying this broken link. Please check my code request policy @ http://goo.gl/qIMQW
Regards
Didier