Таймер с веб-сервером ESP8285

это мой первый проект по ESP. Я нашел код для таймера кофемолки, который запрограммирован для ESP8266, но, к сожалению, тем временем Sonoff сменился на ESP8285 со встроенной flash. Я предполагаю, что это и есть причина проблемы с памятью. По умолчанию время соответствует коду 1000 мс и 2000 мс, но на веб-странице отображаются следующие значения времени:

  • Одиночный выстрел: 16711680 мс
  • Двойной выстрел: 807611680 мс

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

// Библиотеки
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <TTBOUNCE.h>
#include <EEPROM.h>
extern "C" {
#include "user_interface.h"
}

//======СЕРВЕРНАЯ ЧАСТЬ======================================================
const char* ssid     = "SSID";
const char* password = "password";
ESP8266WebServer server ( 80 );
char htmlResponse[3000];
//======ЧАСТЬ ЛОКАЛЕРА======================================================
os_timer_t myTimer;
bool tickOccured;
bool timerrunning;
int RelaisPin = 13;                 // GPIO13 Blaue LED auf dem Sonoff
TTBOUNCE b = TTBOUNCE(0); 

int time_ss = 1000;
int time_ds = 2000;

void handleRoot() {

  snprintf ( htmlResponse, 3000,
"<!DOCTYPE html>\
<html lang=\"en\">\
  <head>\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\
  </head>\
  <body>\
          <h1>Zeiten für Singleshot und Doubleshot</h1>\
          <h3>Singleshot: %d% ms </h3>\
          <input type='text' name='date_ss' id='date_ss' size=2 autofocus> ms \
          <h3>Doubleshot: %d% ms</h3>\
          <input type='text' name='date_ds' id='date_ds' size=2 autofocus> ms \
          <div>\
          <br><button id=\"save_button\">Save</button>\
          </div>\
    <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js \"></скрипт>\    
    <script>\
      var ds;\
      var ss;\
      $('#save_button').click(function(e){\
        e.preventDefault();\
        ss = $('#date_ss').val();\
        ds = $('#date_ds').val();\        
        $.get('/save?ss=' + ss + '&ds=' + ds, function(data){\
          console.log(data);\
        });\
        location.reload();\
      });\      
    </script>\
  </body>\
</html>",

time_ss,
time_ds
); 

   server.send ( 200, "text/html", htmlResponse );  

}


void handleSave() {
  if (server.arg("ss")!= ""){
    Serial.println("Singleshot: " + server.arg("ss"));
    time_ss = server.arg("ss").toInt();
    eeWriteInt(0, server.arg("ss").toInt());
  }
    if (server.arg("ds")!= ""){
    Serial.println("Doubleshot: " + server.arg("ds"));
    time_ds = server.arg("ds").toInt();
    eeWriteInt(4, server.arg("ds").toInt());
  }
  
}

// запуск TimerCallback
void timerCallback(void *pArg) {
Serial.println("Tick OccurredCB");
      tickOccured = true;
}

void setup() {
//======СЕРВЕРНАЯ ЧАСТЬ======================================================
  // Запустить Serial
  Serial.begin(115200);
  delay(100);
WiFi.mode(WIFI_STA);
  // Подключение к сети Wi-Fi
  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");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  server.on ( "/", handleRoot );
  server.on ("/save", handleSave);

  server.begin();
  Serial.println ( "HTTP server started" );
//======ЧАСТЬ ЛОКАЛЕРА======================================================
  os_timer_setfn(&myTimer, timerCallback, NULL);
  pinMode(RelaisPin, OUTPUT);       // GPIO13 als Ausgang definieren
  b.attachClick(click);         // прикрепите метод щелчка к событию
  b.attachDoubleClick(doubleClick);// прикрепите метод двойного щелчка к событию
  b.attachPress(press);        // прикрепите метод двойного щелчка к событию двойного щелчка метод нажатия
  delay(50);
  digitalWrite(RelaisPin, HIGH);  // включить индикатор
  tickOccured = false;
  timerrunning = false;
   EEPROM.begin(8);  //Инициализировать EEPROM 
   time_ss = eeGetInt(0);
   time_ds = eeGetInt(4);
}

void loop() {
//======СЕРВЕРНАЯ ЧАСТЬ======================================================
  server.handleClient();
//======ЧАСТЬ ЛОКАЛЕРА======================================================
  b.update();
  delay(10);

   if (tickOccured == true)
 {
    Serial.println("Timer ausgelaufen");
    tickOccured = false;
    digitalWrite(RelaisPin, HIGH);
    os_timer_disarm(&myTimer);
    timerrunning = false;
 }
 
 yield();  // или delay(0);
}


void click(){
  if (!timerrunning)
  {
    Serial.println("Clicked");
    digitalWrite(RelaisPin, LOW);  // включить ИНДИКАТОР
    os_timer_arm(&myTimer, time_ss, false);
    timerrunning = true;
  }
  else
    {
    Serial.println("ABORT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    tickOccured = false;
    digitalWrite(RelaisPin, HIGH);
    os_timer_disarm(&myTimer);
    timerrunning = false;
    }
}

void doubleClick(){
    if (!timerrunning)
  {
    Serial.println("DoubleClicked");
    digitalWrite(RelaisPin, LOW);  // включить ИНДИКАТОР
    os_timer_arm(&myTimer, time_ds, false);
    timerrunning = true;
  }
    else
    {
    Serial.println("ABORT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    tickOccured = false;
    digitalWrite(RelaisPin, HIGH);
    os_timer_disarm(&myTimer);
    timerrunning = false;
    }
}

void press(){
  if (!timerrunning)
  {
    Serial.println("long_Clicked");
    digitalWrite(RelaisPin, LOW);  // включить ИНДИКАТОР
    os_timer_arm(&myTimer, time_ds-time_ss, false);
    timerrunning = true;
  }
 else
    {
    Serial.println("ABORT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    tickOccured = false;
    digitalWrite(RelaisPin, HIGH);
    os_timer_disarm(&myTimer);
    timerrunning = false;
    }
}

 void eeWriteInt(int pos, int val) {
    byte* p = (byte*) &val;
    EEPROM.write(pos, *p);
    EEPROM.write(pos + 1, *(p + 1));
    EEPROM.write(pos + 2, *(p + 2));
    EEPROM.write(pos + 3, *(p + 3));
    EEPROM.commit();
}

int eeGetInt(int pos) {
  int val;
  byte* p = (byte*) &val;
  *p        = EEPROM.read(pos);
  *(p + 1)  = EEPROM.read(pos + 1);
  *(p + 2)  = EEPROM.read(pos + 2);
  *(p + 3)  = EEPROM.read(pos + 3);
  return val;
}

, 👍1

Обсуждение

с какой проблемой вы столкнулись? ... что ты пытаешься сделать?, @jsotola

Я бы начал с изменения %d% на %d, @Juraj

Где вы “нашли код”? Вы уверены, что код работал? Вы упомянули о “проблеме с памятью”. Что вы имеете в виду под этим? По моему опыту, программно нет почти никакой разницы между ESP8285 и ESP8266, кроме разницы в доступной флэш-памяти, которая, я не думаю, что здесь проблема. Почему вы упомянули Соноффа?, @StarCat

@jsotola: Я хочу запрограммировать таймер для моей кофемолки, на котором я могу регулировать продолжительность помола через WLAN., @Niko

Мой таймер на данный момент не поддается изменению и установлен на странные значения @StarCat: Я нашел код на Kaffee-Netz: https://www.kaffee-netz.de/threads/demoka-m203-timerumbau-und-totraum-minimierung.117220 / и он предназначен для работы на ESP8266. Моя проблема с памятью заключается в том, что длительность однократного и двойного выстрела не изменяется, а значения по умолчанию чрезвычайно высоки и не соответствуют коду 1000 и 2000 мс. Заранее спасибо, @Niko

@ Juraj: спасибо, поскольку я изменил это, я могу изменить значения при первой загрузке после перепрошивки. Но после этого я больше не могу менять значения. Нажатие кнопки сохранения не дает никакого эффекта., @Niko

Попробуйте удалить вызов location.reload (); - возможно, ваш браузер перезагружает страницу до завершения AJAX GET. Также вы должны обернуть свой Javascript в jQuery $(document).обработчик ready() - вы можете погуглить его для получения более подробной информации., @romkey


1 ответ


1

По крайней мере, одна проблема заключается в следующем:

          <h3>Singleshot: %d% ms </h3>\

Если вам нужен буквальный знак процента, вам нужно будет удвоить его, что является формой экранирования:

          <h3>Singleshot: %d%% ms </h3>\

Не совсем ясно, как эта реализация snprintf обрабатывает %<пробел> , но эксперименты здесь показывают, что он не прощает и просто интерпретирует его как %% .

В C и C ++ и через прокси "arduino" смежные строковые литералы объединяются во время компиляции в один логический строковый литерал, так что вы можете сделать это вместо \ , что может показаться вам более чистым.

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

,