Internet de les coses amb ESP32 i ESP8266

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

Dibuixar amb canvas a la pantalla bicolor Midas

Fins ara hem mostrat a la pantalla imatges fixes, predefinides, però tambés hi ha la possibilitat de dibuixar a la pantalla des del programa. Per poder dibuixar cal definir un espai de dibuix, conegut com a canvas, i reservar-li memòria.

Un cop tenim definit el canvas, hi podem representar el que vulguem (que quedarà guardat a la memòria) i després mostrar el canvas en la zona de la pantalla que desitgem.

Cal tenir en compte que els dibuixos que fem es basen en les coordenades del canvas, no en les de la pantalla.

Veiem un exemple que intenta mostrar com funciona el canvas. Recordem que la pantalla té 128 ⨯ 64 píxels i que la part blava mesura 128 ⨯ 48 píxels. Creem un canvas de 64 ⨯ 48, o sigui de la meitat de l'amplada de la part blava. El primer que fem és dibuixar un rectangle de tota la mida del canvas (així el veurem) però no el pintem de blau sinó que l'omplim amb un patró que ompli només el primer i el darrer píxel de cada grup vertical de 8, així veurem tot el canvas ple de ratlles horitzontals (a les posicions 0, 7, 8, 15, 16, etc.; fins a la 47). Aquest canvas el situem (funció blt) a la posició [0,16] (hem posat [0, 2] perquè el posicionament vertical del canvas és en paquets de vuit bits verticals (com ja hem vist en altres casos).

En una segona fase dibuixem quatre rectangles de 8 ⨯ 8, un a cada cantonada del canvas i tornem a mostrar el canvas a la mateixa posició; si no ho féssim, no veuríem el que hem dibuixat després de mostrar el canvas.

En una tercera fase esborrem la pantalla. Aquesta acció deixa la pantalla negra però no afecta al que tenim dibuixat a la memòria del canvas. Tot seguit escrivim dos textos en el canvas, però ara el mostrem a la meitat dreta de la part blava. Si no haguéssim esborrat la pantalla, ara veuríem l'aspecte anterior del canvas al costat esquerre i el nou al costat dret.

#include "ssd1306.h"
#include "nano_gfx.h"
#define cw 64  // Amplada del canvas
#define ch 48  // Alçada del canvas
uint8_t memoCnv[cw*ch/8];  // Memòria per al canvas
NanoCanvas canvas(cw, ch, memoCnv);
void setup(){
  ssd1306_128x64_i2c_init();
  ssd1306_clearScreen();
  ssd1306_setFixedFont(ssd1306xled_font6x8);
}
void loop(){
  ssd1306_clearScreen();  // Esborra la pantalla, no el canvas
  canvas.clear();  // Esborra el canvas
  canvas.fillRect(0, 0, 63, 47, 129);  // Rectangle de tot el canvas
  canvas.blt(0, 2);  // DIbuixa el canvas ocupant la meitat esquerra de la part blava
  delay(1000);
  canvas.fillRect(0, 0, 7, 7, 255);  // Rectangle 8x8 a la cantonada SE
  canvas.fillRect(0, 40, 7, 47, 255);  // Rectangle 8x8 a la cantonada IE
  canvas.fillRect(56, 0, 63, 7, 255);  // Rectangle 8x8 a la cantonada SD
  canvas.fillRect(56, 40, 63, 47, 255);  // Rectangle 8x8 a la cantonada ID
  canvas.blt(0, 2);
  delay(2000);
  ssd1306_clearScreen();  // Esborra la pantalla, no el canvas
  canvas.printFixed(16, 16, "Prova", STYLE_NORMAL);
  canvas.printFixed2x(8, 24, "Test", STYLE_NORMAL);
  canvas.blt(64, 2);  // DIbuixa el canvas ocupant la meitat dreta de la part blava
  ssd1306_printFixed(0, 0, "Rectangles", STYLE_NORMAL);
  delay(3000);
}

Si en lloc de la funció fillRect emprem la funció drawRect (sense el patró, cinquè paràmetre) obtindrem només els contorns dels cinc rectangles.

Ara que ja hem vist com es comporta el canvas, anem a veure altres possibilitats de dibuix.

El programa següent dibuixa la paràbola y = 0,012 x2 - 10 amb uns eixos, posant el canvas de forma que ocupi tota la part blava.

#include "ssd1306.h"
#include "nano_gfx.h"
#define cw 128  // Amplada del canvas
#define ch 48  // Alçada del canvas
uint8_t memoCnv[cw*ch/8];  // Memòria per al canvas
NanoCanvas canvas(cw, ch, memoCnv);
void setup(){
  ssd1306_128x64_i2c_init();
  ssd1306_clearScreen();
  ssd1306_setFixedFont(ssd1306xled_font6x8);
}
void loop(){
  canvas.clear();  // Esborra el canvas
  canvas.drawHLine(4, 24, 123);
  canvas.drawVLine(64, 4, 43);
  for(int x = -60; x < 60; x++){
    int y = (int) (0.012 * x * x - 10);
    canvas.putPixel(60 + x, 24 - y);
  }
  canvas.blt(0, 2);
  ssd1306_printFixed(0, 0, "Dibuix de funcions", STYLE_NORMAL);
  delay(3000);
}

En el canvas també hi podem incloure imatges i sprites, però en un lloc fix. En el següent programa posem dos sprites i una imatge, després invertim la visualització (canviar negre per blau).

got

En el programa següent hem representat els sprites del pop i el peix i també la imatge del got. En el cas de la imatge, que és la mateixa que hem fet servir abans, la codificació és diferent; ja que cada byte codifica vuit bits verticals. Per tant, l'hem de codificar de nou. A cada element tindrem un nombre binari en el qual el bit de menys pes representa la part superior i el de més pes la part inferior. Primer hi ha els vuit bytes que codifiquen la meitat superior del dibuix i després els que codifiquen l'altra meitat.

#include "ssd1306.h"
#include "nano_gfx.h"
#define cw 128  // Amplada del canvas
#define ch 48  // Alçada del canvas
const uint8_t pop[8] PROGMEM = {
  0b11000000,
  0b00100000,
  0b11010110,
  0b00111101,
  0b00111111,
  0b11010110,
  0b00100000,
  0b11000000
};
const uint8_t peix[8] PROGMEM = {
  0b00101000,
  0b00010000,
  0b00101000,
  0b01000100,
  0b01000100,
  0b01001100,
  0b00101000,
  0b00010000
};
const uint8_t got[] PROGMEM = {
  0b00000000, 0b00000000, 0b11110000, 0b00010000,  // Part superior cols. 1 a 4 
  0b00010000, 0b10010000, 0b11010000, 0b01110000, 
  0b00110000, 0b00011000, 0b00011100, 0b11110110, 
  0b00000011, 0b00000001, 0b00000000, 0b00000000, 
  0b00000000, 0b00000000, 0b00011111, 0b11111110,  // Part inferior cols. 1 a 4 
  0b11111111, 0b11111111, 0b11111110, 0b11111110, 
  0b11111110, 0b11111110, 0b11111110, 0b00011111, 
  0b00000000, 0b00000000, 0b00000000, 0b00000000
};
uint8_t memoCnv[cw*ch/8];  // Memòria per al canvas
NanoCanvas canvas(cw, ch, memoCnv);
void setup(){
  ssd1306_128x64_i2c_init();
  ssd1306_clearScreen();
  ssd1306_setFixedFont(ssd1306xled_font6x8);
}
void loop(){
  canvas.clear();  // Esborra el canvas
  canvas.drawHLine(4, 24, 123);
  canvas.drawVLine(64, 4, 43);
  canvas.drawSpritePgm(20, 10, pop);
  canvas.drawSprite(20, 30, peix);
  canvas.drawBitmap(75, 6, 16, 16, got);
  canvas.blt(0, 2);
  ssd1306_printFixed(0, 0, "Sprites", STYLE_NORMAL);
  delay(2000);
  canvas.invert();
  canvas.blt(0, 2);
  delay(2000);
}

Llista de les funcions

Funció Ús Paràmetres Comentaris
NanoCanvas nomCanvas Crea un objecte canvas Amplada del canvas (píxels)
Alçada del canvas (píxels)
Vector on guardarem el canvas
Vector del tipus uint8_t
Mida: amplada ⨯ alçada / 8
Cal la biblioteca nano_gfx
nomCanvas.width Retorna l'amplada del canvas en píxels
nomCanvas.height Retorna l'alçada del canvas en píxels
nomCanvas.buffer Retorna el vector que conté el canvas nomCanvas.buffer()[i]
retorna la component i del vector
nomCanvas.clear Esborra el contingut del canvas No afecta al que es veu a la pantalla, fins que
es torna a mostrar el canvas
nomCanvas.blt Mostra el canvas a la pantalla Posició x a la pantalla
Posició y en múltiples de 8
nomCanvas.printFixed Escriu un text fix al canvas Posició x
Posició y
Text (entre cometes)
Estil
Opcions d'estil:
    STYLE_NORMAL
    STYLE_BOLD
    STYLE_ITALIC
nomCanvas.printFixed2x Escriu un text fix al canvas a mida doble Posició x
Posició y
Text (entre cometes)
Estil
Opcions d'estil:
    STYLE_NORMAL
    STYLE_BOLD
    STYLE_ITALIC
nomCanvas.drawRect Crea un rectangle buit Posició x inicial
Posició y inicial
Posició x final
Posició y final
nomCanvas.fillRect Crea un rectangle farcit amb un patró Posició x inicial
Posició y inicial
Posició x final
Posició y final
Patró (8 bits) [0 a 255]
El patró correspon a 8 píxels verticals, on el bit
menys significatiu és el píxel superior.
Posant 0 no mostra el rectangle (ni les vores).
Posant 255 pinta completament el rectangle.
Un patró entre 0 i 255 donarà franges horitzontals
nomCanvas.drawHLine Dibuixa una línia horitzontal Posició x inicial
Posició y
Posició x final
nomCanvas.drawVLine Dibuixa una línia vertical Posició x
Posició y inicial
Posició y final
nomCanvas.putPixel Pinta un píxel Posició x
Posició y
nomCanvas.drawSprite Mostra l'sprite en el canvas Posició x
Posició y
Vector de la imatge
nomCanvas.drawSpritePgm Mostra l'sprite en el canvas Posició x
Posició y
Vector de la imatge
nomCanvas.drawBitmap Mostra una imatge fixa en el canvas Posició x
Posició y
Amplada
Alçada
Vector de la imatge
nomCanvas.invert Inverteix tots els píxels del canvas Apaga els encesos i encén els apagats

 

 

 

 

 

 

 

 

 

 

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