Jetez éventuellement un oeil sur mon petit projet Contrôleur de T°, Humidité avec pilotage manuel ou automatique - vous verrez dans le code comment je gère la possibilité de définir des consignes
Sinon j'avais aussi déjà posté (il me semble) ce petit bout de code qui démontre comment rentrer une valeur à l'aide d'un petit clavier à membrane qui utilise la touche '#' pour valider une entrée (et '*' pour effacer ce qui a été tapé, 1 caractère à la fois)
// ****** HANDLE KEYPAD ******
#include <Keypad.h> // https://github.com/Chris--A/Keypad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 34, 36, 38, 40 };
// Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
byte colPins[COLS] = {41, 39, 37, 35};
//initialize an instance of class Keypad
Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ****** HANDLE LCD ******
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const byte nbCols = 20;
const byte nbLines = 4;
LiquidCrystal_I2C lcd( 0x3F, nbCols, nbLines); // my LCD is at I2C address 0x3F, 20 cols, 4 rows
// **********************************************************************************
// getNumber()
// if prepare is true, we initialize everything to receive data in a specific field on the LCD
// otherwise it handles the data input
// returns true when user has pressed the # key
// Note: defined defaults value to simplify calling the function when not in prepare stage (see below)
// **********************************************************************************
boolean getNumber(long *dataEntry, const boolean prepare = false, const uint8_t x = 0, const uint8_t y = 0, const uint8_t fieldSize = 2, const char asciiChar = '_')
{
boolean entryCompleted = false;
static uint8_t _x0, _y0, _x, _w;
static char _p; //padding Char
static boolean _fullEntry = false;
if (prepare) { // initialize the capture field
const byte maxLongLength = 12; // enough for -2147483648 so 11 characters + trailing null
char dataBuffer[maxLongLength];
_x0 = _x = x;
_y0 = y;
_w = fieldSize;
_p = asciiChar;
lcd.setCursor(_x0, _y0);
for (uint8_t i = 0; i < _w; i++) lcd.write(_p);
lcd.setCursor(_x0, _y0);
if (dataEntry) { // if we gave an initial value, display the part that fits into the area
ltoa(*dataEntry, dataBuffer, 10); // convert value into c-string in base 10
if (strlen(dataBuffer) < _w) { // do we fit in the reserved area?
_fullEntry = false;
lcd.print(dataBuffer);
_x = _x0 + strlen(dataBuffer);
} else {
dataBuffer[_w] = '\0';
*dataEntry = atol(dataBuffer);
_fullEntry = true;
lcd.print(dataBuffer);
_x = _x0 + strlen(dataBuffer) - 1;
lcd.setCursor(_x, _y0); // and don't go further than the reserved space
}
}
lcd.blink();
} else {
char entry = membraneKeypad.getKey();
switch (entry) // don't deal with case 'A'...'D':
{
case '0'...'9': // add this digit
lcd.print(entry);
if (_fullEntry) {
*dataEntry = (*dataEntry / 10) * 10 + entry - '0'; // overwrite the last digit
lcd.setCursor(_x, _y0); // and don't go further than the reserved space
} else {
*dataEntry = *dataEntry * 10 + entry - '0';
_x++;
if (_x >= _x0 + _w) {
_x--;
lcd.setCursor(_x, _y0);
_fullEntry = true;
}
}
break;
case '*': // erase last digit
*dataEntry = *dataEntry / 10;
if (_fullEntry) {
_fullEntry = false;
} else {
if (_x > _x0) _x--;
}
lcd.setCursor(_x, _y0);
lcd.write(_p);
lcd.setCursor(_x, _y0);
break;
case '#':
lcd.noBlink();
if (!_fullEntry)
for (uint8_t i = _x; i < _x0 + _w; i++) lcd.write(' '); // replace padding with white spaces
entryCompleted = true;
break;
}
}
return entryCompleted;
}
void setup() {
Serial.begin(115200);
lcd.begin();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("Min=")); // to see the area
// prepare the data entry. initial value in empty, prepare mode, start col for field entry, start line for field entry, padding number during entry
getNumber(NULL, true, 4, 0, 5, '_');
}
void loop() {
static long dataEntry = 0; // important to be static to survive across loops
if (getNumber(&dataEntry)) { // wait until we get an entry validated by #
// erase the second line
lcd.setCursor(0, 1);
for (byte i = 0; i < nbCols; i++) lcd.print(F(" "));
lcd.setCursor(0, 1);
// print the data we got
lcd.print(F("Min set @ ")); lcd.print(dataEntry);
// prepare the next data entry. initial value is what has been entered
getNumber(&dataEntry, true, 4, 0, 5, '_'); // we start from the existing value, use * for example on the pad to erase digits if necessary
// if you want to restart from an empty value you would do that instead of the line above
// dataEntry = 0;
// getNumber(NULL, true, 4, 0, 5, '_'); // start with no value
}
// here you could do other stuff
}
Un clavier à membrane ça ressemble à cela et ça coûte 1 euro sur eBay en commandant en asie (ou deux pour 1,72€.. à ce prix là autant en prendre un de rechange)