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