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