Manual
do
Maker
.
com
Essa placa da AFEletronica me conquistou um pouco mais do que outras placas com ESP32, principalmente por ter caído como uma luva no projeto do misturador de cores CMYK, utilizando o display ILI9341 com TFT_eSPI. Nada mais prático do que ter uma placa com todos os recursos periféricos necessários a disposição, sem precisar de wiring, sem solda, sem gambiarra. Isso tudo sem contar que é uma placa nacional, com suporte, garantia e industrial! Por essa e outras sou muito simpático ao hardware desenvolvido pela AFEletronica.
Uma das coisas que essa placa possui e que pode ser interessante em diversos casos, é o RS485, muito utilizado na indústria. Trata-se de uma comunicação two-wire com alcance de até 2km. Sobre a placa estão dispostos 4 módulos relés e 4 entradas digitais, totalizando os 8 bits do PCF8574, que controla esses recursos. O display ILI9341 é um espetáculo à parte. A placa também tem slot para interface ethernet, caso desejado. Do mesmo modo, um barramento I2C exposto, para display OLED.
Para programá-la é simples, basta criar um projeto para ESP32 e escolher a placa ESP32 WROVER ou Espressif ESP32 Dev Module, no Visual Studio Code, utilizando PlatformIO.
Para controlar o PCF8574, recomendo a biblioteca que desenvolvi para exemplificar como criar uma biblioteca para Arduino. Ela está disponível no repositório oficial do Arduino e se chama EasyPCF8574.
Por enquanto estou utilizando a biblioteca TFT_eSPI para o display. Ela é bem simples de utilizar e com a interface um pouco mais elaborada ainda sobram recursos para um bom programa de backend.
Em seguida a esse artigo, estarei editando um vídeo de apresentação bem curtinho, só pra dizer o que escrevi, no intuito de trazer o pessoal do Youtube pra cá para pegar o código, mas também vocês leitores para lá, pra mostrar essa telinha em ação.
A configuração dos pinos do display deve ser feita no arquivo User_Setup.h da biblioteca TFT_eSPI. É só entrar no diretório da biblioteca e editar esse arquivo, então vá até a seção ESP32 e adicione essas linhas:
#define TOUCH_CS 33
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 12
#define TFT_DC 2
#define TFT_RST 4
#define TFT_RST -1
Se for usar a placa AFSmartControl com a mesma disposição de tela que utilizei no ColorMixer e nesse artigo, basta utilizar o código que disponho a seguir, que já contém a devida calibração. De outro modo, siga o tutorial de calibração do artigo dedicado ao display ILI9341.
Além da biblioteca TFT_eSPI, instale também a biblioteca EasyPCF8574, utilizada para controle.
O código é curtinho, parti de um exemplo de botões, mas não tem quase vestígio do sketch original porque achei o exemplo horrível e não valoriza nada a biblioteca. Enfim, com todas as implementações, o código ficou assim:
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <EasyPCF8574.h>
#include <WiFi.h>
#define SSID "SuhankoFamily"
#define PASSWD "fsjmr112"
#define KEY_X 160 // Centre of key
#define KEY_Y 50
#define KEY_W 320 // Width and height
#define KEY_H 22
#define KEY_SPACING_X 0 // X and Y gap
#define KEY_SPACING_Y 1
#define KEY_TEXTSIZE 1 // Font size multiplier
#define BUTTON_X_DELTA 22
#define NUM_KEYS 4
#define BTN_START_POS_X 36 //posição inicial do botão. O incremento é feito a partir dos valores base
#define BTN_START_POS_Y 70 //posição Y do botão
#define BTN_SIZE_X 56 //tamanho do botão em X
#define BTN_START_Y 56 //tamanho do botão em Y
#define BTN_OUTLINE 4 //outline
#define BTN_SPACER 32 //espaçador
int str_positions_x[4] = {10,90,10,90}; //strings das inputs - posição X
int str_positions_y[4] = {166,166,186,186}; //strings das inputs - posição Y
uint8_t relays[4] = {7,6,5,4}; //bits do PCF relacionados aos relés (ordenando aqui)
uint8_t inputs[4] = {3,2,1,0}; //bits do PCF relacionado aos inputs (ordenando também)
uint8_t inputs_state[4] = {0,0,0,0}; //memória de estado para feedback no display
unsigned long timeout_to_click = millis(); //histerese para o clique do botão
unsigned long progress_bar_time = millis(); //atualização continua baseada no intervalor de 10s
String last_relay = " "; //memória do último acionamento de relé pelo display
EasyPCF8574 pcf(0x27,0xFF); //inicializa o barramento I2C com PCF no endereço 0x27 e todos os pinos em HIGH
TFT_eSPI tft = TFT_eSPI(); //objeto do display
TFT_eSPI_Button key[NUM_KEYS]; //4 botões para os 4 relés
void drawBoxes(); //desenha as caixas separadoras
void WiFiInfo(); //informação de conexão
void drawButtons(); //desenha os botões
void drawTitles(); //desenha os títulos das caixas separadoras
void inputStatus(uint8_t bit_to_check); //checa o estado dos pinos de entrada do PCF
void setup()
{
//calibração do display:
//https://www.manualdomaker.com/article/display-ili9341-touch/
uint16_t calData[5] = {331, 3490, 384, 3477, 6};
Serial.begin(9600); //inicia serial
tft.fillScreen(TFT_BLACK); //limpa tela
tft.init(); //inicia o display
//conexão WiFi STA
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWD);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(F("."));
}
//inicialização do barramento I2C
if (!pcf.startI2C(21,22)){
Serial.println("Not started. Check pin and address.");
while (true);
}
//Rotação do display, de 0 à 3 (de 90 em 90 graus)
tft.setRotation(0);
tft.setTouch(calData); //configura o touch com os parâmetros de calibragem
// Clear screen
tft.fillScreen(TFT_BLACK);
//fonte utilizada no programa
tft.setFreeFont(&FreeMono9pt7b);
//inicia as funções anteriormente descritas
drawButtons();
drawBoxes();
drawTitles();
}
void loop(){
WiFiInfo(); //atualiza a informação do SSID de modo temporizado
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
// Get current touch state and coordinates
boolean pressed = tft.getTouch(&t_x, &t_y);
// Adjust press state of each key appropriately
for (uint8_t b = 0; b < 4; b++)
{
if (pressed && key[b].contains(t_x, t_y))
key[b].press(true); // tell the button it is pressed
else
key[b].press(false); // tell the button it is NOT pressed
}
// Check if any key has changed state
for (uint8_t b = 0; b < 4; b++){
inputStatus(b);
// // If button was just pressed, redraw inverted button
if (key[b].justPressed())
{
Serial.println("Button pressed");
if ((millis()-timeout_to_click) > 1000){
pcf.setInvertBit(relays[b]);
timeout_to_click = millis();
if (pcf.getBitValue(relays[b]) <1){
key[b].drawButton(true, "ON");
last_relay = String(b);
}
else{
key[b].drawButton(false, "OFF");
last_relay = String(b);
}
}
}
// If button was just released, redraw normal color button
if (key[b].justReleased())
{
Serial.println("Button released");
}
}
}
void inputStatus(uint8_t bit_to_check){
String act = "None...";
uint8_t bit_value = pcf.getBitValue(inputs[bit_to_check]);
String fromRemote = bit_value < 1 ? "ON" : "OFF";
if (bit_value < 1){ //tem que ser pulsador
act = "R" + String(bit_to_check) + ":" + fromRemote;
pcf.setInvertBit(inputs[bit_to_check]+4);
}
else{
act = "R" + String(bit_to_check) + ":" + fromRemote;
//pcf.setInvertBit(inputs[bit_to_check]+4);
}
if (inputs_state[bit_to_check] != bit_value){
inputs_state[bit_to_check] = bit_value;
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString(act,str_positions_x[bit_to_check],str_positions_y[bit_to_check]);
}
if ((millis()-progress_bar_time) > 9000){
String wifi_ip = WiFi.localIP().toString();
tft.drawCentreString(last_relay,335/2+15,255,2);
tft.drawCentreString(wifi_ip,240/2,298,2);
}
}
void WiFiInfo(){
if ((millis()-progress_bar_time) >10000){
tft.setTextColor(TFT_WHITE, TFT_BLACK);
if (WiFi.status() == WL_CONNECTED){
tft.drawCentreString(SSID,120/2-(strlen(SSID)/2)+5,255,2);
}
else{
tft.drawCentreString("Offline",120/2-(strlen(SSID)/2)+5,230,4);
}
}
}
void drawBoxes(){
tft.drawRoundRect(2,2,238,120,10,TFT_WHITE); // Acionar reles
tft.drawRoundRect(2,128,238,90,10,TFT_WHITE); //acionador remoto
tft.drawRoundRect(2,225,120,60,10,TFT_WHITE); //wifi
tft.drawRoundRect(128,225,110,60,10,TFT_WHITE); //ultimo
tft.drawRoundRect(2,294,236,26,10,TFT_WHITE); //ip
}
void drawTitles(){
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawCentreString("Acionar Reles",240/2-(strlen("Acionar Reles")/2),5,4);
tft.drawCentreString("Acionador Remoto",255/2-(strlen("Acionador Remoto")/2),132,4);
tft.drawCentreString("WiFi",120/2-(strlen("WiFi")/2)+3,230,4);
tft.drawCentreString("Atuador",335/2+15,230,4);
}
void drawButtons(){
uint16_t cor = tft.color565(127,127,0);
uint16_t cor2 = tft.color565(127,0,127);
uint16_t cor3 = tft.color565(0,127,127);
uint16_t cor4 = tft.color565(240,100,0);
//key[0].initButton(&tft,x,y,w,h,outline,fill,textcolor,label,textsize);
//posicao x e y a partir do centro do botao, tamanho x e tamanho y, outline, cor, cor da fonte, texto, tamanho
key[0].initButton(&tft, BTN_START_POS_X, BTN_START_POS_Y, BTN_SIZE_X, BTN_SIZE_X, BTN_OUTLINE, cor, TFT_WHITE, "b0", 1);
key[1].initButton(&tft, BTN_SIZE_X+BTN_SPACER+BTN_OUTLINE, BTN_START_POS_Y, BTN_SIZE_X, BTN_SIZE_X, BTN_OUTLINE, cor2, TFT_WHITE, "b1", 1);
key[2].initButton(&tft, BTN_SIZE_X+BTN_SIZE_X+BTN_SPACER+BTN_OUTLINE, BTN_START_POS_Y, BTN_SIZE_X, BTN_SIZE_X, BTN_OUTLINE, cor3, TFT_WHITE, "b2", 1);
key[3].initButton(&tft, BTN_SIZE_X+BTN_SIZE_X+BTN_SIZE_X+BTN_SPACER+BTN_OUTLINE, BTN_START_POS_Y, BTN_SIZE_X, BTN_SIZE_X, BTN_OUTLINE, cor4, TFT_WHITE, "b3", 1);
for (uint8_t i=0;i<4;i++){
key[i].drawButton(false, "OFF");
}
}
Quanto sai um módulo de 4 relés+frete, um ESP32+frete, um módulo RS485+frete, além de 2 botões, wiring, solda e tempo? Bem, com certeza custa bem mais do que essa placa "plug and play" da AFEletronica. Confira a AFSmartControl no site do fabricante.
O vídeo do display ILI9341 com TFT_eSPI estará disponível em breve no canal (lembrando que é só uma apresentação da placa), mas peço encarecidamente que deixem um like para ajudar a promover nosso humilde canal. O like no vídeo tem muita importância, então, mesmo que o artigo já lhe tenha sido o suficiente, passe no canal para dar uns cliques, pode ser? Se não é inscrito e puder também contribuir dessa forma, seja bem-vindo ao canal Dobitaobytebrasil no Youtube.
Revisão: Ricardo Amaral de Andrade
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.