quinta-feira, 19 de outubro de 2017

Detecção de gestos com APDS-9960



Objetivo

Identificar gestos mostrando a direção por setas em um display


O que foi usado


>> APDS-9960

O APDS-9960 é um sensor de gestos, cor RGB, luminosidade e proximidade. Projetado nativamente para embarcar celulares.
Nesse experimento usando um módulo com o sensor testamos a detecção de gestos.


                                       


>> Tensão de alimentação: 3.3VCC;
>> Interface de comunicação: I2C;
>> Endereço I2C: 0x39;
>> Resolução até 16 bits;
>> Função de interrupção programável com limite superior e inferior; 
>> Alta sensibilidade pode ser usado atrás de vidro escurecido;
>> Desempenho em baixa luminosidade na detecção de proximidade, 0,01 lux;
>> LED IR integrado e driver de LED síncrono;
>> Faixa de detecção: 10 a 20cm;
>> Dimensões aproximadas: 1,4cm x 1,4cm;

>> Pinagem:

> VIN (+3.3)
> GND (-)
> SCL (relógio I2C)
> SDA (dados I2C)
> INT (interrupção)



>> Módulo matriz de leds com MAX7219




>> Pinagem:

> VIN (+5)
> GND (-)
> DIN (dada)
> CS (load)
> CLK (clock)


>> Arduino UNO






Montagem





 Programa

O código utiliza a biblioteca da sparkfun para o APDS-9960 e foi baseado em um de seus exemplos.


Como o ID do sensor que usamos ( 0xA8 ) é diferente do da sparkfun ( 0xAB). Para funcionamento correto foi necessário alterar esse dado no arquivo da biblioteca: SparkFun_APDS9960.h na linha 34

Vem assim:
#define APDS9960_ID_1           0xAB

Alterar para:
#define APDS9960_ID_1           0xA8

Esse arquivo fica dentro da pasta "scr" que estará dentre da pasta da biblioteca : \SparkFun_APDS9960\src

Pode ser aberto com editor de texto como o WorPad ou NotPad++. Este ultimo é próprio para isso. Para salvar é necessário abrir como administrador.


>> Códgo 


// apds9960//////////////////////////////////
#include <Wire.h>
#include <SparkFun_APDS9960.h>

// Pins
#define APDS9960_INT    2 // Needs to be an interrupt pin

// Constants

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;

/////////////////////////////////////////////

int load = 10; // pino do arduino ligado a pino LOAD (CS)
int clock = 11; // pino do arduino ligado a pino CLOCK(CLK)
int dataIn = 12;  // pino do arduino ligado a pino DATA (DIN)

int *aux;

// figuras
int up[8] =   {8,12,14,255,255,14,12,8};
int down[8] = {16,48,112,255,255,112,48,16};
int left[8] = {24,60,126,255,24,24,24,24};
int rigth[8] = {24,24,24,24,255,126,60,24};
int near[8] = {129,66,36,24,24,36,66,129};
int far[8] = {0,0,0,24,24,0,0,0};


int e = 0;

// define  registradores de comando do max7219
// os registradores de digitos vão de 0xx1 a 0xx7

byte max7219_reg_decodeMode  = 0x09;
byte max7219_reg_intensity   = 0x0a;
byte max7219_reg_scanLimit   = 0x0b;
byte max7219_reg_shutdown    = 0x0c;
byte max7219_reg_displayTest = 0x0f;




void setup () {

  pinMode(dataIn, OUTPUT);
  pinMode(clock,  OUTPUT);
  pinMode(load,   OUTPUT);
  pinMode(APDS9960_INT, INPUT);

  Serial.begin(9600);
  digitalWrite(13, HIGH);  

//initiation of the max 7219
  maxSingle(max7219_reg_scanLimit, 0x07);      
  maxSingle(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
  maxSingle(max7219_reg_shutdown, 0x01);    // not in shutdown mode
  maxSingle(max7219_reg_displayTest, 0x00); // no display test
   
  for (e=1; e<=8; e++) { // limpa registradores
    maxSingle(e,0);
  }
  
// the first 0x0f is the value you can set
// range: 0x00 to 0x0f
  maxSingle(max7219_reg_intensity, 0x0f & 0x0f);    
  
  // Initialize interrupt service routine
  attachInterrupt(0, interruptRoutine, FALLING);
  // Initialize APDS-9960 (configure I2C and initial values)
   apds.init();
  // Start running the APDS-9960 gesture sensor engine
  apds.enableGestureSensor(true);
   
} 

void loop () {

   // havendo interrupção o flag vai a 1. A função handleGesture() é chamada
    if( isr_flag == 1 ) {
    detachInterrupt(0);
    handleGesture();
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

void interruptRoutine() {
  isr_flag = 1;
}

// le do sensor que foi o gesto e
// chama a função escolheseta()
// passando o numero correspondente

void handleGesture() {
    if ( apds.isGestureAvailable() ) {
    switch ( apds.readGesture() ) {
      case DIR_UP:
        escolhe_seta(1);
        break;
      case DIR_DOWN:
        escolhe_seta(2);
        break;
      case DIR_LEFT:
        escolhe_seta(3);
        break;
      case DIR_RIGHT:
        escolhe_seta(4);
        break;
      case DIR_NEAR:
        escolhe_seta(5);
        break;
      case DIR_FAR:
        escolhe_seta(6);
        break;
     // default:
      //  Serial.println("NONE");
    }
  }
}


void escolhe_seta(int num)
{
  // escolhe a figura
 switch(num){
 
 case 1:
 aux = up;
 break;
 
 case 2:
 aux = down;
 break;

 case 3:
 aux = left;
 break;

 case 4:
 aux = rigth;
 break;

 case 5:
 aux = near;
 break;

 case 6:
 aux = far;
 break;

 
}
  // mostra no display
    for(int i=1;i<=8;i++)
   {
    maxSingle(i,aux[i-1]);                  
   }
 
  
}

void maxSingle( byte reg, byte col) 
{    
  digitalWrite(load, LOW);       // begin
  
  shiftOut(dataIn, clock, MSBFIRST, reg); //endereço de registrador
  shiftOut(dataIn, clock, MSBFIRST, col); // byte a ser gravado
     
  digitalWrite(load, LOW);    
  digitalWrite(load,HIGH); 
}

segunda-feira, 24 de abril de 2017

Modulo relé 16CH via WIFI com esp8266-01






Objetivo


Controlar, via rede wifi, um módulo relé 16ch


O que foi usado


>> Módulo wifi ESP8266 ESP-01 Com o firmware ESP Easy gravado





Para saber como gravar o firmware ESP Easy no ESP8266 acesse: 


Gravação e teste do firmware ESP easy no esp8266-01


>> Modulo relé 16 canais





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.



>> Modulo I2C PCA9685



trás mais detalhes sobre esse módulo.

Este modulo tem saída em PWM mas usaremos o valor máximo para HIGH ou 1 e o mínimo para estado LOW ou 0.


Montagem





Configurando o ESP-01


Com o firmware ESP Easy já gravado no ESP8266 é necessário fazer apenas uma simples configuração - Definir quais os pinos que serão usados para comunicação I2C.


O ESP-01 disponibiliza apenas 2 pinos de IO. Temos que configura-los como Clock e Data da comunicação I2C.


GPIO 0  >> SCL

GPIO 2  >> SDA

Com o seu ESP8266 ligado e conectado a rede acesse sua página de configuração através do IP como mostrado na postagem:Gravação e teste do firmware ESP easy no esp8266-01





 Na guia hardware altere  SDA para GPIO-2 e SCL para GPIO-0. Em seguida clique em Submit



Testes

Após a montagem e a configuração.
Para acionar um dos 16 relés fazemos da seguinte forma - Considerando os dispositivos conectados à mesma rede - (para controle via internet será necessário IP fixo ou serviços de ddns dinâmico como os oferecidos pelo NoIP, além das configurações de direcionamento de porta em seu roteador):

Através de um computador ou celular conectado na mesma rede passos o comando da seguinte forma:

http:// ESP IP address/control?cmd=pcapwm,pin,Level



Substituindo:


ESP IP address  Pelo IP do ESP8266 em sua rede;


pin Pelo Pino do PCA9685 0 a 15  (que no nosso caso corresponde a um dos reles)


Level Pelo valor de pwm. 

O PCA9685 é um módulo com saída em PWM por isso valor pode ser de 0 a 4095 (4096 níveis possíveis) Isso e interessante para controle de led, servo motores, etc. Nesse projeto utilizamos apenas os extremos para acionar o relé: "0" para nível baixo e "4095" para nível alto.

Exemplo:


Considerando o IP: 192.168.0.5


Para acionar o relé número 15 do módulo enviamos:  http://192.168.0.5/control?cmd=pcapwm,15,4095 


Para desligar o relé número 15 do modulo enviamos:  http://192.168.0.5/control?cmd=pcapwm,15,0



No vídeo utilizei um aplicativo criado no APPInventor que faz basicamente o descrito acima.



sábado, 10 de dezembro de 2016

Gravação e teste do firmware ESP easy no esp8266-01




O ESP8266 é um módulo wifi que tem revolucionado por seu baixo custo e versatilidade. Ele traz em uma placa muito pequena um CI contendo os elementos necessários a comunicação wifi e um microcontrolador de 32bist além de um CI de memória.
Existem alguns modelos deste módulo. Todos os modelos utilizam o mesmo circuito integrado principal. Sendo diferentes basicamente em número de pinos disponibilizados na placa e no tamanho de memória e alguns outros componentes em certos modelos.

O módulo mais básico é o ESP-01. Ele sai de fábrica com um firmware que possibilita controla-lo via comandos AT através de sua interface serial RS232, nível de tensão TTL 3,3V.  Nessa configuração ele funciona como um modulo wifi para um dispositivo externo, como o Arduino, por exemplo.

A nodemcu disponibiliza outros firmwares que possibilitam a programação do microcontrolado interno permitindo que o módulo funcione de forma independente de microcontrolador externo. Essa  programação pode ser feita pela linguagem LUA através de interface adequada ou pela interface de programação do Arduino, adicionando-se para isso os módulos convenientes.

Uma terceira possibilidade, a que usamos aqui, é instalar no ESP8266 a firmware EASY  ESP da letscontrolit.com. Esse firmware permite controlara vários dispositivos com comandos via web por um navegador de internet ou aplicativo. Quando necessário as configurações  adicionais ao modulo poder ser feitas também via browser acessando através do endereço IP a página de configuração do modulo. Isso facilita muito o uso do ESP8266.



Montando o circuito para gravação

O primeiro passo caso não tenha um adaptador pronto para ligar o ESP8266 ao computador é montar o circuito abaixo ou circuito semelhante:


Observe:
a. A alimentação e comunicação deve ser em 3,3V
b. O pino GPIO-0 deve ser ligado ao GND para que seja possível gravar o firmware



Gravando o firmware no ESP8266-ESP01


O tutorial oficial para instalação do firmware no ESP pode ser visto no seguinte link
1 -  Fazer o download do arquivo zip contendo o firmware e ferramentas.  Descompactar. Link 

2 - Clique duas vezes em "flash.cmd". Uma janela de comandos deve começar com três perguntas.


3 - Digite o número da porta COM em que está conectado o ESP8266 via modulo FTDI. Por exemplo se estiver conectado na porta COM9 digite 9.

 


4 - Digite o tamanho da memória flash de seu ESP8266, 512, 1024 ou 4096 (depende do modelo)


5 - Selecione a versão de compilação. 120 ou mais recente.


6 - A gravação será iniciada e terminará, aproximadamente como na seguinte tela.


7 -  Após concluir a instalação do firmware pressionar o reset do ESP ou desligue e religue


Configuração preliminar

Assim que é ligado após a instalação do firmware do EasyESP o ESP8266  criará uma rede wifi que pode ser acessada com um celular, por exemplo, para configuração inicial. Isso permite que ele seja acessado para configurar sua conexão com a rede wifi em que deverá se conectar.

1 - Acessar a rede criada pelo ESP

REDE:  ESP_0
SENHA: configesp

2 - Após conectar nessa rede será possível ajustar as configurações para que o ESP8266 possa se conectar em sua rede wifi.

Para isso acesse com qualquer navegador de internet o IP: 192.168.4.1
Será aberta a seguinte página:


Nela selecione sua rede wifi, digite a senha e pressione connect

Será exibido uma contagem regressiva e logo em seguida, dando tudo certo, será mostrado o IP do ESP8266 em sua rede wifi.

Com esse IP é possível acessar a página de configuração do ESP e também enviar comandos.


Teste com LEDs

Após conectar o ESP8266 a rede via wifi podemos fazer o seguinte teste.

Ligar um LED no GPIO-0 e GPIO-2. Conforme figura abaixo.




Para esse teste não será necessária nenhuma configuração adicional no ESP.

Controlar o estado dos GPIO do ESP com o EASY ESP pe bastante simples.

Utilizei um computador conectado a mesma rede em que está conectado o ESP8266

Para alterar o estado via browser enviamos o seguinte:
http://ESP_IP_address/control?cmd=GPIO,pin,state

Onde:

ESP_IP_address : IP do ESP8266 em sua rede
pin : Pino correspondente ao GPIO
state: Estado desejado para o GPIO. 0 para nivel baixo e 1 para nivel alto.

Por exemplo:
No meu caso o IP do esp8266 é 192.168.0.102. Então:

Para acender o led no GPIO-2 envio:  http://192.168.0.102/control?cmd=GPIO,2,1
Para apagar o led no GPIO-2 envio:  http://192.168.0.102/control?cmd=GPIO,2,0

Para apagar o led no GPIO-0 envio:  http://192.168.0.102/control?cmd=GPIO,0,1
Para apagar o led no GPIO-0 envio:   http://192.168.0.102/control?cmd=GPIO,0,0

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;    
    
  }