Introdução
Neste tutorial, vamos utilizar a Franzininho C0 juntamente com um sensor LDR e um display OLED SSD1306 para criar um sistema de monitoramento de luminosidade. O objetivo é ler os valores do sensor LDR (Light Dependent Resistor) e exibi-los no display OLED utilizando a IDE do Arduino.
Sensor LDR (Light Dependent Resistor)
O sensor LDR, também conhecido como fotoresistor, é um componente eletrônico sensível à luz que varia sua resistência elétrica conforme a intensidade luminosa sobre ele. Esses sensores são feitos de materiais semicondutores especiais, como sulfeto de cádmio, que possuem propriedades únicas de condução elétrica.
Quando expostos à luz, os elétrons no semicondutor do LDR são excitados para níveis de energia mais altos, o que reduz a resistência elétrica do dispositivo. Isso significa que, em ambientes bem iluminados, o LDR apresenta uma resistência menor. Por outro lado, em ambientes escuros, a resistência aumenta, já que menos luz excita os elétrons no material semicondutor.
Circuito
Vamos começar com a montagem do circuito na protoboard.
Material e Montagem da placa
- Franzininho C0
- Protoboard
- Display OLED SSD1306
- Sensor de Luminosidade (LDR)
- Resistor de 10 kΩ
- Jumpers
Pinout da Franzininho C0
Para definir os pinos utilizados, precisamos consultar o pinout da placa:
Acesse a documentação completa em:
https://docs.franzininho.com.br/docs/franzininho-c0/franzininho-c0-board
Montagem do Circuito
Com a protoboard em mãos e a placa Franzininho C0 já inserida nela, siga as instruções abaixo para conectar o display OLED:
Código
Para automatizar o acendimento do LED com um sensor LDR e exibir o valor lido pelo sensor no display SSD1306 usando a Franzininho C0, utilizaremos o código a seguir:
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
// Endereço I2C do SSD1306
#define I2C_ADDRESS 0x3C
// Define pinos
#define LDR A0
#define LED PB7
#define SCL_PIN PB6
#define SDA_PIN PC14
// Limite de luminosidade para acender o LED
#define LIGHT_THRESHOLD 400
// Define reset do display
#define RST_PIN -1
SSD1306AsciiWire oled;
uint8_t colValueStart; // Coluna de início para o valor do LDR
uint8_t rowValue; // Linha para o valor do LDR
//------------------------------------------------------------------------------
void setup() {
Wire.setSCL(SCL_PIN);
Wire.setSDA(SDA_PIN);
Wire.begin();
// Inicializa LED como saída
pinMode(LED, OUTPUT);
#if RST_PIN >= 0
oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else
oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif
oled.setFont(Adafruit5x7);
oled.clear();
oled.set2X();
// Exibe o rótulo fixo uma vez
oled.println("LDR value:");
// Calcular a posição inicial para o valor do LDR
colValueStart = 0; // Valor começará da primeira coluna
rowValue = oled.fontRows(); // Uma linha abaixo do "LDR value"
}
// Limpa a área do valor do LDR
void clearLdrValue() {
oled.clear(colValueStart, oled.displayWidth() - 1, rowValue, rowValue + oled.fontRows() - 1);
}
void loop() {
// Lê o valor analógico do pino LDR
int ldrValue = analogRead(LDR);
clearLdrValue();
// Exibir o novo valor do LDR
oled.setCursor(colValueStart, rowValue);
oled.print(ldrValue);
// Acender o LED se a luminosidade estiver abaixo do limite
if (ldrValue < LIGHT_THRESHOLD) {
digitalWrite(LED, HIGH);
} else {
digitalWrite(LED, LOW);
}
// Pequeno atraso para não sobrecarregar a comunicação serial e o display
delay(500);
}
Obs.1: Antes da IDE iniciar o carregamento do programa, a Franzininho C0 deve executar o bootloader, caso contrário ocorrerá um erro.
Obs.2: Recomendamos o uso da IDE 1.8.x do Arduino para essa aplicação.
Explicação do Código
Antes do setup(), vamos incluir duas bibliotecas Wire, SSD1306Ascii e SSD1306AsciiWire. A biblioteca Wire do Arduino viabiliza a comunicação I2C entre microcontroladores e periféricos. Enquanto as bibliotecas SSD1306Ascii e SSD1306AsciiWire são utilizadas para escrever textos no display SSD1306 e para permitir a comunicação com o display SSD1306 via protocolo I2C, respectivamente.
A biblioteca SSD1306Ascii foi escolhida para programar o display OLED SSD1306 como uma segunda alternativa para minimizar o uso de memória, sendo ideal para a Franzininho C0, que possui 32KB de memória flash.
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"Além disso, são criadas algumas variáveis globais. Usando #define identificamos o endereço do display OLED como ‘0x3C’. O pino A0, conectado ao sensor LDR, é definido e os pinos PB6 e PC14 são definidos como ‘SCL_PIN’, ‘SDA_PIN’, correspondendo aos terminais SCL e SDA do display, respectivamente.
Além disso, é definido o limite de luminosidade lido pelo LDR para acender o LED (esse valor pode precisar ser ajustado de acordo com a iluminação do ambiente em que você estará realizando o projeto). Também definimos o valor de reset do display.
// Endereço I2C do SSD1306
#define I2C_ADDRESS 0x3C
// Define pinos
#define LDR A0
#define LED PB7
#define SCL_PIN PB6
#define SDA_PIN PC14
// Limite de luminosidade para acender o LED
#define LIGHT_THRESHOLD 400
// Define reset do display
#define RST_PIN -1
Em seguida definimos um objeto oled da classe ‘SSD1306AsciiWire’ para controlar o display SSD1306 usando o protocolo I2C. As variáveis ‘colValueStart’ e ‘rowValue’ serão usadas para especificar a posição no display onde os valores lidos pelo sensor LDR (Light Dependent Resistor) serão exibidos.
SSD1306AsciiWire oled;
uint8_t colValueStart; // Coluna de início para o valor do LDR
uint8_t rowValue; // Linha para o valor do LDRNo setup(), começamos definindo com a biblioteca Wire os pinos respectivos ao SCL e ao SDA do display. Em seguida, ‘Wire.begin()’ é usado para configurar o microcontrolador para atuar como mestre no barramento I2C. E o LED é definido como saída (OUTPUT) .
void setup() {
Wire.setSCL(SCL_PIN);
Wire.setSDA(SDA_PIN);
Wire.begin();
// Inicializa LED como saída
pinMode(LED, OUTPUT);
...
}
Em seguida é feita uma verificação se o pino de reset for maior ou igual a 0, o display OLED é inicializado com o endereço I2C e o pino de reset definido (RST_PIN). Mas, se RST_PIN não for definido ou for menor que 0, o display OLED é inicializado sem especificar um pino de reset.
{ ...
#if RST_PIN >= 0
oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else
oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif
...}
Nas demais linhas do setup() realizamos algumas definições do display OLED. Começamos definindo a fonte a ser usada para o texto exibido no display OLED, em que ‘Adafruit5x7’ é uma fonte de tamanho 5×7 pixels fornecida pela biblioteca. Com ‘oled.clear()’ limpamos o conteúdo atual do display OLED, preparando-o para uma nova exibição.
Em seguida, com `oled.set2X()` definimos o modo de exibição em escala 2x, aumentando o tamanho do texto para melhor visualização. Se preferir, você pode remover essa linha para exibir o texto no tamanho normal.
Finalmente, com ‘oled.println(“LDR value:”)’ exibimos a string “LDR value:” no display OLED.
Outras configurações importantes são ‘colValueStart = 0’, que define que o valor do LDR será escrito a partir da primeira coluna no display OLED, alinhado à esquerda. Enquanto ‘rowValue = oled.fontRows()’ calcula a posição vertical onde o valor do LDR será exibido. Isso porque ‘oled.fontRows()’ retorna o número de linhas que podem ser exibidas no display com a fonte atual (Adafruit5x7). Ao atribuir ‘oled.fontRows()’ à variável ‘rowValue’, garantimos que o valor do LDR será escrito uma linha abaixo do texto “LDR value:”, mantendo o display organizado.
{ ...
oled.setFont(Adafruit5x7);
oled.clear();
oled.set2X();
// Exibe o rótulo fixo uma vez
oled.println("LDR value:");
// Calcular a posição inicial para o valor do LDR
colValueStart = 0; // Valor começará da primeira coluna
rowValue = oled.fontRows(); // Uma linha abaixo do "LDR value"
}Depois do setup, criamos a função ‘clearLdrValue()’, responsável por limpar apenas a parte do display que exibe o valor lido pelo LDR. É uma função sem retorno e sem parâmetros.
Dentro dela, usamos o método ‘oled.clear’, que limpa o display OLED, especificando a área a ser limpa. Para especificar usamos alguns parâmetros:
- ‘colValueStart’ é a coluna inicial da área que será limpa, ou seja, define a posição horizontal inicial.
- ‘oled.displayWidth() – 1’ define a coluna final da área que será limpa, pois ‘oled.displayWidth()’ retorna a largura total do display em pixels, e subtrair 1 ajusta o índice para a contagem que começa em 0.
- ‘rowValue’ é a linha inicial da área que será limpa, ou seja, define a posição vertical inicial.
- ‘rowValue + oled.fontRows() – 1’ define a linha final da área que será limpa. ‘oled.fontRows()’ retorna a altura da fonte em número de linhas, a soma de ‘rowValue’ com ‘oled.fontRows() – 1’ define a linha final a ser limpa.
// Limpa a área do valor do LDR
void clearLdrValue() {
oled.clear(colValueStart, oled.displayWidth() - 1, rowValue, rowValue + oled.fontRows() - 1);
}No loop(), começamos lendo o valor do sensor LDR através da função analogRead(), que realiza a leitura de um pino analógico.
void loop() {
// Lê o valor analógico do pino LDR
int ldrValue = analogRead(LDR);
... }
Depois, realizamos a limpeza do display apenas na área onde é exibido o valor do sensor LDR, usando a função ‘clearLdrValue()’. Para exibir um novo valor do LDR, usamos ‘oled.setCursor’, que define a posição do cursor no display OLED. A posição horizontal é definida por ‘colValueStart’ e a posição vertical por ‘rowValue’, ambos definidos no setup.
clearLdrValue();
// Exibir o novo valor do LDR
oled.setCursor(colValueStart, rowValue);
oled.print(ldrValue);Por último, estabelecemos que o LED acenderá apenas se o valor do LDR for inferior ao limite de 400, previamente definido. Adicionamos um delay ao final de cada loop para garantir a comunicação correta com o display.
// Acender o LED se a luminosidade estiver abaixo do limite
if (ldrValue < LIGHT_THRESHOLD) {
digitalWrite(LED, HIGH);
} else {
digitalWrite(LED, LOW);
}
// Pequeno atraso para não sobrecarregar a comunicação serial e o display
delay(500);
}Ao executar o código, conforme mostrado no vídeo, podemos observar que o display exibe o valor lido pelo sensor LDR, e o LED acende somente quando esse valor está abaixo de 400.
Conclusão
Neste artigo, criamos um sistema de monitoramento de luminosidade. O sensor LDR foi utilizado para ler a intensidade de luz do ambiente e os valores lidos foram exibidos no display OLED. O valor do LDR é atualizado constantemente. Além disso, o LED acende quando o valor do LDR está abaixo de 400, indicando baixa luminosidade. Um delay ao final de cada loop assegura a comunicação correta com o display, proporcionando um sistema funcional e eficiente.
Desafio
Neste desafio você irá elaborar um sistema de monitoramento de iluminação com feedback sonoro utilizando o sensor LDR. O objetivo é configurar a Franzininho C0 para ler continuamente os valores de resistência do LDR, que variam conforme a luminosidade ambiente. Quando a luminosidade cair abaixo de um limite predefinido, um buzzer integrado será acionado para soar um alarme, alertando o usuário sobre condições de iluminação insuficiente.






