4 Relay Module

Um relé é um interruptor eletromecânico composto por uma bobina e um conjunto de contatos. Ao ser energizado, uma corrente percorre a bobina fazendo com que os seus contatos abram ou fechem.

O módulo apresentado aqui é um dispositivo com  quatro canais independentes e é ativado com nível lógico baixo. Uma grande vantagem deste módulo é que cada canal utiliza um acoplador ótico, garantindo que não exista nenhum contato elétrico entre o pino da placa Arduino com o circuito de acionamento do relé.

 

Quando o pino de entrada do canal (IN1 a IN4)  vai ao nível lógico baixo (LOW) , o acoplador ótico (U1 a U4) conduz e aciona o transistor (Q1 a Q4) que por sua vez energiza a bobina do relé (K1 a K4) fechando os contatos 2 e 3. Parece confuso com muitos elementos 😀 , porém veja o esquema a seguir.

 

Teste do módulo

Monte o circuito abaixo observando os pinos de ligação.

 

pino módulo Relé pino Arduino
IN1 D7
IN2 D8
IN3 D9
IN4 D10
VCC 5V
GND GND

 

 

 

Aqui vamos criar dois arquivos: o rele.ino que é o código principal e o Rele.h (atente para o primeiro caractere maiúsculo) com a declaração das macros (#define) e a função de tratamento do módulo. A separação, na prática, não é necessária. Estamos sugerindo a separação para que o código seja o mais reutilizável possível. Deste modo você poderá utilizar um mesmo módulo em diversos projetos e ser poupado de escrever tudo novamente 😎 .

Obs.:  toda diretiva de pré-processamento começa com o símbolo #. As diretivas não são comandos da linguagem C ou Arduino. São instruções que antes da compilação efetiva, são tratadas (processadas) no código fonte (sketch) e posteriormente entregues ao compilador.  Ah, a sintaxe também difere dos comandos/declarações C/Arduino. Não temos o ponto e virgula (;) ao termino de uma diretiva. Por convenção, o nome das constantes da diretiva #define são escritas em maiúsculas.

Copie e cole no IDE do Arduino e salve como rele.ino

#include "Rele.h"

void setup() {
  byte arrPinos[] = {RELECH1, RELECH2, RELECH3, RELECH4};

  for ( byte indice = 0; indice < sizeof(arrPinos); indice++ ) {
    pinMode( arrPinos[indice], OUTPUT );
   acionaRele( arrPinos[indice], RELEOFF );
  }

  for ( byte indice = 0; indice < sizeof(arrPinos); indice++ ) {
    acionaRele( arrPinos[indice], RELEON );
    delay(1000);
    acionaRele( arrPinos[indice], RELEOFF );
    delay(1000);
  }
}

void loop() {
}

 

Copie e cole no IDE do Arduino e salve como Rele.h

#define RELEON LOW
#define RELEOFF (! RELEON)
#define RELECH1 7
#define RELECH2 8
#define RELECH3 9
#define RELECH4 10

void acionaRele( byte canal, boolean estado ) {
  digitalWrite( canal, estado );
}

 

LCD – Um guia (quase) completo!

Os LCDs (Liquid-Crystal Display) são módulos simples de serem conectados aos microcontroladores, sendo assim  muito úteis em projetos que necessitam de uma comunicação com o usuário. Os LCDs mais comuns possuem 16 colunas por 2 linhas, normalmente indicados por 16×2 ou 1602 e podem possuir 14 ou 16 pinos, sem e com backlight  (luz de fundo) respectivamente e são equipados com um controlador compatível com o chip HD44780 da Hitachi.  E é exatamente este modelo que vamos ver a seguir.

LCD 2 linhas por 16 colunas
LCD de 2 linhas por 16 colunas

 

Disposição das Linhas e Colunas

Tomando como exemplo um display de 16×2, a disposição dos caracteres estão numa matriz com as colunas numeradas de 0 a 15 e linhas numeradas 0 e 1.

LCD 16x2 - linhas e colunas

Pinos

A numeração e descrição dos pinos:

Pino   Descrição
VSS GND (terra)
VDD +5V
VO Ajuste do contraste – utilizar com um resistor fixo ou variável (potenciômetro ou trimpot)
RS Register Select – sinaliza a instrução ou caractere que está sendo escrito (linha de controle)
R/W Read/Write – sinaliza ao microcontrolador do LCD se a operação é de escrita ou gravação (linha de controle)
Enable Ativação do LCD – se nível baixo, ignora RS e R/W (linha de controle)
D0 Linha de dado
D1 Linha de dado
D2 Linha de dado
10 D3 Linha de dado
11  D4 Linha de dado
12 D5 Linha de dado
13  D6 Linha de dado
14  D7 Linha de dado
15  LED + backlight (anodo) +5V
16  LED – backlight (catodo) GND

Nos LCDs sem backlight não temos os pinos 15 e 16.

 

Módulo I2C para LCD

Uma outra opção, bem mais interessante, é a utilizar um módulo I2C acoplado ao display LCD, como o da figura a seguir.

Este módulo conta com um trimpot para ajuste do contraste e um jumper para ligar/desligar o LED de luz de fundo (backlight). Porém, podemos ligar e desligar este LED por software.

I2C

I2C (IIC – Inter Integrated Circuit) é um barramento de comunicação desenvolvido pela Philips, hoje NXP Semiconductors, para permitir troca de dados entre os componentes que residem na mesma placa de circuito impresso.  A vantagem de usar este tipo de barramento é que precisamos de apenas dois pinos para comunicação, além do pino de alimentação (5V) e o pino terra (GND).

Este módulo em específico possui o chip PCF8574.

Vamos usar  a  biblioteca Wire (nativa no software Arduino) para facilitar o desenvolvimento com o protocolo I2C. Os dois fios de comunicação são conhecidos por SDA (Serial Data Line) e SCL (Serial Clock Line).

Nas placas Arduino Uno e compatíveis, o

SDA é o pino analógico  4 (A4) e o

SCL é o pino analógico 5 (A5).

No Arduino Mega o SDA é o pino digital 20 e o SCL é o pino digital 21.

Os módulos I2C possuem um endereço único para cada módulo. A seleção do endereço é feita pela combinação dos pads A0, A1 e A2.  No caso deste módulo, o endereço padrão é 0x27 (os três pads isolados).  Para configurar outro endereço, conforme a tabela abaixo, solde (coloque em curto) os pads desejados. Por exemplo: pad sem solda é igual a 0 (zero), pad em curto é igual a 1.

A0 A1 A2 endereço
0 0 0 0x27
1 0 0 0x26
0 1 0 0x25
1 1 0 0x24
0 0 1 0x23
1 0 1 0x22
0 1 1 0x21
1 1 1 0x20

Quer dizer que poderíamos ligar até oito módulos LCD no mesmo Arduino, combinando os pads? Sim, mas lembre-se que existem outros módulos I2C no mercado, como módulos de relógio (RTC) e cada um deverá ter o seu próprio endereço.

 

Exemplo prático – monitor de temperatura com o LM35.

Vamos mostrar dois exemplos: sem e com o módulo I2C.

Providencie:

  • 1 sensor de temperatura LM35
  • 1 potenciômetro ou trimpot de 1KΩ (caso monte com a opção sem módulo I2C)
  • 1 módulo LCD 16 x 2 *
  • 1 protoboard
  • e muitos (muitos) fios jumpers.

* é muito mais econômico, caso você não possua um módulo LCD, comprá-lo com o módulo I2C já acoplado (soldado). Se você já possui um ou mais LCDs sem este módulo talvez seja vantajoso comprar o módulo I2C separado, mas terá que soldá-lo ao módulo LCD caso queira uma conexão definitiva entre os módulos.

 Conectando o LCD no Arduino – sem módulo I2C

A biblioteca LiquidCrystal (nativa no software Arduino) utiliza apenas as linhas de dados D4 a D7, ou seja, apenas 4 bits. Para controle/ajuste do contraste utilizamos um trimpot ou um potenciômetro de 1KΩ.

O sketch deverá incluir a biblioteca LiquiCrystal através da diretiva #include e para facilitar a manutenção, os pinos associados ao LCD estarão definidos pela diretiva #define.

Obs.:  toda diretiva de pré-processamento começa com o símbolo #. As diretivas não são comandos da linguagem C ou Arduino. São instruções que antes da compilação efetiva, são tratadas (processadas) no código fonte (sketch) e posteriormente entregues ao compilador.  Ah, a sintaxe também difere dos comandos/declarações C/Arduino. Não temos o ponto e virgula (;) ao termino de uma diretiva. Por convenção, o nome das constantes da diretiva #define são escritas em maiúsculas.

A principal linha do sketch (mais adiante) é

LiquidCrystal  lcd( RS, RW, EN, D4, D5, D6, D7 );

onde lcd é a representação da classe LiquidCrystal  (pode ser qualquer nome, mas lcd nos parece mais apropriado 😉  ).  Também indicamos os pinos de controle e os pinos de dados.

Outro destaque é  a função sprintf() da linguagem C (consulte a apostila do mini curso Linguagem C), que formata dados e copia-os para um array de caracteres. Isto facilita muito o trabalho, porém da forma como esta função está implementada no Arduino, não conseguimos manipular dados do tipo float, por isso temperatura foi definido como int.

Métodos usados no exemplo:

begin( num_colunas, num_ linhas )

Inicializa o LCD e especifica o seu tamanho (linhas e colunas). Note que a ordem dos parâmetros são número de colunas por número de linhas.

clear()

“Limpa” o LCD e posiciona o cursor nas coordenadas 0,0.

setCursor( coluna, linha )

Posiciona o cursor nas coordenadas coluna e linha.

print( dados, [base] )

Imprime dados no LCD a partir do posicionamento do cursor. O parâmetro base é opcional e só se aplica quando dados for numérico (consulte a apostila do curso Linguagem Arduino), tópico Serial.print).

print() também retorna o número de bytes impressos no LCD.

Acompanhe o diagrama abaixo para montagem. São muitos fios jumpers e nossa sugestão é começar pelo módulo LCD.

Olhando o LCD de frente, da esquerda para direita, temos:

pino LCD pino Arduino
VSS GND
VDD 5V
VO pino central do potenciômetro
RS 6
RW 7
E 8
D0 GND
D1 GND
D2 GND
D3 GND
D4 2
D5 3
D6 4
D7 5
A (LED backlight anodo) 5V
K (LED backlight catodo) GND

 

LM35 – oriente-se pela figura a seguir.

ORIGINAL] LM35 LM35DZ TEMPERATURE SENSOR | Shopee Malaysia

 

pino LM35 pino Arduino
VS 5V
Vout A0 (pino analógico zero)
GND GND

Exemplo

#include <LiquidCrystal.h>
#define RS 6
#define RW 7
#define EN 8
#define D4 2
#define D5 3
#define D6 4
#define D7 5
#define TEMP A0

float leitura;
int   temperatura;
char  msg[255];

LiquidCrystal lcd(RS, RW, EN, D4, D5, D6, D7);

void setup() {
  lcd.begin(2, 16);
  lcd.setCursor(2, 0);
  lcd.print("* EADuino *");
  delay(3000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperatura");
}

void loop() {
  leitura = analogRead( TEMP );
  temperatura = (5 * leitura * 100) / 1024;
  sprintf( msg, "%2d C", temperatura );
  lcd.setCursor(0, 1);
  lcd.print(msg);
  delay(5000);
}

 

Conectando o LCD no Arduino – com módulo I2C

Primeiro, verifique se você tem instalado a biblioteca LiquidCrystal_I2C. Vá até o gerenciador de bibliotecas (atalho CTRL-SHIFT-i), digite liquidcrystal. Optamos por instalar esta mostrada na figura.  Caso não encontre, uma boa fonte é o site  Arduino Library List (link no final deste artigo), porém para este módulo faça o download aqui https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c

 

 

Oriente-se pela imagem abaixo.

 

pino I2C pino Arduino
GND GND
VCC 5V
SDA A4
SCL A5

 

Note como o circuito fica muito (mas muito) mais simples. Além da economia de pinos Arduino.

 

 

No sketch a seguir instanciamos a classe

LiquidCrystal_I2C  lcd( 0x27, 16, 2 ); 

e informamos o endereço do módulo,  quantidade de colunas e linhas. Na função setup() iniciamos o módulo e na função loop() mantemos o backlight aceso por 10 segundos e em seguida desligamos o backlight por 20 segundos.

Métodos usados no exemplo:

init( )

Inicializa o LCD.

clear( ) – idêntico ao exemplo anterior

setCursor( ) – idêntico ao exemplo anterior

print( ) – idêntico ao exemplo anterior

noBacklight( )

desliga luz de fundo

backlight( )

liga luz de fundo

setBacklight( HIGH | LOW )

liga/desliga luz de fundo

Exemplo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define TEMP A0

float leitura;
int temperatura;
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();
}

void loop() {
  leitura = analogRead( TEMP );
  temperatura = (5 * leitura * 100) / 1024;
  lcd.clear();
  lcd.backlight(); // ou setBacklight( HIGH );
  lcd.setCursor(0, 0);
  lcd.print("Temperatura");
  lcd.setCursor(10, 1);
  lcd.print(temperatura);
  lcd.print("C");
  delay(10000);
  lcd.noBacklight(); // ou setBacklight( LOW );
  delay(20000);
}

 

Criando novos caracteres (custom chars)

Com o método createChar( )  é possível criar e exibir caracteres personalizados no LCD. Isso é especialmente útil se você deseja exibir um caractere que não faz parte do conjunto de caracteres ASCII padrão.

Em módulos LCDs baseados no controlador HD44780 temos dois tipos de memórias: CGROM e CGRAM (memórias do gerador de caracteres).

  • O CGROM gera todos os padrões de caracteres de 5 x 8 pontos.
  • O CGRAM pode gerar até 8 padrões de caracteres definidos pelo usuário (personalizados).

Como sugestão utilize uma folha de papel quadriculado, separe os quadrados em grupos de 8 por 5 e preencha os quadrados que deseja mostrar ou, melhor ainda, acesse este site https://maxpromer.github.io/LCD-Character-Creator/.  Você pode escolher se é um LCD com ou sem I2C e ainda gerar os valores em binário ou hexadecimal. Depois é só colar o código  😎  .

Métodos usados no exemplo:

createChar( posiçao, mapa de bits )

armazena na  memória CGRAM, na posição de 0 a 7, o mapa de bits do caractere customizado.

write( posição )

exibe no display o caractere customizado na posição de memória de 0 a 7.

Carregue e execute o sketch a seguir.

 Exemplo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// caracteres personalizados - os vetores abaixo foram populados com numeros binarios
byte Heart[] = {
  B00000,
  B01010,
  B11111,
  B11111,
  B01110,
  B00100,
  B00000,
  B00000
};

byte Bell[] = {
  B00100,
  B01110,
  B01110,
  B01110,
  B11111,
  B00000,
  B00100,
  B00000
};

byte Alien[] = {
  B11111,
  B10101,
  B11111,
  B11111,
  B01110,
  B01010,
  B11011,
  B00000
};

byte Check[] = {
  B00000,
  B00001,
  B00011,
  B10110,
  B11100,
  B01000,
  B00000,
  B00000
};

byte Speaker[] = {
  B00001,
  B00011,
  B01111,
  B01111,
  B01111,
  B00011,
  B00001,
  B00000
};

byte Sound[] = {
  B00001,
  B00011,
  B00101,
  B01001,
  B01001,
  B01011,
  B11011,
  B11000
};

byte Skull[] = {
  B00000,
  B01110,
  B10101,
  B11011,
  B01110,
  B01110,
  B00000,
  B00000
};

byte Lock[] = {
  B01110,
  B10001,
  B10001,
  B11111,
  B11011,
  B11011,
  B11111,
  B00000
};

void setup() {
  lcd.init();
  lcd.backlight();

  // cria os novos caracteres
  lcd.createChar(0, Heart);
  lcd.createChar(1, Bell);
  lcd.createChar(2, Alien);
  lcd.createChar(3, Check);
  lcd.createChar(4, Speaker);
  lcd.createChar(5, Sound);
  lcd.createChar(6, Skull);
  lcd.createChar(7, Lock);
  lcd.clear();
}

void loop() {
  byte coluna = 0;
  for ( byte indice = 0; indice <= 7; indice++ ) {
    lcd.setCursor(coluna, 1);
    lcd.write( indice );
    coluna += 2; //incrementa a variavel de dois em dois
  }
}

Um outro exemplo com os vetores populados com números hexadecimais. Preferimos com números binários, pois praticamente você transcreve o que desenhou para o valor binário.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// caracteres personalizados - os vetores abaixo foram populados com numeros hexadecimais
byte sino[]     = {0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4};
byte nota[]     = {0x2, 0x3, 0x2, 0xe, 0x1e, 0xc, 0x0};
byte relogio[]  = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0};
byte coracao[]  = {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0};
byte pato[]     = {0x0, 0xc, 0x1d, 0xf, 0xf, 0x6, 0x0};
byte checklist[]= {0x0, 0x1, 0x3, 0x16, 0x1c, 0x8, 0x0};
byte cruz[]     = {0x0, 0x1b, 0xe, 0x4, 0xe, 0x1b, 0x0};
byte enter[]    = {0x1, 0x1, 0x5, 0x9, 0x1f, 0x8, 0x4};

void setup() {
  lcd.init();
  lcd.backlight();

  // cria os novos caracteres
  lcd.createChar(0, sino);
  lcd.createChar(1, nota);
  lcd.createChar(2, relogio);
  lcd.createChar(3, coracao);
  lcd.createChar(4, pato);
  lcd.createChar(5, checklist);
  lcd.createChar(6, cruz);
  lcd.createChar(7, enter);

  lcd.clear();
}

void loop() {
  byte coluna = 0;
  for ( byte indice = 0; indice <= 7; indice++ ) {
    lcd.setCursor(coluna, 1);
    lcd.write( indice );
    coluna += 2; //incrementa a variavel de dois em dois
  }
}

 

Outros Métodos

home()

posiciona o cursor no topo/esquerda do display – não limpa a tela.

blink()
noBlink()

exibe/esconde cursor em formato de bloco na próxima coluna disponível.

cursor()
noCursor()

exibe/esconde cursor em formato sublinhado (underscore) na próxima coluna disponível.

display()
noDisplay()

liga/desliga o display, mas não apaga o conteúdo em memória.

scrollDisplayLeft()
scrollDisplayRight()

desloca toda a tela do display uma posição a esquerda/direta.

Exemplo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);


void setup() {
  lcd.init();
  lcd.backlight();
}

void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("EADuino");
  lcd.setCursor(0, 1);
  lcd.print("Bem-vindo(a)!");
  delay(5000);

  lcd.clear();
  lcd.print("cursor ");
  lcd.cursor();
  delay(5000);
  lcd.home();
  lcd.print("sem cursor "); 
  lcd.noCursor();
  delay(5000);

  lcd.clear();
  lcd.print("cursor - bloco");
  lcd.blink();
  delay(5000);
  lcd.print("sem cursor    "); 
  lcd.noBlink();
  delay(5000);

  lcd.clear(); 
  lcd.print("EADuino!"); 
  delay(2000);
  lcd.noDisplay();
  delay(2000);
  lcd.display();
  delay(5000);

  lcd.clear();
  int bloco, tamanho, quantidade_blocos, caracteres_restantes;

  tamanho = lcd.print("EADuino - Cursos de Arduino Online!");
  delay(3000);
  quantidade_blocos = tamanho / 16;
  caracteres_restantes = tamanho % 16;

  for (bloco = 1; bloco <= quantidade_blocos - 1; bloco++) {
    for (byte scroll = 0; scroll < 16; scroll++) {
      lcd.scrollDisplayLeft();
      delay(200);
    }
    delay(3000);
  }

  if ( caracteres_restantes > 0 ) {
    for (byte scroll = 0; scroll <= caracteres_restantes; scroll++) {
      lcd.scrollDisplayLeft();
      delay(200);
    }
    delay(3000);
  }
}

Links úteis


 

Módulos RTC – DS1307/DS3231

conteúdo revisto e atualizado – publicado originalmente em 2015

Estes módulos permitem adicionar um relógio em tempo real (RTC – Real Time Clock) aos seus projetos de uma forma bem simples e barata. Mesmo que falte energia ao seu Arduino, o relógio continua a contar pois é alimentado com uma bateria que pode durar muitos e muitos anos!

A maioria dos módulos RTC  são equipados com os circuitos integrados DS1307 e DS3231 ambos da empresa californiana Maxim Integrated e utilizam o barramento de comunicação I2C.

 

DS1307 e DS3231
DS1307 e DS3231

I2C

I2C (IIC – Inter Integrated Circuit) é um barramento de comunicação desenvolvido pela Philips, hoje NXP Semiconductors, para permitir troca de dados entre os componentes que residem na mesma placa de circuito impresso. Este barramento também é conhecido por TWI (Two Wire Interface) implementado pela ATMEL, hoje Microchip Technology.

A vantagem de usar este tipo de barramento é que precisamos de apenas dois pinos para comunicação, além do pino de alimentação (5V) e o pino terra (GND).

Os módulos I2C possuem um endereço único para cada módulo. A seleção do endereço é feita pela combinação dos pads A0, A1 e A2, para o DS3231 .

Mas como saber o endereço do módulo se não tenho a documentação disponível? 🙁

A biblioteca Wire.h (necessária para utilizar o I2C), contém um exemplo que faz uma varredura em módulos I2C acoplados a placa Arduino.  Esta biblioteca é nativa no software Arduino, ou seja, não é preciso instalar.

Na comunicação  I2C temos dois terminais conhecidos por SDA (Serial Data Line) e SCL (Serial Clock Line).

Nas placas Arduino Uno e compatíveis, o

SDA é o pino analógico  4 (A4)

e o

SCL é o pino analógico 5 (A5).

No Arduino Mega o SDA é o pino digital 20 e o SCL é o pino digital 21.

Conectando o módulo DS1307 (Tiny RTC)

Primeiro verifique se você vai usar um módulo com um dos dois chips indicados no começo do artigo. Após, verifique se tem instalado a biblioteca RTClib.h (esta biblioteca serve para os dois modelos).

Vá até o gerenciador de bibliotecas (atalho CTRL-SHIFT-i), digite rtclib. Caso não encontre, acesse o site  Arduino Library List e faça o download em https://www.arduinolibraries.info/libraries/rt-clib

 

Monte o circuito orientando-se pela tabela a seguir:

 

pino Tiny RTC pino Arduino
GND (jumper preto) GND
VCC (jumper vermelho) 5V
SDA (jumper amarelo) A4
SCL (jumper azul) A5

 

 

Agora iremos verificar o endereço do módulo. Carregue o IDE Arduino e acesse:  menu File (Arquivo)  e navegue até Examples (Exemplos), Wire e i2c_scanner. Execute o sketch e veja qual o endereço retornado no monitor serial.

Você deve ter visto esta informação:

Scanning…
I2C device found at address 0x50 !
I2C device found at address 0x68 !
done

Foram exibidos dois endereços. Um é do chip DS1307 (0x68) e o outro da memória EEPROM (0x50). Este sketch é muito útil para identificar outros módulos que usam I2C.

Exemplos

É quase certo que o seu módulo novo está com a data e hora incorretas. Vamos fazer o ajuste e será necessário apenas uma vez, visto que o módulo contém uma bateria para mantê-lo funcionando.

O ajuste será feito utilizando duas macros da linguagem C: __DATE__ e __TIME__, que retornam respectivamente a data e hora do seu sistema operacional. Note que este recurso é válido somente em tempo de compilação do sketch. Não dá para colocar estas macros em um laço de repetição, por exemplo, e exibir valores atualizados. Sempre conterá o valor no momento da compilação.

Aqui temos os métodos:

begin() – retorna false caso não seja detectado um módulo RTC ou o seu endereço é inválido.

adjust() – grava data e hora no seguinte formato ano (AAAA), mês (MM), dia (DD), hora (HH), minuto (MM) e segundo (SS). A classe DateTime formata os valores das macros __DATE__ e __TIME__  corretamente para este método.

now() – retorna data e hora corrente. Novamente usamos a classe DateTime que monta uma estrutura com os seguintes métodos: day(), month(), year(), hour(), minute() e second().

#include <Wire.h>;
#include <RTClib.h>;

RTC_DS1307 rtc;

void setup() {
  Serial.begin(9600);
  delay(1000);

  if (rtc.begin()) {
    rtc.adjust(DateTime((__DATE__), (__TIME__)));

    DateTime now = rtc.now();
    int dia     = now.day();
    int mes     = now.month();
    int ano     = now.year();
    int hora    = now.hour();
    int minuto  = now.minute();
    int segundo = now.second();
    Serial.print(dia);
    Serial.print("/");
    Serial.print(mes);
    Serial.print("/");
    Serial.print(ano);
    Serial.print("\t");
    Serial.print(hora);
    Serial.print(":");
    Serial.print(minuto);
    Serial.print(":");
    Serial.print(segundo);
  }
  else {
    Serial.println("Modulo RTC nao encontrado!");
  }
}

void loop() {

}

No próximo exemplo vamos formatar os dados retornados pelo módulo .

Foram inicializados três vetores: um para armazenar o texto formatado, um contendo os dias da semana e o último contendo os meses do ano.

Os dados foram formatados com a função sprintf() da linguagem C.  Aliás, temos um mini curso de linguagem C que acreditamos seja útil para um melhor entendimento da linguagem Arduino. Não deixe de fazê-lo 😉

Mais um método utilizado:

dayOfTheWeek() – retorna um inteiro (0 a 6) que representa o dia da semana começando em 0 (domingo).

#include <Wire.h>
#include <RTClib.h>


RTC_DS1307 rtc;

void setup() {
  char texto[255];

  char diasDaSemana[7][10] = {
    "Domingo",
    "Segunda",
    "Terca",
    "Quarta",
    "Quinta",
    "Sexta",
    "Sabado"
  };

  char mesDoAno[13][10] = {
    "",
    "Janeiro",
    "Fevereiro",
    "Marco",
    "Abril",
    "Maio",
    "Junho",
    "Julho",
    "Agosto",
    "Setembro",
    "Outubro",
    "Novembro",
    "Dezembro"
  };

  Serial.begin(9600);
  delay(1000);

  if (rtc.begin()) {
    DateTime now = rtc.now();
    int dia     = now.day();
    int mes     = now.month();
    int ano     = now.year();
    int hora    = now.hour();
    int minuto  = now.minute();
    int segundo = now.second();

    sprintf(texto, "Hoje: %s, %02d/%02d/%04d Hora: %02d:%02d:%02d",
            diasDaSemana[now.dayOfTheWeek()], dia, mes, ano, hora, minuto, segundo);
    Serial.println(texto);

    sprintf(texto, "Hoje: %s, %02d/%s/%04d Hora: %02d:%02d:%02d",
            diasDaSemana[now.dayOfTheWeek()], dia, mesDoAno[mes], ano, hora, minuto, segundo);
    Serial.println(texto);
  }
  else {
    Serial.println("Modulo RTC nao encontrado!");
  }
}

void loop() {
}

A saída no monitor serial será a data e hora do dia que você executou este sketch:

Hoje: Sexta, 21/08/2020 Hora: 17:31:42
Hoje: Sexta, 21/Agosto/2020 Hora: 17:31:42

 


Links úteis:


 

Sensor de Presença – HC-SR501

Sensores de presença ou movimento, conhecidos como sensores IR (infravermelho) ou PIR (Passive Infrared Sensor ou Pyroelectric Infrared Sensor), são sensores que detectam radiação emitida pelo corpo humano, por exemplo.

PIR01

O elemento sensor é vedado e oferece grande imunidade a umidade e temperatura e sua área exposta deixa passar somente radiação infravermelha. O circuito ao redor dá suporte a leitura do sensor e posterior conversão em um sinal digital. Portanto, na saída deste sensor teremos um nível alto, quando da detecção do movimento e um nível baixo em estado de repouso.

PIR - ElecFreaks
sensor piroelétrico – fonte http://www.elecfreaks.com

A lente (que cobre o elemento sensor) é do tipo Fresnel, feita de plástico, cuja função é ampliar o ângulo de detecção e concentração dos raios infravermelhos.

fonte http://www.fresnelfactory.com
fonte http://www.fresnelfactory.com

Pinos e Ajustes

Não é crítico mas requer um pouco de tempo para ajustar as suas necessidades.

Pinos:

  • 5V = ligar no pino 5V da placa Arduino
  • sinal = ligar em qualquer pino digital da placa Arduino
  • GND = ligar no pino GND da placa Arduino

Ajustes:

      • tempo (trimpot) = no sentido horário, aumenta o delay (tempo que o sinal ficará em nível alto) para aproximadamente 5 minutos e no sentido anti-horário para aproximadamente 5 segundos.
      • sensibilidade (trimpot) = no sentido horário, aumenta a distância de detecção para aproximadamente 7 metros e no sentido contrário para aproximadamente 3 metros.
      • trigger (jumper)
        low – não repetitivo:  quando alguém é detectado, um nível alto ficará presente no pino digital até que o tempo se esgote, daí o nível muda para baixo por aproximadamente 3 segundos, não aceitando novas detecções neste período.
        high – repetitivo: quando em nível alto, ficará neste estado enquanto o sensor detectar alguém no ambiente (dentro do tempo ajustado, porém o tempo será renovado a cada detecção) até que não haja movimento, daí alterando o nível para baixo por aproximadamente 3 segundos, não aceitando novas detecções neste período.

Um pouco confuso, não? 🙂 A melhor forma de entender estes ajustes é fazer experiências com a montagem sugerida mais adiante.

Montagem do circuito

Nos testes/experiências com este sensor, deixamos os trimpots posicionados no sentido máximo anti-horário e o jumper do modo trigger em high. A nossa sugestão é deixar inicialmente desta forma e ir ajustando conforme a sua necessidade.  O LED, neste período de ajuste, terá grande importância para nos orientar quando sensor estiver em nível alto. O pino de sinal do PIR está conectado ao pino digital 2 do Arduino e o LED está conectado ao pino 13 digital do Arduino através de um resistor de 220Ω.

PIR_protoboard PIR_esquematico   PIR_montagem

Exemplo

#define LED 13
#define PIR 2

void setup() {
   pinMode(LED, OUTPUT);
   pinMode(PIR, INPUT);
   delay(5000);
}

void loop() {
   byte leitura = digitalRead(PIR);
   digitalWrite(LED, leitura);
}

 

Sensores de Temperatura e Umidade – DHT11/DHT22

DHT11/DHT22 (AM2302)

Estes sensores da Aosong Electronics Co, combinam um sensor de umidade e um sensor de temperatura no mesmo invólucro. De baixo custo e fácil implementação, o DHT11 é mais barato que o DHT22 que por sua vez é mais preciso, segundo dados do fabricante.

DHT11 e DHT22
DHT11 e DHT22

A biblioteca que usamos foi desenvolvida (e é mantida) pela equipe da Adafruit. O download pode ser feito do repositório da Adafruit ou no final deste artigo.

Instalando a biblioteca DHT

Com as versões mais recentes da IDE do Arduino (a partir da 1.6.2), a instalação de bibliotecas de terceiros pode ser feita pelo menu Sketch, Include Library, Manage Libraries…

Gerenciando bibliotecas
Gerenciando bibliotecas

Neste exemplo vamos  apresentar uma forma alternativa de instalação, ou seja,   vamos mostrar como adicionar  uma biblioteca manualmente.

Considerando o ambiente operacional Microsoft Windows e se você optou pela instalação padrão do IDE do Arduino, a pasta que contém as bibliotecas de terceiros está localizada no seu perfil de usuário.

Ao fazer o download de uma biblioteca qualquer (geralmente está compactada – .zip), extraia os arquivos e copie para a pasta libraries do seu perfil de usuário. Note que os nomes das bibliotecas  compactadas geralmente apresentam a palavra master como parte  do nome. Por exemplo: DHT-sensor-library-master.zip. Após você descompactar este arquivo, renomeie a pasta para DHT.

gerenciando_libraries_DHT
gerenciado libraries

Após a cópia, se você estiver com o IDE aberto, saia e abra novamente para que o Arduino carregue as bibliotecas instaladas.

Montagem do circuito

A montagem é muito simples, o circuito é o mesmo do DHT11 e DHT22. Você vai precisar de um sensor e um resistor de 10KΩ. Veja as imagens a seguir (oriente-se pelo pino 1 marcado na imagem):

montagem na protoboard
montagem na protoboard
esquemático

Recursos da biblioteca DHT

Infelizmente a documentação, de um modo geral, não é clara ou até mesmo não existe nas bibliotecas de terceiros. Colocamos aqui a funções da biblioteca DHT da Adafruit. Se vocês encontrarem alguma inconsistência, escreva/comente para que possamos corrigi-las.

begin()   configuração inicial do sensor.

readTemperature( true/false )   lê a temperatura e retorna um valor do tipo float em Celsius, se parâmetro false, ou Farenheit, se parâmetro true.

 readHumidity()   retorna um valor (percentual) do tipo float que representa a umidade relativa do ar.

computeHeatIndex( temperatura_Farenheit , umidade )   retorna um valor em Farenheit do tipo float que representa a sensação térmica. Você deve passar os parâmetros de temperatura em Farenheit e umidade (ambos do tipo float).

convertCtoF( temperatura_Celsius )

convertFtoC( temperatura_Farenheit )   converte respectivamente Celsius em Farenheit e Farenheit em Celsius (ambos do tipo float).

Exemplos

Exemplo com DHT11

#include <DHT.h>

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println("EADuino - teste DHT11");
  dht.begin();
}

void loop() {

  float umidade         = dht.readHumidity();
  float temperatura     = dht.readTemperature();
  float temperaturaF    = dht.readTemperature(true);
  float sensacaoTermica = 0;

  sensacaoTermica = dht.computeHeatIndex(temperaturaF, umidade);
  sensacaoTermica = dht.convertFtoC(sensacaoTermica);

  Serial.print("Umidade: ");
  Serial.print(umidade);
  Serial.print("%\t");
  Serial.print("Temperatura: ");
  Serial.print(temperatura);
  Serial.print("C\t");
  Serial.print("Sensacao termica: ");
  Serial.print(sensacaoTermica);
  Serial.println("C");
  delay(1000);
}

Exemplo com DHT22

#include <DHT.h>

#define DHTPIN    2
#define DHTTYPE   DHT22   // AM2302

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println("EADuino - teste DHT22");
  dht.begin();
}

void loop() {
  float umidade = dht.readHumidity();
  float temperatura = dht.readTemperature();
  float temperaturaF = dht.readTemperature(true);
  float sensacaoTermica = 0;

  sensacaoTermica = dht.computeHeatIndex(temperaturaF, umidade);
  sensacaoTermica = dht.convertFtoC(sensacaoTermica);

  Serial.print("Umidade: ");
  Serial.print(umidade);
  Serial.print("%\t");
  Serial.print("Temperatura: ");
  Serial.print(temperatura);
  Serial.print("C\t");
  Serial.print("Sensacao termica: ");
  Serial.print(sensacaoTermica);
  Serial.println("C");
  delay(1000);
}