Apds 9960 как использовать
Перейти к содержимому

Apds 9960 как использовать

  • автор:

Датчик жестов, приближения, освещенности, цвета (Trema-модуль)

Trema-модуль Датчик жестов, приближения, освещенности, цвета — способен определять уровень освещённости в Lux (как общий, так и по трём каналам спектра — красный, зелёный, синий), приближение объектов (препятствий) и жесты (движение объектов влево, вправо, вверх, вниз, к датчику и от него). У более ранней модели APDS9930 имеются только функции определения приближения и уровня общей освещённости.

Видео:

Подключение:

Для удобства подключения к Arduino воспользуйтесь Trema Shield, Trema Power Shield, Motor Shield или Trema Set Shield.

Модуль подключается к аппаратной шине I2C Arduino. Для удобства подключения, предлагаем воспользоваться TremaShield.

Модуль удобно подключать 4 способами, в зависимости от ситуации:

Способ — 1 : Используя проводной шлейф и Piranha UNO

Используя провода «Папа — Мама», подключаем напрямую к контроллеру Piranha UNO.

Способ — 2 : Используя Trema Set Shield

Модуль можно подключить к любому из I2C входов Trema Set Shield.

Способ — 3 : Используя проводной шлейф и Shield

Используя 4-х проводной шлейф, к Trema Shield, Trema-Power Shield, Motor Shield, Trema Shield NANO и тд.

Питание:

Напряжение питания модуля 5В постоянного тока, подаётся на выводы «VCC» и «GND» модуля.

Подробнее о модуле:

Модуль построен на базе датчика APDS9960, в состав которого входят:

  • ИК-светодиод с программируемым драйвером;
  • 4 фотодиода для обнаружения жестов;
  • 3 фотодиода, реагирующих на разные спектры для определения цвета;
  • 1 фотодиод общей освещённости;
  • Уф- и ИК-фильтры;
  • Усилители с программируемым коэффициентом усиления;
  • МК;
  • АЛУ;
  • АЦП;
  • ОЗУ;
  • и множество дополнительных блоков.

Результаты освещённости в Lux выводятся с использованием эмпирической формулы для аппроксимации реакции человеческого глаза.

Примеры:

1. Определение жестов

// Подключаем библиотеки: // #include // Для работы с шиной I2C #include // Для работы с датчиком APDS-9960 SparkFun_APDS9960 apds = SparkFun_APDS9960(); // Определяем объект apds, экземпляр класса SparkFun_APDS9960 // void setup()< // Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек // Инициируем работу датчика: // if(apds.init())< // Если инициализация прошла успешно, то . Serial.println("Initialization OK!"); // Выводим сообщение об успешной инициализации датчика >else // Иначе, выводим сообщение оо ошибке инициализации датчика // // Устанавливаем коэффициент усиления приёмника: // Доступные значения: 1х, 2х, 4х, 8х (GGAIN_1X, GGAIN_2X, GGAIN_4X, GGAIN_8X). Чем выше коэффициент тем выше чувствительность if(apds.setGestureGain(GGAIN_2X))< // Если установлен коэффициент усиления приёмника в режиме обнаружения жестов, то . Serial.println("Set gain OK!"); // Выводим сообщение об успешной установке коэффициента усиления приёмника >else // Иначе, выводим сообщение об ошибке при установке коэффициента усиления приёмника // Прочитать установленный коэффициент усиления приёмника можно так: uint8_t i = apds.getGestureGain(); // в переменную i сохранится значение: GGAIN_1X, или GGAIN_2X, или GGAIN_4X, или GGAIN_8X // Устанавливаем силу тока драйвера ИК-светодиода: // Доступные значения: 100мА, 50мА, 25мА, 12.5мА (LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA). Чем выше сила тока, тем выше чувствительность. if(apds.setGestureLEDDrive(LED_DRIVE_100MA))< // Если устанавлена сила тока драйвера (яркость) ИК-светодиода для обнаружения жестов, то . Serial.println("Set LED drive OK!"); // Выводим сообщение об успешной установке силы тока драйвера >else // Иначе, выводим сообщение об ошибке при установке силы тока драйвера // Прочитать установленную силу тока можно так: uint8_t i = apds.getGestureLEDDrive(); // в переменную i сохранится значение: LED_DRIVE_100MA, или LED_DRIVE_50MA, или LED_DRIVE_25MA, или LED_DRIVE_12_5MA // Разрешаем режим обнаружение жестов: // if(apds.enableGestureSensor(false))< // Если механизм обнаружения жестов (false - без прерываний на выходе INT) запущен, то . Serial.println("Start gesture sensor OK!"); // Выводим сообщение об успешном запуске механизма обнаружения жестов >else // Иначе, выводим сообщение об ошибке запуска механизма обнаружения жестов // Запретить работу механизма обнаружения жестов можно так: bool j = apds.disableGestureSensor(); // в переменную j сохранится результат выполнения функции (true/false) // Ждём завершение инициализации и калибровки: // delay(500); // > // // void loop() < // // Выводим название зафиксированного жеста: // if(apds.isGestureAvailable())< // Если зафиксировано движение, то . switch(apds.readGesture())< // Сверяем значение соответствующее жесту . case DIR_UP: Serial.println("UP" ); break; // Зафиксировано движение вперёд или вверх (зависит от положения датчика) case DIR_DOWN: Serial.println("DOWN" ); break; // Зафиксировано движение назад или вниз (зависит от положения датчика) case DIR_LEFT: Serial.println("LEFT" ); break; // Зафиксировано движение влево case DIR_RIGHT: Serial.println("RIGHT"); break; // Зафиксировано движение вправо case DIR_NEAR: Serial.println("NEAR" ); break; // Зафиксировано движение к датчику case DIR_FAR: Serial.println("FAR" ); break; // Зафиксировано движение от датчика default: Serial.println("NONE" ); break; // Зафиксировано движение, но жест не опознан >// > // // // Приостанавливаем выполнение скетча на 0,1 секунду: // delay(100); // Чтоб не перегружать шину I2C постоянными запросами > //

2. Определение освещённости и цвета

// Подключаем библиотеки: // #include // Для работы с шиной I2C #include // Для работы с датчиком APDS-9960 SparkFun_APDS9960 apds = SparkFun_APDS9960(); // Определяем объект apds, экземпляр класса SparkFun_APDS9960 // // Объявляем переменные: // uint16_t lightAmbient = 0; // Определяем переменную для хранения освещённости общей в люксах uint16_t lightRed = 0; // Определяем переменную для хранения освещённости красного спектра в люксах uint16_t lightGreen = 0; // Определяем переменную для хранения освещённости зелёного спектра в люксах uint16_t lightBlue = 0; // Определяем переменную для хранения освещённости синего спектра в люксах // void setup()< // Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек // Инициируем работу датчика: // if(apds.init())< // Если инициализация прошла успешно, то . Serial.println("Initialization OK!"); // Выводим сообщение об успешной инициализации датчика >else // Иначе, выводим сообщение об ошибке инициализации датчика // // Разрешаем режим определения освещённости: // if(apds.enableLightSensor(false))< // Если режим определения освещённости запущен (false - без прерываний на выходе INT), то . Serial.println("Start light sensor OK!"); // Выводим сообщение об успешном запуске режима определения освещённости >else // Иначе, выводим сообщение об ошибке запуска режима определения освещённости // Запретить режим определения освещённости можно так: bool j = apds.disableLightSensor(); // в переменную j сохранится результат выполнения функции (true/false) // Ждём завершение инициализации и калибровки: // delay(500); // > // // void loop()< // // Читаем значения освещённости в переменные: // if(apds.readAmbientLight (lightAmbient) // Если прочитано значение общей освещённости && apds.readRedLight (lightRed) // И прочитано значение освещённости красного спектра, и && apds.readGreenLight (lightGreen) // И прочитано значение освещённости зелёного спектра, и && apds.readBlueLight (lightBlue) )< // И прочитано значение освещённости синего спектра, то . Serial.println((String) "Ambient=" + lightAmbient + ", Red=" + lightRed + ", Green=" + lightGreen + ", Blue=" + lightBlue + " lx"); // Выводим все прочитанные значения >else // Иначе, выводим сообщение об ошибке чтения освещённости // // Приостанавливаем выполнение скетча на 1 секунду: // delay(1000); // Чтоб не перегружать шину I2C постоянными запросами > //

3. Определение приближения

// Подключаем библиотеки: // #include // Для работы с шиной I2C #include // Для работы с датчиком APDS-9960 SparkFun_APDS9960 apds = SparkFun_APDS9960(); // Определяем объект apds, экземпляр класса SparkFun_APDS9960 // // Объявляем переменные: // uint8_t proximityData = 0; // Определяем переменную для хранения значения приближения // void setup()< // Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек // Инициируем работу датчика: // if(apds.init())< // Если инициализация прошла успешно, то . Serial.println("Initialization OK!"); // Выводим сообщение об успешной инициализации датчика >else // Иначе, выводим сообщение оо ошибке инициализации датчика // // Устанавливаем коэффициент усиления приёмника: // Доступные значения: 1х, 2х, 4х, 8х (PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X). Чем выше коэффициент тем выше чувствительность if(apds.setProximityGain(PGAIN_2X))< // Если установлен коэффициент усиления приёмника в режиме определения расстояния, то . Serial.println("Set gain OK!"); // Выводим сообщение об успешной установке коэффициента усиления приёмника >else // Иначе, выводим сообщение об ошибке при установке коэффициента усиления приёмника // Прочитать установленный коэффициент усиления приёмника можно так: uint8_t i = apds.getProximityGain(); // в переменную i сохранится значение: PGAIN_1X, или PGAIN_2X, или PGAIN_4X, или PGAIN_8X // Разрешаем режим определения приближения: // if(apds.enableProximitySensor(false))< // Если механизм определения приближения (false - без прерываний на выходе INT) запущен, то . Serial.println("Start proximity sensor OK!"); // Выводим сообщение об успешном запуске механизма определения приближения >else // Иначе, выводим сообщение об ошибке запуска механизма определения приближения // Запретить работу механизма определения приближения можно так: bool j = apds.disableProximitySensor(); // в переменную j сохранится результат выполнения функции (true/false) // Ждём завершение инициализации и калибровки: // delay(500); // > // // void loop()< // // Читаем определённое датчиком значение приближения: // if(apds.readProximity(proximityData))< // Если значение приближения корректно прочитано в переменную proximityData, то .. Serial.println((String) "Proximity="+proximityData); // Выводим значение приближения >else // Иначе, выводим сообщение об ошибке чтения приближения // // Приостанавливаем выполнение скетча на 1 секунду: // delay(1000); // Чтоб не перегружать шину I2C постоянными запросами > //

Жесты:

    Trema-модуль Датчик жестов, приближения, освещенности, цветаспособен реагировать на следующие жесты:
  • UP — Движение руки перед датчиком ВПЕРЁД или ВВЕРХ (зависит от положения датчика в пространстве).
  • DOWN — Движение руки перед датчиком НАЗАД или ВНИЗ (зависит от положения датчика в пространстве).
  • LEFT — Движение руки перед датчиком ВЛЕВО.
  • RIGHT — Движение руки перед датчиком ВПРАВО.
  • NEAR — Приближение руки К датчику.
    Плавно приблизьте руку к датчику сверху на расстояние ≈ 1-5 см., задержите её не менее чем на 1 секунду и быстро уберите в любую сторону.
  • FAR Удаление руки ОТ датчика.
    Быстро приблизьте руку к датчику с любой стороны, на расстояние ≈ 1-5 см., задержите её не менее чем на 1 секунду и плавно уберите от датчика вверх.
  • NONE Датчик зафиксировал движение, но не смог его распознать.

Ссылки:

  • DataSheet;
  • Библиотека SparkFun_APDS9960;
  • Trema-модуль Датчик жестов, приближения, освещенности, цвета;
  • Датчик APDS9930 (более ранняя модель);

Датчик жестов APDS-9960

Датчик жестов APDS-9960

Датчик жестов, цвета, приближения и освещенности APDS-9960 — может распознавать: взмахи рукой вправо, влево, от себя к себе и вверх/вниз от датчика. Измеряет освещённость. Так же определяет яркость значений цветов красный, синий, зелёный. В первой версии модуля APDS-9930 работал ограниченный функционал: отдаление/приближение и измерение яркости света в Lux. Первым эти сенсоры применила компания Samsung, в своих телефонах Galaxi S5. Теперь когда стоимость сенсора распознавания жестов снизилась и датчик стал доступным, его стали применять совместно с платами Arduino. Используя это модуль можно спаять невероятные устройства. Например светильник управляемый взмахом руки. Или настенный выключатель к которому не нужно прикасаться. Используя OLED дисплей и этот модуль, можно управлять экранным меню, при помощи жестов. Вы можете скачать библиотеку APDS9960 и воспользоваться описанием всех используемых в библиотеке функций. Что бы увеличить дистанцию срабатывания датчика приближения, нужно запитать ИК передатчик от 4,5 В. Для этого потребуется паяльник и опыт работы с ним. Нужно убрать на плате перемычку «PS» и подключить к выводу «VL» модуля, напряжение 4,5 В. При подключении и программировании Arduino для платы модуля жестов, примите во внимание, то что сигнал прерывания INT — это логический «0». Который будет активным при каждом срабатывании любого из сенсоров модуля.

Характеристики:

Диапазон питающего напряжения 2,4 .. 3,6 В
Интерфейс I2C
Частота шины I2C 400 кГц
I2C адрес 0x39
Диапазон чувствительности распознавания датчика 10 — 20 см
Температура эксплуатации -30 .. +80° С
Размеры 20 x 15

Видео демонстрирующее работу датчика

Категории: Датчики фотоэлектрические Электронные модули Теги: APDS-9960

Датчик жестов APDS-9960 отзывы

Средняя оценка покупателей: (1)

Датчик жестов Ардуино APDS-9960 подключение

Датчик жестов Ардуино APDS-9960 подключение

Датчик распознавания жестов GY-9960 APDS Arduino — это модуль со встроенным сенсором, который обеспечивает обнаружение света и цвета, определение приближения и бесконтактное распознавание жестов. С помощью этого модуля простым жестом руки можно управлять роботами, освещением и другими устройствами. Рассмотрим, как подключить SparkFun APDS 9960 модуль распознавания жестов к плате Ардуино.

Необходимые компоненты:

  • Arduino Uno / Arduino Nano / Arduino Mega
  • сенсор SparkFun APDS-9960
  • дисплей lcd 1602 i2c
  • коннекторы
  • библиотека SparkFun_APDS9960.h и LiquidCrystal_I2C.h
  1. Лазерный дальномер VL53L1X, VL53L0X
  2. Датчик ультрафиолетового излучения ML8511
  3. Подключение датчика цвета TCS230 к Ардуино

Датчик жестов GY-9960 APDS SparkFun имеет встроенный датчик окружающего освещения, ультрафиолетовый и инфракрасный фильтр, четыре отдельных фотодиода (приемники, которые обнаруживают ИК-излучение, отраженное от объекта) и ИК-светодиод (передатчик). Когда мы делаем жест рукой, датчик получает отраженное ИК-излучение, а микроконтроллер Arduino вычисляет направление движения руки.

APDS-9960 Arduino характеристики, распиновка

APDS-9960 Arduino характеристики, распиновка

Характеристики APDS-9960 (datasheet)

  • Напряжение питания: 3,3 В
  • Адрес I2C: 0x39
  • Обнаружение приближения
  • Обнаружение жестов
  • Окружающее освещение и определение цвета RGB
  • Рабочий диапазон: от 10 до 20 см

На передней панели модуля находятся 2 перемычки PS и I2C PU:

PS — эта перемычка подключает питание к модулю и ИК-светодиоду. Когда перемычка замкнута, питание должно подаваться только на вывод VCC на модуле. Когда перемычка разомкнута, для включения ИК-светодиода необходимо подать отдельное питание на вывод VL датчика SparkFun от Ардуино. По умолчанию эта перемычка замкнута.

I2C PU — эта перемычка используется для подключения подтягивающих резисторов к линиям SDA и SCL. Если резисторы не требуются, разомкните перемычку.

Как подключить датчик жестов APDS-9960 Ардуино

Как подключить датчик жестов APDS-9960 к Ардуино

APDS-9960 i2c Arduino Uno Arduino Nano Arduino Mega
GND GND GND GND
VDD 5V 5V 5V
SDA A4 A4 20
SCL A5 A5 21

Датчик способен определять общий уровень освещенности в люксах или уровень освещенности в трех каналах спектра — красном, зеленом, синем (RGB). Определяет приближение и удаление объекта от сенсора, простые жесты рукой (движение влево, вправо, вверх, вниз). Для работы с модулем необходимо установить библиотеку APDS9960.h, а после сборки схемы загрузите следующую программу в плату Arduino.

Скетч для распознавания жестов с помощью APDS-9960

#include "Wire.h" #include "SparkFun_APDS9960.h" #define APDS9960_INT 2 SparkFun_APDS9960 apds = SparkFun_APDS9960(); int isr_flag; void setup() < Serial.begin(9600); attachInterrupt(0, interruptRoutine, FALLING); if ( apds.init() ) < Serial.println(F("APDS-9960 initialization complete")); >else < Serial.println(F("Something went wrong during APDS-9960 init!")); >if ( apds.enableGestureSensor(true) ) < Serial.println(F("Gesture sensor is now running")); >else < Serial.println(F("Something went wrong during gesture sensor init!")); >> void loop() < if( isr_flag == 1 ) < detachInterrupt(0); handleGesture(); isr_flag = 0; attachInterrupt(0, interruptRoutine, FALLING); >> void interruptRoutine() < isr_flag = 1; >void handleGesture() < if ( apds.isGestureAvailable() ) < switch ( apds.readGesture() ) < case DIR_UP: Serial.println("UP"); break; case DIR_DOWN: Serial.println("DOWN"); break; case DIR_LEFT: Serial.println("LEFT"); break; case DIR_RIGHT: Serial.println("RIGHT"); break; case DIR_NEAR: Serial.println("NEAR"); break; case DIR_FAR: Serial.println("FAR"); break; default: Serial.println("NONE"); >> >

Подключение датчика APDS-9960 к Ардуино с дисплеем

Подключение датчика APDS-9960 к Ардуино с дисплеем

LCD 1602 i2c Arduino Uno Arduino Nano Arduino Mega
GND GND GND GND
VDD 5V 5V 5V
SDA A4 A4 20
SCL A5 A5 21

Скетч для датчика APDS-9960 с дисплеем LCD 1602

#include "Wire.h" #include "SparkFun_APDS9960.h" #define APDS9960_INT 2 SparkFun_APDS9960 apds = SparkFun_APDS9960(); #include "Wire.h" #include "LiquidCrystal_I2C.h" LiquidCrystal_I2C LCD(0x27,16,2); int isr_flag; void setup() < LCD.init(); LCD.backlight(); Serial.begin(9600); attachInterrupt(0, interruptRoutine, FALLING); if ( apds.init() ) < Serial.println(F("APDS-9960 initialization complete")); >else < Serial.println(F("Something went wrong during APDS-9960 init!")); >if ( apds.enableGestureSensor(true) ) < Serial.println(F("Gesture sensor is now running")); >else < Serial.println(F("Something went wrong during gesture sensor init!")); >> void loop() < if( isr_flag == 1 ) < detachInterrupt(0); handleGesture(); isr_flag = 0; attachInterrupt(0, interruptRoutine, FALLING); >> void interruptRoutine() < isr_flag = 1; >void handleGesture() < LCD.setCursor(0, 0); if ( apds.isGestureAvailable() ) < switch ( apds.readGesture() ) < case DIR_UP: Serial.println("UP"); LCD.clear(); LCD.print("UP"); break; case DIR_DOWN: Serial.println("DOWN"); LCD.clear(); LCD.print("DOWN"); break; case DIR_LEFT: Serial.println("LEFT"); LCD.clear(); LCD.print("LEFT"); break; case DIR_RIGHT: Serial.println("RIGHT"); LCD.clear(); LCD.print("RIGHT"); break; case DIR_NEAR: Serial.println("NEAR"); LCD.clear(); LCD.print("NEAR"); break; case DIR_FAR: Serial.println("FAR"); LCD.clear(); LCD.print("FAR"); break; default: Serial.println("NONE"); LCD.clear(); LCD.print("NONE"); >> >

Заключение. Датчик GY 9960 LLC легко определяет приближение и удаление объекта, простые жесты, свет и цвета (яркость цветовых значений RGB). В библиотеке SparkFun_APDS9960.h есть другие примеры, демонстрирующие возможности датчика. Например, скетч AmbientLightInterrupt позволяет измерять окружающее освещение, а пример ColorSensor считывает значения красного, зеленого и синего света.

Распознавание жестов с помощью APDS-9960

image

Читая комментарии к моей предыдущей статье про APDS-9960, где речь шла про распознавание цвета и уровня освещенности для меня стали очевидными две вещи: 1) тема распознавания жестов интересна и 2) тема эта не раскрыта.

Действительно, если уж взялся за описание APDS-9960, то без рассмотрения жестов описание это выглядит несколько незавершенным. Поэтому я нашел свободное время, чтобы исследовать и эту тему тоже.

В данной статье я предлагаю Вашему вниманию обзор возможностей для распознавания жестов которые предоставляет сенсор APDS-9960.

В статье будет рассмотрен механизм настройки сенсора, сбор данных, их обработка и представление. Вы сами сможете убедиться в том насколько это просто — работать с жестами с помощью APDS-9960.

Как и в прошлый раз, статья будет сопровождаться кодом, все происходящее в котором будет подробно описано. Полная версия кода доступна в конце статьи.

Сразу небольшая ремарка: встроенного автоматического механизма определения жестов у APDS-9960 не предусмотрено; то есть такого, чтобы прям вот, прочитал, значит, регистр, а там уже и жест обработанный лежит — такого в APDS-9960 нет; а это означает, что придется писать свой алгоритм интерпретации жестов, чем впоследствии и займемся.

Вообще, это одновременно и хорошо и не очень. Не очень — потому что может усложнить исследование данного сенсора для начинающего, а хорошо, потому что, вкупе с данными о приближении, можно, изощряясь, вообще напридумывать собственных жестов различных каких угодно разнообразных и всяких.

Но, поскольку данная статья несет лишь обзорную функцию, мы ограничимся только базовыми UP-DOWN-LEFT-RIGHT жестами.

Ну что же, приступим.

Теория

Позволю себе чуточку матчасти.

Для получения необходимой информации о движении и направлении движения в APDS-9960 используются ИК светодиод и четыре фотодиода, которые, как наглядно проиллюстрировано на рисунке ниже, регистрируют сигналы в диапазоне ближнего ИК (NIR).

image

ИК светодиод (LED) несет функцию подсветки, а фотодиоды (UDLR) регистрируют отраженный от «препятствия» свет.

Фотодиоды расположены на сенсоре таким образом, что в зависимости от направления движения «препятствия», соответствующий фотодиод получит большую часть отраженного ИК-сигнала на входе и меньшую часть на выходе. В то же время документация на APDS-9960 недвусмысленно подсказывает нам, что интерпретировать направление движения можно измеряя и сравнивая амплитуду и разность фаз сигналов с фотодиодов UDLR.

image

Практика

Для работы с APDS-9960, как и в прошлой раз, будем использовать STM32VLDISCOVERY. Подключение также не поменялось.

Производим первоначальную настройку сенсора.

APDS9960_init

void APDS9960_init(void)

Что же здесь происходит? Давайте разбираться.

i2c1_write(APDS9960_CONTROL, DEFAULT_PGAIN);

PGAIN (Proximity Gain Control) — это параметр который управляет коэффициентом усиления чувствительности приближения. Присвоим ему значение 2, что соответствует усилению в четыре раза.

i2c1_write(APDS9960_GPENTH, DEFAULT_GPENTH); i2c1_write(APDS9960_GEXTH, DEFAULT_GEXTH); 

GPENTH (Gesture Proximity Enter Threshold Register) — этот параметр устанавливает пороговое значение близости для определения начала распознавания жеста.

GEXTH (Gesture Exit Threshold Register), соответственно, устанавливает пороговое значение для определения окончания распознавания жеста.

i2c1_write(APDS9960_GCONF2, DEFAULT_GGAIN); 

В регистре GCONF2 (Gesture configuration two) мы явно устанавливаем только параметр GGAIN (Gesture Gain Control) в значение усиления в четыре раза.

i2c1_write(APDS9960_GPULSE, DEFAULT_PULSE_LENGTH); i2c1_write(APDS9960_PPULSE, DEFAULT_PULSE_LENGTH); 

Подсветка. По умолчанию значение для источника тока ИК светодиода подсветки установлено в 0, что соответствует току в 100 мА, нас это вполне устроит — менять не будем.

ИК подсветка в APDS-9960 представляет собой последовательность импульсов и характеризуется соответствующими параметрами регистров для жестов GPULSE (Gesture pulse count and length): GPLEN (Gesture Pulse Length) и GPULSE (Number of Gesture Pulses), а также приближения PPULSE (Proximity Pulse Count Register): PPLEN (Proximity Pulse Length) и PPULSE (Proximity Pulse Count) задающими количество импульсов и период каждого отдельного импульса.

Определим, что GPLEN и PPLEN примут значение 2 равное 16 мкс, а GPULSE и PPULSE значение 9, которое соответствует 10 импульсам.

Как видите, настройка оказалась ненамного сложнее аналогичной для распознавания цветов и освещения из предыдущего обзора APDS-9960.

Теперь переместимся в основной цикл программы, в котором начнем то и дело регистрировать и интерпретировать данные с фотодиодов, а также научимся находить отличия одного жеста от другого.

Перво-наперво, стартуем APDS-9960 с функциями работы с жестами и приближением.

GesturesSet(GESTURES_START); 

И сразу же начинаем отслеживать параметр GVALID. GVALID (Gesture FIFO Data) — это параметр регистра GSTATUS (Gesture Status Register), который, находясь в отличном от нуля состоянии, сообщает нам о том, что у сенсора имеются пригодные для использования данные о жестах.

Документация учит нас, что информация о жестах находится в буфере, в области оперативной памяти, которая в общем случае имеет размер 32 x 4 байт.

На практике, фактический размер этого буфера можно узнать прочитав значение регистра GFLVL (Gesture FIFO level), т.е. по моим сугубо эмпирическим экспериментальным наблюдениям, получается GFLVL*4. Как-то так:

image

Ну и как следует из названия буфера, данные в нем располагаются в порядке First In — First Out. То есть, грубо говоря, чем «раньше» поступил сигнал с каждого из фотодиодов тем «выше» в GFLVL он располагается.

Данные с фотодиодов (UDLR) можно прочитать из соответствующих регистров Gesture FIFO Register:

— GFIFO_U (Gesture FIFO Data, UP)
— GFIFO_D (Gesture FIFO Data, DOWN)
— GFIFO_L (Gesture FIFO Data, LEFT)
— GFIFO_R (Gesture FIFO Data, RIGHT)

После каждого чтения значений из этих регистров, GFLVL декрементируется; таким образом, по хорошему, необходимо произвести чтение полностью всего буфера до момента пока GFLVL не достигнет нуля.

Для определения жестов нам понадобятся только первые четыре байта этого буфера, не больше. Поэтому и прочитаем мы только их.

GestureUp = i2c1_read(APDS9960_GFIFO_U); GestureDown = i2c1_read(APDS9960_GFIFO_D); GestureLeft = i2c1_read(APDS9960_GFIFO_L); GestureRight = i2c1_read(APDS9960_GFIFO_R); 

Чтобы интерпретировать какой же именно жест произошел, произведем нехитрые вычисления:

GestUpDown = GestureUp-GestureDown; GestLeftRight = GestureLeft-GestureRight; 

Для определения того какой из жестов в данный момент случился нам важны не сами значения GestUpDown и GestLeftRight, а только лишь знак, так сказать, вещественного числа.

То есть, иными словами, принимая на вход отрицательные и положительные значения переменных GestUpDown и GestLeftRight определяем какой жест совершен.

Таблица истинности для переменных GestUpDown и GestLeftRight представлена на рисунке ниже

image

Теперь обнулим GFLVL:

GesturesSet(GESTURES_STOP); 

… и вернемся в начало основного цикла программы.

А теперь весь код целиком:

 #include "stm32f10x.h" #define APDS9960_I2C_ADDR 0x39 #define APDS9960_ENABLE 0x80 #define APDS9960_GSTATUS 0xAF #define APDS9960_GFLVL 0xAE //Gesture FIFO Register (0xFC – 0xFF): #define APDS9960_GFIFO_U 0xFC #define APDS9960_GFIFO_D 0xFD #define APDS9960_GFIFO_L 0xFE #define APDS9960_GFIFO_R 0xFF #define APDS9960_CONTROL 0x8F #define APDS9960_GPENTH 0xA0 #define APDS9960_GEXTH 0xA1 #define APDS9960_GCONF2 0xA3 #define APDS9960_GPULSE 0xA6 #define APDS9960_PPULSE 0x8E #define GESTURES_START 0x01 #define GESTURES_STOP 0x02 #define DEFAULT_GPENTH 40 // Threshold for entering gesture mode #define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode #define DEFAULT_PGAIN 8 // Proximity Gain Control: 4X #define DEFAULT_GGAIN 0x40 // Gesture Gain Control: 4X #define DEFAULT_PULSE_LENGTH 0x89 // 16us, 10 pulses /* Bit fields */ #define APDS9960_PON 0x01 #define APDS9960_AEN 0x02 #define APDS9960_PEN 0x04 #define APDS9960_WEN 0x08 #define APSD9960_AIEN 0x10 #define APDS9960_PIEN 0x20 #define APDS9960_GEN 0x40 #define APDS9960_GVALID 0x01 int GestUpDown = 0; int GestLeftRight = 0; //----------------------------------------------------------------------- uint8_t i2c1_read(uint8_t addr); void i2c1_write(uint8_t addr, uint8_t data); void I2C1_init(void) < I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_StructInit(&I2C_InitStructure); I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_InitStructure.I2C_OwnAddress1 = 0x01; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); >//----------------------------------------------------------------------- void APDS9960_init(void) < i2c1_write(APDS9960_CONTROL, DEFAULT_PGAIN); i2c1_write(APDS9960_GPENTH, DEFAULT_GPENTH); i2c1_write(APDS9960_GEXTH, DEFAULT_GEXTH); i2c1_write(APDS9960_GCONF2, DEFAULT_GGAIN); i2c1_write(APDS9960_GPULSE, DEFAULT_PULSE_LENGTH); i2c1_write(APDS9960_PPULSE, DEFAULT_PULSE_LENGTH); >//----------------------------------------------------------------------- uint8_t i2c1_read(uint8_t addr) < uint8_t data; while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, APDS9960_I2C_ADDR//----------------------------------------------------------------------- void i2c1_write(uint8_t addr, uint8_t data) < I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, APDS9960_I2C_ADDR; > //----------------------------------------------------------------------- void GesturesSet(uint8_t GestSel) < switch (GestSel) < case GESTURES_START: i2c1_write(APDS9960_ENABLE, APDS9960_GEN | APDS9960_PEN | APDS9960_PON); break; case GESTURES_STOP: i2c1_write(APDS9960_ENABLE, APDS9960_PEN | APDS9960_PON); break; default: i2c1_write(APDS9960_ENABLE, APDS9960_GEN | APDS9960_PEN | APDS9960_PON); >> //----------------------------------------------------------------------- int main() < uint8_t GFLVL_buf = 0; uint8_t GSTATUS_buf = 0; uint8_t GestureUp = 0; uint8_t GestureDown = 0; uint8_t GestureLeft = 0; uint8_t GestureRight = 0; I2C1_init(); APDS9960_init(); while (1) < GFLVL_buf = 0; GSTATUS_buf = 0; GestureUp = 0; GestureDown = 0; GestureLeft = 0; GestureRight = 0; GestUpDown = 0; GestLeftRight = 0; GesturesSet(GESTURES_START); GSTATUS_buf = i2c1_read(APDS9960_GSTATUS); if(GSTATUS_buf & APDS9960_GVALID) < GFLVL_buf = i2c1_read(APDS9960_GFLVL); if(GFLVL_buf) < GestureUp = i2c1_read(APDS9960_GFIFO_U); GestureDown = i2c1_read(APDS9960_GFIFO_D); GestureLeft = i2c1_read(APDS9960_GFIFO_L); GestureRight = i2c1_read(APDS9960_GFIFO_R); //Truth table: //UP: GestUpDown(+) | GestLeftRight(+) //DOWN: GestUpDown(-) | GestLeftRight(-) //LEFT: GestUpDown(+) | GestLeftRight(-) //RIGHT: GestUpDown(-) | GestLeftRight(+) GestUpDown = GestureUp-GestureDown; GestLeftRight = GestureLeft-GestureRight; GesturesSet(GESTURES_STOP); >> > > 

Хочу отметить, что механизм жестов у APDS-9960 работает очень даже неплохо. Распознавание стабильное, хорошо работают встроенные в APDS-9960 UV and IR фильтры.

Надеюсь, данный материал кому-нибудь окажется полезен. Спасибо за внимание.

  • APDS-9960
  • STM32
  • DIY
  • электроника для начинающих
  • программирование микроконтроллеров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *