Стартовый светофор для автогонок

rygoravich
Offline
Зарегистрирован: 04.05.2016

Предыстория такая - регулярно смотрю гонки формулы-1, ну и четырехлетний сын тоже подсел. Причем подсел серьезно - мало того, что со мной репортажи смотрит, так еще и свои гонки проводит - игрушечными машинками. Все по-взрослому - команды, пилоты и т.п. Так вот задумал я ему светофор подогнать для большего реализмуса.

Немного о сути задачи - светофор состоит из 5 красных фонарей (строго говоря, там есть еще фонари, но непосредственно в процедуре старта задействованы только красные). Изначально все потушены. Когда директор гонки нажимает на кнопку запуска процедуры старта они начинают поочередно загораться с интервалом в 1 секунду. После того как загорается последний происходит случайная задержка (в интервале от 1 до 2 секунд) и все огни разом гаснут - в этот момент гонщикам можно стартовать. Случайная задержка нужна для того, чтобы гонщики реагировали конкретно на потухшие огни, а не выжидали интервал после того, как загорится последний. Если процедура старта запущена, но старт еще не дан, то директор гонки может отменить старт - если на трассе произошло что-то, делающее старт небезопасным, например, если заглох один из болидов. Соответственно, для отмены старта жмется кнопка, фонари 2 и 4 загораются, остальные гаснут.

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

Дождался, посылки, распаковал... И тут всплывает один моментик. Изначально никаких коробочек не планировалось, я счел вполне приемлемым собрать все на хлебной доске (не знаю, правильно ли по-русски сей причиндал обозвал, то, что на али breadboard'ом называется). Я прикинул, что из предлагаемых на али мне подойдет плата на 830 отверстий, но - у меня уже была одна на 400, другая на 400 входила в заказанный наборчик, а поскольку они стекируемые (т.е. две платы можно физически соединить в одну при помощи специальных пазов и штырьков по краям), то не стал заказывать большую плату, предполагая обойтись двумя маленькими, собрав их вместе. Но тут меня ждал облом - хотя пришедшая в комплекте плата тоже была стекируемой, ее соединительные элементы отличались от тех, что были на моей старой плате. Видимо, у каждого производителя свои стандарты. Ну что ж, пришлось обходиться одной (дать ребенку две платы, скрепленные только проводами я не решился - это ж каждые две минуты надо будет заново провода втыкать). К счастью кое-как уместить удалось, хотя и плотненько получилось - соединительные провода сильно мешаются.

О схеме - ардуину я воткнул прямо в плату, светодиоды соединил последовательно с резисторами на 220 Ом и вывел на ноль и цифровые выводы 2-6 ардуинки. Две тактовые кнопки (запуск и отмена процедуры старта) вывел одной стороной на 5V, другой - на выводы 11-12 ардуинки и на ноль через резисторы 10 кОм. Запитал ардуинку через VIN от "кроны", отчекрыжив конец пришедшего в наборе разъемчика (который был рассчитан на arduino uno) и распихав оголившиеся провода в плату.

Выключения питания предусмотрено не было - не было в наличии подходящего переключателя, да и места для него в плате почти не осталось.

По факту вот такой вот девайс получился:

Софтину запилил такую:

// порты светодиодов
int leds[]={6, 5, 4, 3, 2};
// Кнопка старта
const int btnStart=11;
// Кнопка отмены
const int btnBreak=12;

void setup() {
  int i;
  for (i=0; i<5; i=i+1) {
    pinMode(leds[i], OUTPUT);
  }
  pinMode(btnStart, INPUT);
  pinMode(btnBreak, INPUT);
  randomSeed(analogRead(0));
}

void loop() {
  if (digitalRead(btnStart) == HIGH) {
    f1start();
  }
  delay(100);
}

void f1start() {
  int i;
  long nextLedTime;
  resetLeds();
  delay(1000);
  nextLedTime=millis();
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], HIGH);
    nextLedTime = nextLedTime + 1000;
    if (i==4) {
      nextLedTime = nextLedTime + random(1000);
    }
    while (millis() < nextLedTime) {
      if (f1startBreak()) return;
    }
  }
  resetLeds();
}

void resetLeds() {
  int i;
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], LOW);
  }
}

int f1startBreak() {
  if (digitalRead(btnBreak) == HIGH) {
    digitalWrite(leds[0], LOW);
    digitalWrite(leds[1], HIGH);
    digitalWrite(leds[2], LOW);
    digitalWrite(leds[3], HIGH);
    digitalWrite(leds[4], LOW);
    return 1;
  }
  return 0;
}

Из опыта практического использования: ребенок остался доволен, а вот жена - не очень. Когда он наигрался с машинками, то решил, что эта штука вполне подходит для старта забега с мамой из кухни в гостиную и наоборот. Итого за день, наверное, больше сотни забегов провели.

За один вечер новую (правда, солевую) "крону" посадили. Т.е. когда должен был загораться последний пятый светодиод он только вспыхивал на мгновение, все светодиоды гасли и вспыхивал диод перезагрузки на ардуине. Соответственно, встал вопрос об энергосбережении. В качестве первого этапа заменил резисторы на светодиодах с 220 Ом до 1k. Визуально яркость практически не изменилась и ладно.

В дальнейших планах:

1. Перенос устройства на плату побольше (чтобы связки проводов не мешали давить батоны) - плату заказал.

2. Замена 20см проводов на 10см (чтобы шлейфы не так нагло торчали) - провода тоже заказал. Можно, конечно, позачищать жилы от витой пары, но таки лень...

3. Глобально пересмотреть концепцию в пользу энергосбережения. В частности, включать питание кнопкой (при нажатии активируется реле, не дающее отключиться питанию при отпускании кнопки, сразу запускается процедура старта, после выполнения устройство дает реле сигнал на отключение питания). При отмене старта реализовать отключение устройства через то же реле через 30 секунд. Подходящую релешку тоже жду :) .

nevkon
Offline
Зарегистрирован: 20.01.2015

А еще посадить это дело на литий-ионный аккумулятор с простейшей платой защиты-зарядки(USB) и можно будет забыть о покупках дорогих и нерациональных крон. Выключатель лучше не кнопочкой с реле делать - реле съест больше чем сэкономите, а именно переключателем или уводить ардуину в сон и выводить по кнопке.

rygoravich
Offline
Зарегистрирован: 04.05.2016

nevkon, спасибо за дельные советы :) .

Насчет аккумулятора - буду думать, если другие способы не дадут возможности продлить срок службы крон до хотя бы месяца-двух.

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

Тут еще следует учитывать нюанс, что это в первый день устройству пришлось поработать по-полной, далее использование будет эпизодическим - несколько раз в день, да и то не каждый.

Переключатель вряд ли стоит рассматривать, т.к. вряд ли сын будет заботиться о том, чтобы его каждый раз выключать, а значит высока вероятность, что девайс все-таки целыми днями будет включен.

По поводу сна - честно говоря, не знал, что ардуины такое умеют. Спасибо за наводку, буду курить маны, о результатах доложу :) .

rygoravich
Offline
Зарегистрирован: 04.05.2016

Итак, почитал о спящем режиме, вроде бы более-менее разобрался...

Переписал скетч для использования сна, вот что получилось:

/*

Race Lights Control

(C) Rygoravich, 2017

License: This code is public domain but you buy me a beer if you use this and we meet someday
(Beerware license).

*/

#include <avr/sleep.h>

// порты светодиодов
int leds[]={8, 9, 10, 11, 12};
// Кнопка старта
const int btnStart=2;
// Кнопка отмены
const int btnBreak=3;
// Светодиод спящего режима
const int pwLed=13;
// Ожидание до засыпания, мс
int waitSleep = 20000;
// Время засыпания
unsigned long timeSleep = 0;
// Стартовая процедура завершена
boolean startEnded=false;

void setup() {
  pinMode(pwLed, OUTPUT);
  digitalWrite(pwLed, HIGH);
  int i;
  for (i=0; i<5; i=i+1) {
    pinMode(leds[i], OUTPUT);
  }
  pinMode(btnStart, INPUT);
  pinMode(btnBreak, INPUT);
  randomSeed(analogRead(0));
  Serial.begin(9600);
}

void loop() {
  startEnded=false;
  setTimeSleep();
  while (!startEnded) {
    if (digitalRead(btnStart) == HIGH) {
      startEnded=f1start();
      setTimeSleep();
    }
    else {
      if (
           digitalRead(btnBreak) == HIGH
        || (timeSleep>0 && millis()>timeSleep)
      ) {
        startEnded=true;
      }
    }
    delay(100);
  }
  sleepNow();
}

void setTimeSleep() {
  timeSleep = millis() + waitSleep;
}

void sleepNow() {
  resetLeds();
  attachInterrupt(0, wakeUpNow, RISING);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  digitalWrite(pwLed, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);
}

void wakeUpNow() {
  digitalWrite(pwLed, HIGH);
}

boolean f1start() {
  int i;
  long nextLedTime;
  resetLeds();
  delay(1000);
  nextLedTime=millis();
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], HIGH);
    nextLedTime = nextLedTime + 1000;
    if (i==4) {
      nextLedTime = nextLedTime + random(1000);
    }
    while (millis() < nextLedTime) {
      if (f1startBreak()) {
        return false;
      }
    }
  }
  resetLeds();
  return true;
}

void resetLeds() {
  int i;
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], LOW);
  }
}

boolean f1startBreak() {
  if (digitalRead(btnBreak) == HIGH) {
    digitalWrite(leds[0], LOW);
    digitalWrite(leds[1], HIGH);
    digitalWrite(leds[2], LOW);
    digitalWrite(leds[3], HIGH);
    digitalWrite(leds[4], LOW);
    setTimeSleep();
    delay(1000);
    return true;
  }
  return false;
}

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

В самом девайсе поменял пины для светодиодов и кнопок - с тем, чтобы можно было отлавливать прерывания для выхода из сна. Соответственно, кнопки сейчас висят на 2 и 3 пинах, леды - на 8-12.

К сожалению, не могу пока судить о том, насколько эти изменения эффективны... Поставил новую батарейку (на сей раз щелочную), посмотрим на сколько ее хватит.

А вообще на будущее заказал из поднебесной usb-тестер - придет, буду пробовать замерять потребление энергии в разных режимах при работе от usb - хоть общее представление получить :) .

Замечания и предложения по коду или устройству в целом приветствуются :) .

rygoravich
Offline
Зарегистрирован: 04.05.2016

Замерил ток между батарейкой и схемой... Все печально. В спящем режиме ардуинка хавает 11,4 мА. Это очень много - за два-три дня батарейка сядет в любом случае. Походу, спящий режим неэффективен - по крайней мере для nano.

Попробую все-таки вариант с реле - когда оно придет...

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

https://youtu.be/DwI65tBNN1I?t=417   сделайте так как там показано.

rygoravich
Offline
Зарегистрирован: 04.05.2016

Спасибо, конечно, за совет, но пожалуй не рискну.

Дело в том, что у меня только одна ардуинка... Была бы запасная - можно было бы и попробовать, но единственной рисковать совсем не хочется, тем более, что результат в принципе неизвестен - нет указаний, каково будет энергопотребление с такими изменениями. Может, сэкономится пара процентов...

Собственно, недавно заказал вторую, но пока она дойдет...

Параллельно народ расспрашиваю в этой теме: http://arduino.ru/forum/apparatnye-voprosy/spyashchii-rezhim-i-power-led, вот думаю, может еще pro mini заказать?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А все равно придется. Светодиод Повер "спать не ложиться" вместе со стабилизатором на+3,3B.

rygoravich
Offline
Зарегистрирован: 04.05.2016

Не, как минимум сначала дождусь второй экземпляр :) . Кстати, для сравнения заказал еще pro mini.

nevkon
Offline
Зарегистрирован: 20.01.2015

Питание от кроны и отсутствие стабилизатора никак не уживется. Поэтому и советовал литий - с него подавать напряжение на пин +5В напрямую можно, все будет в рабочем допуске МК (2.5-5.5В для МК, некоторые экземпляры 1.8-5.5В, а литий дает 2.7-4.3В). Ну или 3 пальчиковых (мизинчиковых) батарейки тоже можно напрямую подключить.

bwn
Offline
Зарегистрирован: 25.08.2014

nevkon пишет:

Питание от кроны и отсутствие стабилизатора никак не уживется. Поэтому и советовал литий - с него подавать напряжение на пин +5В напрямую можно, все будет в рабочем допуске МК (2.5-5.5В для МК, некоторые экземпляры 1.8-5.5В, а литий дает 2.7-4.3В). Ну или 3 пальчиковых (мизинчиковых) батарейки тоже можно напрямую подключить.

Я бы еще самоблокировку добавил из полевичка с кнопкой по питанию, а в скетчик измерение напряжения на литии и период неактивности кнопок. В итоге, нажали-отпустили кнопку питания, МК открыл полевик и работает, низкое напряжение или долго не нажимали рабочие кнопки - отключились нах. ИМХО.

rygoravich
Offline
Зарегистрирован: 04.05.2016

Случайно сегодня в магазине обнаружил бокс на три AA батарейки - ессно, не прошел мимо. Воткнул туда соответствующие элементы, попробовал запитать то же самое, ессно, не через VIN, а сразу на +5В. Результат меня удивил - потребление схемы в спящем режиме составило 11,0А, т.е. чуть ниже, чем когда она питалась от кроны, несмотря на разницу в напряжении. В том смысле, что при питании от кроны энергопотребление составляет 11,4мА*7,53В=85,8мВт, а от 3xAA - 11,0мА*4,8В=52,8мВт (тут напряжение на кроне 7,53 - т.к. батарейка уже подсевшая, а 4,8 на 3xAA - т.к. батарейки новые). Подозреваю, что если бы крона тоже была новой и выдавала чуть более 9В - разница вообще была бы двукратной. При всем этом емкость AA выше, чем у кроны (судя по интернет-источникам, сам не мерил, но с учетом разницы в габаритах и массе 3АА и должны быть более емкими), а цена 3 AA составляет 60% от цены одной кроны (аккурат так получилось, что в одном магазине брал и крону и AA, оба варианта щелочные от одного производителя и под одной торговой маркой).

В общем, для ардуинок больше кроны пользовать и пытаться не буду. Единственное - на текущий момент не совсем уверен, как nano себя поведет после того, как батарейки немного просядут... По идее с точки зрения МК проблем быть не должно, пока общее напряжение до 2,7 не дойдет (т.е. просадка до 0,9В каждая), но таки там еще и обвязка есть.

Что же касается непосредственно устройства - завтра попробую раздобыть "голый" микроконтроллер, вроде как обещали подогнать ATmega8A в DIP-исполнении, планирую попробовать заменить им ардуину. И вообще, как немножко начал копаться в теме - сразу появились мысли "а на кой ляд вообще эта ардуина сдалась, если там почти все лишнее" :) . О результатах отпишу.

bwn
Offline
Зарегистрирован: 25.08.2014

rygoravich пишет:

 но с учетом разницы в габаритах и массе 3АА и должны быть более емкими), а цена 3 AA составляет 60% от цены одной кроны (аккурат так получилось, что в одном магазине брал и крону и AA, оба варианта щелочные от одного производителя и под одной торговой маркой).

Литий от старого сотика вовсе бесплатный, зарядка на 20руб потянет. А по отдаче я думаю и крону а 3АА переплюнет. ИМХО.

rygoravich
Offline
Зарегистрирован: 04.05.2016

Ну, если не лежал годами - то в принципе согласен, но не для этого проекта. Тут идея в том, чтобы снизить потребление до таких значений, когда можно поставить батарейки и совсем о них забыть - хотя бы на полгода :) . Постоянно заряжать - не вариант... А литий еще и сравнительно опасен - не хотелось бы его ставить в детскую игрушку, которая не имеет корпуса и при этом возможно будет неоднократно роняться/топтаться/защемляться дверьми и т.п.

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

nevkon
Offline
Зарегистрирован: 20.01.2015

При низком напряжении может нестабильно работать - здесь как повезет. В даташите на МК есть где-то табличка какое питание требуется при какой частоте. Нано работает на частоте 16МГц от внешнего кварца. Для вашего проекта кварц не нужен, внутренний генератор дает частоту если не ошибаюсь 1МГц или 8МГц. Сделайте под минимальную частоту, заодно и потребление упадет (для голого МК).

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

bwn
Offline
Зарегистрирован: 25.08.2014

rygoravich пишет:

Ну, если не лежал годами - то в принципе согласен.

Оффтоп: Тож смотря какой литий, года два назад откопал в сарае Нокию 250 с батареей, раскурочил и обнаружил в ней две соньки 18650. Обе живые оказались, одна сейчас честно в китайской отвертке служит. В сарайку попали максимум в начале 2000-ных, а может и пораньше.

rygoravich
Offline
Зарегистрирован: 04.05.2016

nevkon пишет:

При низком напряжении может нестабильно работать - здесь как повезет. В даташите на МК есть где-то табличка какое питание требуется при какой частоте. Нано работает на частоте 16МГц от внешнего кварца. Для вашего проекта кварц не нужен, внутренний генератор дает частоту если не ошибаюсь 1МГц или 8МГц. Сделайте под минимальную частоту, заодно и потребление упадет (для голого МК).

Нашел как раз удобные таблички: для ATmega и для ATtiny. Вкратце - для большинства устройств достаточно 2,7В при работе на частоте до 10MHz (хотя для каждого конкретного МК лучше, конечно, уточнить в даташите). Это значит, что три батарейки будут справляться до тех пор, пока не просядут до 0,9 - вполне нормально. Ну, это касается собственно, микроконтроллеров, для обвязки, конечно надо смотреть отдельно. В частности, для собственно ардуин вообще никто ничего не гарантирует, если плата запитана не через USB и минуя VIN (который в свою очередь должен запитываться не менее, чем от 6В).

Итак, продолжение истории. В городе, где есть университет с радиотехническим факультетом, раздобыть ATmega в DIP-исполнении оказалось нереально (а я не настолько крут в обращении с паяльником, чтобы принимать во внимание существование других типов корпусов). Ну, хотя бы нарыл пару ATtiny2313A - хотя знал, что скомпилированный под nano скетч больше, чем влез бы в память этого чипа, но рассчитывал что-нибудь придумать. Надо сказать, обошлись они мне в разы дороже, чем продаются в Китае, но таки из Китая ждать долго. Впрочем, раз уж такая байда пошла - на будущее заказал в Китае десяточек ATmega8A - выбор чипа был обусловлен прежде всего ценой (83,5 цента за штуку) при возможностях, которых хватит на большинство моих потребностей. Если для какого-то проекта этих чипов не хватит - закажу чипы покруче дополнительно. Также к плюсам этого чипа можно отнести возможность работы на 16MHz при 2,7В - большинство других МК этой линейки для такой частоты требуют минимум 4,5В.

Встала задача - адаптировать имеющийся скетч с учтом особенностей чипа ATtiny2313A, в частности, оптимизировать размер, чтобы он влез на 2k flash. При этом очень не хотелось использовать прямую работу с портами, чтобы сохранить возможность оперативно менять назначение пинов. Увы, полностью логику сохранить не удалось. Во-первых, у этого чипа отсутствуют аналоговые входы, следовательно, неоткуда взять энтропию для инициализации генератора случайных чисел (поправьте меня, если знаете другой источник). Во-вторых, собственно функция random() оказалась для этого чипа непозволительной роскошью: замена строки "nextLedTime = nextLedTime + random(1000);" на "nextLedTime = nextLedTime + 1000;" позволила сэкономить 568 байт flash-памяти (т.е. больше четверти доступной на ATtiny2313A).

Итого после некоторых изменений загрузил в чип самодельным (на arduino nano) программатором прошивку, которая уже могла выполнять свои прямые функции - зажигать и гасить светодиоды с нужным алгоритмом в ответ на нажатие кнопок управления. Собрал схему. Генератор частоты использовал встроенный, кварц мне показался излишним, в fuse оставил включенным бит деления частоты на 8 (т.е. чип работал на 1MHz - для таких задач более чем достаточно). Естественно, с учетом изложенного в предыдущих постах в первую очередь меня интересовало энергопотребление в моменты простоя. Сразу со спящим режимом сладить не удалось, посему замерил в активном. Результаты получились достаточно обнадеживающими - без сна новая схема потребляла 3мВ, т.е. в разы меньше, чем arduino nano в спящем режиме. По моим расчетам этого уже было достаточно для питания устройства от трех AA в течение месяца в режиме простоя. Что ж, гораздо лучше, чем неделя (максимум) при использовании ардуины. Но, разумеется хотелось большего. Не без помощи форумчан таки удалось заставить спящий режим правильно работать - и тут я уже почувствовал чувство глубокого удовлетворения: мой тестер НЕ СМОГ замерить ток, проходящий через схему в режиме ожидания. Показания прыгали между 0 и 1мкА. Даже если допустить, что тестер на малых показаниях врет и реально там пусть даже 10мкА - все равно батареек емкостью 2000мАч хватит более чем на 20 лет, ну, это конечно, при допущении, что саморазряд и старение у них отсутствует.

На радостях вернул назад резисторы по 220 Ом на диодах (напомню, ранее я заменял их на 1К). При активном использовании максимальный ток составил 51мА - тоже не проблема для такого питания. Фактически получаем, что реально батарейки скорее состарятся, чем сядут от использования и теоретически можно их заменить на существенно менее емкие (например, солевые AAA).

Ну и собственно, последняя версия скетча (в сравнении с предыдущей - адаптировано для ATtiny2313A, расположение кнопок изменено).

/*

Race Lights Control

(C) Rygoravich, 2017

License: This code is public domain but you buy me a beer if you use this and we meet someday
(Beerware license).

*/

#include <avr/sleep.h>
#include <avr/power.h>

// порты светодиодов
const int leds[]={8, 9, 10, 11, 12};
// Кнопка старта
const int btnStart=4;
const int btnInterrupt=0;
// Кнопка отмены
const int btnBreak=5;
// Светодиод спящего режима
const int pwLed=13;
// Ожидание до засыпания, мс
const int waitSleep = 20000;
// Время засыпания
unsigned long timeSleep = 0;
// Стартовая процедура завершена
boolean startEnded=false;

void setup() {
  // Светодиод спящего режима
  pinMode(pwLed, OUTPUT);
  digitalWrite(pwLed, HIGH);
  
  // Сигнальные светодиоды
  int i;
  for (i=0; i<5; i=i+1) {
    pinMode(leds[i], OUTPUT);
  }

  // Кнопки
  pinMode(btnStart, INPUT);
  pinMode(btnBreak, INPUT);

  // Инициализация генератора случайных чисел
  // Раскомментить для МК с аналоговыми выходами
  //randomSeed(analogRead(0));
}

void loop() {
  sleepNow();
  startEnded=false;
  setTimeSleep();
  while (!startEnded) {
    if (digitalRead(btnStart) == LOW) {
      startEnded=f1start();
      setTimeSleep();
    }
    else {
      if (
           digitalRead(btnBreak) == LOW
        || (timeSleep>0 && millis()>timeSleep)
      ) {
        startEnded=true;
      }
    }
    delay(100);
  }
}

void setTimeSleep() {
  timeSleep = millis() + waitSleep;
}

void sleepNow() { // Спим
  resetLeds();
  attachInterrupt(btnInterrupt, wakeUpNow, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  digitalWrite(pwLed, LOW);
  sleep_enable();
  sleep_mode();
}

void wakeUpNow() { // Просыпаемся
  sleep_disable();
  detachInterrupt(btnInterrupt);
  digitalWrite(pwLed, HIGH);
}

boolean f1start() {
  int i;
  long nextLedTime;
  resetLeds();
  delay(1000);
  nextLedTime=millis();
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], HIGH);
    nextLedTime = nextLedTime + 1000;
    if (i==4) {
      nextLedTime = nextLedTime + 1000;
      //nextLedTime = nextLedTime + random(1000); // Если хватает флэш-памяти - раскомментить
    }
    while (millis() < nextLedTime) {
      if (f1startBreak()) {
        return false;
      }
    }
  }
  resetLeds();
  return true;
}

void resetLeds() {
  int i;
  for (i=0; i<5; i=i+1) {
    digitalWrite(leds[i], LOW);
  }
}

boolean f1startBreak() {
  if (digitalRead(btnBreak) == LOW) {
    digitalWrite(leds[0], LOW);
    digitalWrite(leds[1], HIGH);
    digitalWrite(leds[2], LOW);
    digitalWrite(leds[3], HIGH);
    digitalWrite(leds[4], LOW);
    setTimeSleep();
    delay(1000);
    return true;
  }
  return false;
}

В планах:

1. Заменить чип на ATmega8A (когда придет посылка из Китая) и вернуть на место временно отключенную функцию случайного интервала перед гашением диодов.

2. Таки отказаться от беспаечной макетной платы и перенести на печатную (хоть потренируюсь с паяльником), возможно, добавить какую-нибудь коробочку.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Включение МК одной кнопкой и автоматическое отключение после выполнения задачи.
http://avrproject.ru/publ/poleznaja_informacija/upravlenie_pitaniem_ustr...
Схему можно упростить практически до одного полевого транзистора.
Извиняюсь за повторение если кто уже предлогал.

rygoravich
Offline
Зарегистрирован: 04.05.2016

Спасибо, конечно, за познавательную ссылку (хотя, признаться, с ходу не разобрался, как это работает), но поскольку, как выяснилось, голый МК не имеет проблем с высоким потреблением в спящем режиме (в отличие от ардуино), то в принципе неактуально... Зачем усложнять схему с отключением питания, если во сне потребление менее одного (или пусть даже порядка нескольких) мкА?

Хотя пока работал с ардуино нано, была мысля использовать для энергосбережения отключение питания через реле - конечно, ваш вариант предпочтительнее :) .