Датчик PIR и сон (прерывание) на Mega2560

Итак, я начал получать некоторые знания о ИК-датчике и о том, как позволить Arduino «заснуть», пока ИК-датчик не обнаруживает движения.

Я нашел где-то следующий код, и он выглядел довольно просто. Поэтому я решил попробовать и взял свой Mega2560, светодиод и датчик PIR.

Хотя на первый взгляд казалось, что это работает, Arduino делает противоположное тому, что я ожидал. Он выключает светодиод и Arduino, когда есть движение, вместо того, чтобы выключать Arduino, когда движения НЕТ. Как я уже говорил, все происходит наоборот.

Возможно, это простое решение, но я не могу найти его самостоятельно.

Код:

#include <avr/sleep.h>  

int wakePin = 2;                 // пин, используемый для пробуждения
int led = 13;  

void wakeUpNow() {  
}  

void setup() {  
  pinMode(wakePin, INPUT_PULLUP);  
  pinMode(led, OUTPUT);   
  attachInterrupt(0, wakeUpNow, LOW); // используем прерывание 0 (вывод 2) и запускаем функцию wakeUpNow, когда вывод 2 получает НИЗКИЙ уровень
}  

void sleepNow() {  
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // здесь устанавливается спящий режим
    sleep_enable();          // включает бит сна в регистре mcucr
    attachInterrupt(0,wakeUpNow, LOW); // используем прерывание 0 (вывод 2) и запускаем функцию
    digitalWrite(led,LOW);
    sleep_mode();            // здесь устройство действительно усыплено!!
    // ПРОГРАММА ПРОДОЛЖАЕТСЯ С ЭТОГО ПОСЛЕ ПРОБУЖДЕНИЯ
    sleep_disable();         // первое, что нужно сделать после пробуждения от сна: отключить сон...
    detachInterrupt(0);      // отключает прерывание 0 на выводе 2, поэтому код wakeUpNow не будет выполняться в обычное время работы.
    digitalWrite(led,HIGH);
}  

void loop() {  
  sleepNow();     // здесь вызывается функция сна
}

Заранее спасибо.

Код адаптирован к следующему, и теперь он работает. Когда движение обнаруживается ИК-датчиком, он включает светодиод на контакте 13; когда движение не обнаружено, светодиод выключается.

Остались два вопроса:

1) Как я могу быть уверен, что Arduino действительно сейчас спит?

2) Когда Arduino только что перешел в спящий режим, требуется несколько секунд (+/- 6 с), прежде чем он сможет уловить другое движение. Могу ли я получить более быстрое обнаружение или другой метод «сна» или «энергосбережения», который позволит Arduino быстрее реагировать на движение?

#include <avr/sleep.h>  

const int wakePin = 2;                 // пин, используемый для пробуждения
const int led = 13;  

int wakeVal = 0;
int wakeState = LOW;

void wakeUpNow() {

}  

void setup() {  
  Serial.begin(9600);
  pinMode(wakePin, INPUT_PULLUP);  
  pinMode(led, OUTPUT);   
  //attachInterrupt(0, sleepNow, LOW); // используем прерывание 0 (вывод 2) и запускаем функцию wakeUpNow, когда вывод 2 получает НИЗКИЙ уровень
}  

void sleepNow() {  
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // здесь устанавливается спящий режим
    sleep_enable();          // включает бит сна в регистре mcucr
    attachInterrupt(0,wakeUpNow, LOW); // используем прерывание 0 (вывод 2) и запускаем функцию
    sleep_mode();            // здесь устройство действительно усыплено!!
} 

void disSleep(){
  // ПРОГРАММА ПРОДОЛЖАЕТСЯ С ЭТОГО ПОСЛЕ ПРОБУЖДЕНИЯ
    sleep_disable();         // первое, что нужно сделать после пробуждения от сна: отключить сон...
    detachInterrupt(0);      // отключает прерывание 0 на выводе 2, поэтому код wakeUpNow не будет выполняться в обычное время работы.
}

void loop() {
  wakeVal = digitalRead(wakePin);
  if (wakeVal == HIGH){

    disSleep();

    digitalWrite(led,HIGH);
    delay(1000);

    if (wakeState == LOW){
      Serial.println("Motion detected");
      wakeState = HIGH;
    }
  }
  else{
    digitalWrite(led,LOW);
    delay(1000);

    if (wakeState == HIGH){
      Serial.println("Motion stopped - Going to Sleep Mode !");
      wakeState = LOW;
      delay(1000);

      sleepNow();     // здесь вызывается функция сна
    }
  }  
}

, 👍2

Обсуждение

Вы предполагаете, что ваш датчик дает низкий выходной сигнал, когда обнаруживает движение? Возможно, все наоборот?, @uint128_t

@uint128_t прав. Большинство ИК-датчиков переходят в ВЫСОКИЙ уровень, когда обнаруживают движение., @dinotom

attachInterrupt(0,wakeUpNow, HIGH); может быть?, @Gerben

Да, я знаю, что движение = высокое, и ни одно движение не должно быть низким. Я уже пробовал присоединить Interrupt(0,wakeUpNow,HIGH). Вроде не решает., @Y.Terz


1 ответ


2

Это проблема платы Arduino Mega. На Mega D2 не INT0, как на Uno. Это INT4. В спецификации есть сноска, в которой говорится, что поддерживается только прерывание уровня. Это означает, что вы не можете использовать RISING, FALLING или CHANGE. Ваш единственный выбор — использовать LOW. Таким образом, Arduino проснется, когда движение выключится, а не включится. Вот почему это отстало. Если вы используете Uno вместо Mega, вы можете использовать RISING, и он будет работать так, как вы думаете.

,