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.
Fotografia: AdafruitLa 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.
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à.
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.
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).
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.

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