Dispositivos de Saída


Tarefa em grupo

Tarefa individual

Resultados de aprendizagem:

Você:


Ferramentas usadas


Software usado


Arquivos

  1. Arquivos do Eagle: arquivos
  2. Arquivos de G-code: arquivos
  3. Arquivos de código: arquivos
  4. Datasheets: arquivos

Tarefa em grupo

Veja a página da tarefa em grupo.


Introdução

Comecei esta tarefa com a intenção de melhorar a automação da irrigação da fazenda. A gente já tem um ESP8266 controlando uma bomba e 4 relés e monitorando a corrente da bomba. O problema é que o ESP8266, com o programa dele, não responde bem, e isso faz com que configurar os horários leve muito tempo. Isso acontece por causa de uma limitação no número de pinos ADC. Quem me explicou foi o Shakeel, um voluntário que a gente teve na fazenda: o ESP8266 usa o único pino ADC que tem para monitorar a conexão wifi, então ele criou um programa que reduz as amostras feitas pelo amperímetro para poder dividir o pino com o wifi. Bom, isso funciona, mas deixa a conexão wifi instável, então meu desafio vai ser tentar entender o ESP32 para conseguir portar o programa dele e, ao mesmo tempo, completar a tarefa. Vamos tentar!

A outra coisa que eu queria destacar é que vou focar mais no código, porque já mostrei o processo de fabricação de placas nas outras semanas. Além disso, uma grande mudança na forma como faço a tarefa é que vou documentar enquanto aprendo e faço as coisas, então a tarefa vai parecer mais um diário do que um tutorial.


Objetivos

Meu objetivo inicial vai ser entender melhor o ESP32; depois, como segundo objetivo, fazer ele substituir o controle de irrigação atual; o terceiro objetivo vai ser aplicar tudo isso no meu projeto final da chocadeira.


Pinagem

Pinagem do ESP32


Plano do código

  1. verificar a hora
  2. ligar a bomba se estiver dentro do horário
  3. ler o amperímetro procurando subcorrente e sobrecorrente; se detectar, para a operação da bomba

Pesquisa do código

Comecei olhando o site techtutorialsx.com.

Como a página explica, o código para ligar um relé é bem parecido com outros códigos de Arduino que já vi, então vamos ver.

Vou usar int pumprelayPin1 = 22; para definir a variável pumprelayPin1 como o pino 22, e ela vai guardar o valor como um inteiro.

pinMode(pumprelayPin1, OUTPUT); define o modo do pino pumprelayPin1 como saída, ou seja, ele vai ser ativo, ao contrário de uma entrada, que fica monitorando um sinal de forma passiva.

digitalWrite(pumprelayPin1, LOW); vai colocar o pino no estado desligado com o LOW.

delay(4000); vai mandar o programa esperar 4 segundos, ou 4000 milissegundos.

É assim que meu código está até agora:

int pumprelayPin1 = 22;

void setup() {
  
  pinMode(pumprelayPin1, OUTPUT);
  digitalWrite(pumprelayPin1, LOW);

}

void loop() {

  digitalWrite(pumprelayPin1, HIGH);
  delay(4000);
  digitalWrite(pumprelayPin1, LOW);
  delay(4000);

}

Até aqui, este código vai iniciar e depois ligar e desligar o relé com 4 segundos entre cada operação.

Agora, para a segunda parte, quero pegar a hora de um relógio de tempo real (RTC) para ligar a bomba em certos horários. Então, primeiro preciso incluir a biblioteca do relógio RTC. Estou usando um chip de relógio RTC DS1302, então esta biblioteca deve resolver com este código #include <virtuabotixRTC.h>, de acordo com a documentação da biblioteca aqui.

Segundo, a gente precisa declarar os pinos do relógio RTC com este código virtuabotixRTC myRTC(5, 18, 19); e RtcDS1302<ThreeWire> Rtc(myWire);. Isso quer dizer que, quando o ESP32 se comunicar com o chip do relógio de tempo real, ele vai usar o pino 5 para CLK, o 18 para DAT e o 19 para RST.

Atenção: RtcDS1302<ThreeWire> Rtc(myWire); é de outra biblioteca (a Rtc do Makuna, RtcDS1302.h) e myWire nunca é definido, então essa linha não compila do jeito que está. Com a biblioteca virtuabotixRTC usada aqui, basta virtuabotixRTC myRTC(5, 18, 19);.

Agora, para mostrar a hora do relógio de tempo real, coloco isto na área void setup() {} ou na área void loop() {}. A primeira vai imprimir uma vez só; a segunda vai imprimir enquanto eu deixar rodando. Claro que a gente precisa colocar um delay de pelo menos um minuto com delay(60000);. A unidade da variável é milissegundo, então 1000 quer dizer 1 segundo e 60000 quer dizer 60 segundos.

    Serial.begin(115200);

 myRTC.updateTime();
    Serial.println();

Se o RTC nunca foi usado antes, você pode acertar a hora rodando uma vez o seguinte código: myRTC.setDS1302Time(00, 28, 16, 7, 23, 5, 2020);, sendo os primeiros números os segundos, depois minutos, horas (modo 24h), dia da semana, dia do mês, mês e ano. (Corrigido depois: o dia da semana conta a partir de 1 = domingo, então sábado 23/05/2020 é 7 e domingo 24/05/2020 é 1; o código tinha 6 nos dois.)

É assim que o código está ficando:

#include <virtuabotixRTC.h>

virtuabotixRTC myRTC(5, 18, 19);// (CLK,DAT,RST)

int pumprelayPin1 = 22;

void setup() {

    Serial.begin(115200);
    pinMode(pumprelayPin1, OUTPUT);
}
void loop() {

    myRTC.updateTime();
  
    Serial.print(myRTC.hours);
    Serial.print(":");
    Serial.print(myRTC.minutes);
    delay(58000);
  
    digitalWrite(pumprelayPin1, HIGH);
    delay(1000);
    digitalWrite(pumprelayPin1, LOW);
    delay(1000);

}

Até aqui não tem nenhum teste lógico: o código mostra a hora a cada minuto e liga e desliga o relé. Então, para adicionar um teste lógico, a gente precisa do comando if. Ele verifica se alguma coisa é verdadeira e aí executa o que vem em seguida no programa.

Tirado da referência do Arduino:

if (condition) {
    //statement(s)
}

Então, para verificar a hora e ligar meu relé, vou tentar algo assim: if ((myRTC.hours) == 15 && (myRTC.minutes) == 0) {digitalWrite(pumprelayPin1, HIGH);}

Para desligar, o código vai ser assim: if ((myRTC.hours) >= 15 && (myRTC.minutes) >= 1) {digitalWrite(pumprelayPin1, LOW);}

Agora meu código está assim:

//libraries
#include <virtuabotixRTC.h>

//Settings
virtuabotixRTC myRTC(5, 18, 19);// (CLK,DAT,RST)
int pumprelayPin1 = 22;


//run once
void setup() {

   Serial.begin(115200);
   
myRTC.setDS1302Time(50, 15, 16, 1, 24, 5, 2020); // sets seconds, minutes, hours (24h mode), day of the week, day, month, year) comment after first compile
  
  pinMode(pumprelayPin1, OUTPUT);
  
}

//run in loop
void loop() {
  myRTC.updateTime();//updates time
  Serial.print("Current Time: ");
  Serial.print(myRTC.hours);
  Serial.print(":");
  Serial.print(myRTC.minutes);
  Serial.print(":");
  Serial.print(myRTC.seconds);
  Serial.println();
  delay (1000);
//condition (logic test)
if ((myRTC.minutes) == 16) digitalWrite(pumprelayPin1, HIGH);  
if ((myRTC.minutes) >= 17) digitalWrite(pumprelayPin1, LOW);

}

Veja como ele roda na placa de desenvolvimento ESP32:

Dá para ver em resolução maior no YouTube


Design da placa

Para esta placa vou precisar de pelo menos 4 pinos digitais, e de um pino analógico se eu quiser medir a corrente da bomba no futuro. Então acho que o ATtiny44 vai dar conta. Vou deixar o ESP32 para a semana de Networking ;-). Além disso, meus componentes SMD de ESP32 ainda não chegaram; acho que é por causa da quebra das cadeias de fornecimento com a COVID-19. Por isso fiz os experimentos com a placa de desenvolvimento ESP32 que eu tinha à mão.

Pinagem do ATtiny44

Pinagem do ATtiny44

Com isso em mãos, vou modificar a placa tiny45 que fiz na semana de Input Devices, adicionando mais um header para programar e monitorar a serial com mais conforto, além de todos os pinos, para deixar esta placa o mais modular possível.

Não vou detalhar o design no Eagle nem a fresagem, porque já fiz isso na semana de Input Devices. Em vez disso, vou mostrar só os comandos que talvez eu não tenha usado, como o replace, e depois algumas hero shots e testes.

Então vamos começar o redesign!

  1. Começo abrindo o arquivo antigo do Eagle aqui.
  2. Tentei o comando replace, mas não funcionou para trocar o ATtiny45 pelo ATtiny44; acho que eles são diferentes demais. Então vou ter que adicionar o componente novo, refazer as conexões com net, depois name, e depois rotear tudo de novo na placa. Vamos ver.

Estes são o esquemático e o layout da placa:

Esquemático da Tiny44 Esquemático

Layout da placa Tiny44Layout da placa

Depois rodo a ULP pcb-gcode, do jeito que expliquei em Input Devices.

Visualização do G-code de isolamentoVisualização do G-code de isolamento

Depois uso o programa Autoleveller, também explicado em Input Devices, e consigo um G-code ajustado às imperfeições da placa virgem.

Resultado do AutolevellerResultado do Autoleveller

Fresando a placa

A placa fresada

Placa fresadaPlaca fresada

A placa ATtiny44 com os componentes soldados fica assim.

Placa ATtiny44 montadaPlaca montada

Agora que a placa está pronta, mudei o código para rodar no ATtiny44. Uma coisa que vale destacar é que o ATtiny44 precisa de uma biblioteca de serial por software, que chamei com este código #include <SoftwareSerial.h>. Mais duas coisas para a serial funcionar: a biblioteca precisa saber quais pinos vão ser o RX e o TX, SoftwareSerial Monitor(1, 0);; em void setup() {} coloquei a inicialização do monitor serial com Monitor.begin(115200); em vez do habitual Serial.begin(115200);; e, por fim, em void loop() {}, toda vez que eu queria que a serial imprimisse alguma coisa, precisava usar o código Monitor.print(); em vez do habitual Serial.print();.

No fim, meu código de teste ficou assim:

//libraries
#include <virtuabotixRTC.h>
#include <SoftwareSerial.h>

//Settings
virtuabotixRTC myRTC(3, 8, 7);// (CLK,DAT,RST)
int pumprelayPin1 = 2;
SoftwareSerial Monitor(1, 0);

//run once
void setup() {

   Monitor.begin(115200);
   
myRTC.setDS1302Time(50, 15, 16, 1, 24, 5, 2020); // sets seconds, minutes, hours (24h mode), day of the week, day, month, year) comment after first compile
  
  pinMode(pumprelayPin1, OUTPUT);
  
}

//run in loop
void loop() {
  myRTC.updateTime();//updates time
  Monitor.print("Current Time: ");
  Monitor.print(myRTC.hours);
  Monitor.print(":");
  Monitor.print(myRTC.minutes);
  Monitor.print(":");
  Monitor.print(myRTC.seconds);
  Monitor.println();
  delay (1000);
//condition (logic test)
if ((myRTC.minutes) == 16) digitalWrite(pumprelayPin1, HIGH);  
if ((myRTC.minutes) >= 17) digitalWrite(pumprelayPin1, LOW);

}

Atenção: SoftwareSerial a 115200 baud no ATtiny44 rodando com o oscilador interno de 8 MHz é pouco confiável (o erro de tempo embaralha os caracteres). Use Monitor.begin(9600); e coloque o monitor serial em 9600, que é a velocidade segura.

Agora vamos programar! Para outro método sem a Arduino IDE, veja Embedded Programming.

Programador USBaspUSBasp

Programando uma placa ATtiny44 com Arduino usando o USBasp.

Programador FabISPFabISP

Programar uma placa ATtiny44 com Arduino usando um FabTinyISP ou USBtinyISP que eu fiz foi tranquilo. O único inconveniente é ter que alimentar a placa alvo.

Comece abrindo a Arduino IDE, depois em Tools escolha a placa, no meu caso ATtiny24/44/84. Em seguida, em Processor, escolhi ATtiny44.

Escolha da placa na Arduino IDE

Depois escolha o clock. Como não estou usando cristal externo, escolhi "Internal 8MHz".

Escolha do clock na Arduino IDE

Depois vá em Programmer: "USBasp", ou "USBtiny" para o FabISP.

Escolha do programador na Arduino IDE

No vídeo abaixo, mostro o processo de programação com o FabISP.

Para ver o vídeo em resolução total, acesse o YouTube

Neste vídeo, mostro o processo de programação com o USBasp.

Para ver o vídeo em resolução total, acesse o YouTube

Dá para ver o ATtiny44 controlando um relé para ligar um compressor num horário definido no programa.

Para ver o vídeo em resolução total, acesse o YouTube

Hero shot

Hero shot da placaHero shot


Notas de rodapé

Ver no futuro como usar o millis.

← (15 abr) Aplicações e Implicações · todas as semanas · Moldagem e Fundição (29 abr) →