спящий режим
- Войдите на сайт для отправки комментариев
Пнд, 20/01/2014 - 00:38
Всем привет, хочу с помощью кнопки выводить Arduino из спящего режима. Правильно я понимаю, что кнопка привязывается к выходу, отвечающему за прерывание? Вот этот скетч для этого годится?
#include <avr/sleep.h>
#include <avr/power.h>
int pin = 2;
void wakeUp()
{
Serial.print("WakeUp"); //Проснулись
detachInterrupt(0); //Отключаем прерывания
while(1); //Бесконечный цикл
}
void EnterSleep()
{
attachInterrupt(0, wakeUp, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
delay(100);
sleep_enable(); //Разрешаем спящий режим
sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
sleep_disable(); //Запрещаем спящий режим
}
void setup()
{
Serial.begin(9600);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Определяем режим сна
pinMode(pin, INPUT);
}
void loop()
{
...
}
Класс! Ваш ардуино проснется от нажатии кнопки и закружится, закружится... Только не в танце, а в бесконечном цикле. Нафига она такая кому то нужна?
Идея правильная, только скетч кривой.
Тут важно как кнопка подключена, если она подключена на GND, то нужно позаботиться о подтяжке входа на плюс питания или внешним или внутренним регистром
еще полезно в даташите на МК прочитать раздел про режимы питания/сна, чтобы понимать разницу между разными режимами
Кнопку подключил к массе, скетч изменил. Светотодиод горит при нажатии, только не понятно как сделать, как вводит Arduino в спящий режим с помощью кнопки, а не только выводить #include <avr/sleep.h> #include <avr/power.h> int Switchpin = 2; int pinled=13; void wakeup() // { Serial.print("Wake"); // detachInterrupt(0); // digitalWrite(13,HIGH); } void EnterSleep() // { attachInterrupt(0, wakeup,LOW); // sleep_enable(); // sleep_mode(); // sleep_disable(); // } void setup() { Serial.begin(9600); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // pinMode(Switchpin , INPUT_PULLUP); // pinMode(13, OUTPUT); } void loop() { Serial.print("Hello World"); delay(5000); Serial.print("Sleep"); EnterSleep(); // }вы для начала определитесь с задачей
если хотите, чтобы кнопка работала и во время сна и во время бодрствования, то поставьте
attachInterruptпосле выхода из сна и прицепите прерывание к другой функции, которая будет работать от кнопки во время бодрствования. Это первый вариант. Второй вариант - тупо считывать значения порта в loop() но нужно будет "бороться" с дребезгом контактов, иначе одно нажатие кнопки у вас вызовет несколько засыпаний и несколько просыпаний и конечный результат не гарантирован))первый вариант интересует.
Попробовал вот так, привязал кнопку к фунциям для входа в сон и выхода из него. Но походу не правильно (
#include <avr/sleep.h> #include <avr/power.h> int switchpin = 2; int pinled=13; void wach() // { Serial.print("wakeup"); // attachInterrupt(0,EnterSleep,CHANGE); // digitalWrite(13,HIGH); } void EnterSleep() // { attachInterrupt(0, wakeup,LOW); sleep_enable(); // sleep_mode(); // sleep_disable(); // digitalWrite(13,LOW); } void setup() { Serial.begin(9600); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // pinMode(switchpin , INPUT_PULLUP); // pinMode(13, OUTPUT); } void loop() { Serial.print("Hello World"); }wakeup серийный порт не пишет
первый вариант интересует.
Попробовал вот так, привязал кнопку к фунциям для входа в сон и выхода из него. Но походу не правильно (
#include <avr/sleep.h> #include <avr/power.h> int switchpin = 2; int pinled=13; void wach() // { Serial.print("wakeup"); // attachInterrupt(0,EnterSleep,CHANGE); // digitalWrite(13,HIGH); } void EnterSleep() // { attachInterrupt(0, wakeup,LOW); sleep_enable(); // sleep_mode(); // sleep_disable(); // digitalWrite(13,LOW); } void setup() { Serial.begin(9600); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // pinMode(switchpin , INPUT_PULLUP); // pinMode(13, OUTPUT); } void loop() { Serial.print("Hello World"); }wakeup серийный порт не пишет
Посмотрите на 20-ю строчку вашего кода и скажите, а где функция wakeup (что вы вызываете прерыванием)? Да и не понятно, где вы делаете attachInterrupt при инициализации? Вот запустили вы ардуину - какая функция после запуска будет обрабатывать нулевое прерывание на 2-й ноге? Где вы инициализировали это?
Вообще, интересная статья здесь.
По ее мотивам переписал код для вас. Проверить не на чем пока, должно работать:
#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() для засыпания } }Спасибо за помощь, работает как надо.
Только такой вопрос, есть темп.сенсор, записываю его показания на SD карту. Командные строчки для инициализации SD карты нужно забросить в фунцкию
wakeUpNowили в setup? И то, и другое контроллер выполняет один раз.Serial.begin(9600); while (!Serial) { ; } setSyncProvider(RTC.get); // Serial.print("SD Initializing..."); pinMode(10, OUTPUT); if (!SD.begin(10)) { Serial.println("Feilure, SD not initialized"); digitalWrite(A0, HIGH); analogWrite(3,0); // мотор не стартует, если инициализация не прошла return; } Serial.println("SD initialized."); analogWrite(3,pwm); // мотор стартует, если инициализация успещнаНу если по коду, который я вам дал, то функция wakeUpNow выполняется каждый раз после "пробуждения".
Делайте выводы.
Ребята помогите!!!
Залил код с поста #5 поправленный CityCat, ардуино ушла в сон а вывести из сна никак не могу.(((
Arduino pro micro (ATmega 32u4)
Как я понял проснутся должна от нажатия кнопки. Кнопка подключена к выводу 2 замыкание на минус. Также подключен резистор 220Ом от вывода 2 к +5В. Так должно быть?
p/s вообще по замеру тока она вроде как просыпается если удержиать кнопку в замкнутом состоянии, но ком порт не подключается.
Ребята помогите!!!
Залил код с поста #5 поправленный CityCat, ардуино ушла в сон а вывести из сна никак не могу.(((
Arduino pro micro (ATmega 32u4)
Как я понял проснутся должна от нажатия кнопки. Кнопка подключена к выводу 2 замыкание на минус. Также подключен резистор 220Ом от вывода 2 к +5В. Так должно быть?
p/s вообще по замеру тока она вроде как просыпается если удержиать кнопку в замкнутом состоянии, но ком порт не подключается.
Она не просыпается. Вы просто просаживаете питание на землю. Уберите резистор вообще или поставьте резистор побольше (килоОм на 10). В 36-й строке кода видно как нога подтягивается к плюсу программно. Зачем там еще резистор, тем более такого номинала?
Подскадите, почему мотор останавливается, только если я функцию sleep() analogWrite(9,0 ) вставляю. Разве в режиме Power dowm таймер не выключается? #include <avr/sleep.h> int motorPin=9; int Pin=8; byte pwm=150; void setup() { Serial.begin(9600); pinMode(motorPin, OUTPUT); pinMode(Pin, OUTPUT); pinMode(3,INPUT_PULLUP); } void wake () // { sleep_disable(); detachInterrupt(1); Serial.println("waking up"); ADCSRA = _BV(ADEN); } void loop() { if(digitalRead(3)==HIGH) {analogWrite (9,250); } if (digitalRead(3)==LOW) { sleep(); } } void sleep() // Sleep { Serial.println("going to sleep"); delay(50); ADCSRA = 0; set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); noInterrupts (); analogWrite(9,0); attachInterrupt (1, wake, HIGH); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); interrupts (); sleep_cpu (); }Всё равно не работает(((
Засыпает, а просыпаться не хочет. И после ресета не всегда Serial поднимается.
crecker а у Вас всё заработало по скетчу из поста #5 от CityCat. Нечего в нём не меняли?
ничего не менял, работает все.
А светодиод всегда загорается/тухнет при выходе/входе в спящий режим?
Подскажите, почему если я меняю строчку 32 из кода в 10 ответе на вот это, то мотор не стартует при нажатии кнопки. Очень важно
{ if ( millis ()-prev_Miliis>1000) // { if (x==x_alt) // { analogWrite ( 9,0); digitalWrite(A0, HIGH); // z=67; exit(o); } x_alt=x; // prev_Miliis=millis(); // if (z<65){ analogWrite(3,pwm++); Serial.println ("pwm:"); Serial.println(pwm); // } if (z>70) { analogWrite(3,pwm--); Serial.println ("pwm:"); Serial.println(pwm); } } }В общем получается вот что:
Убрал строку 36, сделал аппаратную подтяжку резистором 10кОм ноги 2 к +5В.
/Залил скетч в arduino pro mini (Atmega 328 5v)
После включения сразу загорается светодиод, идёт отсчёт 10 сек, по истечению 10 сек диод тухнет ардуино засыпает.
Если замкнуть ногу 2 на GND (без разницы временно или постоянно) диод загорается и начинается отсёт 10 сек, после чего ардуино опять засыпает. и.т.д. Это правельный алгоритм? Я думал что она должна бодорствовать пока на ноге 2 низкий уровень и засыпать когда на ноге 2 появляется высокий уровень.
/Залил скетч в arduino pro micro (Atmega 32u4) (на ней и планирую использовать спящйи режим)
А тут творится вообще что то непонятное
//Если питать от USB то начало правильно:
Ресет - светодиод загорается, идёт отсчёт, светодиод гаснет, ардуино засыпает. При этом USB становится не опознано.
Замыкаем ногу 2 на землю и либо нет реакции вообще либо светодиод быстро вспыхнет и дальше опять тишина(((
//Если питать от отдельного питания без подключения по USB:
Начало правильное - отсчёт, светодиод погас, ардуино засыпает.
на замыкание ноги два на GND первые пару-тройку раз работает нормально (включается светодиод, начинается отсчёт, засыпает). Потом достаточно просто поднести палец не косаясь ноги к ноге 2 и происходит включение светодиода, начинается отсчёт, светодиод гаснет, ардуино засыпает. 0_о
1. C мегой 328 работает корректно. Внимательно прочитайте код, который я приводил - в частности комментарии - для кого я писал? Там увидите и прерывание по заднему фронту на кнопке и то что прерывание нулевое, но на второй ноге (важно к пониманию для дальнейшегно рассмотрения). Здесь и далее i-й номер ноги = digital(i) pin ардуины.
Вот если, например, вы нажмете кнопку не дождавшись отсчета в 10 сек. при горящем диоде - ардуина уйдет тут же в спячку (ну либо через 10 сек. бездействия), а вот вывести ее можно только нажатием кнопки - в этом и весь смысл был. И обращаю внимание - это лишь пример работы с режимами низкого потребления и приведен он исключительно в ознакомительных целях. Если вам нужен конкретный алгоритм - никто за вас его здесь писать не будет - разбирайтесь.
2. Если мы посмотрим на ардуину Pro mini, то увидим (читайте внимательнее, чтоб не приходилось обращать ваше внимание на очевидные вещи!), что пользователю доступны лишь 2 прерывания (посик на странице по слову "прерывание") - нулевое (на второй ноге) и первое (на третьей ноге).
В свою очередь, если взглянуть на описание платы arduino micro, и опять-таки поискать там слово "прерывания", то можно наблюдать, что здесь уже пользователю достыпно 4 (ЧЕТЫРЕ) прерывания: нулевое (на нулевой ноге), первое (на первой ноге), второе (на второй ноге) и третье (на третьей ноге) прерывания.
Если еще не понятно, то обратимся к описанию функции attachInterrupt() (может я не совсем популярно описал). Буквально во второй строке читаем:
Но вот беда - наш микро - не относится к большинству (в данном контексте), посему нулевое прерывание у него на цифровой ноге ноль, а не на второй, как у про мини (или та же уно), например. А на какое прерывание мы вешаем вход и выход из спящего режима? На какой ноге?
Логика понятна? Надеюсь, что да. Оставляю для самостоятельного решения остаток проблемы.
3. Что у вас там за фантомы бродят и почему все так реагирует от внешнего источника питания - я не знаю. Возможно, вы подаете внешних 5 вольт, а не больше как рекомендовано, в том же описании - читайте внимательно. Возможно, где-то в цепи не хватает сглаживающих конденсаторов, возможно еще чего-то. Как не раз здесь говорили "гадать по кофейной гуще можно долго" (с) - не мой.
Удачи!
Потом достаточно просто поднести палец не косаясь ноги к ноге 2 и происходит включение светодиода, начинается отсчёт, светодиод гаснет, ардуино засыпает. 0_о
Повесьте кондёр на прерывание 1-10 н
CityCat, trembo спасибо, я понял ошибки. Не держите зла я только начинаю изучать ардуино. Нужен он мне для одного проекта.
Разьясните пожалйста если не трудно я правельно понял спящий режим?
Я планирую в проекте на ардуино сделать питание, резистивные кнопки, соединение ардуино pro micro с ардуино pro mini (на ардуино про мини будут висеть ещё кнопки и энкодер для управления) и управление аудиопроцессором TEA6320.
вся перефирия будет отключатся при пропадании внешнего сигнала (ACC на авто). Под напряжением останется только ардуино pro micro. В ней крутится кроме всего остально скетч управления питанием перефирии.
В результате у меня будет занято на pro micro
pin 0,1 (Rx, Tx) для соединения с arduino pro mini (ардуино будет выключатся при выключении всей системы)
pin 2,3 (sda, scl) для управления по I2c аудиопроцессором TEA6320 (тоже будет выключатся при отключении всей системы)
То есть я ни как не смогу сделать уменьшение электропотребления arduino pro micro (по таймеру и uart тоже не подходит)
Ну, во-первых, лично я не вижу смысла в использовании 2-х МК. Разве одного не хватит?
Потом, лично я не понял - чего вы хотите и чего куда у вас подключено и при каких условиях и главное где вы собираетесь включать спящий режим? На обоих? На одной? На какой? При каких условиях? Очень мало входных данных для того, чтоб вам что-то подсказать.
Мало того, если уж так не хочется использовать нроги 0 и 1 для связи, то может слышали о замечательной библиотеке SoftwareSerial (гуглите по слову SoftwareSerial - например вот - исключительно примера ради). Опять-таки - это описано в описании платы - ну прочтите ее внимательно наконец!
P.S. Кондер по питанию повесить не лишнее, но вот на цифровую ногу я бы кондер не вешал. Личное ИМХО.
Ну, во-первых, лично я не вижу смысла в использовании 2-х МК. Разве одного не хватит?
Потом, лично я не понял - чего вы хотите и чего куда у вас подключено и при каких условиях и главное где вы собираетесь включать спящий режим? На обоих? На одной? На какой? При каких условиях? Очень мало входных данных для того, чтоб вам что-то подсказать.
Мало того, если уж так не хочется использовать нроги 0 и 1 для связи, то может слышали о замечательной библиотеке SoftwareSerial (гуглите по слову SoftwareSerial - например вот - исключительно примера ради). Опять-таки - это описано в описании платы - ну прочтите ее внимательно наконец!
P.S. Кондер по питанию повесить не лишнее, но вот на цифровую ногу я бы кондер не вешал. Личное ИМХО.
Второй МК нужен только из за того что джойстик с кнопками будет удалён от первой МК на расстояние примерно 1,5 метра и не хотелось тянуть кучу проводов от джойстика до 1-ой МК. а так будет всего четыре провода Rx,Tx,+Uпит,GND
В спящий режим должна уходить только 1-ая мк вся остальная перефирия включая 2-ю мк будет отключатся по питанию.
К 1-ой мк подходит внешний сигнал. Либо +5 на ноге X когда вся переферия отключена (и 1-й МК уходит в сон) либо GND на ноге X и когда надо включить всё. (1-й МК просыпается, на нём крутится скетч по включению всей остальной перефирии включая второй МК)
Скетч включения и внешнюю обвязку я уже сделал всё работает а вот при отключении всего 1-й мк потребляет около 40мА что много для автомобильного АКБ.
Как то так
Я так понимаю я могу 2-ю МК соединить с первой с помощью SoftwareSerial (не используя ноги 0 и 1 первой МК). А спящий режим прицепить на прерывание 0 1-й МК.
Я так понимаю я могу 2-ю МК соединить с первой с помощью SoftwareSerial (не используя ноги 0 и 1 первой МК). А спящий режим прицепить на прерывание 0 1-й МК.
Правильно.
Скетч включения и внешнюю обвязку я уже сделал всё работает а вот при отключении всего 1-й мк потребляет около 40мА что много для автомобильного АКБ.
Я так понимаю я могу 2-ю МК соединить с первой с помощью SoftwareSerial (не используя ноги 0 и 1 первой МК). А спящий режим прицепить на прерывание 0 1-й МК.
Правильно.
Скетч включения и внешнюю обвязку я уже сделал всё работает а вот при отключении всего 1-й мк потребляет около 40мА что много для автомобильного АКБ.
Светодио только один - питание. Можно конешно попробовать но замер я делал только с скетчем питания, а как я понял чем больше будет скетч тем больше она будет потреблять.
У меня вот такая про микро и то не спарк а китайский клон))
... а как я понял чем больше будет скетч тем больше она будет потреблять...
Это где такое написано? О_о
... а как я понял чем больше будет скетч тем больше она будет потреблять...
Это где такое написано? О_о
Незнаю, пока изучал отложилось в голове)))
Когда пробовал Ваш скетч в спящем режиме ардуино потребляла 4,5 мА (это на ардуино про микро) и светодид питания светился, так что я не думаю что физическое отключение светодиода питания сильно снизит потребление.
Незнаю, пока изучал отложилось в голове)))
Что-то не ты вы изучали. Вообще-то есть конечно взаимосвязь того, что написано в скетче и потреблении, но не такая "прямая", как вам хотелось бы ))))
Когда пробовал Ваш скетч в спящем режиме ардуино потребляла 4,5 мА (это на ардуино про микро) и светодид питания светился, так что я не думаю что физическое отключение светодиода питания сильно снизит потребление.
А зря. Сильно снизит. Попробуйте отдельно светодиод запитать и измерить его потребление - скоолько вы думаете он будет потреблять? )))) Но это уж на любителя и к данной теме не относится.
Вообще, можно ж просыпаться и по приходу данных в уарт. Например вот здесь можно почитать. Это просто как вариант вам ;)
Помогите разобраться, пожалуйста, никак не пойму связь между спящим режимом и таймером. Если убираю строчки
из вот этого кода, то работает как надо. Если строчки не убираю, то программа не делает вообще ничего.
#include <avr/sleep.h> #include <TimerOne.h> #include <LiquidCrystal_I2C.h> // #include <Sensirion.h> // #include <Wire.h> #include <DS1307RTC.h> #include <Time.h> #include <SD.h> const int PWM_pin = 5; const int Lightsensor = 2; const int switch = 3; const uint8_t dataPin = 6; // const uint8_t clockPin = 7; // const int chipSelect = 10; static boolean Start = true; byte pwm=200; float Temperature=0; // float Humidity=0; float dew_point=0; volatile unsigned long x = 0; // unsigned long previousMillis = 0; volatile unsigned long y = 0; Sensirion Temperatursensor = Sensirion(dataPin, clockPin); LiquidCrystal_I2C lcd(0x20,16,2); void setup(){ Serial.begin(9600); lcd.init(); lcd.backlight(); pinMode(PWM_pin, OUTPUT); pinMode(Lightsensor, INPUT); // pinMode(switch,INPUT); attachInterrupt(0, count, RISING); //attachInterrupt(1, wake, HIGH); Timer1.initialize(8000000); // Timer1.attachInterrupt(mesure); // } void mesure() { ... } void wake () // { sleep_disable(); detachInterrupt(1); Serial.println("waking up"); } void loop (){ if (digitalRead(switch)==HIGH) { // Включаю кнопку, мотор вращается. if (Start){ // y=0; Serial.println("Start Motor."); // analogWrite(PWM_pin,pwm); previousMillis = millis(); // x = 0; // Start = false; } if (millis()-previousMillis>1000){ // previousMillis = millis(); // жду секунду, контролирую обороты Serial.print("RPM= ");Serial.print(x*60);Serial.println("RPM"); // if ( x*60<2520) { analogWrite(5,pwm++);} if ( x*60>2550) { analogWrite(5, pwm--);} if ( x*60==0) { analogWrite( 5, 0);} y+=x; x = 0; // } }else { // кнопка выключена, ардуино спит Start = true; sleep(); } } // end loop() void count(){ x++; // } void sleep() // { Serial.println("going to sleep"); delay(50); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); attachInterrupt (1, wake, HIGH); sleep_disable(); detachInterrupt(1); }Прокоментировал код, надеюсь откликов будет больще
#include <avr/sleep.h> #include <TimerOne.h> #include <Sensirion.h> // #include <Wire.h> #include <DS1307RTC.h> #include <Time.h> #include <SD.h> const int PWM_pin = 5; // мотор const int Lightsensor = 2; // сенсор для подчсета оборотов const int switchpin = 3; // кнопка для активации программы const uint8_t dataPin = 6; // темп. сенсор const uint8_t clockPin = 7; // темп. сенсор const int chipSelect = 10; // SD карта static boolean Start = true; //сигнал для старта byte pwm=200; float Temperature=0; // float Humidity=0; float dew_point=0; volatile unsigned long x = 0; // для подсчета оборотов за одну петлю unsigned long previousMillis = 0; // время volatile unsigned long y = 0; // для подсчета общего количества оборотов Sensirion Temperatursensor = Sensirion(dataPin, clockPin); void setup(){ Serial.begin(9600); pinMode(PWM_pin, OUTPUT); // мотор на выходе pinMode(Lightsensor, INPUT); // датчик на входе pinMode(switchpin,INPUT); // кнопка прерывание attachInterrupt(0, count, RISING); // прерыввание //attachInterrupt(1, wake, HIGH); Timer1.initialize(8000000); // функция должна вызыватся каждые 8 секунд Timer1.attachInterrupt(mesure); // } void mesure() { } void wake () // сон { sleep_disable(); detachInterrupt(1); Serial.println("waking up"); } void loop (){ if (digitalRead(switchpin)==HIGH) { // Включаю кнопку, мотор вращается. if (Start){ // y=0; // общие обороты равны нулю Serial.println("Start Motor."); // analogWrite(PWM_pin,pwm); previousMillis = millis(); // обновление времени x = 0; // Start = false; // старт прошел } if (millis()-previousMillis>1000){ // жду секунду, контролирую обороты previousMillis = millis(); // обновляется время Serial.print("RPM= "); Serial.print(x*60); Serial.println("RPM"); // контроль оборотов if ( x*60<2520) { analogWrite(5,pwm++); } if ( x*60>2550) { analogWrite(5, pwm--); } if ( x*60==0) { analogWrite( 5, 0); } y+=x; // прежде чем обнулить показания датчика они сохраняются x = 0; // обнуляю датчик } } else { // кнопка выключена, ардуино спит Start = true; sleep(); } } // end loop() void count(){ //cчитаются обороты x++; } void sleep() // { Serial.println("going to sleep"); delay(50); set_sleep_mode (SLEEP_MODE_PWR_DOWN); //режим сна sleep_enable(); // активировать сон attachInterrupt (1, wake, HIGH); // кнопка активна sleep_disable(); // деактивировать сон detachInterrupt(1); // }Код работает, только при нажатии кнопки, вместо ухода в сон прыгает между сном и бодрствлванием, тоесть серийный порт пишет
и мотор крутится дальше, подскажите в чем ошибка.
crecker, все верно. Потому как:
А вот
Для кого я писал комменты?
Оно просто не засыпает - оно включает и выключает бит, разрешпющий режим слип.
Где в вашем коде sleep_mode();?
Переписал вот так, мотор крутится написано старт и больше ничего не происходит
#include <avr/sleep.h> #include <TimerOne.h> #include <Sensirion.h> // #include <Wire.h> #include <DS1307RTC.h> #include <Time.h> #include <SD.h> const int PWM_pin = 5; // мотор const int Lightsensor = 2; // сенсор для подчсета оборотов const int switchpin = 3; // кнопка для активации программы const uint8_t dataPin = 6; // темп. сенсор const uint8_t clockPin = 7; // темп. сенсор const int chipSelect = 10; // SD карта static boolean Start = true; //сиграл для старта byte pwm=200; int sleepStatus=0; float Temperature=0; // float Humidity=0; float dew_point=0; volatile unsigned long x = 0; // для подсчета оборотов за одну петлю unsigned long previousMillis = 0; // время volatile unsigned long y = 0; // для подсчета общего количества оборотов Sensirion Temperatursensor = Sensirion(dataPin, clockPin); void setup(){ Serial.begin(9600); pinMode(PWM_pin, OUTPUT); // мотор на выходе pinMode(Lightsensor, INPUT); // датчик на входе pinMode(switchpin,INPUT); // кнопка прерывание attachInterrupt(0, count, RISING); // прерыввание attachInterrupt(1, wake, FALLING); Timer1.initialize(8000000); // функция должна вызыватся каждые 8 секунд Timer1.attachInterrupt(function); // } void function() { Serial.print("Hello"); } void wake () // проснулся { if (sleepStatus) { sleep_disable(); Serial.println("waking up"); sleepStatus=0; } else { Serial.println ("Timer: Entering Sleep mode"); delay(100); sleep(); } } void loop (){ if (digitalRead(switchpin)==HIGH) { // Включаю кнопку, мотор вращается. if (Start){ // y=0; // общие обороты равны нулю Serial.println("Start Motor."); // analogWrite(PWM_pin,pwm); previousMillis = millis(); // обновление времени x = 0; // Start = false; // старт прошел } if (millis()-previousMillis>1000){ // жду секунду, контролирую обороты previousMillis = millis(); // обновляется время Serial.print("RPM= "); Serial.print(x*60); Serial.println("RPM"); // контроль оборотов if ( x*60<2520) { analogWrite(5,pwm++); } if ( x*60>2550) { analogWrite(5, pwm--); } if ( x*60==0) { analogWrite( 5, 0); } y+=x; // прежде чем обнулить показания датчика они сохраняются x = 0; // обнуляю датчик } } else { // кнопка выключена, ардуино спит Start = true; sleep(); } } // end loop() void count(){ //cчитаются прерывания x++; } void sleep() // сон { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); //attachInterrupt(0,wake, LOW); sleepStatus=1; sleep_mode(); }Использую вот этот выключатель, подключение 5 вольт и пин 3.
А что должно происходить? Вы на самом деле считаете нас телепатами и мы должны догадываться о ваших действиях? По вашему коду и должно при подключении питания писать "Hello" (каждые 8 сек.) и если включен этот, с позволения сказать "выключатель" - "Start Motor.". Что еще вам нужно? Мы гадать должны?
Про объявления - вообще интересно: читать здесь внимательно - в основном про подтяжку (подсказывать не буду - думайте сами где и почему у вас что не так с подтяжкой)
Далее - зачем вообще вот эти строки (они когда-нибудь будут выполнены? Когда?)?
109 else { // кнопка выключена, ардуино спит 110 Start = true; 111 112 sleep(); 113 }Создается впечатление, что вы совсем не понимаете, как работает ваш код - здесь могут подсказать, а не рассказывать как работает каждая строка вашего кода.
Внимательно изучите свой код. Поймите смысл строки:
Соответственно, должно прийти понятие что не так и почему.
Еще раз прочитайте описание функции attachInterrupt. Вы уверены, что у вас правильно инициализировано прерывание? Может в вашем случае нужно не FALLING а что-то иное?
P.S. Все о чем я писал касается спящего режима, его включения и выключения. Про ваш код отдельная история, но не в этой теме (то есть я не рассматривал и не искал ошибки в нем - он мне неинтересен).
ок, задумка была такая. После загрузки кода ардуино сначала спит, тоесть ничего не делает и потребляет минимум электроэнергии. При нажатии кнопки, программа начинает работу: делает инициализацию, вращает мотор и переодически меряет температуру и запивывает на SD карту.
При смене положения кнопки программа прерывается и ардуино уходит в спящий режим до последующего нажатия кнопки.
Почему то мотор не выключается, ведь при переходе в режим
должны выключатся все таймеры, отвечающие за шим.
Строчки
else { // кнопка выключена, ардуино спит 110 Start = true; 111 112 sleep(); 113 }работают, если sleep() заменить на
тоесть при выключении кнопки мотор останавливается.
Ну, во-первых, переход в режим сна осуществляется вот этой строкой (сколько можно говорить уже):
а не этой:
Если нужна реакция при смене положения кнопки, то очевидно, что прерывание нужно ставить по CHANGE, а не FALLING - это тоже почему-то непонятно и я уже не в первый раз об этом говорю.
Ну и в-третьих, при смене сигнала с 1 в 0 (задний фронт) на пине, на котором вы повесили прерывание (читай - при выключении кнопки) собственно и сработает функция, которая вызывается прерыванием, а она уведет ардуину в спящий режим, посему все что после else (строки 109-113 вашего кода) обрабатывать будет некому - ардуина спит. Но это было бы... Если б вы подтянули ногу к земле, т.к. при отключении от нее 5в., неизвестно что на ней будет - собственно писал вам про подтяжку. Когда же вы включите свою кнопку, на ноге будет лог.1, следовательно то, что под else тоже не будет обрабатываться. Внимание вопрос (повторяю тоже второй раз): зачем вообще вот эти строки (они когда-нибудь будут выполнены? Когда?)?
Вам сложно почитать? Нужно разжевать?
P.S. Зачем вам такие сложности? Включате кнопкой питание ардуины - все работает. Выключаете - все останавливается. В чем проблема-то?
Ну так у ардуино есть 6 спящих режимов
надо же указать какой именно режим должен вызываться или не правильно.
Ну так у ардуино есть 6 спящих режимов
надо же указать какой именно режим должен вызываться или не правильно.
Всегда думал что их 5:
С засыпанием просыпанием всё заработало как часики))) Спасибо большое CityCat.
Вот только есть одно НО....
Какая то проблема с USB. При первой подачи питания, если не уводить ардуину в сон USB (COM порт) работает как пологается. А вот после просыпания никак не хочет. При чём это не зависимо от кода который у меня использует Serial, пробовал и без него всё равно такой же результат.
Возможно как то корректно деактивировать перед уходом в сон и активировать после просыпания COM порт кроме Serial.end(), Serial.begin().?
#include <avr/sleep.h> #include <avr/power.h> int ACCPin = 2; // Пин используемый для просыпания (прерывания), включения, отключения питания хаба и планшета int sleepStatus = 0; // Переменная для хранения статуса (спим, проснулись) - не используется в коде #define relePinHUB 8 // питание HUB #define relePinTablet 7 // питание +5 в ОТГ планшета, управление аудиоусилителя, управление усилителя радиоантены #define ONHUB 500 // время включения реле HUB #define ONTablet 5000 // время включения планшета #define OFFHUB 30000 // время выключения реле HUB #define OFFTablet 3000 // время выключения планшета unsigned long duration, millisold, off = 0; boolean stateACC, relestate1, relestate2 = 0; int buttonPin=6; //пин для резистивных кнопок int data; int flag=0; long previousMillis = 0; int val=0; void wakeUpNow() // Прерывание сработает после пробуждения { if (sleepStatus) // Если мы спали, { sleep_disable(); // то первое, что нужно сделать после просыпания - выключить спящий режим sleepStatus = 0; // В переменную заносим статус бодрствования detachInterrupt(1); // Выключаем прерывание - при нормальном режиме wakeUpNow() не будет вызываться } // Код, который здесь выполнится перед возвращением в цикл loop() // Таймеы и код, использующий таймеры (serial.print и др...) здесь не будет работать // Также мы не должны выполнять какие-то спец. функции здесь, // Т.к. здесь мы просто просыпаемся } void setup() { pinMode(ACCPin, INPUT); attachInterrupt(1, wakeUpNow, FALLING); // Используем прерывание 1 (pin 2) для выполнения функции wakeUpNow pinMode(relePinHUB, OUTPUT); pinMode(relePinTablet, OUTPUT); Keyboard.begin(); Serial.begin(9600); } void sleepNow() // Функция увода ардуины в спячку. { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип attachInterrupt(1, wakeUpNow, FALLING); // Используем прерывание 1 (pin 2) для выполнения функции wakeUpNow при появлении низкого уровня на пине 2 sleepStatus = 1; // В переменную заносим статус сна sleep_mode(); // Здесь устройство перейдет в режим сна!!! //-------------------------ПОСЛЕ ПРОСЫПАНИЯ ВЫПОЛНЕНИЕ КОДА ПРОДОЛЖИТСЯ ОТСЮДА!!!--------------------------// } void loop() { Power(); Knopki(); delay(10); } void Power() { if (!digitalRead(ACCPin)&&stateACC) { stateACC=0; duration = millis(); } if (digitalRead(ACCPin)&&!stateACC) { stateACC=1; off = millis(); } if(!digitalRead(ACCPin) && !stateACC && millis ()-duration > ONHUB){ digitalWrite(relePinHUB, HIGH); relestate1 = 1; millisold = millis(); } if(!digitalRead(ACCPin) && !stateACC && millis ()-duration > ONTablet){ digitalWrite(relePinTablet, HIGH); relestate2 = 1; millisold = millis(); } if(digitalRead(ACCPin) && stateACC && millis () -off> OFFHUB){ digitalWrite(relePinHUB, LOW); relestate1 = 0; millisold = millis(); delay (2000); sleepNow(); } if(digitalRead(ACCPin) && stateACC && millis ()-off > OFFTablet){ digitalWrite(relePinTablet, LOW); relestate2 = 0; millisold = millis(); } } void Knopki() { data=analogRead(buttonPin); //читаем значение нажатой кнопки Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта if (data<=900) //если нажата любая из кнопок начинается отсчёт { if (millis() -previousMillis >200) { previousMillis = millis(); val++; //кнопка громкости + if (data>=210 && data<=232 && flag==0 && val==1) //одиночное нажатие { Remote.increase(); //прибавить громкость на ед. Remote.clear(); flag=1; val=0; } if (data>=210 && data<=232 && val>=2) // удержание { Remote.increase(); //прибавлять громкость до отпускания Remote.clear(); val=0; } //кнопка громкости - if (data>=460 && data<=488 && flag==0 && val>=1 && val<=3) //одиночное нажатие { Remote.decrease(); //убавить громкость на ед. Remote.clear(); flag=1; val=0; } if (data>=460 && data<=488 && val>=4) //удержание { Remote.decrease(); //убавлять громкость до отпускания Remote.clear(); val=0; } //кнопка следующий трек if (data==0 && flag==0 && val==1) //одиночное нажатие { Remote.next(); //следующий трек Remote.clear(); flag=1; val=0; } if (data==0 && val>=2) //удержание { Remote.forward(); //перемотка вперёд Remote.clear(); val=0; } //кнопка предидущий трек if (data>=76 && data<=92 && flag==0 && val>=1 && val<=5) //одиночное нажатие { Remote.previous(); //предидущий трек Remote.clear(); flag=1; val=0; } if (data>=76 && data<=92 && val>=6) //удержание { Remote.rewind(); //перемотка назад Remote.clear(); val=0; } //кнопка приглушения звука if (data>=565 && data<=594 && flag==0) //нажата кнопка { Remote.mute(); Remote.clear(); flag=1; val=0; } } } //не нажата не одна из кнопок if (data>=950 && data<=960 && flag==1) { flag=0; } }Какая то проблема с USB. При первой подачи питания, если не уводить ардуину в сон USB (COM порт) работает как пологается. А вот после просыпания никак не хочет. При чём это не зависимо от кода который у меня использует Serial, пробовал и без него всё равно такой же результат.
В этом вопросе вам может помочь изучение разных режимов сна. http://avr.ru/beginer/understand/sleep_mode
Для меня detachInterrupt() так и осталась непонятной, поэтому у меня однократно в setup() ставится прерывание и всё. И если оно вдруг случилось во включенном состоянии - смотрим флаг "включаемся" - если true, подождать пару сек и если со входа кнопки всё ещё ноль (т. о. кнопа жмётся) - продолжать заводить, иначе спать. А если флаг false - то значит однозначно проснулись, если истекло более 5 сек, значит спать. Это позволяет по кнопке проснуться не сразу а её надо жать долго (2 с), а по повторному нажатию засыпать (если прошло не менее 5 с). В примере прога для фонарика с восемью выходами для светодиодов, там регулируется больше/меньше и умеет спать.
#include <avr/sleep.h> #include <avr/power.h> volatile boolean onflag=false, // going on state onflagdone=false; // on state int seconds=0; byte lev=0; unsigned long last_on=millis(), last_key=millis(); void waking(void){ onflag=true; } void sleeping(void){ onflag=false; onflagdone=false; seconds=0; lev=0; digitalWrite(5,LOW); digitalWrite(6,LOW); digitalWrite(7,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW); digitalWrite(10,LOW); digitalWrite(11,LOW); digitalWrite(12,LOW); delay(100); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); } void setup(){ pinMode(5,OUTPUT); // outs pinMode(6,OUTPUT); pinMode(7,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT); pinMode(11,OUTPUT); pinMode(12,OUTPUT); pinMode(4,INPUT); // unused pinMode(13,INPUT); pinMode(3,INPUT_PULLUP); // on pinMode(2,INPUT_PULLUP); // < pinMode(1,INPUT_PULLUP); // > pinMode(0,INPUT_PULLUP); // max attachInterrupt(1,waking,LOW); sleeping(); } void loop(){ if(onflag){ if(millis()-last_on>=1000){ seconds++; last_on=millis(); } if(!onflagdone){ delay(2000); if(digitalRead(3)==LOW) onflagdone=true; else sleeping(); }else{ digitalWrite(5,HIGH); if(lev>0) digitalWrite(6,HIGH); else digitalWrite(6,LOW); if(lev>1) digitalWrite(7,HIGH); else digitalWrite(7,LOW); if(lev>2) digitalWrite(8,HIGH); else digitalWrite(8,LOW); if(lev>3) digitalWrite(9,HIGH); else digitalWrite(9,LOW); if(lev>4) digitalWrite(10,HIGH); else digitalWrite(10,LOW); if(lev>5) digitalWrite(11,HIGH); else digitalWrite(11,LOW); if(lev>6) digitalWrite(12,HIGH); else digitalWrite(12,LOW); if(digitalRead(3)==LOW && seconds>=5){ digitalWrite(5,LOW); delay(500); sleeping(); } if(digitalRead(2)==LOW && millis()-last_key>=300){ if(lev>0) lev-=1; last_key=millis(); } if(digitalRead(1)==LOW && millis()-last_key>=300){ if(lev<7) lev+=1; last_key=millis(); } if(digitalRead(0)==LOW && millis()-last_key>=300){ if(lev!=1) lev=1; else lev=7; last_key=millis(); } } } }всем привет. киньте плиз ссыль на либс <avr/sleep.h> и на ее описание
Какую ссыль? Эта либа уже есть в IDE.
Кое-какое описание есть внутри самой либы, которая находится в "C:\Program Files\Arduino\hardware\tools\avr\avr\include\avr\"
Вот ещё нашлось: http://inet-deal.mpa.ru/articles/arduino-003.html, http://playground.arduino.cc/Learning/ArduinoSleepCode
жека спасиб, но у меня в иде 1.5.7 нет либы авр , где ее слитьможно в архиве но, чтоб в ней была либа слип
народ, киньте пример. как загнать уно в сон (пофиг в каком режиме), чтоб она выходила из сна после снятия и последующей подачи питания. не используя прерывания, таймеры и прочее. но!!!!! чтоб скетч начинал стартовать как обычно с инклюда, а не с места засыпания.
хотя и на то в каком месте проснется тоже пофиг))) главное покажите как отключать сон)) плиз
жека спасиб, но у меня в иде 1.5.7 нет либы авр , где ее слитьможно в архиве но, чтоб в ней была либа слип
Ну не правда же... Сейчас специально скачал 1.5.7 и проверил - всё там есть.
жека, впрограм файлах в тулсе папка авр есть. но в либах нет ни авр ни слипов ни поверов
единственное упоминание о авр это- в либах не активная кнопка платы авр
жека ткни носом как добавить к скетчу либу <avr/sleep.h> не набирая ее текстом, а выбрав из списка всех либ. мож туплю уже?
жека ткни носом как добавить к скетчу либу <avr/sleep.h> не набирая ее текстом, а выбрав из списка всех либ. мож туплю уже?
Никак, в списке либ её и не должно быть. Чтобы подключить нужно именнно вручную написать #include <avr/sleep.h>
P.S. Кстати, все либы подключаются через #include. Даже те, которые есть в списке либ. Список даёт возможность лишь выбрать готовый пример кода (example), в котором #include уже прописано.
жека ткни носом как добавить к скетчу либу <avr/sleep.h> не набирая ее текстом, а выбрав из списка всех либ. мож туплю уже?
Никак, в списке либ её и не должно быть. Чтобы подключить нужно именнно вручную написать #include <avr/sleep.h>
P.S. Кстати, все либы подключаются через #include. Даже те, которые есть в списке либ. Список даёт возможность лишь выбрать готовый пример кода (example), в котором #include уже прописано.