Jump to content
iT4iT.CLUB

Recommended Posts

Всем, кто столкнулся с проблемой "SPIFFS Error: esptool not found!" поделюсь опытом:

Плагин очень привередлив к версии питона. Буквально недавно вышел плагин корректно работающий с 3 версией. При использовании этой версии  https://github.com/esp8266/arduino-esp8266fs-plugin/releases/ ошибок не возникает. 

  • Like 1

Share this post


Link to post
Share on other sites

Здравствуйте. Спасибо за проект. Хочу внести свои изменения и сохранить всё у себя га git в открытом доступе. Есть  ваш проект на гите? Должна быть преемственность проектов и чтобы все желающие видели, что у истоков стоите вы :)

Share this post


Link to post
Share on other sites

Доброе время суток

18.03.2020 в 10:56, IvAn сказал:

Насколько я понял, проблема с диапазоном 1...-1 в графиках скорее всего из-за этого:

String sensors::clear(float value) {
  if ((int)value == 0) return "0";
  else if (value - (int)value == 0) return String((int)value);
  else return String(value);
}

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

String sensors::clear(float value) {
  if ((int)value == value) return String((int)value);
  return String(value);
}

 

14.03.2020 в 11:43, Neon сказал:

а не подскажете, хотя бы направление , какие шаги нужно выполнить, чтобы можно добавить в метеостанцию работу с nrf24?

Вроде уже было упоминание об NRF в теме и люди делились рабочими вариантами.

28.03.2020 в 17:18, 451-F сказал:

1. Почему при наличии свободного места на флеш, статистика датчиков:

- хранится всего 1 день.

- слетает после потери питания .

Хотелось бы реализовать запись в энергонезависимую память данных на длительный срок.

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

Конечно, если очень хочется, то это можно реализовать. В первую очередь надо определиться с приемлемым сроком жизни устройства и уже отталкиваться от этого. На сколько я помню, память рассчитана на 100000 циклов перезаписи. Значит если записывать данные каждый час, то примерно через 11 лет устройство выйдет из строя. Естественно это все очень грубо посчитано, но закроем на это глаза.

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

На данный момент, при передачи данных для графика в web интерфейс, дополнительно передается время в миллисекундах с последней добавленной точки, а уже на стороне клиента (в браузере) берется время устройства (компьютер, телефон, планшет) и зная время последней точки, мы можем разрисовать временную шкалу графика. Это очень простая система, не требующая никаких часов на микроконтроллере. В принципе, наверное, только из-за простоты я и выбрал её. Но и другие варианты тоже имеют право на жизнь.

28.03.2020 в 17:18, 451-F сказал:

2. Наблюдается проблема такого плана. 

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

Я не смог воссоздать данную ситуацию. Осмелюсь предположить, что Вы могли не дождаться этого момента, контроллер, после потери связи с маршрутизатором, создает собственную точку доступа и периодически, с интервалом в 5 минут, пытается найти маршрутизатор. Вот как это выглядело у меня. Я потушил WiFi интерфейс маршрутизатора, к которому цеплялся контроллер, а как пропала связь, восстановил его обратно.

image.png

 

Share this post


Link to post
Share on other sites
28.04.2020 в 12:15, Tarisper сказал:

Хочу внести свои изменения и сохранить всё у себя га git в открытом доступе. Есть  ваш проект на гите?

На данный момент нет. На мой взгляд, он требует большой переработки.

Вы можете опубликовать его у себя, я только попрошу оставить ссылку на первоисточник и не удалять раздел "О проекте и обратная связь" в web интерфейсе.

Share this post


Link to post
Share on other sites

Добрый день! Можно ли добавить закладки в web-интерфейсе помимо "in" и "out".  У меня 39 датчиков на одной странице, трудно ориентироваться, хотелось бы распределить на 3-4 страницы. На форуме решения не нашел. Заранее благодарен за ответ

Share this post


Link to post
Share on other sites

Доброе время суток

08.05.2020 в 09:18, post125 сказал:

Добрый день! Можно ли добавить закладки в web-интерфейсе помимо "in" и "out".  У меня 39 датчиков на одной странице, трудно ориентироваться, хотелось бы распределить на 3-4 страницы. На форуме решения не нашел. Заранее благодарен за ответ

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

В прошивке микроконтроллера идем в файл sensors.h b и ищем объект отписывающий типы листы на которых отображаются элементы.

class device {
  public:
    typedef enum list_t {out = 1, in = 2};
  
  /* ... */
}

Можете расширить тип list_t и указать свои варианты

typedef enum list_t {out = 1, in = 2, garage = 3, bathroom = 4};

Таким образом при инициализации датчика вы сможете указывать новые листы

sensors.add(new knob_t(-100, 0, "1", "RSSI", "dbm"), device::garage, "rssi",[&](){ 
	return wifi.isConnected() ? WiFi.RSSI() : 0; 
});

На этом работа с прошивкой закончена и переходим к web интерфейсу.

В файле index.htm имеется блок, отвечающий за размещение датчиков.

<div class="sensorsContent" hidden>
        <div class="menu">
            <div id="sensors" class="list1"></div>
            <div id="graph"></div>
            <div id="settings"></div>
        </div>
        <div id="list1"></div>
        <div id="list2" hidden></div>
        <div prototype hidden>
            <div class="sensor">
                <div class="title">{title}</div>
                <div class="unit">{unit}</div>
                <input class="knob {name}" data-width="200" data-displayPrevious=true data-fgColor="#FFF" data-skin="tron" data-thickness=".1" value="0" data-min="{min}" data-max="{max}" data-step="{step}" readonly>
            </div>
        </div>
    </div>

Все датчики, в зависимости от их целочисленного идентификатора в нашей прошивке микроконтроллера в типе list_t помещаются в <div> блоки

<div id="list1"></div>
<div id="list2" hidden></div>

Добавляем новые листы

<div id="list1"></div>
<div id="list2" hidden></div>
<div id="list3" hidden></div>
<div id="list4" hidden></div>

Вообще правильнее было автоматизировать процесс создание листов, как это сделано с датчиками, но это отдельная история

Теперь необходимо распространить на новые листы необходимые стили, для этого в разделе с css разметкой ищем

.sensorsContent #list1,
.sensorsContent #list2 { max-width: 90%; margin: auto; min-height: calc(100vh - 160px); }

Аналогичным образом добавляем новые листы

.sensorsContent #list1,
.sensorsContent #list2,
.sensorsContent #list3, 
.sensorsContent #list4 { max-width: 90%; margin: auto; min-height: calc(100vh - 160px); }

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

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

Но предварительно, мы сделаем еще одно добавление, а точнее его уже сделаете Вы. Каждая иконка хранится в виде BASE64 хэша бинарной иконки в формате PNG. Если мне не подводит память, то размер иконки составляет 35х35 пикселей. Если Вы не меняете глобально этот интерфейс, то советую не использовать иконки другого размера для данного меню.

Для перевода PNG иконок в используемый формат я использовал этот ресурс https://www.base64-image.de/

После перевода вы получите строку, которую необходимо использовать в css разметке для придания новым иконкам желаемого вида. На этом стоит остановиться подробнее. Уже имеющиеся иконки меню Вы можете найти в css разметке поискав по ключевым словам

.menu #sensors.list

Вы найдете следующее, я укажу в виде фото т.к объем текста просто огромный. Надеюсь Вы используете какой-то более мене нормальный редактор, и он преобразует этот огромный набор текста в читаемый вид, я использую Visual Studio Code

image.png

По аналогии добавьте свои иконки для новых элементов меню, не забудьте менять номера листов

На этом этапе Вы уже должны иметь набор новых иконок с именами: list1, list2, list3 и т.д. Теперь их необходимо организовать в меню. И тут мы возвращаемся к нашему начальному html блоку, который был описан в самом начале, это тот, в котором мы добавляли новые листы.

image.png

Давайте теперь добавим и таким образом отобразим все имеющиеся иконки.

image.png

На этом этапе в интерфейсе имеются все новые иконки, но логика работы их переключения все еще не изменена. Давайте исправим это. Для этого нам понадобится внести изменения и JavaScript код нашего с Вами проекта. Это последний и самый сложный этап.

Ищем следующий код

$(".menu #sensors").click(function() {
    var list = $(this).attr("class");
    switch (list) {
        case 'list1': $("#list1").fadeToggle('slow', function(){ $("#list2").fadeToggle('slow'); }); break;
        case 'list2': $("#list2").fadeToggle('slow', function(){ $("#list1").fadeToggle('slow'); }); break;
    }
    $(this).toggleClass("list1", !$(this).hasClass("list1")).toggleClass("list2", !$(this).hasClass("list2"));
});

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

Давайте преобразуем его в следующий вид. Сразу скажу, что так делать не правильно, как и многое в этом проекте, но так будет нагляднее и Вам не придется делать лишние шаги которые могут запутать. В идеале, можно добавить новый, одинаковый идентификатор, для все наших слове (<div>) и по нему плавно скрыть все элементы и потом плавно показать нужный.

$(".menu #sensors").click(function() {
    var list = $(this).attr("class");

    $("#list1").hide();
    $("#list2").hide();
    $("#list3").hide();
    $("#list4").hide();

    $("#"+list).show();
});

Теперь ищем код который скрывает первоначальные элементы меню

if (hideSensorsMenu) $(".menu #sensors.list1").css("display", "none");

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

PS: я не могу ручаться за достоверность всех описанных действий т.к не проверял их на практике. Это просто совет, который должен направить Вас, ... и только направить.

  • Thanks 1

Share this post


Link to post
Share on other sites
16.05.2020 в 00:06, Kitsum сказал:

я не могу ручаться за достоверность всех описанных действий т.к не проверял их на практике

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

Share this post


Link to post
Share on other sites
Скрытый текст

Без-названия22.png

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

Edited by post125

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Similar Content

    • By Kitsum
      Хотите помочь проекту или спонсировать новый?
      Yandex.Money PayPal.me Тема проекта
      Arduino IDE + Project + Libraries + tools: https://yadi.sk/d/jseefFB50NMhAg
    • By Kitsum
      Просмотреть файл [esp8266] Библиотека CMD, реализует настройку микроконтроллера и управление вашей программой через терминал.
      Основная задача библиотеки, это прием пользовательских команд через UART интерфейс, их обработка и выполнение пользовательского кода, связанного с той или иной командой.
      Данная библиотека позволяет реализовать:
      Управление микроконтроллером Любую настройку, будь то WiFi, другие библиотеки или часть Вашей программы Вызывать Ваши задачи (функции) из терминала по команде и передавать им требуемые параметры Использовать контроллер в качестве шлюза между датчиками и программами на PC Внимание: любая команда, передаваемая в терминал обязана заканчиваться символом перевода строки "\n".
      Подключение библиотеки
      #include <cmd.h> Инициализация объекта, к которому мы будем обращаться для добавления команд. В качестве параметра объекту необходимо передать указатель на объект Serial или любой другой схожий по типу интерфейс.
      cmd command(&Serial); В функции Setup описываем какие команды требуется обрабатывать. Например, по команде "test" вызывать пользовательскую функцию с именем "myFunctionName". Имя пользовательской функции может быть абсолютно любым.
      void Setup() { Serial.begin(115200); command.add("test", myFunctionName); } Пользовательская функция будет вызываться каждый раз, когда по интерфейсу Serial поступит команда "test". Если команда будет передана с параметрами, то эти параметры будут переданы в качестве аргументов пользовательской функции.
      В функции loop должна находится команда вызова обработчика.
      void loop() { command.handleEvents(); } Пользовательская функция обязана соответствовать ряду требований:
      Не возвращать никакого результата (быть объявленной с типом void) Принимать в качестве первого аргумента переменную с типом byte в которой будет храниться число равное количеству переданных параметров Принимать в качестве второго параметра переменную с типом char** в которой будет храниться указатель на массив со всеми указателями (char*) на переданные параметры void myFunctionName(byte argc, char** argv) { /* ... */ } Функция всегда должна иметь такой вид, даже если не подразумевается, что ей будут передаваться какие-либо параметры.
      Чтобы перебрать все переданные параметры и вывести их в консоль, можно воспользоваться следующим примером
      void myFunctionName(byte argc, char** argv) { if (0 < argc) { for (uint8_t i = 0; i < argc; i++) { Serial.printf("%i. %s\n", i, argv[i]); } } } Пример вызова пользовательской функции без параметров и с ними
      # test No parameter was passed # test p1 p2 p3 p4 p5 0. p1 1. p2 2. p3 3. p4 4. p5 Помните, что параметры представлены в виде указателей и работать с ними нужно как с обычными переменными не получится т.к указатель содержит не значение переменной (переданный параметр), а указатель на ту область памяти микроконтроллера в которой это значение находится.
      Чтобы сравнить два значения, например, параметр под индексом 0 (идет первым в списке) с каким-либо значением в программе, воспользуйтесь функцией strcmp, которая возвращает целочисленное значение, указывающее на лексическое расхождение строк. Если строки равны, то возвращаемое значение равно 0.
      if (!strcmp(argv[0], "wifi")) { Serial.println(F("Первый аргумент WiFi")); } else { Serial.println(F("Первый аргумент НЕ WiFi!!!")); } Для копирования значения указателя в другую переменную с типом char можно воспользоваться функцией strcpy
      char myVar[20]; strcpy(myVar, argv[0]); if (myVar == "123456") { Serial.prinln(F("ok")); } Также можно обернуть указатель объектом String и получить весь функционал этого объекта, который будет содержать значение параметра
      String param1(argv[0]); // String param1 = argv[0]; Serial.printf("argv[0] length: %i\n", param1.length()); Serial.printf("argv[0] is integer?: %s\n", param1.toInt() ? "YES" : "NO"); if (param1 == "qwerty") { Serial.println(F("Hello QWERTY!")); } С библиотекой идут несколько примеров, в том числе и пример конфигурации WiFi в режиме STA.
      Автор Kitsum Добавлен 05.12.2018 Категория Библиотеки  
    • By Kitsum
      Просмотреть файл [esp8266] Библиотека smartBlink, реализует умное управление штатным светодиодом, что позволяет добавить индикацию состояния вашей программы или микроконтроллера.
      Основная задача библиотеки, это добавление индикации состояния Вашей программы или микроконтроллера. Отображение состояния производится посредством светодиода. Что самое важное, работа библиотеки через прерывание, это позволяет ей поддерживать индикацию даже в то время, когда выполняется длительный код основной программы. Например, Вы можете использовать её для отображения в каком режиме сейчас работает WiFi микроконтроллера, STA или AP и т.д. Или ход выполнения какой-либо операции, например, передача данных на внешний сервер.
      Подключение библиотеки
      #include <smartBlink.h> Чтобы инициализировать управление светодиодом необходимо создать объект, через который мы буем задавать режимы работы индикации.
      smartBlink::smartBlink(byte gpio, bool on = LOW); Объекту необходимо передать два параметра, первый это номер порта, на котором находится светодиод, а второй это уровень логического сигнала, который заставит светодиод работать. Сигнал может быть низким (LOW) или высоким (HIGH), это зависит от схемотехники подключения светодиода.
      Например, штатный светодиод модуля ESP12, использующий GPIO2 (порт 2) можно объявить следующим образом.
      #define led2_pin 2 #define led2_on_signal LOW smartBlink led2(led2_pin, led2_on_signal); Теперь можно в основной программе использовать метод устанавливающий какой режим индикации использовать.
      smartBlink::setMode(mode_t mode); Например, зададим режим светодиода led2 в котором светодиод будет давать одну короткую вспышку раз в секунду.
      led2.setMode(smartBlink::mode_flash1); Режимов работы может быть несколько.
      led2.setMode(smartBlink::mode_off); led2.setMode(smartBlink::mode_flash1); led2.setMode(smartBlink::mode_flash2); led2.setMode(smartBlink::mode_flash3); led2.setMode(smartBlink::mode_flash4); led2.setMode(smartBlink::mode_burn); led2.setMode(smartBlink::mode_inhalf); Чтобы вернуть предыдущий режим индикации для ранее объявленного светодиода led2 используйте следующий метод
      led2.previous(); Благодаря работе библиотеки через прерывания по таймеру, индикация будет работать даже в тех случаях, когда выполняется долгий код.
      С библиотекой идут несколько примеров.
      Автор Kitsum Добавлен 10.12.2018 Категория Библиотеки  
    • By Kitsum
      Основная задача библиотеки, это добавление индикации состояния Вашей программы или микроконтроллера. Отображение состояния производится посредством светодиода. Что самое важное, работа библиотеки через прерывание, это позволяет ей поддерживать индикацию даже в то время, когда выполняется длительный код основной программы. Например, Вы можете использовать её для отображения в каком режиме сейчас работает WiFi микроконтроллера, STA или AP и т.д. Или ход выполнения какой-либо операции, например, передача данных на внешний сервер.
      Подключение библиотеки
      #include <smartBlink.h> Чтобы инициализировать управление светодиодом необходимо создать объект, через который мы буем задавать режимы работы индикации.
      smartBlink::smartBlink(byte gpio, bool on = LOW); Объекту необходимо передать два параметра, первый это номер порта, на котором находится светодиод, а второй это уровень логического сигнала, который заставит светодиод работать. Сигнал может быть низким (LOW) или высоким (HIGH), это зависит от схемотехники подключения светодиода.
      Например, штатный светодиод модуля ESP12, использующий GPIO2 (порт 2) можно объявить следующим образом.
      #define led2_pin 2 #define led2_on_signal LOW smartBlink led2(led2_pin, led2_on_signal); Теперь можно в основной программе использовать метод устанавливающий какой режим индикации использовать.
      smartBlink::setMode(mode_t mode); Например, зададим режим светодиода led2 в котором светодиод будет давать одну короткую вспышку раз в секунду.
      led2.setMode(smartBlink::mode_flash1); Режимов работы может быть несколько.
      led2.setMode(smartBlink::mode_off); led2.setMode(smartBlink::mode_flash1); led2.setMode(smartBlink::mode_flash2); led2.setMode(smartBlink::mode_flash3); led2.setMode(smartBlink::mode_flash4); led2.setMode(smartBlink::mode_burn); led2.setMode(smartBlink::mode_inhalf); Чтобы вернуть предыдущий режим индикации для ранее объявленного светодиода led2 используйте следующий метод
      led2.previous(); Благодаря работе библиотеки через прерывания по таймеру, индикация будет работать даже в тех случаях, когда выполняется долгий код.
      С библиотекой идут несколько примеров.
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...