![]() |
Librairie Arduino esp8266 et esp32 |
Février 2021 |
Quand on développe sur Arduino où ESP on a souvent besoin de proposer différent choix à l'utilisateur.
Cette librairie est utilisée à plusieurs reprises dans ce site voir les exemples dans le chapitre électronique.
Si vous n'avez pas déjà utilisé l'une des librairies sai_oled ou menu_oled
il faut directement choisir la
librairie lib_1306_rot qui regroupe
toutes les fonctions des librairies citées
ainsi que des fonctions additionnelles.
Attention c'est celle-ci
qu'il faut télécharger sur le site "github", elle est différente de celle qui est disponible dans l'environnement "Arduino".
On la reconnait au "w" de Wire qui doit dans notre cas être une majuscule. (Merci à Guy, pour cette précision qui peut éviter pas mal de galère !).
Merci également à tous les contributeurs(46) de ce petit package qui contient plusieurs librairies. Vous devez charger le zip complet comme montré sur
l'image ci-contre.
// Choix selectionnés dans menu
int A_menu;
const int nb_ch_menuA = 5;
const String ch_menuA[] = {"Ouverture / Fermeture", "Param nb tour moteur", "Param date heure", "Param Réseaux", "Param seuil lumiere"};
String _ch_menuA = * ch_menuA;
int B_menu;
const int nb_ch_menuB = 2;
const String ch_menuB[] = {"Vérif. Date Heure", "Retour"};
String _ch_menuB = * ch_menuB;
int C_menu;
const int nb_ch_menuC = 5;
const String ch_menuC[] = {"Temps par tour", "Nb tour ouvre", "Test ouvre", "Nb tour ferme", "Test ferme"};
String _ch_menuC = * ch_menuC;
int D_menu;
const int nb_ch_menuD = 5;
const String ch_menuD[] = {"Login Wifi", "Adresse IP mosquitto", "Login mosquitto", "Passe mosquitto", "Aff. param Wifi"};
String _ch_menuD = * ch_menuD;
switch (A_menu){ // Menu général
case 0 : // Saisie du nom
// Traitement choix 1
break;
case 1 : // Saisie du prénom
// Traitement choix 2
break;
case 2 : // Affichage du nom et du prénom
// Traitement choix 3
break;
}
L'encodeur rotatif est disponible en brut ou sur plaquette qui doit inclure 3 résistances de rappel au + (positif).
Différents Encodeurs rotatifs sont supportés mais l'objet a été créée avec un KY-040 30 pas.
Cette librairie a été développée avec un encodeur qui comporte bien une résistance de rappel au positif sur les trois signaux. Il existe cependant sur le marché des
encodeurs sur plaquette ou la résistance sur le signal "SW" n'a pas été installée, pour fonctionner avec cette librairie cette résistance doit être ajoutée.
Voir ici en bas de page.
Si vous utilisez un encodeur brut (sans pré câblage sur une plaquette)
vous devez réaliser le câblage des résistance comme sur le schéma ci-contre.
L'encodeur rotatif est ici connecté sur un PCF85741 celui-ci ainsi que l'écran OLED ssd1306 sont ensuite raccordés sur le bus I2C.
Autre possibilité (fond de tirroir) les circuits I2C qui sont conçus pour le raccordement des anciens LCD 2 lignes genre "1602".
On peut donc utiliser la petite carte code 4585 équipée du PCF8574...
Attention brochage particulier des sorties P0 à P..
P0 P1 P2 P3 P4 P5 P6 P7
4 5 6 NC 11 12 13 14
Je vous livre ici le code complet en "Open Source".
Si vous utilisez ce code, merci de mettre un lien vers ce site : https://castoo.fr
// menu_oled_i2c.h
// Affiche un menu sur LCD Oled 1306 raccordé sur I2C
// Affichage/Saisie depuis le menu et retourne le choix de l'utilisateur
// Castoo
// avril 2020
// v2.0 fevrier 2021 (prise en charge de l'adresse i2c de l'interface i/o)
/*
menu_oled.h
- Objet destiné à être utilisé avec Arduino ou ESPxxx.
Possibilité de supporter différents LCD mais l'objet a été créée avec un OLED SD1306
Possibilité de supporter différents Encodeurs rotatifs mais l'objet a été créée avec un KY-040 30 pas
Création Jean Michel Castille décembre 2019 / https://castoo.fr
Cette bibliothèque est un logiciel libre;
Vous pouvez la redistribuer et ou la modifier.
Cette bibliothèque est distribuée dans l'espoir qu'elle sera utile,
mais SANS AUCUNE GARANTIE, sans même la garantie implicite de
QUALITÉ MARCHANDE ou ADÉQUATION À UN USAGE PARTICULIER.
*/
#ifndef menu_oled_i2c_h
#define menu_oled_i2c_h
// Adresse I2C du 4585
//pour mémo 0x3F => interface vieux ecrans tft
//pour mémo 0x21 => interface E/S PCF85741
#include "Wire.h"
#include "SSD1306Wire.h"
// circuit I2C PCF8574 correspondance des broches sur le connecteur I2C LCD adr de base i2c : 0x3F
// Ce tableau est à revoir suivant schèma réél de la plaquette !
// exemple => menu_oled mes_menus_oled(2, 1, 0, display); //clk en P2 dt en P1 sw en P0 donc broches 6, 5 et 4
// P0 P1 P2 P3 P4 P5 P6 P7
// 4 5 6 NC 11 12 13 14
// ou
// circuit I2C PCF85741 interface I/OLED adr de base i2c : 0x21
// Dans ce cas P0 à P7 sans surprise !
class menu_oled{
private:
SSD1306Wire *_ecran; // Ecran OLED
uint8_t adr_i2c_4585; // adresse i2c circuit i/o
uint8_t PinCLK; // P x sur sortie Clk du selecteur rotatif
uint8_t PinDT; // P x sur sortie DT du selecteur rotatif
uint8_t PinSW; // P x sur sortie SW du selecteur rotatif
int max_ch; // Nb max de chaine du menu
String * _ch_menu; // Pointeur sur tableau des chaines
public:
// Constructeur permet de passer les cnx du bouton de commande et le nom du LCD
menu_oled(uint8_t adr_i2c_io, uint8_t vclk, uint8_t vdt, uint8_t vsw, SSD1306Wire &ecran);
// Initialisation du menu permet de passer le nb de choix et un tableau des chaines de choix
uint8_t init(int nb_ch_menu, String &ch_menu);
// retourne etat du signal CLK
bool li_rot_clk();
// retourne etat du signal dt
bool li_rot_dt();
// retourne etat du signal sw
bool li_rot_sw();
private:
// Affichage du menu A
void aff_menu(int pos);
// Selection dans le menu A à l'aide selecteur rotatif
uint8_t sel_menu(int max);
};
#endif
// menu_oled_i2c.cpp
// Affiche un menu sur LCD Oled 1306 raccordé sur I2C
// Affichage/Saisie depuis le menu et retourne le choix de l'utilisateur
// Castoo
// avril 2020
// v2.0 fevrier 2021 (prise en charge de l'adresse i2c de l'interface i/o)
/*
menu_oled.cpp
- Objet destiné à être utilisé avec Arduino ou ESPxxx.
Possibilité de supporter différents LCD mais l'objet a été créée avec un OLED SD1306
Possibilité de supporter différents Encodeurs rotatifs mais l'objet a été créée avec un KY-040 30 pas
Création Jean Michel Castille décembre 2019 / https://castoo.fr
Cette bibliothèque est un logiciel libre;
Vous pouvez la redistribuer et ou la modifier.
Cette bibliothèque est distribuée dans l'espoir qu'elle sera utile,
mais SANS AUCUNE GARANTIE, sans même la garantie implicite de
QUALITÉ MARCHANDE ou ADÉQUATION À UN USAGE PARTICULIER.
*/
#include "menu_oled_i2c.h"
// Constructeur permet de passer les cnx du bouton de commande et le nom du LCD
menu_oled::menu_oled(uint8_t adr_i2c_io, uint8_t vclk, uint8_t vdt, uint8_t vsw, SSD1306Wire &ecran){
this->adr_i2c_4585 = adr_i2c_io; // Adr circuit i/o
this->PinCLK = vclk; // Clk du selecteur rotatif
this->PinDT = vdt; // DT du selecteur rotatif
this->PinSW = vsw; // SW du selecteur rotatif
this->_ecran = &ecran; // Ecran OLED
}
// Initialisation du menu permet de passer le nb de choix et un tableau des chaines de choix
uint8_t menu_oled::init(int nb_ch_menu, String &ch_menu){
this->_ecran->flipScreenVertically();
this->_ecran->setFont(ArialMT_Plain_10);
this->_ecran->setTextAlignment(TEXT_ALIGN_LEFT);
this->max_ch = nb_ch_menu;
this->_ch_menu = &ch_menu;
return this->sel_menu(this->max_ch);
}
// retourne etat du signal CLK
bool menu_oled::li_rot_clk(){
uint8_t lect_octet;
Wire.requestFrom(this->adr_i2c_4585, 1);
lect_octet = Wire.read();
Wire.endTransmission();
return bitRead(lect_octet, this->PinCLK);
}
// retourne etat du signal DT
bool menu_oled::li_rot_dt(){
uint8_t lect_octet;
Wire.requestFrom(this->adr_i2c_4585, 1);
lect_octet = Wire.read();
Wire.endTransmission();
return bitRead(lect_octet, this->PinDT);
}
// retourne etat du signal SW
bool menu_oled::li_rot_sw(){
uint8_t lect_octet;
Wire.requestFrom(this->adr_i2c_4585, 1);
lect_octet = Wire.read();
Wire.endTransmission();
return bitRead(lect_octet, this->PinSW);
}
// Affichage du menu et encadrement de la valeur en cours de selection
void menu_oled::aff_menu(int pos){
this->_ecran->clear();
for (uint8_t i = 0; i < this->max_ch; i++) this->_ecran->drawString(0, (12*i), this->_ch_menu[i+1]);
this->_ecran->drawRect(0, (12*pos), (this->_ch_menu[pos+1].length()*5)+25, 13);
this->_ecran->display();
}
// Selection dans le menu à l'aide du selecteur rotatif
uint8_t menu_oled::sel_menu(int max){
max--;
bool B_val = false, val_clk = true, memo_clk = true;
int B_choix = 0;
this->aff_menu(B_choix);
while (! B_val){
val_clk = this->li_rot_clk();
if (val_clk != memo_clk){
if (this->li_rot_dt() != val_clk) { B_choix++; if (B_choix > max) B_choix = max;}
else { B_choix--; if (B_choix < 0) B_choix = 0;}
this->aff_menu(B_choix); delay(10);
}
if (!(this->li_rot_sw())) { B_val = true; } // Bouton validation
memo_clk = val_clk; delay(5);
}
this->aff_menu(B_choix);
return B_choix;
}
Le fichier d'exemple d'utilisation des deux objets (mais chacun peut bien sûr être utilisé seul dans vos montage).
Ne pas oublier de personnaliser les PIN GPio en fonction du circuit sur lequel vous désirez tester l'exemple !
L'exemple a été testé avec un Wemos -D1 mini pro.
// test_obj_sai_menu_oled_i2c.ino
// Test des objets sai_oled et menu_oled
// Castoo https://castoo.fr
// Décembre 2019
// Màj février 2021
#include "SSD1306Wire.h"
#include "sai_oled_i2c.h"
#include "menu_oled_i2c.h"
// l'adresse I2C (ici 0x3C) peut être différente en fonction du module utilisé
//SSD1306Wire display(0x3c, 4, 5); // I2C sur un esp8266 donc gpio 4 > SDA & gpio 5 > SCL
SSD1306Wire display(0x3c, D2, D1); // I2C sur un Wemos D1 mini (esp8266 donc gpio 4 (ou D2) > SDA & gpio 5 (ou D1) > SCL)
#define adr_pcf85741 0x21 // Adresse du circuit I2C 8 I/O
#define encod_sw 0 // P0
#define encod_dt 1 // P1
#define encod_clk 2 // P2
// Pour initialiser les objets sai_oled et menu_oled il faut passer les sorties Gpio utilisées pour le bouton rotatif
// Il est également necessaire de preciser le nom de l'objet écran utilisé (celui-ci peut facilement être modifié)
// L'adresse du circuuit PCF8574 doit etre passé en premier parametre ceci permet l'utilisation de différents types de circuit I/O
// L'adresse peut etre 20 ou 21 ou tout autre suivant circuit ...
//sai_oled Sai_oled(adr, 16, 13, 0, display); // init saisie (Adresse PCF85741 0x21, Gpio vclk, Gpio vdt, Gpio vsw et nom de l'objet LCD)
sai_oled Sai_oled(adr_pcf85741, encod_clk, encod_dt, encod_sw, display); // init saisie (Adresse PCF85741 0x21, Gpio vclk, Gpio vdt, Gpio vsw et nom de l'objet LCD)
//menu_oled Menus_oled(adr, 16, 13, 0, display); // init saisie (Adresse PCF85741 0x21, Gpio vclk, Gpio vdt, Gpio vsw et nom de l'objet LCD)
menu_oled Menus_oled(adr_pcf85741, encod_clk, encod_dt, encod_sw, display); // init saisie (Adresse PCF85741 0x21, Gpio vclk, Gpio vdt, Gpio vsw et nom de l'objet LCD)
// Menus_oled.li_rot_sw() Sortie SW du selecteur rotatif sera utilisée pour valider les delais d'attente
int A_menu; // Choix selectionné dans menu
const int nb_ch_menuA = 3; // choix du menu Principal
const String ch_menuA[] = {"Saisir votre nom", "Saisir votre prénom", "Afficher Nom Prénom"};
String _ch_menuA = * ch_menuA;
String nom = "";
String prenom = "";
String ch_result = "";
// Initialisation
void setup() {
// Init OLED
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_24);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
// Init des objets sai_oled
Sai_oled.init(); // Initialisation ecran pour saisie OLED
Sai_oled.sortie_deb(false); // Invalide sortie balayage aprés chaque saisie (+ rapide mais perso, j'aime pas !) à tester à true...
}
// Boucle principale
void loop(){
A_menu = 0;
A_menu = Menus_oled.init(nb_ch_menuA, _ch_menuA);
delay(300);
switch (A_menu){ // Menu général
case 0 : // Saisie du nom
Sai_oled.init(); // Initialisation ecran OLED pour saisie
nom = Sai_oled.aff_menu_Alpha(); // On lance la saisie
break;
case 1 : // Saisie du prénom
Sai_oled.init(); // Initialisation ecran OLED pour saisie
prenom = Sai_oled.aff_menu_Alpha(); // On lance la saisie
break;
case 2 : // Affichage du nom et du prénom
delay(200); // Anti rebond bouton
ch_result = nom + " " + prenom;
if(ch_result == " ") ch_result = "Vous devez faire une saisie !";
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
display.drawString(64, 25, ch_result);
display.display();
while(Menus_oled.li_rot_sw()){ // On attend que le bouton soit pressé pour sortir de l'affichage
delay(10);
}
break;
}
delay(800);
}