EEPROM - Armazenando dados na memória não volátil do Arduino
Armazenando dados de forma não volátil no Arduino - EEPROM
A necessidade de se armazenar informações é algo bastante recorrente no desenvolvimento de projetos embarcados. Sejam elas um conjunto de variáveis para configurar o seu sistema, ou até mesmos dados que você queira visualizar após um intervalo de tempo, o armazenamento de informações é muito importante em praticamente todos os tipos de projetos. Porém nem sempre dispomos de um cartão SD, seja por limitações de custo ou até mesmo pinos de I/O, impossibilitando assim que a utilização de um cartão SD resolvesse o problema. Sabendo disso, neste tutorial, você aprenderá como utilizar a memória EEPROM existente nos microcontroladores Atmega das placas Arduino para armazenar dados permanentemente.
[toc]
Memória EEPROM
A memória EEPROM ou Electrically-Erasable Programmable Read-Only Memory, consiste em um modelo de memória onde diferente da memória RAM, podemos manter dados armazenados após desligarmos o nosso equipamento. Desta forma, é possível salvar informações que podem ser necessárias para o funcionamento do sistema após o seu desligamento, como por exemplo:
- Configurações
- Dados de difícil obtenção
- Dados estáticos
A utilização de memórias EEPROM, possibilitam com que o desenvolvedor seja capaz de armazenar diversas informações do sistema para uso posterior. Porém, este tipo de memória possui um ciclo muito pequeno de escritas, o que torna o seu uso viável apenas para o armazenamento de informações que serão pouco modificadas.
Memória eeprom i2c com encapsulamento dip.
O processo de leitura e escrita neste tipo de memória pode ser feito de duas formas:
- Paralelo: Cada byte é escrito de forma paralela na memória, sendo este escrito com base no endereço definido no barramento. Mais rápida, porém gasta uma maior quantidade de pinos para I/O
- Serial: Cada byte é escrito de forma serializada (normalmente utilizando o protocolo i2c) na memória eeprom. Mais lenta, porém gasta uma menor quantidade de pinos para I/O
Memória EEPROM no Arduino
Os microcontroladores ATmega possuem em sua arquitetura uma pequena memória eeprom, que pode ser utilizada como uma unidade de armazenamento. Cada microcontrolador possui uma de tamanho específico, segmentada em 1 byte por endereço. A lista abaixo ilustra a quantidade de memória disponível para a microcontroladores utilizados em plataformas como Arduino Nano, Arduino Uno e Arduino Mega:
- ATmega8,ATmega168 - 512 Bytes
- ATmega326 - 1024 Bytes
- ATmega1280, ATmega2560 - 4096 Bytes
Mãos à obra – Armazenando dados na memória EEPROM do Arduino
Neste projeto iremos apenas aprender a como manipular e realizar leituras e escritas na memória EEPROM do Arduino, desta forma iremos precisar apenas de um Arduino com algum dos microcontroladores citados acima.
Componentes Utilizados
Neste projeto iremos utilizar um Arduino Nano, porém praticamente todos os microcontroladores ATmega dispõem de uma memória eeprom nativa.
Programando
- Bibliotecas
Como iremos apenas aprender como armazenar e ler dados da memória EEPROM do Arduíno, iremos utilizar apenas a biblioteca EEPROM.h que já é nativa da ide que pode ser importada ao seu código da seguinte forma:
#include <EEPROM.h>
- Código Utilizado
Agora que temos o nosso sistema montado, e as bibliotecas adicionadas ao projeto, podemos partir para o código. Observem o código a seguir que utilizaremos como base para o nosso manipulador de memória.
#include <EEPROM.h> // Biblioteca para acesso e manipulação da EEPROM void setup() { Serial.begin(115200); // Inicialização da comunicação serial Serial.print("Espaco Disponivel em Bytes: "); // Mostra a quantidade de memória da EEPROM do seu microcontrolador Serial.println(EEPROM.length()); // Mostra a quantidade de memória da EEPROM do seu microcontrolador escreveByte(0,254); // Escreve o valor 255 na posição 0 da memória byte valor = leByte(0); // Lê o endereço 0 da memória ( onde escrevemos 255 ) Serial.print("Byte Armazenado: "); // Mostra o Byte Armazenado Serial.println(valor); // Mostra o Byte Armazenado escreveInt(1,2,1200); // Escreve o valor 1200 na EEPROM ( por ser um int de 2 bytes precisamos utilizar 2 endereços para armazenar) Serial.print ("Inteiro Armazenado: "); // Mostra o inteiro Armazenado Serial.println(lerInt(1,2)); // Mostra o inteiro Armazenado escreveString(3,"Vida de Silício"); // Escreve a String Vida de Silício na EEPROM, começando no endereço 3 Serial.println("String Armazenada: "+leString(3)); // Mostra a String armazenada } void loop(){ } byte leByte (int endereco1){ return EEPROM.read(endereco1); // Realizamosa leitura de 1 byte e retornamos } void escreveByte (int endereco1, byte valor){ // Escreve um byte na EEPROM no endereço especificado byte valorAtual = leByte(endereco1); // Lemos o byte que desejamos escrever if (valorAtual == valor){ // Se os valores forem iguais não precisamos escrever ( economia de ciclos de escrita ) return; } else { // Senão escrevemos o byte no endereço especificado na função EEPROM.write(endereco1,valor); // Escreve o byte no endereço especificado na função } } void escreveInt(int endereco1, int endereco2, int valor){ // Escreve um inteiro de 2 bytes na EEPROM int valorAtual = lerInt(endereco1,endereco2); // Lemos o valor inteiro da memória if (valorAtual == valor){ // Se o valor lido for igual ao que queremos escrever não é necessário escrever novamente return; } else{ // Caso contrário "quebramos nosso inteiro em 2 bytes e escrevemos cada byte em uma posição da memória byte primeiroByte = valor&0xff; //Executamos a operação AND de 255 com todo o valor, o que mantém apenas o primeiro byte byte segundoByte = (valor >> 8) &0xff; // Realizamos um deslocamento de 8 bits para a direita e novamente executamos um AND com o valor 255, o que retorna apenas o byte desejado EEPROM.write(endereco1,primeiroByte); // Copiamos o primeiro byte para o endereço 1 EEPROM.write(endereco2,segundoByte); // Copiamos o segundo byte para o endereço 2 } } int lerInt(int endereco1, int endereco2){ // Le o int armazenado em dois endereços de memória int valor = 0; // Inicializamos nosso retorno byte primeiroByte = EEPROM.read(endereco1); // Leitura do primeiro byte armazenado no endereço 1 byte segundoByte = EEPROM.read(endereco2); // Leitura do segundo byte armazenado no endereço 2 valor = (segundoByte << 8) + primeiroByte; // Deslocamos o segundo byte 8 vezes para a esquerda ( formando o byte mais significativo ) e realizamos a soma com o primeiro byte ( menos significativo ) return valor; // Retornamos o valor da leitura } void escreveString(int enderecoBase, String mensagem){ // Salva a string nos endereços de forma sequencial if (mensagem.length()>EEPROM.length() || (enderecoBase+mensagem.length()) >EEPROM.length() ){ // verificamos se a string cabe na memória a partir do endereço desejado Serial.println ("A sua String não cabe na EEPROM"); // Caso não caiba mensagem de erro é mostrada } else{ // Caso seja possível armazenar for (int i = 0; i<mensagem.length(); i++){ EEPROM.write(enderecoBase,mensagem[i]); // Escrevemos cada byte da string de forma sequencial na memória enderecoBase++; // Deslocamos endereço base em uma posição a cada byte salvo } EEPROM.write(enderecoBase,'\0'); // Salvamos marcador de fim da string } } String leString(int enderecoBase){ String mensagem=""; if (enderecoBase>EEPROM.length()){ // Se o endereço base for maior que o espaço de endereçamento da EEPROM retornamos uma string vazia return mensagem; } else { // Caso contrário, lemos byte a byte de cada endereço e montamos uma nova String char pos; do{ pos = EEPROM.read(enderecoBase); // Leitura do byte com base na posição atual enderecoBase++; // A cada leitura incrementamos a posição a ser lida mensagem = mensagem + pos; // Montamos string de saídaa } while (pos != '\0'); // Fazemos isso até encontrar o marcador de fim de string } return mensagem; // Retorno da mensagem }
Colocando pra funcionar
Se nada tiver sido modificado no código e sua EEPROM ainda possuir ciclos de escrita, a seguinte mensagem será apresentada no monitor serial:
Entendendo a Fundo
Software
- Incluindo bibliotecas necessárias
Para este sistema, iremos precisar apenas da biblioteca EEPROM.h que já é nativa do Arduíno e será utilizada como interface entre a EEPROM e o nosso código, desta forma ela pode ser adicionada da seguinte forma:
#include <EEPROM.h>
- Função Setup
Em nossa função setup, iremos basicamente escrever e ler as variáveis que desejamos armazenar na EEPROM, foram definidos um conjunto de 6 funções, sendo três para escrita e três para leitura de tipos de dados normalmente utilizados, sendo eles:
- Int
- Byte
- String
Sendo assim, no setup iremos apenas utilizar estas funções, da seguinte forma:
- Função escreve byte
Escreve um valor em byte no endereço especificado, neste exemplo estamos escrevendo o valor 254 no endereço 0 da memória.
escreveByte(0,254); // Escreve o valor 255 na posição 0 da memória
- Função lê byte
Realiza a leitura de um único byte no endereço especificado pelo usuário, neste exemplo estamos lendo o endereço 0.
byte valor = leByte(0);
- Função escreve int
Escreve um valor inteiro composto por 2 bytes, em duas posições quaisquer da eeprom, neste exemplo estamos escrevendo o valor 1200 utilizando os endereços 1 e 2.
escreveInt(1,2,1200);
- Função lê int
Realiza a leitura de dois endereços especificados pelo usuário, reconstruindo o valor inteiro que elas representam, neste exemplo estamos lendo os endereços 1 e 2 da memória.
Serial.println(lerInt(1,2));
- Função escreve string
Escreve uma determinada string de forma sequencial na EEPROM, neste exemplo estamos utilizando um total de 15 endereços (começando do endereço 3) para escrever a string "Vida de Silício" em nossa memória.
escreveString(3,"Vida de Silício");
- Função lê string
Dado um endereço base fornecido, esta função lê sequencialmente toda a string armazenada.
leString(3);
Entendendo cada função implementada
Cada função implementada possui um grau complexidade devido a realização de operações lógicas para quebra de bytes e armazenamento sequencial, desta forma iremos mostrar a forma como cada função é capaz de salvar e recuperar seus respectivos tipos de dados. Porém antes vamos entender um pouco a forma como a nossa memoria funciona.
Imagine a sua memória como um um conjunto de blocos onde podemos armazenar valores em um intervalo de 0 até 255, e cada um desses intervalos está associado a um endereço, sendo assim, podemos imaginar a nossa memória da seguinte forma: Com essa estrutura de memória podemos salvar qualquer tipo de informação, desde que o espaço seja suficientemente grande para armazenar todos os valores.
- Função escreveByte
A função escreveByte recebe como argumentos o endereço e o valor a ser escrito naquela posição, verificando apenas se o byte que desejamos escrever já não está lá, desta forma economizamos uma escrita que seria feita desnecessariamente, prologando assim a vida útil de nossa memória.
void escreveByte (int endereco1, byte valor){ byte valorAtual = leByte(endereco1); if (valorAtual == valor){ return; } else { EEPROM.write(endereco1,valor); } }
Estruturalmente, podemos dizer que esta função executa a seguinte operação:
- Função leByte
Já a função leByte, basicamente realiza a leitura do endereço especificado em seu argumento, retornando assim o valor que está armazenado naquele endereço.
byte leByte (int endereco1){ return EEPROM.read(endereco1); }
Utilizando o nosso modelo de memória, podemos dizer que estamos realizando a seguinte operação:
- Função escreveInt
Nos microcontroladores ATmega, uma variável do tipo int, é representada por um total de 2 bytes, sendo estes divididos entre mais significativos (HB) e menos significativos (LB), como a nossa memória permite apenas o armazenamento de 1 byte por endereço. Sabendo disso, é necessário que a nossa função seja capaz de "quebrar" o nosso valor inteiro de 2 bytes, em duas variáveis de 1 byte cada, para que assim seja possível armazenar esta informação na memória. Para que isso seja feito, iremos utilizar dois tipos de operações lógicas existente em praticamente todas as arquiteturas de computadores, que são as operações rigth shift e and bitwise.
void escreveInt(int endereco1, int endereco2, int valor){ int valorAtual = lerInt(endereco1,endereco2); if (valorAtual == valor){ return; } else{ byte primeiroByte = valor&0xff; byte segundoByte = (valor >> 8) &0xff; EEPROM.write(endereco1,primeiroByte); EEPROM.write(endereco2,segundoByte); } }
Sabendo disso o algoritmo funciona da seguinte forma:
- Inicialmente verificamos se o valor que desejamos inserir é igual ao que está na memória ( se for economizamos duas escritas na memória )
- Caso não seja executamos a seguinte operação:
- Dado o nosso valor de exemplo 1001, serão executadas as seguintes operações:
- Aplicamos uma operação AND bit a bit sob o valor que desejamos quebrar com o número 255, desta forma iremos preservar apenas os bits da primeira cadeia de byte que desejamos armazenar. A figura abaixo ilustra como o processo é feito e o resultado obtido através da operação realizada.
- Para o segundo byte, realizaremos o mesmo processo do passo 2, porém ao invés apenas aplicar a operação lógica AND, iremos antes deslocar os bits que estão na camada superior. Para que dessa forma, cheguem a posição dos bits menos significativos para a aplicação da máscara.
- Por fim, com os bytes separados, a função salva cada um deles no endereço especificado como mostra a figura abaixo:
- Função leInt
O processo de leitura segue praticamente a lógica inversa do processo de escrita, onde iremos ler cada byte e montar o nosso valor da seguinte forma:
- Relizamos uma leitura do endereço de valor mais significativo, este valor é deslocado 8 bits a esquerda para que volte a sua posição de bit mais significativo.
- Realizamos uma leitura do endereço de valor menos significativo, este valor é somado ao valor deslocado para que volte a posição de bit menos significativo.
- Temos o nosso valor montado novamente.
int lerInt(int endereco1, int endereco2){ int valor = 0; byte primeiroByte = EEPROM.read(endereco1); byte segundoByte = EEPROM.read(endereco2); valor = (segundoByte << 8) + primeiroByte; return valor; }
- Função escreveString
A função escreve string por sua vez, não utiliza de recursos de deslocamento de bits, devido ao fato de que cada caractere, é um único byte. Ou seja, uma string nada mais é do que um vetor de bytes alocados sequencialmente. Sabendo disso, o nosso algoritmo de salvar uma string na memória segue a seguinte lógica:
- Dado um endereço base, e o tamanho da string verificamos se é possível o armazenamento ou não.
- Caso não seja possível, o valor não é salvo.
- Caso seja possível, a string é alocada sequencialmente na memória começando com o endereço base e terminando sempre com um ''\0''
void escreveString(int enderecoBase, String mensagem){ if (mensagem.length()>EEPROM.length() || (enderecoBase+mensagem.length()) >EEPROM.length() ){ Serial.println ("A sua String não cabe na EEPROM"); } else{ for (int i = 0; i<mensagem.length(); i++){ EEPROM.write(enderecoBase,mensagem[i]); enderecoBase++; } EEPROM.write(enderecoBase,'\0'); } }
- Função leString
A função leString por sua vez, realiza praticamente o mesmo processo que a leitura, porém ao invés de armazenar os bytes como na função escreveString, ela utiliza a função read, para ler cada byte armazenado sequencialmente. Desta forma podemos dizer que o algoritmo funciona da seguinte forma:
- Com base no endereço inicial, a função lê cada byte lido, até que o caractere de fim de texto '\0', seja encontrado. Quando encontrado uma string montada é retornada pela função.
String leString(int enderecoBase){ String mensagem=""; if (enderecoBase>EEPROM.length()){ return mensagem; } else { char pos; do{ pos = EEPROM.read(enderecoBase); enderecoBase++; mensagem = mensagem + pos; } while (pos != '\0'); } return mensagem; }
Desafio
Agora que sabemos como manipular a memória EEPROM do nosso Arduino, tente adicionar esta funcionalidade a algum projeto que seja necessária a configuração de uma variável em tempo real. Um exemplo de sistema desse tipo são os dataloggers, onde precisamos configurar informações como tempo de leitura e configuração de sensores.
Considerações finais
Este tutorial, teve como objetivo mostrar como manipular a memória EEPROM, interna do seu Arduino, funcionando como uma pequena unidade de armazenamento para informações importantes. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
Sensor de umidade do solo com Arduino - Higrômetro
Sensor de umidade do solo com Arduino - Higrômetro
Neste tutorial daremos o primeiro passo para desenvolver um sistema inteligente voltado para o monitoramento e controle das variáveis existentes em uma plantação. Começaremos aprendendo como usar o sensor de umidade do solo, também chamado de Higrômetro, em conjunto com um Arduino Nano.
[toc]
Sistemas automáticos na Agricultura
Plantas precisam de um solo de boa qualidade para crescerem de forma saudável e com qualidade, porém, existem vários tipos de situações ambientais que dificultam o seu crescimento, sendo algumas delas:
- Irradiação solar excessiva;
- Falta de nutrientes no solo;
- Solo com baixa umidade;
- Pragas;
- Entre outros.
Todas as situações descritas anteriormente podem gerar prejuízo. Por este motivo, faz-se necessária a utilização de, sistemas automáticos os quais vêm sendo cada vez mais explorados que auxiliem o agricultor no monitoramento de seus cultivos visando obter uma eficiência cada vez maior e consequentemente a redução da ocorrência de situações indesejadas
Sensor umidade do solo - Higrômetro
Neste tutorial, iremos utilizar o sensor de umidade do solo, para aferir a condutividade do solo através de uma haste com dois eletrodos existentes no mesmo. O princípio de funcionamento deste circuito é bem simples, pois, resume-se ao fato de que, através da aplicação de uma determinada corrente X nos eletrodos citados, é possível estimar o quão úmido ou seco o solo estará em virtude da condutividade do solo em ambos os casos. Basicamente, quando o solo estiver úmido, teremos uma condutividade melhor devido a absorção da água e isso resultará em um fluxo maior de corrente entre os dois eletrodos. Entretanto se o solo estiver seco, teremos pouca ou até nenhuma corrente entre os eletrodos.
O sensor é composto basicamente duas hastes que ficaram presas ao solo que iremos monitorar e um circuito comparador que irá nos retornar o nível de condutividade do solo. Este circuito é composto por um total de 6 pinos, sendo dois destes utilizados para conectar a haste de metal ao circuito de comparação. As outras 4 entradas possuem as funções de alimentar o circuito e retornar o nível de umidade do solo.
A determinação do nível de umidade do solo pode ser feita de duas formas, sendo elas:
- Um sinal digital que basicamente informa se o solo está seco ou não ( Menor precisão, porém não depende de um circuito ADC )
- Um sinal analógico que pode ser utilizado para estimar o quão úmido o solo está ( Maior precisão, porém dependerá de um circuito ADC )
Especificações do dispositivo
- Tensão de Operação: 3,3-5v
- Sensibilidade ajustável via potenciômetro
- Saída Digital TTL (D0) e Analógica(A0)
- Led indicador de detecção de umidade
Mãos à Obra - Medindo a umidade do solo utilizando o Arduino - Higrômetro
Componentes utilizados
Montando o projeto
Nesta primeira parte do tutorial, iremos apenas conectar o sensor de umidade, desta forma, iremos utilizar o seguinte esquema de ligação:
A montagem final do nosso sistema deve ser semelhante ao modelo abaixo
Veja só como ficou o nosso sistema inicial.
Antes de ligar o seu circuito, verifique se todas as conexões foram feitas corretamente. Um curto circuito causado por uma ligação errada pode danificar todo o seu projeto.
Programando
Com a parte física do nosso projeto montada, iremos agora partir para a parte de codificação do sistema. Nesta primeira versão não iremos utilizar nenhuma biblioteca em especial, porém iremos utilizar funções para leitura de dados analógicos e também iremos construir o nosso sistema de leituras de uma forma um pouco diferente como pode ser visto no código abaixo:
/* Nome: Sistema de aferição de umidade de solo - Higrômetro * Feito por: Danilo Almeida * Data: 7/11/2017 */ #define sensorUmidade A0 // Sensor de umidade de solo do módulo unsigned long tempoAnterior = 0; // Variável utilizada para guardar o tempo anterior unsigned long intervalo = 1000; // Intervalo de tempo em MS para cada leituraa void setup() { Serial.begin(9600); // Inicialização da comunicação serial } void loop() { unsigned long tempoAtual = millis(); // Realizamos a leitura atual do tempo em que o nosso Arduino Nano está ligado if (tempoAtual-tempoAnterior > intervalo){ // Pequena lógica para realizar leituras temporizadas sem parar o microcontrolador tempoAnterior =tempoAtual; // Guardamos o tempo anterior como o ultimo intervalo de tempo lido int leitura = analogRead(sensorUmidade); // Leitura dos dados analógicos vindos do sensor de umidade de solo if (leitura<=1023 && leitura>=682){ // Se a leitura feita for um valor entre 1023 e 682 podemos definir que o solo está com uma baixa condutividade, logo a planta deve ser regada Serial.println("Nível de Umidade Baixo"); }else{ if (leitura<=681 && leitura>=341){ // Se a leitura feita for um valor entre 681 e 341 podemos definir que o solo está com um nível médio de umidade, logo dependendo da planta pode ou não ser vantajoso regar Serial.println("Nível de Umidade Médio"); } else{ if (leitura<=340 && leitura>=0){ // Se a leitura feita for um valor entre 0 e 340 podemos definir que o solo está com um nível aceitável de umidade, logo talvez não seja interessante regar neste momento Serial.println("Nível de Umidade Alto"); } } } } }
Entendendo a Fundo
Software
- Definições e variáveis utilizadas no projeto
Inicialmente definimos todas as variáveis que iremos utilizar tanto para controlar as leituras que serão efetuadas quanto para realizar a leitura da entrada analógica do sistema. Neste trecho de código definimos as variáveis intervalo, tempoAnterior e criamos uma definição para o pino A0 do Arduino com o nome de sensorUmidade.
#define sensorUmidade A0 // Sensor de umidade de solo do módulo unsigned long tempoAnterior = 0; // Variável utilizada para guardar o tempo anterior unsigned long intervalo = 1000; // Intervalo de tempo em MS para cada leitura
- Função Setup - Inicialização da comunicação serial
Nesta primeira versão, iremos apenas verificar o nível de umidade do solo e com base nesta medição informar se o solo está úmido ou não. Para isso iremos utilizar a comunicação serial. Logo neste trecho de código basicamente inicializamos a comunicação serial do nosso Arduino.
void setup() { Serial.begin(9600); // Inicialização da comunicação serial }
- Função Loop - Usando a função millis para contar o tempo
Nossa função loop tem como objetivo realizar o processo de leitura dentro de cada intervalo de tempo definido na variável intervalo, porém diferente de como fazemos na maioria das implementações, não iremos utilizar o comando delay para sincronizar cada leitura realizada. Isso ocorre pois o comando delay "congela" o microcontrolador o impedindo de executar outras ações, como por exemplo ler um outro sensor, ou receber dados da porta serial. Com isso neste projeto iremos utilizar a função millis para sincronizar as leituras e não "congelar"o microcontrolador, possibilitando assim com que ele faça outras tarefas enquanto aguarda o tempo de realizar uma nova leitura.
O processo de sincronizar a leitura de forma não bloqueante é feito de uma maneira bem simples:
- Inicialmente armazenamos o tempo atual ( que é retornado pela função millis ).
unsigned long tempoAtual = millis(); // Realizamos a leitura atual do tempo em que o nosso Arduino Nano está ligado
- Com o tempo atual do microcontrolador armazenado, iremos agora realizar uma operação de subtração entre o tempo atual lido e o último tempo que armazenamos.
if (tempoAtual-tempoAnterior > intervalo)
- Se a subtração entre o tempo atual do microcontrolador e o último tempo armazenado for maior que o intervalo de tempo para cada leitura, significa que já é hora de realizar a leitura desejada, porém antes devo atualizar o meu tempo anterior já que realizei uma leitura.
tempoAnterior =tempoAtual; // Guardamos o tempo anterior como o ultimo intervalo de tempo lido
- Recomeçamos o processo no passo 1
- Leitura do nosso medidor de umidade de solo
Agora iremos realizar a leitura do nosso sensor de umidade de solo através da porta A0, esta leitura é feita através da função analogRead como mostra o código abaixo:
int leitura = analogRead(sensorUmidade); // Leitura dos dados analógicos vindos do sensor de umidade
Esta função basicamente retorna um valor numérico entre 0 e 1023, que representa o valor tem Volts lido do sensor de umidade. O valor está entre 0 e 1023 devido a resolução do circuito ADC que já vem integrado ao Arduíno, se você precisar de uma resolução maior, pode também utilizar circuitos ADC's dedicados.
- Tomada de decisão baseada no valor medido pelo sensor de umidade
Já por fim ( porém não menos importante ), iremos mostrar através da porta serial, em qual intervalo de valores a sua leitura está contida. Para isso, basicamente dividimos o valor da resolução máxima do circuito ADC do Arduino 1024 valores por três, o que resulta em três estados chamados: umidade baixa, umidade média, umidade alta.
if (leitura<=1023 && leitura>=682){ // Se a leitura feita for um valor entre 1023 e 682 podemos definir que o solo está com uma baixa condutividade, logo a planta deve ser regada Serial.println("Nível de Umidade Baixo"); }else{ if (leitura<=681 && leitura>=341){ // Se a leitura feita for um valor entre 681 e 341 podemos definir que o solo está com um nível médio de umidade, logo dependendo da planta pode ou não ser vantajoso regar Serial.println("Nível de Umidade Médio"); } else{ if (leitura<=340 && leitura>=0){ // Se a leitura feita for um valor entre 0 e 340 podemos definir que o solo está com um nível aceitável de umidade, logo talvez não seja interessante regar neste momento Serial.println("Nível de Umidade Alto"); } } }
Desafio
Agora que temos o nosso projeto montado e funcionando tente melhorar um pouco o nível de medição do sistema. Divida o valor máximo do conversor ADC por um valor maior que três e crie mais ifs para que você seja capaz de identificar melhor o nível de umidade do solo.
Considerações Finais
Este tutorial teve como objetivo apresentar e ilustrar o funcionamento do sensor de umidade do solo, que por sua vez, tem uma aplicação bastante interessante e importante que é identificar em qual momento uma planta deve ser regada, para que dessa forma ela tenha uma qualidade de vida melhor e seja capaz de produzir e aumentar a qualidade de sua produção. Como dito anteriormente, este projeto será uma série onde iremos construir um sistema de monitoramento em tempo real do solo e do ambiente onde nossa plantação está. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
SCT-013 - Sensor de Corrente Alternada com Arduino
SCT-013 - Sensor de Corrente Alternada com Arduino
Neste tutorial ensinaremos a você como medir corrente alternada e estipular a potência instantânea de um circuito utilizando o Sensor de corrente alternada não invasivo SCT-013 juntamente com Arduino. Para este projeto, iremos medir a corrente e a potência de um ferro de solda.
Esse tutorial é dividido em três partes.
- Introdução: Nessa parte você conhecerá um pouco mais o sensor SCT013
- Mãos à obra: Aqui você aprenderá a usar o Sensor de corrente SCT-013 na prática
- Entendendo a fundo: Por fim você entenderá como funciona o software e hardware usado na experiência da parte 2
[toc]
Sensor de corrente não invasivo SCT-013
O sensor de corrente SCT-013 é muito versátil e tem como principal vantagem o fato de não precisar de contato elétrico com o circuito para medir a corrente elétrica alternada. Ou seja, não precisamos abrir o circuito para ligá-lo em série com a carga, basta apenas "abraçar" um dos fios ligados ao equipamento a ser monitorado.
Um pouco de física
Para fazer a medição da corrente sem a necessidade de contato elétrico com o circuito esse sensor de corrente alternada utiliza as propriedades magnéticas da corrente elétrica.
- Lei de Ampère
A Lei de Ampère diz que todo condutor por onde flui uma corrente elétrica induz ao seu redor um campo magnético proporcional à corrente.
- Corrente Alternada
A corrente alternada tem uma peculiaridade de se comportar como uma senoide, sendo assim sua intensidade varia ao longo do tempo indo do máximo positivo ao máximo negativo. Esse comportamento oscilatório tem uma frequência que pode ser de 50Hz ou de 60Hz conforme o país ou região. No Brasil é adotado a frequência de 60Hz, ou seja: a corrente elétrica varia entre positivo e negativo 60 vezes em 1 segundo.
Como o campo magnético é proporcional ao valor de corrente, o campo magnético gerado ao redor do condutor percorrido por uma corrente alternada irá variar ao logo do tempo conforme a variação da mesma.
- Lei de Faraday - lei da indução eletromagnética
A lei de Faraday diz que um campo magnético que varia ao longo do tempo induz em uma espira uma força eletromotriz que gera um corrente elétrica proporcional a intensidade do campo magnético.
Na figura acima podemos entender essa lei na prática. Veja que ao aproximar o imã das espiras estamos variando o campo magnético e está sendo indicado uma tensão no voltímetro (força eletromotriz) chegando quase a 20V. Depois, ao afastar o imã temos a tensão indo quase a 20V no sentido contrário.
- Resumo
- Lei de Ampère: Um condutor percorrido por uma corrente induz a formação de um campo magnético ao seu redor de valor proporcional à corrente;
- Corrente Alternada: A corrente alternada varia ao longo do tempo gerando um campo magnético também variante ao longo do tempo;
- Lei da indução de Faraday: Um campo magnético variante no tempo induz numa espira uma tensão, e por consequência um corrente elétrica, proporcional à intensidade do campo magnético
Levando em conta essas três propriedades, podemos montar um transformador de corrente.
Transformadores de corrente
Existe uma grande gama de sensores de corrente que usam essas propriedades magnéticas. Esse sensores são conhecidos com TC (Transformador de Corrente), que em inglês é CT (Current Transformer).
Um transformador de corrente, nada mais é que um conjunto de espiras que são colocadas ao redor de um condutor ao qual queremos medir a corrente. O transformador de corrente (TC) terá em seus polos uma corrente alternada induzida Is, que é proporcional a corrente alternada Ic que percorre o condutor ao qual pretendemos medir a corrente elétrica.
A corrente induzida no TC também será inversamente proporcional ao número de espiras de sua bobina.
Esse sensores são divididos em 2 modelos: Os split-core (núcleo dividido) e os solid-core (núcleo sólido).
Transformador de corrente SCT-013
SCT é a sigla para Split-core Current Transformer, ou seja, Transformador de corrente de núcleo dividido. Para fazer fazer a medição da corrente elétrica o SCT-013 possui uma bobina interna em sua estrutura, como podemos ver na figura abaixo.
Podemos ver essa bobina com mais detalhes na foto a seguir
O circuito é bem simples:
- Os Modelos de SCT-013
Com base nesse princípio de funcionamento, foram criados diferentes tipos de sensores não-invasivos, como pode ser observado em seu datasheet, com o objetivo de atenderem os mais diversos cenários, de forma que não exista um "melhor", mas sim o mais recomendado para a aplicação recorrente.
As duas principais diferenças são a Corrente eficaz máxima a ser medida (Input current) - e o Tipo de saída do sensor (Output type).
É possível observar que somente o modelo SCT-013-000 apresenta uma variação de corrente em sua saída de 0-50mA, já os outros modelos apresentam uma variação tensão de 0-1V, onde por meio destas variações é possível mensurar a corrente elétrica.
Para sabermos qual será a taxa variação tanto de corrente quanto de tensão basta dividirmos o valor máximo da saída pelo valor máximo a ser medido. Abaixo temos alguns exemplos deste cálculo:
- SCT-013-000:
- 0,05 / 100 = 0,5mA. A cada um Ampere a mais ou a menos, sua saída será de 0,5mA para mais ou a menos;
- SCT-013-005:
- 1 / 5 = 0,2V. A cada um Ampere a mais ou a menos, sua saída será de 0,2V para mais ou a menos;
- SCT-013-050:
- 1 / 50 = 0,02V. A cada um Ampere a mais ou a menos, sua saída será de 0,02V para mais ou a menos.
- SCT-013-000 - 100A / 0-50mA
Para esse tutorial usaremos o SCT-013-000. Ele poder medir valores de 0 até 100A de corrente alternada. Em sua saída teremos valores entre 0 a 50mA proporcionais ao valor de corrente percorrido no condutor principal.
Como nosso Arduino só lê valores de tensão, iremos precisar montar um circuito auxiliar para que essa corrente percorra um resistor e assim possamos converter os valores de correntes gerado pelo sensor em valores de tensão. Explicaremos o passo a passo de como dimensionar esse circuito no tópico Entendendo o Hardware.
Mãos à Obra - Monitorando a corrente AC com o Sensor de corrente SCT-013
Componentes necessários
Serão necessários os seguintes componentes para a execução deste projeto:
- 1 x Placa Arduino;
- 1 x Sensor de corrente SCT-013 100A;
- 1 x Protoboard;
- 2 x Resistores de 10kΩ;
- 1 x Resistor de 330Ω;
- 1 x Capacitor eletrolítico de 100uF;
- Jumpers;
Utilizaremos o SCT-013 100A e o Arduino Uno, além de um aparelho que terá sua corrente elétrica medida, no nosso caso, um ferro de solda. Você poderá medir a corrente elétrica de outros dispositivos.
O resistor de 330Ω foi dimensionado por meio de uma sequência de cálculos com o propósito de aumentar a precisão das medidas deste sensor de corrente. Os cálculos poderão ser visto na sessão "Entendendo o SCT-013".
*Caso o seu SCT-013 seja de outro modelo ao invés de 100A, o passo a passo será diferente.
Montando o projeto
Esse sensor de corrente normalmente vem com um plugue P2 do tipo macho em sua ponta. Para esse tutorial nós removemos ele e conectamos os dois fios presentes no interior do cabo diretamente na protoboard. Caso você não queira remover o plugue P2, recomendamos que você adquira um plugue P2 do tipo fêmea para poder utilizar esse sensor de corrente.
Com os componentes em mãos, montaremos o seguinte circuito na protoboard:
Após realizar esta montagem, é necessário conectar o SCT-013 ao condutor por onde a corrente elétrica a ser medida passará.
AVISO: Não conecte este sensor de corrente de acordo com a imagem abaixo, pois não será possível medir a corrente elétrica. A explicação do por quê será feita mais abaixo.
Como a corrente elétrica produz campo magnético conforme seu sentido e o sentido da corrente em um fio é o oposto ao sentido do outro fio, os campos magnéticos produzido pelos dois acabam se anulando. Se não há campo magnético, não há indução magnética no transformador do sensor de corrente, fazendo com que não circule a corrente Is necessária para a medição da corrente Ic consumida. Por esse motivo não podemos conectar este sensor aos dois fios de alimentação.
Com isso finalizamos o hardware do nosso projeto. Agora, bora programar!
Programando
- Bibliotecas necessária
É necessário baixar a biblioteca EmonLib (download). Após baixar, descompacte e mova para a pasta libraries da IDE do Arduino. A EmonLib será utilizada para nos auxiliar a calcular o valor da corrente elétrica consumida.
- Código utilizado
Para sabermos quantos Amperes estão passando pelo condutor, basta realizar a seguinte programação:
#include "EmonLib.h" EnergyMonitor SCT013; int pinSCT = A0; //Pino analógico conectado ao SCT-013 int tensao = 127; int potencia; void setup() { SCT013.current(pinSCT, 6.0606); Serial.begin(9600); } void loop() { double Irms = SCT013.calcIrms(1480); // Calcula o valor da Corrente potencia = Irms * tensao; // Calcula o valor da Potencia Instantanea Serial.print("Corrente = "); Serial.print(Irms); Serial.println(" A"); Serial.print("Potencia = "); Serial.print(potencia); Serial.println(" W"); delay(500); Serial.print("."); delay(500); Serial.print("."); delay(500); Serial.println("."); delay(500); }
Após compilar e enviar o código ao Arduino, os valores de corrente elétrica e potência instantânea serão mostrados no Monitor Serial da IDE do Arduino, e serão atualizados a cada 2 segundos.
Colocando para funcionar
Código compilado e circuito montado! Veja abaixo o resultado.
Entendendo a fundo
Software
– Incluindo as bibliotecas a serem utilizadas no projeto
Inicialmente, observe que foi necessário incluir uma biblioteca no código para que o mesmo pudesse funcionar corretamente. A biblioteca EmonLib.h é a responsável por realizar os cálculos para encontrar o valor eficaz da corrente a ser medida, baseando-se nas amostras colhidas no pinSCT.
#include "EmonLib.h"
– Declarando o objeto SCT013
Em seguida, cria-se um objeto que será utilizado posteriormente para representar o sensor de corrente SCT-013 no código.
Lembre-se: SCT013 é apenas um nome, sendo assim, é importante ressaltar que este objeto poderia ser chamado por qualquer outro nome, como por exemplo, sensorSCT.
EnergyMonitor SCT013;
– Definindo as configurações iniciais
Declaramos pinSCT = A0 para poder facilitar e tornar intuitivo o uso da porta analógica do arduino.
int pinSCT = A0; //Pino analógico conectado ao SCT-013
Declaramos duas variáveis, uma chamada Tensao, e atribuímos o valor de 127, que equivale a tensão da rede aqui no nosso estado, e outra chamada Potencia, que será utilizada para reservar o resultado da multiplicação da tensão e da corrente.
int tensao = 127; int potencia;
No void setup(), chamamos a função SCT013.current(pinSCT, 6.0606) da biblioteca EmonLib, para que seja realizado o cálculo do valor eficaz da corrente, onde ele se baseará nas amostras lidas do pinSCT, e é empregado um valor de calibração de 6.0606 que ensinaremos como encontra-lo mais abaixo.
SCT013.current(pinSCT, 6.0606);
Habilitamos também a comunicação serial entre o arduino e o computador por meio do comando Serial.begin(9600).
Serial.begin(9600);
Caso você tenha dúvidas sobre como utilizar a comunicação serial do arduino, recomendamos que veja o tutorial Comunicação Serial Arduino (clique aqui), presente no portal.
– Aquisição do valor de corrente
Na função void loop(), utiliza-se primeiramente a função SCT013.calcIrms() para atribuir o valor de corrente à variável Irms. O valor entre parênteses representa o número de amostras que a função irá ler do pinSCT.
double Irms = SCT013.calcIrms(1480);
Veja que SCT013 é o nome que definimos para o objeto. Para usar uma função ligada a esse objeto, colocamos seu nome seguido de ponto e o nome da função. Ex: nomeobjeto.calcIrms().
- Cálculo da potência instantânea
Por meio da multiplicação da corrente Irms pela tensão estipulada, conseguimos descobrir a potência do dispositivo.
potencia = Irms * tensao;
Em seguida imprimimos o valor de corrente e da potência no monitor serial:
Serial.print("Corrente = "); Serial.print(Irms); Serial.println(" A"); Serial.print("Potencia = "); Serial.print(potencia); Serial.println(" W");
Esperamos um tempo para a próxima medição.
delay(500); Serial.print("."); delay(500); Serial.print("."); delay(500); Serial.println("."); delay(500);
Hardware
- Corrente gerada pelo sensor
O sensor é calibrado para medir a corrente alternada máxima de 100A AC. Esse valor de 100A é o valor RMS, que também é chamado de valor eficaz. O valor RMS é igual ao máximo valor que a corrente pode alcançar (corrente de pico) dividido pela raiz quadrada de dois.
Então, temos que a corrente de pico máxima medida é de 141.4A:
i (medido) = √2 * i (rms) = 1,414 * 100A = 141,4 A
Sabendo que para uma corrente de 100A no primário, ele produz 50mA no secundário, é só jogarmos na fórmula de relação de transformação. O resultado será:
N1 / N2 = I2 / I1
- I1 = corrente no primário (corrente a ser medida);
- I2 = corrente no secundário;
- N1 = número de votas do primário (no caso deste sensor, N1 será igual a 1);
- N2 = número de voltas do secundário.
N2 = 2000 espiras.
A corrente na saída do sensor é inversamente proporcional ao número de voltas (aqui é 2000):
i (sensor) = i (medido) / numero_de_espiras = 141,4A / 2000 = 0,0707A
Teremos na saída do sensor o sinal da corrente induzida semelhante ao da figura a seguir:
- Transformando corrente em tensão - Calculando a resistência de carga
O Arduino UNO só realiza, em seus pinos de entrada analógica, a leitura de níveis de tensão (entre 0V a 5V). Dessa forma, precisamos converter o sinal de corrente alternada do SCT-013 para um valor de tensão que seja legível para o Arduino.
O primeiro passo é adicionar um resistor de carga entre os polos do sensor de corrente:
Como a corrente alterna em torno de zero, vamos escolher um resistor que de na saída um valor máximo de tensão de 2,5V.
R(carga) = U(sensor)/I(sensor) = 2,5V / 0,0707A = 35,4Ω
O resistor de carga ideal é de 35,4Ω para uma corrente de até 100A, nesse caso usariamos um resistor de 33Ω. Dessa forma teremos o seguinte sinal de tensão sobre o resistor de carga:
OBS: Para nosso projeto, não iremos medir valores maiores que 10A. Dessa forma, podemos considerar que nossa corrente máxima é 10 vezes menor. Logo:
i (sensor) = i (medido) / numero_de_espiras = 14,14A / 2000 = 0,00707A
R(carga) = U(sensor)/I(sensor) = 2,5V / 0,00707A = 354Ω
Portanto, para nosso projeto adotamos o resistor de 330Ω.
Ou seja, você pode calcular o resistor ideal para a faixa de operação que você precisa. Se for 100A, você pode adotar o de 33Ω, se for de 10A você pode usar um resistor de 330Ω. Para outros valores, basta você calcular.
Seguiremos essa explicação considerando a faixa de operação de 100A, que é o máximo para nosso sensor.
- Convertendo sinal de tensão AC para DC
Agora temos um sinal de tensão alternada variando entre 2,5V positivo e 2,5V negativo. O Arduino não pode medir tensão negativa, então precisamos somar 2,5 V ao sinal para que ele varie entre 0V a 5V.
O primeiro passo para isso é montar um divisor de tensão usando a alimentação de 5V que a placa Arduino fornece. Assim, consideramos R1 e R2 iguais a 10kΩ, e com isso, a tensão sobre eles será igual, pois os 5V provenientes do Arduino se dividirá igualmente entre eles.
Em seguida adicionamos um capacitor entre o GND e a saída de 2,5V no meio do divisor de tensão:
Esse circuito funcionará como uma bateria de 2,5V adicionando essa tensão à fonte AC. Este valor de tensão que acrescentamos a forma de onda é chamado de offset.
Veja como vai fica nosso circuito:
Na figura a seguir mostramos o circuito com seus respectivos sinais:
Como explicado, o circuito de offset funciona como uma fonte tensão de 2,5V DC, somando essa tensão à senoide do SCT-013. O circuito poderia ser ilustrado como a figura a seguir:
- Calibrando o software
Agora que sabemos o sensor carga, modificamos a função SCT013.current onde definimos o pino de entrada e o valor de calibração.
SCT013.current(pinSCT, Valor_de_Calibracao);
Este valor é de calibração, destinado justamente para caso queiramos mudar o valor do resistor de carga. Para descobrir ele, basta dividir o número total de voltas (espiras) do secundário pelo valor do resistor de carga dimensionado:
- Valor_de_Calibração = 2000 / 33
- Valor_de_Calibração = 60,606
Dessa forma, teremos:
SCT013.current(pinSCT, 60,606);
obs: Para nosso projeto prático nosso resistor escolhido foi de 330Ω devido ao fato de trabalharmos com uma faixa de operação de 10A. Dessa forma o valor de calibração usado no projeto prático foi de 6,0606.
Valor_de_Calibração = 2000 / 330 = 6,0606
Mudando o range de medição
Calculamos até aqui o valor de uma resistência de carga e valor de calibração do software que possibilita nosso software medir valores de corrente eficazes de até 100A, que é o máximo valor de projeto do sensor. Só que conforme a aplicação, nunca chegaremos a correntes tão altas. Por isso, podemos calibrar nosso software e circuito para ler valores de máxima corrente distintos, desde que estejam dentro do permitido para esse sensor.
Talvez você tenha percebido inclusive que o valor de resistência encontrado em nossos cálculos (33Ω) foi 10 vezes menor que o usada em nossa experiencia (330Ω). Para nosso projeto adotamos uma corrente máxima de 10A, visto que a maiorias dos eletrodomésticos consomem correntes menores que esse valor.
Para calcular a resistência de carga adequada basta repetirmos os seguintes passos:
- Passo 1 - Escolher a corrente rms máxima que será medida pelo circuito
imax (rms) = 10A
- Passo 2 - Converter esta corrente para o valor de pico:
i (medido) = √2 * imax (rms) = 1,414 * 10A = 14,14 A
- Passo 3 - Descobrir o número total de espiras da bobina do secundário:
Sabendo que para uma corrente de 100A no primário, ele produz 50mA no secundário, é só jogarmos na fórmula de relação de transformação. O resultado será:
N1 / N2 = I2 / I1
- I1 = corrente no primário (corrente a ser medida);
- I2 = corrente no secundário;
- N1 = número de votas do primário (no caso deste sensor, N1 será igual a 1);
- N2 = número de voltas do secundário.
N2 = 2000 espiras.
- Passo 4 - Calcular a corrente de pico máxima do secundário do SCT-013:
i (sensor) = i (medido) / numero_de_espiras = 14,14A / 2000 = 0,00707A
- Passo 5 - Dimensionar o resistor de carga:
R(carga) = U(sensor)/I(sensor) = 2,5V / 0,00707A = 354Ω
Para o projeto, arredondamos este valor para 330Ω, que é um valor comercial de resistor.
R(carga) = 330Ω
- Passo 6 - Colocando o valor de calibração no software:
Agora que sabemos o sensor carga, modificamos a função SCT013.current onde definimos o pino de entrada e o valor de calibração.
SCT013.current(pinSCT, Valor_de_Calibracao);
Este valor é de calibração, destinado justamente para caso queiramos mudar o valor do resistor de carga. Para descobrir ele, basta dividir o número total de voltas (espiras) do secundário pelo valor do resistor de carga dimensionado:
Valor_de_Calibração = N2 / R(carga)
Valor_de_Calibração = 2000 / 330
Valor_de_Calibração = 06,0606
Dessa forma, teremos:
SCT013.current(pinSCT, 6.0606);
Pronto, agora você sabe como adaptar o hardware para o seu projeto.
Desafio
Desenvolva um projeto em que seja possível medir a potência requisitada por um determinado equipamento. Para isto, utilize o sensor de corrente SCT-013 (tratado com detalhes neste material) em conjunto com, por exemplo, o sensor de tensão GBK P8.
Considerações finais
Esperamos que este tutorial tenha esclarecido algumas dúvidas sobre os procedimentos necessários para realizar monitoramento das correntes elétricas utilizadas nos acionamentos dos seus equipamentos. Obrigado pela atenção e continue buscando conhecimento no portal do Vida de Silício.
Usando Transistor no Arduino
Usando Transistor no Arduino
Porquê usar transistores?
Os microcontroladores, tais como Atmega, PIC e MSP, são dispositivos lógicos. Eles são usados com o intuito de ser a inteligencia do circuito. Dessa forma, esses componentes não são produzidos para suportar grandes correntes. O Arduino UNO, por exemplo, que usa o Atmega328, suporta um máximo de 40mA em suas portas I/O e fornece uma tensão de 5V.
O Arduino UNO suporta um máximo de 40mA em suas portas I/O
Para muitas aplicações isso não é o suficiente. Segue alguns exemplos:
- Motores DC;
- Fitas de LED;
- Relé;
- Ou qualquer componente que precise de mais de 5V ou 40mA.
A solução pode parecer complicada mas é simples, o nome dela é Transistores.
Nesse Post iremos focar nos transistores BJT (junção bipolar), tentarei ser o mais prático possível, pensando em alguém que não saiba nada de eletrônica. Caso queira saber mais sobre transistores, existe bastante material na internet explicando os vários tipos e suas propriedades de forma mais detalhada.
Um Pouco de História!
Uma das invenções mais importantes do Milênio, os transistores possibilitaram uma revolução tecnológica inimaginável. Agora mesmo, usando o seu computador ou qualquer aparelho eletrônico você está colhendo os frutos dessa invenção.
Antes dos transistores, os computadores funcionavam a partir do uso de válvulas termoiônicas, elas até que funcionavam bem, porém ocupavam muito espaço fazendo com que computadores ocupassem espaços muito grandes. Dessa forma, se viu a necessidade de descobrir uma forma de utilizar um substituto menor.
Em 1947, nos Laboratórios da Bell Telephone, os pesquisadores John Bardeen e Walter Houser Brattain inventaram o primeiro transistor feito de germânio. Em 23 de Dezembro de 1948, foi demonstrado para o mundo por John Bardeen, Walter Houser Brattain e William Bradford Shockley, que ganharam o Nobel de Física em 1956.
Hoje, o material semicondutor mais usado na fabricação de transistores é o silício. O silício é preferível porque possibilita o funcionamento a temperaturas mais elevadas (175 ºC, quando comparado com os ~75ºC dos transistores de germânio) e também porque apresenta correntes de fuga menores. Com a evolução tecnológica existe a necessidade de diminuir cada vez mais o tamanho dos transistores para que se diminua o tamanho dos equipamentos e que se aumente a capacidade de processamento. Uma das novas tecnologias é o chamado transistor 3D que tem dimensões nanométricas.
Como funcionam?
Imagine uma válvula hidráulica, a do seu chuveiro por exemplo, ela tem a função de controlar o fluxo de água que sairá pelo chuveiro, correto? Podemos ter a válvula totalmente fechada, totalmente aberta ou em uma abertura especifica, limitando a corrente de água.
Nessa válvula temos:
- Uma entrada, onde entra a corrente de água;
- Uma saída, nesse caso vai para o chuveiro
- Um elemento de controle de fluxo, no caso o volante da válvula.
O transistor é muito semelhante, porém tratamos de uma corrente de elétrons. O transistor atua como uma válvula. No transistor NPN, temos:
- Uma entrada, chamada coletor, por onde entra a corrente de elétrons;
- Uma saída, chamada emissor, por onde sai a corrente de elétrons;
- E um entrada de controle, chamada base, que no caso é controlada a partir de uma corrente de controle.
Como assim, corrente de controle?
Quando trabalhando no estado Ativo, o transistor aumenta ou reduz o fluxo de corrente entre o coletor e o emissor conforme à corrente de base aumenta ou reduz. Dessa forma, existe uma relação entre corrente do emissor e coletor com a corrente de base. Ela é:
Icoletor ≅ Iemissor ≅ Ibase.hfe
Repare que a corrente de emissor e coletor são aproximadamente iguais (em breve explicaremos porque) e que as duas são proporcionais a corrente de base.
Mas quem é esse hfe?
O hfe, também conhecido como β (beta), é o coeficiente de ganho de corrente. Ele relaciona a corrente de base com a corrente de coletor e emissor. Todo transistor tem o seu valor, esse pode ser consultado na folha de dados do componente (datasheet). Esse valor costuma ser na ordem de centenas. Assim, a corrente de base é muito pequena, em relação às correntes de coletor e de base.
Contudo, a corrente de base tem que fluir para algum lugar. No caso do transistor NPN, ela se junta a corrente de coletor, fluindo em direção ao emissor. Logo, no transistor NPN:
Iemissor = Icoletor + Ibase = Ibase.hfe + Ibase
Iemissor = Ibase.(hfe + 1) ≅ Ibase.hfe
Icoletor ≅ Iemissor
Como hfe >> 1 (muito maior que 1), podemos aproximar o termo (hfe+1) para hfe e assim considerar que as correntes de emissor e coletor são aproximadamente iguais, cometendo um erro inferior a 3% em transistores típicos.
Mas o que acontece se a corrente de base for muito grande?
O transistor entrará em um estado de Saturação. Chega um instante em que a corrente de base é tão grande que a corrente de coletor não consegue ser proporcional a ela. Nesse instante, o transistor libera o máximo de corrente de coletor que pode. É como um registro totalmente aberto.
Icoletor < Ibase . hfe
(Condição de Saturação)
E como restringir toda a corrente?
Quando nenhuma corrente flui entre coletor (c) e emissor (e), podese dizer que o transistor está em corte. Para que possamos entrar nesse estado, algumas condições são necessárias No transistor NPN, as condições são:
- Vb < Vc, Tensão de coletor maior que tensão de base;
- Vb - Ve < 0.7, Tensão de base deve ser 0,7V maior que tensão de Emissor.
Observe que caso o emissor tenha uma tensão de 0V e colocarmos uma tensão de 0V na base, é o suficiente para que o transistor não conduza. Já que a tensão de base não será 0,7V maior que a tensão de emissor.
Será que entendi?
O transistor possui 3 estados de operação, são eles:
- Ativo, Icoletor ≅ Iemissor ≅ Ibase.hfe;
- Corte, Icoletor ≅ Iemissor ≅ 0;
- Saturado, Icoletor < Ibase.hfe (deixa toda a corrente fluir).
Para o transistor NPN funcionar em estado ativo é necessário que:
- Vb < Vc, Tensão de coletor maior que tensão de base;
- Vb - Ve < 0.7, Tensão de base 0,7V maior que tensão de Emissor;
Transistor PNP
Além do transistor NPN, existe também o PNP. Os dois possuem configurações internas diferentes que mudam um pouco o funcionamento deles.
- No transistor NPN a corrente flui do coletor para o emissor, e a corrente de base entra somando junto a contente de emissor, fluindo da base para o emissor.
- No transistor PNP a corrente flui do emissor para o coletor e a corrente de base flui do emissor para a base.
Veja a imagem a seguir:
Além disso, os parâmetros para que não entre em Corte mudam. Para o transistor PNP funcionar, precisamos que:
- Tensão de Base seja maior que tensão de Coletor;
- Tensão de Emissor 0,7V maior que tensão de Base;
Observe que a corrente de base continua sendo muito pequena, considerando Icoletor ≅ Iemissor.
Qual transistor usar?
Para selecionar um transistor, é importante verificar os níveis de corrente, tensão e dissipação de potência em que ele irá trabalhar. Isso é feito na etapa de projeto, utilizando teoria de circuitos ou (quando possível) simulando o comportamento do circuito em softwares específicos. Então, deve-se escolher um dispositivo com capacidade de suportar tais correntes, tensões. Para isso existem duas abordagens principais. A mais comum e simples, é utilizar dispositivos de projetos parecidos (amplamente disponíveis na internet) pois já foram testados por outras pessoas. A abordagem ideal porém mais trabalhosa é consultar a folha de dados (datasheet) dos transistores. Nos datasheets é possível descobrir a SOA (Safety Operation Area) ou 'área de operação segura' dos transistores e assim poder confiar no seu funcionamento correto e na sua durabilidade.
O que devemos verificar:
- Pol: polarização; negativa quer dizer NPN e positiva significa PNP.
- VCEO: tensão entre coletor e emissor com a base aberta.
- VCER: tensão entre coletor e emissor com resistor no emissor.
- IC: corrente máxima do coletor.
- PTOT: é a máxima potência que o transistor pode dissipar (Corrente Máxima de coletor vezes Tensão máxima entre coletor e base)
- hFE: ganho (beta).
- Encapsulamento: a maneira como o fabricante encapsulou o transistor, nos fornece a identificação dos terminais.
Como usar transistores no Arduino?
Veremos agora como usar um transistor NPN junto ao Arduino. Existem varias configurações de circuitos usando transistores, mas vamos nos ater a uma das mais simples. Ela é apresentada na figura a seguir. Nesse caso, estamos controlando um LED através do Arduino com o auxilio do transistor:
Saída Arduino
A saída do Arduino será:
- 5V, quando em nível lógico alto;
- 0V, quando em nível lógico baixo.
Para que o LED acenda, precisamos que quando a saída do Arduino estiver em nível lógico alto, o transistor conduza (Estado Ativo ou Saturado) e que quando estiver em nível lógico baixo, não conduza (Estado de Corte).
Relembrando
O transistor possui 3 estados de operação, são eles:
- Ativo, Icoletor ≅ Iemissor ≅ Ibase.hfe;
- Corte, Icoletor ≅ Iemissor ≅ 0;
- Saturado, Icoletor < Ibase.hfe (deixa toda a corrente fuir).
Para o transistor NPN conduza precisamos que:
- Vb < Vc, Tensão de coletor maior que tensão de base;
- Vb - Ve < 0.7, Tensão de base 0,7V maior que tensão de Emissor;
Transistor em Corte
Como o emissor está conectado ao GND, sua tensão é de 0V. Assim, quando a saída do Arduino estiver em 0V não atenderá um dos requisitos para que o transistor conduza (Tensão de Emissor 0,7V maior que tensão de Base) . Dessa forma o transistor entrará em estado de Corte.
Transistor Conduzindo
Quando o Arduino estiver com 5V em sua saída, sendo a tensão de coletor maior que a tensão de base, teremos o transistor na região ativa ou saturada. Para garantimos que quando em região ativa teremos a corrente de coletor suficiente para acionar o LED precisamos dimensionar os resistores de base(R2) e de coletor(R1) corretamente.
Resistor R1
O resistor R1 tem função de limitar a corrente de coletor. Para acionar um LED, precisamos de uma corrente de pelo menos 10mA. Para uma tensão de 9V um resistor de 150Ohm atende muito bem, veja os cálculos a seguir.
Aplicando a 1ª lei de Ohm considerando uma queda de tensão de 2,5V no LED e desconsiderando a queda de tensão no transistor, temos:
Icoletor-máx = (Vfonte - Queda de tensão no componente) /R = (9-2,5)V/150 Ohm = 43mA
O que é suficiente para alimentar o LED.
Resistor R2 - O mais importante
O resistor R2 tem a função de limitar a corrente de base. Sendo ela responsável por controlar a corrente que irá fluir do coletor para o emissor, temos que escolhe-la com cuidado para garantir a mínima corrente no coletor que conseguirá acender o LED.
Aplicando a 1ª lei de Ohm temos que a corrente de base é:
Ibase = (5-0,7)/R2 = 4,3/R2-max
Mas precisamos que a corrente de coletor seja pelo menos de 10mA, para isso temos que:
Icoletor-min ≅ Iemissor-min ≅ 10mA = 0,01A = Ibase.hfe
0,01A = Ibase-min.hfe
Considerando que estamos usando o transistor BC547A, temos que seu hfe = 110(Consultado na Folha de Dados - datasheet), dessa forma:
0,01A = Ibase.110
Ibase-min=0,01/110 = 0,00009= 0,09mA
Logo:
Ibase-min= 0,00009 = 4,3/R2
R2-max = 4,3/0,00009 =52,2KOhm
Dessa forma, devemos usar um resistor menor que o calculado. Vamos adotar 4,7KOhm. Com esse resistor, teremos:
Ibase=4,3/4,7KOhm=0,9mA
Icoletor'=Ibase.hfe
Icoletor'=0,9mA.110=99mA
Como: Ibase.hfe > Icoletor -> 99mA > 43mA, então:
Transistor Saturado
Resumo dos cálculos
Requisito
Icoletor > 10mA -> Corrente de coletor deve ser maior que 10mA quando o transistor estiver conduzindo para que o LED acenda.
Componentes
- Fonte externa de 9V;
- Transistor BC547A -> hfe=110;
- R1 -> resistor que limitará a corrente de coletor, definindo a corrente máxima;
- R2-> resistor que define a corrente de base que por sua vez define a máxima corrente de coletor.
Especificações
- R1=150 Ohm, Limita a corrente de coletor em 43mA
- R2 < 52,2 kOhm, adotamos R2=4,7 kOhm para corrente de base mínima de 0,09mA, logo a corrente de coletor mínima é 10mA
O que você precisa saber?
Ao projetar um circuito usando o transistor NPN, devemos:
- Escolher qual transistor usar a partir das tensões e correntes máximas;
- Dimensionar os resistores R1 e R2.
Para dimensionar R1, que é o resistor responsável por limitar a corrente de coletor, precisamos saber:
- Qual a tensão da fonte;
- Qual a queda de tensão no componente;
- Qual a corrente necessária para que o componente controlado funcione corretamente (Icoletor-min).
Formula para calculo do R1:
Icoletor-min =(Vfonte - Queda de tensão no componente) /R1-max
R1 não deve ser muito menor que R1-max.
Para dimensionar R2, que é responsável por controlar a corrente de coletor através da corrente de base (Icoletor max = Ibase.hfe), precisamos saber:
- Qual a corrente necessária para que o componente controlado funcione corretamente (Icoletor-min);
- hfe do transistor escolhido.
Formula para calculo do R2:
Ibase = 4,3/R2-max
Ibase = Icoletor/hfe
obs.: É importante dimensionar bem esse resistor para que não se restrinja demais a corrente de coletor do transistor. O ideal, para esse tipo de aplicação, é trabalharmos com o transistor saturado (Icoletor < Ibase.hfe). Para isso, geralmente escolhemos um resistor bem menor que o R2 calculado.
DICAS
Para esse tipo de aplicação, na maioria dos casos, podemos adotar:
- R1 = 150 Ohm;
- R2 = 1 kOhm a 4,7 kOhm
- Fonte externa até 12V para o BC547A
No lugar do LED podemos colocar um relé ou outro componente que consuma até 100mA, caso esteja usando o BC547A
Costumo usar na maioria das vezes os seguintes transistores NPN:
- BC547A (Tensão de coletor máx =45V; Corrente de coletor máx = 100mA ; hfe=110)
- BD137 (Tensão de coletor máx =60V; Corrente de coletor máx =1,5A ; Corrente de Base máx = 500mA; hfe=40)
- TIP122 (Tensão de coletor máx =100V; Corrente de coletor máx = 5A ; Corrente de Base máx = 120mA; hfe= 1000)
Fechamento
Esperamos que tenham gostado, deixe seu comentário com duvidas, sugestões ou com a foto ou vídeo de seu projeto!! Compartilhe à vontade.