quarta-feira, 9 de novembro de 2016

Controlando módulo relé 16 canais via I2C com Arduino




Objetivo

Controlar um módulo relé 16 canais com arduino através de interface em display de cristal liquido 16x2 via modulo I2C PCA9685

Cada canal do relé pode ser usado para controlar carga em até 240V / 10A. Como lâmpadas, pequenos motores e outros eletro-eletrônicos.

O que foi utilizado

Módulo relé 16 canais
Arduino UNO R3
LCD shield
Modulo I2C PCA9685 (nativamente um modulo para controle de servomotores)
Fonte 12V
Jumpers

O Módulo relé 16 canais

>> Tensão de alimentação: 12V;
>> Possui regulador de tensão integrado 5V o que permite alimentar o arduino e demais dispositivos através dos pinos de saída 5V e GND;
>> Sinal de acionamento, lógico: Nível baixo GND. O ideal para uso com o PCA9685 seria o com acionamento em nível alto já que o módulo parece inicializar com todos os pinos em nível baixo.


O LCD shield

>> Display LCD16x2 (pinos D4 a D10 do arduino)
 >> 5 botões, ligados a apenas um pino analógico do arduino, o pino A0, via divisor de tensão.
quando um botão é pressionado seu valor correspondente (entre 0 e 1023) pode ser lido com a função analogRead(A0); . Dessa forma é possível identificar qual botão foi pressionado.

O Modulo I2C PCA9685

trás mais detalhes sobre esse módulo.

Montagem



Como funciona

O canal desejado é selecionado via botões UP e DOWN.
O display mostrará o estado do canal selecionado: ON ou OFF
Para alterar o estado do canal pressionar o botão SELECT  e em seguida LEFT ou RIGHT para alternar entre ON e OFF. Após selecionar o estado desejado pressionar novamente SELECT para validar a alteração.


Programa

O PCA9685 é um modulo PWM, saída analógica então para usá-lo com o modulo relé trabalhamos nos extremos da saída PWM: 0V para nível baixo (aciona relé) e 4095 para nível alto (desliga relé). Se estiver usando um módulo relé com acionamento por nível alto será necessário inverter no programa onde tem 4095 para 0 e vice versa no local indicado.

É necessário adicionar a biblioteca: Adafruit_PWMServoDriver
 

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); //LiquidCrystal lcd(RS,E, D4, D5, D6, D7);

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

int canal_state[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


// BOTOES

int DLY_BT = 300;
boolean Right;
boolean Up;           
boolean Down;
boolean Left;
boolean Select;

int cnt_canal = 0;


void setup() {
  
  //delay(1000);
  
  lcd.begin(16, 2);
  pwm.begin();
  pwm.setPWMFreq(1600);  // This is the maximum PWM frequency

for(int a= 0; a<16; a++)
pwm.setPin(a,4095); // pino, valor, inverte 

delay(1000);

lcd.print("Modulo rele 16CH");

  lcd.setCursor(0, 1);
  lcd.print("                "); 
  lcd.setCursor(0, 1);
  lcd.print("Canal ");
  lcd.print(cnt_canal + 1);
  if(canal_state[cnt_canal] == 0)
  lcd.print(": OFF");
  else
  lcd.print(": ON");


}

void loop() {
  

  Zera_bts();
  Le_bts();  // ler botoes

  if( Up == true && cnt_canal > 0)
  {
  cnt_canal --;
  lcd.setCursor(0, 1);
  lcd.print("                "); 
  lcd.setCursor(0, 1);
  lcd.print("Canal ");
  lcd.print(cnt_canal + 1);
  if(canal_state[cnt_canal] == 0)
  lcd.print(": OFF");
  else
  lcd.print(": ON");
  }
  else if( Down == true && cnt_canal < 15)
  {
  cnt_canal ++;
  lcd.setCursor(0, 1);
  lcd.print("                "); 
  lcd.setCursor(0, 1);
  lcd.print("Canal ");
  lcd.print(cnt_canal + 1);
  if(canal_state[cnt_canal] == 0)
  lcd.print(": OFF");
  else
  lcd.print(": ON");
  }
  
//  if(Down == true && cnt_canal == 16}
   
  
  
 // Zera_bts();
//  Le_bts();  // ler botoes
 
  if(Select == true)
 {
           lcd.setCursor(0, 1); 
           lcd.print("                "); 
           lcd.setCursor(0, 1);
           lcd.print("SetCanal ");
           lcd.print(cnt_canal + 1);
           if(canal_state[cnt_canal] == 0)
           lcd.print(": OFF");
           else
           lcd.print(": ON");
           
               Zera_bts();
               Le_bts();  // ler botoes
                        
              while(Select != true){
                
               Zera_bts();
               Le_bts();  // ler botoes
                
              if(Right == true || Left == true)
             {
              canal_state[cnt_canal] = ! canal_state[cnt_canal];
              lcd.setCursor(0, 1);
              lcd.print("                "); 
              lcd.setCursor(0, 1); 
              lcd.print("SetCanal ");
              lcd.print(cnt_canal + 1);
              if(canal_state[cnt_canal] == 0)
              lcd.print(": OFF");
              else
              lcd.print(": ON");
              delay(300);           
      
              }
              } 
              
                 lcd.setCursor(0, 1); 
                 lcd.print("                "); 
                 lcd.setCursor(0, 1);
                 lcd.print("Canal ");
                 lcd.print(cnt_canal + 1);
                 if(canal_state[cnt_canal] == 0)
                 {
                 lcd.print(": OFF");
                 pwm.setPin(cnt_canal , 4095);  // trocar para 0 se o modulo
                 }                             // acionar em nivel alto
                 else
                 {
                 lcd.print(": ON");
                 pwm.setPin(cnt_canal , 0);  // trocar para 4095 se o modulo
                 }                          // acionar em nivel alto
    }

}

///FUNÇÃO LÊ BOTÕES/////////////////////////////
// {50, 200, 400, 600, 800 };
 void Le_bts()
 {
   while( Right == false &&
             Up == false &&        
           Down == false &&   
           Left == false &&    
         Select == false )
   {
    
   int input = analogRead(0);   //le o pino analogico onde esta os botoes
   
   if (input < 40)
   Right = true;
   else if(input > 50 && input < 150)
   Up = true;
   else if(input > 200 && input < 300)
   Down = true;
   else if(input > 380 && input < 450)
   Left = true;
   else if(input > 550 && input < 700)
   Select = true;
  

   }
    delay (DLY_BT);
 }


///FUNÇÃO ZERA BOTÕES/////////////////////////////
 
 void  Zera_bts()                                                                                                       
   {
    
 Right = false;
 Up = false;        
 Down = false;    
 Left = false;    
 Select = false;    
    
  }

terça-feira, 8 de novembro de 2016

Controlador PWM 16 CH PCA9685 com servos e Led






Teste com servos

Teste com leds


Foram utilizados os exemplo que acompanham a biblioteca da adafruit para arduino nos testes descritos aqui. Em breve postarei dois outros exemplos de utilização deste módulo, um deles com o ESP8266.

Com esse módulo baseado no PCA9685 é possível adicionar 16 portas de  PWM de 12 bits ao arduino, ao esp8266 ou a outro microcontrolador com I2C. Pode controlar, por exemplo, 16 servomotores, 16 leds inclusive a intensidade do brilho, entre outras aplicações.

Características do módulo


>> 16 canais;
>> Resolução do PWM: 12bits 4096 valores possíveis;
>> Frequências: 40 - 1000Hz;
>> Tensão de alimentação 2,3 V to 5,5 V;
>> Corrente máxima saída (pinos de PWM)  25mA;
>> Tensão lógica: 3 a 5V;
>> Tensão para servos (V+) máxima:  6V;


Datasheet do módulo adafruit
 
Datasheet do CI
 
Pinagem:



Endereço I2C

A comunicação I2C utiliza apenas dois fios, um para clock (SCL) e outro para dada (SDA). Nela é possível, teoricamente conectar até 128 elementos em um mesmo barramento. Cada elemento é definido por um endereço. Esse endereço é definido via hardware. O fabricante seguindo as normas do padrão I2C determina o endereço ou faixa de endereços quando o dispositivo é projetado.

Neste módulo:


>> 64 endereços I2C possíveis;
>> Dois endereços reservados:  LED All Call address (1110 000) and Software Reset (0000 0110);
>> Permite ligar, teoricamente, até 62 módulos no mesmo barramento I2C. Endereço padrão 0x40 (em hexadecimal) , B1000000 (em binário)

O endereço I2C pode ser alterado através dos jumpers A0 a A5 na placa. Eles estão todos abertos por padrão.



Para mudar o endereço basta fechar com solda, alterando o bit para 1, o(s) jumper(s) correspondente ao endereço desejado. Observe que o primeiro dígito do endereço é fixo.




fixo
A5
A4
A3
A2
A1
A0
jumper fechado (1). aberto (0)
1
0
0
0
0
0
0
endereço padrão ( todos os jumpers abertos)

Fechando o jumper A0, por exemplo teremos o endereço !2C: B1000001 (em binário) ou 0x41 (em hexa)

Ligação com os servos



Ligação com os leds



O programa
Conforme mencionado no inicio foram utilizados os código que acompanham a biblioteca da adafruit. Ela pode ser baixada pelo link abaixo.





Esta biblioteca tem 2 exemplos:




 pwmteste >> usado no exemplo dos leds
  servo >> usado no exemplo dos servos