Распознать взмахи рукой

NazarovAlexandr
Offline
Зарегистрирован: 27.08.2014

Добрый день!

Прошу помочь в таком вопросе - хочу управлять устройством не прикасаясь, пусть это будет плеер - типа один раз махнуть рукой = play, 2 раза = перемотка, 3 раза=... и т.д. Кроме того по длинному приближению руки пусть включается регулировка громкости как функции расстояния до руки, т.е. подержали, а дальше ближе=тише, дальше=громче.

1.Как изящнее написать функцию, возвращающую кол-во взмахов, или 255, если это "длинное" удержание?

2. Какой датчик лучше использовать? Ультразвуковой иногда сбоит, видимо у него "луч" очень узкий, т.е. стоит руку чуть в сторону отвести, и расстояние сразу неправильно показывается. От руки видимо, плохо отражается, т.к. если водить чем-то плоским, типа книжки, расстояние мереется идеально. И вдогонку, чем можно закрыть датчик, чтобы было красиво и пропускало ультразвук?

Araris
Offline
Зарегистрирован: 09.11.2012

Я на кухне жестами управляю светом, вентилятором, клапаном водяного фильтра с помощью Adjustable Infrared Sensor Switch (с Алиэкспресса), вот такого: http://www.dfrobot.com/index.php?route=product/product&product_id=114. Отслеживаю взмахи руки. Могу поделиться куском скетча. Но лучше почитайте  отличную статью на Хабре, там датчик Sharp GP2Y0A21YK и куча наворотов с взмахами, удалением-приближением. Схема, скетч, все здесь: http://habrahabr.ru/post/243037/

NazarovAlexandr
Offline
Зарегистрирован: 27.08.2014

Спасибо большое,, почитал, обдумал, много понял :)

а ваш датчик именно дистанцию определяет или как триггер работает - поднесли=замкнулось, убрали=разомкнулось? И скетч, тоже посмотреть хотелось бы, я ж не настоящий сварщик, я только очки нашел :)

Araris
Offline
Зарегистрирован: 09.11.2012

Датчик работает как триггер с регулируемой чувствительностью (слово Switch какбы намекает)). В данном [простейшем] случае распознавание жестов в программе сводится к классической задаче - подсчету количества импульсов за промежуток времени. Здесь на форуме, кстати, есть немало тем, где она обсуждалась.

Итак, на словах алгоритм такой: 1-циклически опрашиваем датчик; 2-если датчик сработал, то увеличиваем значение счетчика импульсов и запускаем отсчет времени; 3-пока идет отсчет времени, считаем импульсы; 4-по окончании отсчета времени анализируем счетчик импульсов и что-то делаем.

Если импульс был один и он продолжался весь период отсчета времени, то это "длинный" жест, можем как-то на него прореагировать. На одно срабатывание датчика я не реагирую, считая его случайным (датчик стоит над кухонной мойкой, место достаточно посещаемое).

Теперь конкретика, даже с комментами )) :

 







#define IR_SWITCH_PIN 11

int IRSwitchCounter = 0; // счетчик срабатываний свитча
unsigned long IRSwitchOldTime = 0; // начало отсчета времени 
boolean IRSWitchState = true; // текущее состояние свитча
boolean IRSWitchStateOld = false; // предыдущее состояние свитча
boolean IRSWitchLongTapState = false; // "длинный" жест
unsigned long IRSwitchDelay = 1500; // период отсчета времени

void setup()
{
pinMode(IR_SWITCH_PIN, INPUT);
}

void loop()
{
IRSWitchState = digitalRead(IR_SWITCH_PIN);
IRSWitchLongTapState = !IRSWitchState;
if ( IRSWitchState != IRSWitchStateOld ) // состояние свитча изменилось
 {
 if ( IRSwitchOldTime == 0 ) { IRSwitchOldTime = millis(); } // начинаем отсчет времени
 if ( !IRSWitchState ) { IRSwitchCounter++; } // свитч инвертированный, поэтому !IRSWitchState
 IRSWitchStateOld = IRSWitchState;   
 delay(30); // debounce 
 }
if ( ( IRSwitchOldTime > 0 ) && ((millis() - IRSwitchOldTime) > IRSwitchDelay) ) // если отсчет времени происходит && период закончился
 {
  switch (IRSwitchCounter)
  {
  case 1: // был один жест
   if (IRSWitchLongTapState) // но нас интересует только "длинный" жест  
    {
    // Start/stop fan
    }
  break;   
  case 2: // было два жеста
   // Start/stop lights
  break;   
  case 3: // было три жеста 
   // Start/stop water
  break;   
  default:
  }
 IRSwitchCounter = 0;
 IRSwitchOldTime = 0; // ноль как признак того, что отсчет времени не происходит
 }
}