• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Deep sleep с пробуждением по кнопке

Beerukoff

New member
поставить шлюз типа ключевика двустороннего (например, мультиплексор или демультиплексор) подсоединить еспшку к флэхе через него.
Во время записи на флэху с помощью ключа отдельного гасить плэйер по команде с есп. Или, вернее, перед CRUD :) операциями гасить его - чтобы плэйер и еспшка не мешали друг другу во время работы с флэхой.
Закончили редактирование файлов с помощью есп - перещёлкиваем оба ключевика - отключаем есп от флэхи и поднимаем обратно плэйер.
С помощью Яндекса я, конечно, через некоторое время пойму, что именно вы предложили :)


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

Arthur

Active member
С помощью Яндекса я, конечно, через некоторое время пойму, что именно вы предложили :)


Но для начала хочется все же научится правильно переходить в спящий режим (не обязательно DS) и выходить из него по нажатию кнопки.
Тогда Google вам в помощь - SPIFFS.
 

Beerukoff

New member
Просто пока я до получения компонентов с Али читал разные статьи и форумы, мне казалось, что заснуть ЕСПшку несложно и это вполне себе штатный режим работы.
А вот сейчас во время написания кода никак не могу найти какой-то простой пример для видоизменения и использования
 

Arthur

Active member
Просто пока я до получения компонентов с Али читал разные статьи и форумы, мне казалось, что заснуть ЕСПшку несложно и это вполне себе штатный режим работы.
А вот сейчас во время написания кода никак не могу найти какой-то простой пример для видоизменения и использования
Не ясен тогда вопрос ваш - так вопрос в том, как проресетить корректно и подняться в нужное состояние? - или Я чего-то не понимаю и звучит вопрос как "Как сделать всё с нуля, покажите, пожалуйста, прошивки, код и схему?" :).
 

Beerukoff

New member
Сейчас не хватает только кода засыпания и просыпания.
Все остальное (пусть пока и по частям) я уже сделал (и схему, и код). Кнопка нажимается, музыка играет, лампочки мигают, веб сервер поднимается, громкость с андроид приложения регулируется
 

pvvx

Активный участник сообщества
А если не погружать в DS, а просто отключать все, что можно отключить (кроме канала контроля кнопки), то насколько меньше проработает устройство от батареек?
У вас снова - питание от АКБ или батареек. Это уже часть внешней схемы у модуля и вопрос не в сколько потребляет модуль, когда спит, а сколько жрет внешний стабилизатор и система пробуждения по кнопке.
Не забываем и про контроль разряда АКБ. В итого у вас, если по самому простому, 2 микросхемы и индикатор разряда (например при нажатии этой одной кнопки он быстро мигает в течении n секунд с замедлением - индикация разряда батареи).
Тут кто-то просил схему - получите и распишитесь. :)
tststst.gif
Все условия тут выполнены - контроль разряда с ADC(! :eek:), стабилизатор и использование 1-го порта двунаправленных DIO сигналов для передачи кодов кнопки к ESP и кода отключения от EPS.
Стабилизатор импульсный, с более менее КПД, можно махнуть и на другой - при рисовании схемы такой первый выпал - не выбирал.
Схема умещается между выводами ESP8266 :)
Номера ног у I/O PIC10 делаются по разводке, а не по схеме - потом перепрограмируете, а провода потом перепаивать сложнее :)
 
Последнее редактирование:

Arthur

Active member
У вас снова - питание от АКБ или батареек. Это уже часть внешней схемы у модуля и вопрос не в сколько потребляет модуль, когда спит, а сколько жрет внешний стабилизатор и система пробуждения по кнопке.
Не забываем и про контроль разряда АКБ. В итого у вас, если по самому простому, 2 микросхемы и индикатор разряда (например при нажатии этой одной кнопки он быстро мигает в течении n секунд с замедлением - индикация разряда батареи).
Тут кто-то просил схему - получите и распишитесь. :)
Посмотреть вложение 3800
Все условия тут выполнены - контроль разряда с ADC(! :eek:), стабилизатор и использование 1-го порта двунаправленных DIO сигналов для передачи кодов кнопки к ESP и кода отключения от EPS.
Стабилизатор импульсный, с более менее КПД, можно махнуть и на другой - при рисовании схемы такой первый выпал - не выбирал.
Схема умещается между выводами ESP8266 :)
Чот Вы загнули чутка, слишком далеко вперёд прыгнули, с контролем разряда и потреблением тока стабилизатором...
Мы пока что ещё с дип слип ещё не разобрались, какой контроль разряда... )
 

Beerukoff

New member
Я планировал запитать от двух АА батарей (в разбираемой игрушке так) напрямую. Насколько я понял пока батарейки довольно свежие все должно работать и так.

Мне просто хочется ограничиться использованием nodemcu, dfplayer и динамика, а все остальное уже есть в игрушке. Во всяком случае на бредборде все работает (правда пока с питанием от USB). Плюс находил в интернете статьи как ардуина может измерять питающее напряжение, чтобы понять остаток батареек. Если разберусь, тоже приделаю с выводом его через веб-сервер.

А потом, если батарейки будут садиться очень быстро, уже думать дальше
 
Последнее редактирование:

pvvx

Активный участник сообщества
Чот Вы загнули чутка, слишком далеко вперёд прыгнули, с контролем разряда и потреблением тока стабилизатором...
Мы пока что ещё с дип слип ещё не разобрались, какой контроль разряда... )
Ну такой простой - села или не батарейка. Как узнать то, если нет индикатора?
И так самый примитив нарисовал - концепцию. Можно взять с проц другой буквой - с немного большей программной памятью и на пару выводов, выкинуть второй чип, а поставить два мосфета - будет и контроль заряда АКБ и импульсный стабилизатор :)
Размеры то всё равно останутся почти те-же, типа 5x8 мм :) :) У нас же самая большая и главная деталь - кнопка, светодиод и динамик. Всё остальное - это второстепенные деталюшки и должны укладываться между основными :)
И не совсем понятно - если главные задачи у устройства - управление динамиком, то при чем тут deep_sleep и другие нюансы типа Arduino, SPIFFS и прочих никчемных решений для неё? Это обязательная нагрузочная часть решения задачи управления динамиком с автономным питанием? :eek: Типа потупим по тупиковым внедренным в мозх системам, не годящихся для решения данной задачи?
 
Последнее редактирование:

pvvx

Активный участник сообщества
Мне просто хочется ограничиться использованием nodemcu,
У NodeMCU проблемы с deep_sleep и RESET. Размер деталей и их кол-во для доработки NodeMCU до рабочего варианта, годящегося под описание, больше чем использование пустого модуля.
Но не исключаю, что эта переработка NodeMCU и есть главная задача в данном развлечении...
 

Arthur

Active member
"Зевнул и потянулся" - Скучно это всё, господа, скучно.
Интересно было бы в дальнейшем узнать, будет ли этот проект реализован и что получится...
У меня часто получается вот в таком стиле:
upload_2017-3-30_17-25-25.jpeg
 

pvvx

Активный участник сообщества
Уже реализовал. Кнопка включается на PB_1, в модуль заливаем немного модифицированную прошивку MP3. К питанию модуля подключаем любой современную импульсную микруху на дцать МГц со встроенным в корпус дросселем и остальными причендалами. Подключаем через сборку двух мосфет один динамик на один канал и второй для стерео - аналогично. Включаем, нажимаем кнопку - модуль стартует и поет песни с внешнего URL в формате MP3. Такая замена за 200 рупь Хиаоми MP3, но стерео. Жмыкаем кнопку ещё раз - переключается радиостанция. Давим кнопку дольше - модуль упал в deep_sleep. Модуль всего-то другой, на 30 руб дороже, но не надо думать о кнопке старта...
 

Arthur

Active member
Уже реализовал. Кнопка включается на PB_1, в модуль заливаем немного модифицированную прошивку MP3. К питанию модуля подключаем любой современную импульсную микруху на дцать МГц со встроенным в корпус дросселем и остальными причендалами. Подключаем через сборку двух мосфет один динамик на один канал и второй для стерео - аналогично. Включаем, нажимаем кнопку - модуль стартует и поет песни с внешнего URL в формате MP3. Такая замена за 200 рупь Хиаоми MP3, но стерео. Жмыкаем кнопку ещё раз - переключается радиостанция. Давим кнопку дольше - модуль упал в deep_sleep. Модуль всего-то другой, на 30 руб дороже, но не надо думать о кнопке старта...
Я про проект ТСа грил...
 

Beerukoff

New member
В итоге за 3 дня фонового изучения языка (читал статьи, форумы, искал подходящие примеры, понимал логику языка) сделал следующий скетч, который делает все из моего ТЗ, кроме перехода в энергоэкномичный режим (не обязательно deep sleep) по истечению определенного времени

Код, наверняка, не оптимальный, но во всяком случае он работает. Обратную связь по вывод инфы в монитор порта в конце уберу

Код:
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <ESP8266WiFi.h>

//Распиновка
int button = D0;
int MP3BusyPin = D1;
int MP3Com1 = D3;
int MP3Com2 = D4;
int led1 = D5;
int led2 = D6;
int led3 = D5;

//Параметры wi-fi сети
const char* ssid = "WiFiVillage";
const char* password = "***";

//Параметры для светодиодов
const byte totalLEDs = 3; // Number of LEDS used -- number <255 so use a byte or uint8_t
const byte ledPin[totalLEDs] = {led1,led2,led3}; //Pins assigned to those LEDS -- number <255 so use a byte or uint8_t
boolean ledState[totalLEDs] =   {0,0,0}; // What is the current LED state -- used a byte to store true/false as boolean since it is ON or OFF (0 or not 0)
unsigned int ledOn[totalLEDs] = {0,0,0}; // used to store ON times, using unsigned int to hold time up to 65535 ms) -- used INT (16 bits to store larger values
unsigned int ledOff[totalLEDs] ={0,0,0}; // used to store OFF times, using unsigned int to hold time up to 65535 ms) -- used INT (16 bits to store larger values
unsigned long previousMillis[totalLEDs] = {0,0,0}; // What time was the LED last tumned OFF -- Needs to store largest possible value (4 bytes used)
unsigned long currentMillis;

//Начальная громкость
int MP3Vol = 1;

WiFiServer server(80);
//Описание ответов вебсервера
int i;
char* Ans[]={"Volume +", "Volume -", "Play Next"};

SoftwareSerial mySoftwareSerial(MP3Com1, MP3Com2); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

static unsigned long timerMP3;

void setup()
{
  pinMode(button, OUTPUT);
  pinMode(MP3BusyPin, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(MP3Vol);  //Set volume value. From 0 to 30
  myDFPlayer.next();  //Play the first mp3
  timerMP3 = millis();

// Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");
  // Print the IP address
  Serial.println(WiFi.localIP());

  //Настройка светодиодов
  for (byte currentLED=0; currentLED<totalLEDs; ++currentLED)
  {
    pinMode(ledPin[currentLED], OUTPUT); //initilize all used LED pins as outputs
    digitalWrite(ledPin[currentLED], LOW); //Turn LEDs off to start
  }

}

void loop()
{

if(digitalRead(button) == HIGH && digitalRead(MP3BusyPin) == HIGH)
{
PlayMP3:
Serial.println("play MP3");
myDFPlayer.next ();
timerMP3 = millis();

//delayplay = 0;
}

//Раздел выбора следующего MP3 при нажатии на кнопку во время проигрывания текущего
if (millis() - timerMP3 > 2000 && digitalRead(button) == HIGH && digitalRead(MP3BusyPin) == LOW)
  {
      myDFPlayer.next();
      timerMP3 = millis();
  }


//Раздел мигания светодиодами во время проигрывания MP3
if(digitalRead(MP3BusyPin) == LOW)
{

  currentMillis = millis();           // Get the current time

  for (byte currentLED=0; currentLED<totalLEDs; ++currentLED)
{
  if (currentMillis - previousMillis[currentLED] > (ledState[currentLED] ? ledOff[currentLED]:ledOn[currentLED])){   // using a conditional operator
    digitalWrite(ledPin[currentLED], ledState[currentLED] = !ledState[currentLED]);    // Flip the state and output it
 
    (ledState[currentLED] == 0) ? ledOn[currentLED]=random(400, 800) : ledOff[currentLED]=random(800, 1400);
   
    previousMillis[currentLED] = currentMillis;  // reset the blinker time
   }
}
}

//Выключение светодиодов при тишине
if(digitalRead(MP3BusyPin) == HIGH && digitalRead(button) == LOW)
{
  for (byte currentLED=0; currentLED<totalLEDs; ++currentLED)
  {
    digitalWrite(ledPin[currentLED], LOW); //Turn LEDs off to start
  }
}

//  if (myDFPlayer.available()) {
//    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
//  }
//}





  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

   // Match the request
  if (req.indexOf("/BeerukoffaMusicBox/1") != -1)
  {
    i=0;
    MP3Vol++;
    myDFPlayer.volume (MP3Vol);
  }
  else if (req.indexOf("/BeerukoffaMusicBox/0") != -1)
  {
    i=1;
    MP3Vol--;
    myDFPlayer.volume (MP3Vol);
  }
  else if (req.indexOf("/BeerukoffaMusicBox/2") != -1)
  {
    i=2;
    myDFPlayer.next ();
  }
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }
  Serial.println(Ans[i]);
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\ ";
  s += Ans[i];
  s += "</html>\n";
  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

}


void printDetail(uint8_t type, int value){
  switch (type) {
  case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

Звук регулируется таким приложением на телефоне

Все соединено на бредборде, питается пока от USB и ждет второго (железячного) этапа.

Теперь разбираюсь с засыпанием устройства по таймеру неактивности
 

pvvx

Активный участник сообщества
кроме перехода в энергоэкномичный режим (не обязательно deep sleep) по истечению определенного времени
Ну нету у ESP8266 возможности засыпания с просыпанием по кнопке с его SDK от Espressif, который и используется в Arduino. Надо что-нибудь довешивать.
Теперь разбираюсь с засыпанием устройства по таймеру неактивности
Команда system_deep_sleep_set_option() и system_deep_sleep() в SDK работают. Сложностей там вроде нет, кроме времени исполнения (времени от подачи команды до отключения - он потупит не менее 0.1 сек и отключиться).
Ошибка в system_deep_sleep() во всех последних SDK, ставящая неправильный флаг для следующего просыпания вам не помешает. (Ошибка связана с тем, что по последующему просыпанию система считает, что перезагрузилась по причине "протектед", а не по "deep_sleep" и соответственно будет полностью инициализировать WiFi, а не как это описано в документации. Причина в неправильном коде процедуры в iram переключения процессора в deep_sleep и аппаратно отключив flash он по ret в ней успевает возвращаться в коды flash, а там уже неопределенный код... и успевает сработать "протектед", записывая в RTC память причину перезагрузки по ошибке... Т.е. ошибка плавающая - успеет или не успеет нарваться в отключенном "кэш" на кривую инструкцию. На 160 MHz - успевает всегда...).
 
Последнее редактирование:

Beerukoff

New member
Значит буду просто wifi вырубать и смотреть сколько в таком случае от батарек работать будет.
 

Сергей_Ф

Moderator
Команда форума
Beerukoff, на nodeMCU WiFi вырубать бессмысленно. Линейный стабилизатор все равно будет жрать батарею.
 

pvvx

Активный участник сообщества
Посмотрите команды SDK wifi_fpm...()
В Arduino их реализации не видел.
 
Сверху Снизу