По ее мотивам переписал код для вас. Проверить не на чем пока, должно работать:
#include <avr/sleep.h>
int wakePin = 2; // Пин используемый для просыпания (прерывания)
int sleepStatus = 0; // Переменная для хранения статуса (спим, проснулись) - не используется в коде
int count = 0; // Счетчик
int LedPin=13; // Светодиод
void wakeUpNow() // Прерывание сработает после пробуждения
{
if (sleepStatus) // Если мы спали,
{
sleep_disable(); // то первое, что нужно сделать после просыпания - выключить спящий режим
digitalWrite(LedPin, HIGH); // Включаем светодиод
sleepStatus = 0; // В переменную заносим статус бодрствования
}
else
{
Serial.println("Timer: Entering Sleep mode");
delay(100); // Этот делэй необходим, чтоб функция sleep не вызывала ошибку по Serial
sleepNow(); // Вызов функции sleep() для засыпания
}
// Код, который здесь выполнится перед возвращением в цикл loop()
// Таймеы и код, использующий таймеры (serial.print и др...) здесь не будет работать
// Также мы не должны выполнять какие-то спец. функции здесь,
// Т.к. здесь мы просто просыпаемся
}
void setup()
{
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, HIGH); // Включаем светодиод
pinMode(wakePin, INPUT);
digitalWrite(wakePin, HIGH); // Подтягивем ногу к 5.
Serial.begin(9600);
attachInterrupt(0, wakeUpNow, FALLING); // Используем прерывание 0 (pin 2) для выполнения функции wakeUpNow (прерывание вызывается только при смене значения на порту с HIGH на LOW - подтянуть ногу 2 на 5в.)
}
void sleepNow() // Функция увода ардуины в спячку.
{
digitalWrite(LedPin, LOW); // Выключаем светодиод
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна
sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип
//attachInterrupt(0,wakeUpNow, LOW); // Используем прерывание 0 (pin 2) для выполнения функции wakeUpNow при появлении низкого уровня на пине 2
count = 0; // Обнуляем счетчик прошедших секунд
sleepStatus = 1; // В переменную заносим статус сна
sleep_mode(); // Здесь устройство перейдет в режим сна!!!
// -----------------------------------------------ПОСЛЕ ПРОСЫПАНИЯ ВЫПОЛНЕНИЕ КОДА ПРОДОЛЖИТСЯ ОТСЮДА!!!
//sleep_disable(); // Первое, что нужно сделать после просыпания - выключить спящий режим
//detachInterrupt(0); // Выключаем прерывание - при нормальном режиме wakeUpNow() не будет вызываться
}
void loop()
{
// Отображаем информацию о счетчике
Serial.print("Awake for ");
Serial.print(count);
Serial.println("sec");
count++;
delay(1000); // Ждем секунду
// Проверяем - если прошло 10 секунд - засыпаем
if (count >= 10)
{
Serial.println("Timer: Entering Sleep mode");
delay(100); // Этот делэй необходим, чтоб функция sleep не вызывала ошибку по Serial
count = 0;
sleepNow(); // Вызов функции sleep() для засыпания
}
}
У меня этот код не заработал. Засыпает как надо, просыпается и..... зависает. Может из-за более новой версии IDE.
Для меня проще свой код написать, чем разбираться почему чужой не работает. Почитал статью, все понятно.
Проц Atmega328P, при подключении питания - работает, не засыпает, при нажатии и удержании кнопки 2 сек - засыпает. При очередном нажатии и удержании - просыпается. Может кому пригодится. Критика приветствуется.
Кнопка, разумеется, со второго пина на землю.
#include <avr/sleep.h>
#define THRESHOLD 2000//порог срабатывания в мсек
const byte LED = 13;
bool flagWokeUp = 1;//начальное состояние - не спим
bool data = 1;
void wakeUp (){ //функция просыпания
sleep_disable();
detachInterrupt (0);
}
void setup ()
{
Serial.begin(9600);
pinMode (2, INPUT_PULLUP);
pinMode (LED, OUTPUT);
}
void loop () {
unsigned long time = 0;
if (!(PIND & (1 << 2))) time = millis();//если кнопка нажата
while (!(PIND & (1 << 2))); //ждем пока кнопку отпустят
if (time) {
if ((millis() - time) > THRESHOLD) {
flagWokeUp = !flagWokeUp;
time = 0;
}
}
if (flagWokeUp) {
// В этом блоке выполняем то, что нужно выполнять
// во включеном состоянии
//например мигаем диодом
delay (50);
digitalWrite (LED, data);
delay (50);
data = !data;
digitalWrite (LED, data);
}
if (!flagWokeUp)goSleep();
}
void goSleep() {//функция ухода в сон
delay(100);
ADCSRA = 0;
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
noInterrupts ();
attachInterrupt (0, wakeUp, FALLING);
EIFR = bit (INTF0);
MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);
interrupts ();
sleep_cpu ();
}
Прошу прощения, совсем запутался, пробовал разные варианты засыпает и не просыпается. Что надо, есть небольшой проект для автомобиля, наобходимо по наличию напряжения с замка зажигания пробуждать ардуинку и при отсутствии засыпать. Как выполнено в железе статус провод с замка зажигания подключен на аналоговый вход A(1), а также при появлении напряжения полевик(IFR 520N ноги G и S шунтированны резистором 10 к ) замыкает на землю контакт D2.
Пока реализовано только выключение дисплея. Сосбственно сам код. Немогу сообразить как сюда прикрутить алгоритм засыпания чтоб работало корректно.
#include <LiquidCrystal_I2C.h>
#include <avr/sleep.h>
#define THRESHOLD 2000//порог срабатывания в мсек
#define PIN_RELAY 5 // Определяем пин, используемый для подключения реле(вкл компрессора)
#define PIN_RELAY2 6 // Определяем пин, используемый для подключения реле(вкл пер блок)
#define PIN_RELAY3 7 // Определяем пин, используемый для подключения реле(вкл зад блок)
#define PIN_RELAY4 8 // Определяем пин, используемый для подключения реле(вкл зад блок)
LiquidCrystal_I2C lcd(0x27, 16, 2); // Устанавливаем дисплей
bool flagWokeUp = 1;//начальное состояние - не спим
bool data = 1;
void wakeUp (){ //функция просыпания
sleep_disable();
detachInterrupt (0);
}
void setup()
{
Serial.begin(9600);
pinMode (2, INPUT);
pinMode(PIN_RELAY, OUTPUT); // Объявляем пин реле как выход
pinMode(PIN_RELAY2, OUTPUT);
pinMode(PIN_RELAY3, OUTPUT);
pinMode(PIN_RELAY4, OUTPUT);
digitalWrite(PIN_RELAY, HIGH); // Выключаем реле - посылаем высокий сигнал
digitalWrite(PIN_RELAY2, HIGH);
digitalWrite(PIN_RELAY3, HIGH);
digitalWrite(PIN_RELAY4, HIGH);
lcd.init();
}
void loop()
{
if (digitalRead(2) == LOW) {
flagWokeUp;
}
if (digitalRead(2) != LOW){
!flagWokeUp;
}
if (flagWokeUp) {
// label :
float z = analogRead(A1); // Вход наличия включения зажигания.
z = z * 5. / 1024. / 6.8 * (20 + 6.8);
// if ( z > 10) {
lcd.backlight(); // Включаем подсветку дисплея
lcd.display(); //Включаем дисплей.
// } else {
// lcd.noDisplay(); // выключаем дисплей
// lcd.noBacklight();
// delay(1000);
// goto label;
// }
float val = analogRead(A0); // Вход датчика давления
val = val * 5. / 1024.;
val = 3 * val - 1.5;
float v = analogRead(A2); // вход измерения напряжения
v = v * 5. / 1024. / 6.8 * (20 + 6.8);
float kk = analogRead(A3); // вход кнопки компрессора
kk = kk * 5. / 1024. / 6.8 * (20 + 6.8);
float kvpb = analogRead(A6); // вход кнопки включения передней блокировки
kvpb = kvpb * 5. / 1024. / 6.8 * (20 + 6.8);
float kvzb = analogRead(A7); // вход кнопки включения задней блокировки.
kvzb = kvzb * 5. / 1024. / 6.8 * (20 + 6.8);
// delay(1000);
if (val < 0 ){
val = 0.0; // Убираем значения лежащие ниже предела измерения
}
if (val > 12){
val = 12; // Убираем значения лежащие выше предела измерения
}
if (kk > 10 and val <= 8 and z > 10){
lcd.setCursor(8, 1);
lcd.print("COMP ON ");
digitalWrite(PIN_RELAY, LOW); // Включаем реле - посылаем низкий уровень сигнала
}
if (kk < 10 || val >= 10 || z < 10){
lcd.setCursor(8, 1);
lcd.print("COMP OFF");
digitalWrite(PIN_RELAY, HIGH); // Отключаем реле - посылаем высокий уровень сигнала
}
if (kvpb > 10){
digitalWrite(PIN_RELAY2, LOW); // Включаем реле - посылаем низкий уровень сигнала
} else {
digitalWrite(PIN_RELAY2, HIGH); // Отключаем реле - посылаем высокий уровень сигнала
}
if (kvzb > 10){
digitalWrite(PIN_RELAY3, LOW); // Включаем реле - посылаем низкий уровень сигнала
} else {
digitalWrite(PIN_RELAY3, HIGH); // Отключаем реле - посылаем высокий уровень сигнала
}
// digitalWrite(PIN_RELAY2, LOW);
lcd.setCursor(0, 0);
lcd.print("P");
lcd.setCursor(2, 0);
lcd.print(val,1);
lcd.setCursor(9, 0);
lcd.print("V");
lcd.setCursor(11, 0);
lcd.print(v,1);
// Устанавливаем курсор на вторую строку и нулевой символ.
lcd.setCursor(0, 1);
// Выводим на экран количество секунд с момента запуска ардуины
lcd.print(millis() / 1000);
}
if (!flagWokeUp)goSleep();
}
void goSleep() {//функция ухода в сон
delay(100);
ADCSRA = 0;
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
noInterrupts ();
attachInterrupt (0, wakeUp, FALLING);
EIFR = bit (INTF0);
MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);
interrupts ();
sleep_cpu ();
}
ruslan_rachinsk, ADCSRA=(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2)|(1<<ADEN)|(1<<ADSC);
Я сделал так, вроде все зароботала, это куски кода.
byte old_ADCSRA; // для включения процесора (Глобальная переменная )
Потом когда проснулся,
Теперь буду знать как активировать процесор вашим способом!!!!
По ее мотивам переписал код для вас. Проверить не на чем пока, должно работать:
У меня этот код не заработал. Засыпает как надо, просыпается и..... зависает. Может из-за более новой версии IDE.
Для меня проще свой код написать, чем разбираться почему чужой не работает. Почитал статью, все понятно.
Проц Atmega328P, при подключении питания - работает, не засыпает, при нажатии и удержании кнопки 2 сек - засыпает. При очередном нажатии и удержании - просыпается. Может кому пригодится. Критика приветствуется.
Кнопка, разумеется, со второго пина на землю.
Прошу прощения, совсем запутался, пробовал разные варианты засыпает и не просыпается. Что надо, есть небольшой проект для автомобиля, наобходимо по наличию напряжения с замка зажигания пробуждать ардуинку и при отсутствии засыпать. Как выполнено в железе статус провод с замка зажигания подключен на аналоговый вход A(1), а также при появлении напряжения полевик(IFR 520N ноги G и S шунтированны резистором 10 к ) замыкает на землю контакт D2.
Пока реализовано только выключение дисплея. Сосбственно сам код. Немогу сообразить как сюда прикрутить алгоритм засыпания чтоб работало корректно.