Internet de les coses amb ESP32 i ESP8266

Exemples Referència Plaques   Recursos CITCEA
Projectes Programació Perifèrics   Inici

Pantalla monocrom FeatherWing

La FeatherWing és una pantalla monocrom de 128 ⨯ 32 píxels que permet representar text i gàfics senzills. Incorpora tres polsadors que podem fer servir per al que vulguem. Fa sevir la connexió I2C per comunicar-se amb el microcontrolador.

NeoPixel  Fotografia: Adafruit

La pantalla està dissenyada per acoblar-se sobre la placa Feather HUZZAH. Atès que no és possible acoblar-la sobre la placa MKR WIFI 1010, caldrà fer servir cables o un circuit imprès per connectar-la.

La pantalla fa servir les següents potes del microcontrolador:

Connexió Pota Feather HUZZAH Pota MKR WIFI 1010
3,3 V 3V VCC
GND GND GND
SDA D4 11
SCL D5 12
Botó A D0    0   
Botó B D16 A1   
Botó C D2    2   

    En la placa Feather HUZZAH les potes D0 i D2 corresponen, respectivament, als LED vermell i blau. Això vol dir que quan premem aquests polsadors s'encendrà el LED que els correspon.

    Atès que la placa MKR WIFI 1010 l'hem de connectar manualment, podríem fer servir quasi qualsevol pota. Hem triat aquestes perquè els programes que presentem serveixin per a les dues plaques sense canviar l'assignació de potes.

Aquí veurem les principals funcions disponibles per escriure text, dibuixar gràfics, mostrar imatges i les configuracions de la pantalla. Totes les possibilitats de la biblioteca GFX es poden trobar al web d'Adafruit.

Escriptura de text

A continuació tenim un programa de prova en el que escrivim text a la pantalla i fem servir els polsadors.

#include <SPI.h>  // Per a la conexió I2C
#include <Wire.h>  // Per a la conexió I2C
#include <Adafruit_GFX.h>  // Per als gràfics
#include <Adafruit_SSD1306.h>  // Per a la pantalla
#define botoA 0
#define botoB 16
#define botoC 2
Adafruit_SSD1306 pantalla = Adafruit_SSD1306(128, 32, &Wire);
void setup() {
  pinMode(botoA, INPUT_PULLUP);
  pinMode(botoB, INPUT_PULLUP);
  pinMode(botoC, INPUT_PULLUP);
  // Configura la pantalla
  pantalla.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // Mostra el contingut de la pantalla
  // Inicialment hi ha el logo d'Adafruit
  pantalla.display();
  delay(2000);
  // Esborra la pantalla
  pantalla.clearDisplay();
  pantalla.display();
  // Escriu text
  pantalla.setTextSize(1);
  pantalla.setTextColor(WHITE);
  pantalla.setCursor(0,0);
  pantalla.println("Programa de prova");
  pantalla.println("FeatherWing");
  pantalla.println();
  pantalla.println("Cap polsador premut");
  pantalla.display(); // Mostra el contingut
  delay(2000);
}
void loop() {
  if(!digitalRead(botoA)){
    pantalla.clearDisplay();
    pantalla.setCursor(0,16);
    pantalla.print("Premut polsador A");
  } else if(!digitalRead(botoB)){
    pantalla.clearDisplay();
    pantalla.setCursor(0,16);
    pantalla.print("Premut polsador B");
  } else if(!digitalRead(botoC)){
    pantalla.clearDisplay();
    pantalla.setCursor(0,16);
    pantalla.print("Premut polsador C");
  } else {
    pantalla.clearDisplay();
    pantalla.setCursor(0,16);
    pantalla.print("Cap polsador premut");
  }
  delay(10);
  yield(); // Alliberem recursos
  pantalla.display();
  delay(100);
}

El nostre programa posa text a la pantalla i quan ha acabat crida la funció display que ho mostra tot de cop. En el moment d'engegar la pantalla té a la memòria el logotip d'Adafruit que es mostra quan es crida la funció display i es manté durant dos segons. Si no volem que es mostri el logotip haurem de suprimir les línies següents:

  // Mostra el contingut de la pantalla
  // Inicialment hi ha el logo d'Adafruit
  pantalla.display();
  delay(2000);

i així no es mostrarà res a la pantalla fins que haguem escrit el text.

L'origen de coordenades és la cantonada superior esquerra de la pantalla. La coordenada X anirà de 0 a 127 i la coordenada Y de 0 a 31. En ser una pantalla monocrom, els colors només podran ser negre (BLACK) i blanc (WHITE).

La biblioteca només té els caràcters ASCII bàsics; per tant no podrem escriure caràcters amb accents o la ce trencada, entre altres.

Les principals funcions disponibles a la biblioteca GFX per escriure text són:

Funció Utilització Paràmetres
Valor Tipus
setCursor Situa el cursor Coordenada X
(punt superior esquerra del caràcter)
uint16_t
Coordenada Y
(punt superior esquerra del caràcter)
uint16_t
setTextColor Fixa el color del text Color uint16_t
setTextColor Fixa el color del text
i el del fons de la seva caixa
Color uint16_t
Color de fons uint16_t
setTextSize Fixa la mida del text Mida uint8_t
setTextWrap Controla la presentació del text Estat boolean

La mida dels caràcters pot ser 1, 2 o 3. Els de mida 1 fan 5 x 8 píxels. Els de mida 2 es creen duplicant cada píxel en horitzontal i vertical (per tant, mesuren 10 x 16 píxels).

Si l'estat de setTextWrap és true (valor per defecte) el text que no cap a l'amplada de la pantalla es seguirà escrivint a la línia següent. Si és false no es mostrarà.

Configuració de la pantalla

Les principals funcions disponibles a la biblioteca GFX per configurar la pantalla són:

Funció Utilització Paràmetres
Valor Tipus
setRotation Estableix la rotació de la pantalla Rotació uint8_t
fillScreen Esborra el contingut i estableix el color de fons de la pantalla Color uint16_t

La rotació pot ser 0, 1, 2 o 3. Cada cop que s'incrementa el contingut de la pantalla gira 90°. Cal tenir present que a cada rotació es permuten les mides de la pantalla.

Representació de gràfics

El següent programa ens mostra alguns exemples sobre representació gràfica a la pantalla. Ens mostra deu figures distribuïdes de manera aleatòria. El polsador A ens permet commutar entre vídeo normal (blanc sobre negre) o vídeo invers (negre sobre blanc), recordem que és una pantalla monocrom. El polsador B commuta entre rectàngles de 10 x 8 píxels i circumferències de quatre píxels de radi. Finalment el polsador C commuta entre dibuixar només el contorn o omplir la figura.

#include <SPI.h>  // Per a la conexió I2C
#include <Wire.h>  // Per a la conexió I2C
#include <Adafruit_GFX.h>  // Per als gràfics
#include <Adafruit_SSD1306.h>  // Per a la pantalla
#define botoA 0
#define botoB 16
#define botoC 2
byte invers = false;
byte cercle = false;
byte ple = false;
uint16_t color = WHITE;
bool pendent = true;
Adafruit_SSD1306 pantalla = Adafruit_SSD1306(128, 32, &Wire);
void setup() {
  pinMode(botoA, INPUT_PULLUP);
  pinMode(botoB, INPUT_PULLUP);
  pinMode(botoC, INPUT_PULLUP);
  // Configura la pantalla
  pantalla.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // Esborra la pantalla
  pantalla.clearDisplay();
  pantalla.display();
}
void loop() {
  if(!digitalRead(botoA)){
    invers = ~invers;
    pendent = true;
  }
  if(!digitalRead(botoB)){
    cercle = ~cercle;
    pendent = true;
  }
  if(!digitalRead(botoC)){
    ple = ~ple;
    pendent = true;
  }
  delay(10);
  yield(); // Alliberem recursos
  if(pendent){
    pantalla.clearDisplay();
    if(invers){
      // Posa fons blanc
      pantalla.fillScreen(WHITE);
      color = BLACK;
    } else {
      color = WHITE;
    }
    for (byte i = 0; i < 10; i++){
      int X0 = (int)random(0, 118);
      int Y0 = (int)random(0, 22);
      if(ple){
        if(cercle){
          pantalla.fillCircle(X0+5, Y0+5, 4, color);
        } else {
          pantalla.fillRect(X0, Y0, 10, 8, color);
        }
      } else {
        if(cercle){
          pantalla.drawCircle(X0+5, Y0+5, 4, color);
        } else {
          pantalla.drawRect(X0, Y0, 10, 8, color);
        }
      }
    }
    pantalla.display();
    pendent = false;
    delay(1000);
  }
}

El programa anterior dona per suposat que les dades que envia l'script arriben en una de les dues darreres línies rebudes. Però podria passar que no fos així i, de fet, sovint Google modifica el funcionament de les seves aplicacions per introduir elements de seguretat. Podríem fer que l'script enviés les dades amb un marcador, de manera que la línia on hi ha les dades quedés perfectament identificada. Podeu trobar una mostra de com fer-ho en aquest exemple.

Les principals funcions disponibles a la biblioteca GFX per dibuixar gràfics són:

Funció Utilització Paràmetres
Valor Tipus
drawPixel Dibuixa un punt Coordenada X uint16_t
Coordenada Y uint16_t
Color uint16_t
drawLine Dibuixa una línia Coordenada X inicial uint16_t
Coordenada Y inicial uint16_t
Coordenada X final uint16_t
Coordenada Y final uint16_t
Color uint16_t
drawRect Dibuixa el contorn d'un rectangle Coordenada X inicial
(punt superior esquerra)
uint16_t
Coordenada Y inicial
(punt superior esquerra)
uint16_t
Amplada uint16_t
Alçada uint16_t
Color uint16_t
fillRect Dibuixa un rectangle ple Coordenada X inicial
(punt superior esquerra)
uint16_t
Coordenada Y inicial
(punt superior esquerra)
uint16_t
Amplada uint16_t
Alçada uint16_t
Color uint16_t
drawRoundRect Dibuixa el contorn d'un rectangle arrodonit Coordenada X inicial
(punt superior esquerra)
uint16_t
Coordenada Y inicial
(punt superior esquerra)
uint16_t
Amplada uint16_t
Alçada uint16_t
Radi corba uint16_t
Color uint16_t
fillRoundRect Dibuixa un rectangle arrodonit ple Coordenada X inicial
(punt superior esquerra)
uint16_t
Coordenada Y inicial
(punt superior esquerra)
uint16_t
Amplada uint16_t
Alçada uint16_t
Radi corba uint16_t
Color uint16_t
drawCircle Dibuixa una circumferència Coordenada X del centre uint16_t
Coordenada Y del centre uint16_t
Radi uint16_t
Color uint16_t
fillCircle Pinta un cercle Coordenada X del centre uint16_t
Coordenada Y del centre uint16_t
Radi uint16_t
Color uint16_t
drawTriangle Dibuixa el contorn d'un triangle Coordenada X punt 1 uint16_t
Coordenada Y punt 1 uint16_t
Coordenada X punt 2 uint16_t
Coordenada Y punt 2 uint16_t
Coordenada X punt 3 uint16_t
Coordenada Y punt 3 uint16_t
Color uint16_t
fillTriangle Dibuixa un triangle ple Coordenada X punt 1 uint16_t
Coordenada Y punt 1 uint16_t
Coordenada X punt 2 uint16_t
Coordenada Y punt 2 uint16_t
Coordenada X punt 3 uint16_t
Coordenada Y punt 3 uint16_t
Color uint16_t
drawChar Dibuixa un caràcter Coordenada X inicial
(punt superior esquerra)
uint16_t
Coordenada Y inicial
(punt superior esquerra)
uint16_t
Caràcter char
Color uint16_t
Color de fons uint16_t
Mida uint8_t

La mida dels caràcters pot ser 1, 2 o 3. Els de mida 1 fan 5 x 8 píxels. Els de mida 2 es creen duplicant cada píxel en horitzontal i vertical (per tant, mesuren 10 x 16 píxels).

Representació d'imatges

Podem representar imatges (icones, logotips, etc.) a la pantalla. Aquestes imatges hauran d'estar a la memòria del microcontrolador. Atès que la memòria de dades és relativament petita, serà convenient que aquestes imatges es guardin a la memòria de programa. La funció drawBitmap s'encarrega de representar una imatge que està guardada a la memòria de programa.

La imatge ha de ser monocrom (un bit per cada píxel). La funció pintarà del color indicat els píxels que estiguin a 1 en el vector. Atès que la pantalla és monocrom, el color haurà de ser blanc si hem fet el fons negre o negre si l'hem fet blanc.

Funció Utilització Paràmetres
Valor Tipus
drawBitmap Mostra una imatge a la pantalla Coordenada X
(punt superior esquerra de la imatge)
uint16_t
Coordenada Y
(punt superior esquerra de la imatge)
uint16_t
Variable tipus vector que conté la imatge uint8_t
Amplada de la imatge uint16_t
Al&ccdil;ada de la imatge uint16_t
Color uint16_t

En el programa següent es mostra a la pantalla el logotip de la UPC i, al seu costat, les lletres UPC. Atès que el programa només vol mostrar com fer això, no es fan servir els polsadors ni hi ha cap instrucció al loop del programa. La instrucció PROGMEM en la definició de la llista on es guarda la imatge li indica al compilador que l'ha de guardar a la memòria de programa.

#include <SPI.h>  // Per a la conexió I2C
#include <Wire.h>  // Per a la conexió I2C
#include <Adafruit_GFX.h>  // Per als gràfics
#include <Adafruit_SSD1306.h>  // Per a la pantalla
// 'logoUPCbn', 28x28px
const unsigned char myBitmap [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xfe, 0x00, 
  0x07, 0xff, 0xff, 0x00, 0x0f, 0x18, 0x8f, 0x80, 0x1f, 0x10, 0x87, 0x80, 0x3f, 0x18, 0x8f, 0xc0, 
  0x3f, 0xff, 0xff, 0xe0, 0x7f, 0x19, 0xcf, 0xe0, 0x7f, 0x10, 0x87, 0xe0, 0x7f, 0x10, 0x87, 0xe0, 
  0x7f, 0x19, 0xcf, 0xf0, 0x7f, 0xff, 0xff, 0xf0, 0x7f, 0x18, 0x8f, 0xf0, 0x7f, 0x10, 0x87, 0xf0, 
  0x7f, 0x18, 0x8f, 0xf0, 0x7f, 0xbd, 0xdf, 0xe0, 0x7f, 0xff, 0xff, 0xe0, 0x3f, 0x69, 0xcf, 0xe0, 
  0x3f, 0x6a, 0x9f, 0xc0, 0x1f, 0x48, 0xbf, 0xc0, 0x1f, 0x4b, 0x9f, 0x80, 0x0f, 0x9b, 0xcf, 0x00, 
  0x07, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0x80, 0x00
};
Adafruit_SSD1306 pantalla = Adafruit_SSD1306(128, 32, &Wire);
void setup() {
  // Configura la pantalla
  pantalla.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // Esborra la pantalla
  pantalla.clearDisplay();
  pantalla.drawBitmap(2, 2, myBitmap, 28, 28, WHITE);
  pantalla.setTextSize(3);
  pantalla.setTextColor(WHITE);
  pantalla.setCursor(40,6);
  pantalla.println("UPC");
  pantalla.display();
}
void loop() {
}

Pot ser pesat i molt entretingut generar manualment el vector corresponent a una imatge. Disposem, però, d'una eina que ens ho fa automàticament. L'eina image2cpp ens permet carregar una imatge i convertir-la directament en un vector que podem enganxar directament al nostre programa. En el cas de l'exemple del programa anterior hem partit de la imatge del logotip de la UPC en blanc i negre de 28 x 28 píxels. En la pàgina image2cpp l'hem carregat picant el botó Elegir archivos i hem conservat la majoria d'opcions per defecte excepte que a Background color hem marcat black i a Code output format hem triat Arduino code. Picant el botó Generate code hem obtingut el següent:

// 'logoUPCbn', 28x28px
const unsigned char myBitmap [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xfe, 0x00, 
  0x07, 0xff, 0xff, 0x00, 0x0f, 0x18, 0x8f, 0x80, 0x1f, 0x10, 0x87, 0x80, 0x3f, 0x18, 0x8f, 0xc0, 
  0x3f, 0xff, 0xff, 0xe0, 0x7f, 0x19, 0xcf, 0xe0, 0x7f, 0x10, 0x87, 0xe0, 0x7f, 0x10, 0x87, 0xe0, 
  0x7f, 0x19, 0xcf, 0xf0, 0x7f, 0xff, 0xff, 0xf0, 0x7f, 0x18, 0x8f, 0xf0, 0x7f, 0x10, 0x87, 0xf0, 
  0x7f, 0x18, 0x8f, 0xf0, 0x7f, 0xbd, 0xdf, 0xe0, 0x7f, 0xff, 0xff, 0xe0, 0x3f, 0x69, 0xcf, 0xe0, 
  0x3f, 0x6a, 0x9f, 0xc0, 0x1f, 0x48, 0xbf, 0xc0, 0x1f, 0x4b, 0x9f, 0x80, 0x0f, 0x9b, 0xcf, 0x00, 
  0x07, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0x80, 0x00
};

que hem copiat i enganxat en el nostre programa.

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.