Jump to content
iT4iT.CLUB

All Activity

This stream auto-updates     

  1. Last week
  2. Скрытие иконок даже и не нужно, так даже удобнее- видно сразу, куда надо нажимать, тем более иконки небольшие и не перекрывают обзор.
  3. Всё супер работает, благодарю. Иконки, правда, какие-то корявые получаются - надо с ними поэкспериментировать. Еще один вопрос, можно ли один и тот же датчик отображать на нескольких страницах?
  4. Здравствуйте. Если тема ещё в теме - каламбур, как сделать индентификацию карты не по UID, а по другому, перезаписываемому блоку. Ну например по 4 или какому другому. Неподскажите где скетч подправить?
  5. Earlier
  6. Доброе время суток Думаю, да, тут больше работы в самом 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 По аналогии добавьте свои иконки для новых элементов меню, не забудьте менять номера листов На этом этапе Вы уже должны иметь набор новых иконок с именами: list1, list2, list3 и т.д. Теперь их необходимо организовать в меню. И тут мы возвращаемся к нашему начальному html блоку, который был описан в самом начале, это тот, в котором мы добавляли новые листы. Давайте теперь добавим и таким образом отобразим все имеющиеся иконки. На этом этапе в интерфейсе имеются все новые иконки, но логика работы их переключения все еще не изменена. Давайте исправим это. Для этого нам понадобится внести изменения и 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: я не могу ручаться за достоверность всех описанных действий т.к не проверял их на практике. Это просто совет, который должен направить Вас, ... и только направить.
  7. Добрый день! Можно ли добавить закладки в web-интерфейсе помимо "in" и "out". У меня 39 датчиков на одной странице, трудно ориентироваться, хотелось бы распределить на 3-4 страницы. На форуме решения не нашел. Заранее благодарен за ответ
  8. На данный момент нет. На мой взгляд, он требует большой переработки. Вы можете опубликовать его у себя, я только попрошу оставить ссылку на первоисточник и не удалять раздел "О проекте и обратная связь" в web интерфейсе.
  9. Доброе время суток Да, Вы совершенно правы. Этот метод использовался чтобы убрать лишние нули в массивах передаваемых для постройки графиков. Попробуйте заменить этим. String sensors::clear(float value) { if ((int)value == value) return String((int)value); return String(value); } Вроде уже было упоминание об NRF в теме и люди делились рабочими вариантами. Все очень просто, Flash память не рассчитана на большое количество циклов перезаписи и постоянное сохранение данных попросту убьет ее. В связи с этим данные хранятся в оперативной памяти и предоставляются по требованию, что кстати еще и намного быстрее. В текущей реализации память практически вечная. Конечно, если очень хочется, то это можно реализовать. В первую очередь надо определиться с приемлемым сроком жизни устройства и уже отталкиваться от этого. На сколько я помню, память рассчитана на 100000 циклов перезаписи. Значит если записывать данные каждый час, то примерно через 11 лет устройство выйдет из строя. Естественно это все очень грубо посчитано, но закроем на это глаза. Другие нюансы, это понимание контроллером, что делать с сохраненными данными, как поступить с ними после перезагрузки и как связать их с текущими, новыми, данными. По идеи, все это упирается в систему точного времени и тут тоже подводные камни - использование внешнего модуля часов усложняет систему, добавляет точку отказа и требует дополнительного обслуживания, как минимум по замене аккумулятора. Можно использовать собственную систему тактирования для отсчета времени, что вполне приемлемо при регулярной синхронизации с NTP сервером, что требует наличия выхода в Интернет... На данный момент, при передачи данных для графика в web интерфейс, дополнительно передается время в миллисекундах с последней добавленной точки, а уже на стороне клиента (в браузере) берется время устройства (компьютер, телефон, планшет) и зная время последней точки, мы можем разрисовать временную шкалу графика. Это очень простая система, не требующая никаких часов на микроконтроллере. В принципе, наверное, только из-за простоты я и выбрал её. Но и другие варианты тоже имеют право на жизнь. Я не смог воссоздать данную ситуацию. Осмелюсь предположить, что Вы могли не дождаться этого момента, контроллер, после потери связи с маршрутизатором, создает собственную точку доступа и периодически, с интервалом в 5 минут, пытается найти маршрутизатор. Вот как это выглядело у меня. Я потушил WiFi интерфейс маршрутизатора, к которому цеплялся контроллер, а как пропала связь, восстановил его обратно.
  10. Здравствуйте. Спасибо за проект. Хочу внести свои изменения и сохранить всё у себя га git в открытом доступе. Есть ваш проект на гите? Должна быть преемственность проектов и чтобы все желающие видели, что у истоков стоите вы :)
  11. Всем, кто столкнулся с проблемой "SPIFFS Error: esptool not found!" поделюсь опытом: Плагин очень привередлив к версии питона. Буквально недавно вышел плагин корректно работающий с 3 версией. При использовании этой версии https://github.com/esp8266/arduino-esp8266fs-plugin/releases/ ошибок не возникает.
  12. {"cod":"200","message":0,"cnt":40,"list":[{"dt":1586379600,"main":{"temp":5.05,"feels_like":1.37,"temp_min":3.49,"temp_max":5.05,"pressure":1020,"sea_level":1020,"grnd_level":999,"humidity":83,"temp_kf":1.56},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01n"}],"clouds":{"all":2},"wind":{"speed":2.96,"deg":322},"sys":{"pod":"n"},"dt_txt":"2020-04-08 21:00:00"},{"dt":1586390400,"main":{"temp":3.26,"feels_like":-0.12,"temp_min":2.09,"temp_max":3.26,"pressure":1020,"sea_level":1020,"grnd_level":999,"humidity":86,"temp_kf":1.17},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01n"}],"clouds":{"all":1},"wind":{"speed":2.24,"deg":305},"sys":{"pod":"n"},"dt_txt":"2020-04-09 00:00:00"},{"dt":1586401200,"main":{"temp":1.98,"feels_like":-1.59,"temp_min":1.2,"temp_max":1.98,"pressure":1019,"sea_level":1019,"grnd_level":999,"humidity":86,"temp_kf":0.78},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01d"}],"clouds":{"all":0},"wind":{"speed":2.24,"deg":249},"sys":{"pod":"d"},"dt_txt":"2020-04-09 03:00:00"},{"dt":1586412000,"main":{"temp":6.25,"feels_like":1.88,"temp_min":5.86,"temp_max":6.25,"pressure":1018,"sea_level":1018,"grnd_level":997,"humidity":70,"temp_kf":0.39},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01d"}],"clouds":{"all":6},"wind":{"speed":3.67,"deg":236},"sys":{"pod":"d"},"dt_txt":"2020-04-09 06:00:00"},{"dt":1586422800,"main":{"temp":10.59,"feels_like":5.34,"temp_min":10.59,"temp_max":10.59,"pressure":1015,"sea_level":1015,"grnd_level":995,"humidity":54,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":59},"wind":{"speed":5.03,"deg":240},"sys":{"pod":"d"},"dt_txt":"2020-04-09 09:00:00"},{"dt":1586433600,"main":{"temp":11.79,"feels_like":6.05,"temp_min":11.79,"temp_max":11.79,"pressure":1012,"sea_level":1012,"grnd_level":992,"humidity":50,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":77},"wind":{"speed":5.74,"deg":229},"sys":{"pod":"d"},"dt_txt":"2020-04-09 12:00:00"},{"dt":1586444400,"main":{"temp":10.83,"feels_like":6.09,"temp_min":10.83,"temp_max":10.83,"pressure":1010,"sea_level":1010,"grnd_level":990,"humidity":55,"temp_kf":0},"weather":[{"id":804,"main":"Clouds","description":"пасмурно","icon":"04d"}],"clouds":{"all":100},"wind":{"speed":4.41,"deg":226},"sys":{"pod":"d"},"dt_txt":"2020-04-09 15:00:00"},{"dt":1586455200,"main":{"temp":8.54,"feels_like":3.79,"temp_min":8.54,"temp_max":8.54,"pressure":1008,"sea_level":1008,"grnd_level":988,"humidity":61,"temp_kf":0},"weather":[{"id":804,"main":"Clouds","description":"пасмурно","icon":"04n"}],"clouds":{"all":100},"wind":{"speed":4.26,"deg":225},"sys":{"pod":"n"},"dt_txt":"2020-04-09 18:00:00"},{"dt":1586466000,"main":{"temp":8.42,"feels_like":3.41,"temp_min":8.42,"temp_max":8.42,"pressure":1006,"sea_level":1006,"grnd_level":985,"humidity":69,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":5.03,"deg":223},"rain":{"3h":0.14},"sys":{"pod":"n"},"dt_txt":"2020-04-09 21:00:00"},{"dt":1586476800,"main":{"temp":7.52,"feels_like":3.57,"temp_min":7.52,"temp_max":7.52,"pressure":1005,"sea_level":1005,"grnd_level":985,"humidity":82,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":3.93,"deg":274},"rain":{"3h":1.3},"sys":{"pod":"n"},"dt_txt":"2020-04-10 00:00:00"},{"dt":1586487600,"main":{"temp":4.44,"feels_like":-0.78,"temp_min":4.44,"temp_max":4.44,"pressure":1006,"sea_level":1006,"grnd_level":986,"humidity":81,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10d"}],"clouds":{"all":87},"wind":{"speed":4.94,"deg":320},"rain":{"3h":0.22},"sys":{"pod":"d"},"dt_txt":"2020-04-10 03:00:00"},{"dt":1586498400,"main":{"temp":5.18,"feels_like":-1.23,"temp_min":5.18,"temp_max":5.18,"pressure":1008,"sea_level":1008,"grnd_level":987,"humidity":63,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":69},"wind":{"speed":6.06,"deg":327},"sys":{"pod":"d"},"dt_txt":"2020-04-10 06:00:00"},{"dt":1586509200,"main":{"temp":7,"feels_like":1.03,"temp_min":7,"temp_max":7,"pressure":1009,"sea_level":1009,"grnd_level":989,"humidity":55,"temp_kf":0},"weather":[{"id":801,"main":"Clouds","description":"небольшая облачность","icon":"02d"}],"clouds":{"all":15},"wind":{"speed":5.41,"deg":328},"sys":{"pod":"d"},"dt_txt":"2020-04-10 09:00:00"},{"dt":1586520000,"main":{"temp":7.97,"feels_like":2.59,"temp_min":7.97,"temp_max":7.97,"pressure":1010,"sea_level":1010,"grnd_level":990,"humidity":51,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10d"}],"clouds":{"all":40},"wind":{"speed":4.54,"deg":332},"rain":{"3h":0.14},"sys":{"pod":"d"},"dt_txt":"2020-04-10 12:00:00"},{"dt":1586530800,"main":{"temp":7.6,"feels_like":2.67,"temp_min":7.6,"temp_max":7.6,"pressure":1011,"sea_level":1011,"grnd_level":990,"humidity":52,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":79},"wind":{"speed":3.88,"deg":319},"sys":{"pod":"d"},"dt_txt":"2020-04-10 15:00:00"},{"dt":1586541600,"main":{"temp":4.1,"feels_like":-0.98,"temp_min":4.1,"temp_max":4.1,"pressure":1012,"sea_level":1012,"grnd_level":992,"humidity":66,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10n"},{"id":600,"main":"Snow","description":"небольшой снег","icon":"13n"}],"clouds":{"all":86},"wind":{"speed":4.09,"deg":332},"rain":{"3h":0.19},"snow":{"3h":0.19},"sys":{"pod":"n"},"dt_txt":"2020-04-10 18:00:00"},{"dt":1586552400,"main":{"temp":1.9,"feels_like":-2.73,"temp_min":1.9,"temp_max":1.9,"pressure":1013,"sea_level":1013,"grnd_level":992,"humidity":76,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04n"}],"clouds":{"all":76},"wind":{"speed":3.41,"deg":322},"sys":{"pod":"n"},"dt_txt":"2020-04-10 21:00:00"},{"dt":1586563200,"main":{"temp":0.23,"feels_like":-4.06,"temp_min":0.23,"temp_max":0.23,"pressure":1013,"sea_level":1013,"grnd_level":992,"humidity":88,"temp_kf":0},"weather":[{"id":802,"main":"Clouds","description":"переменная облачность","icon":"03n"}],"clouds":{"all":40},"wind":{"speed":2.99,"deg":335},"sys":{"pod":"n"},"dt_txt":"2020-04-11 00:00:00"},{"dt":1586574000,"main":{"temp":-0.52,"feels_like":-4.23,"temp_min":-0.52,"temp_max":-0.52,"pressure":1013,"sea_level":1013,"grnd_level":992,"humidity":93,"temp_kf":0},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01d"}],"clouds":{"all":8},"wind":{"speed":2.17,"deg":337},"sys":{"pod":"d"},"dt_txt":"2020-04-11 03:00:00"},{"dt":1586584800,"main":{"temp":2.35,"feels_like":-2.35,"temp_min":2.35,"temp_max":2.35,"pressure":1013,"sea_level":1013,"grnd_level":993,"humidity":75,"temp_kf":0},"weather":[{"id":802,"main":"Clouds","description":"переменная облачность","icon":"03d"}],"clouds":{"all":25},"wind":{"speed":3.55,"deg":344},"sys":{"pod":"d"},"dt_txt":"2020-04-11 06:00:00"},{"dt":1586595600,"main":{"temp":2.75,"feels_like":-3.02,"temp_min":2.75,"temp_max":2.75,"pressure":1014,"sea_level":1014,"grnd_level":994,"humidity":72,"temp_kf":0},"weather":[{"id":600,"main":"Snow","description":"небольшой снег","icon":"13d"}],"clouds":{"all":96},"wind":{"speed":5.05,"deg":331},"snow":{"3h":0.47},"sys":{"pod":"d"},"dt_txt":"2020-04-11 09:00:00"},{"dt":1586606400,"main":{"temp":2.6,"feels_like":-4.39,"temp_min":2.6,"temp_max":2.6,"pressure":1015,"sea_level":1015,"grnd_level":994,"humidity":71,"temp_kf":0},"weather":[{"id":600,"main":"Snow","description":"небольшой снег","icon":"13d"}],"clouds":{"all":98},"wind":{"speed":6.73,"deg":347},"snow":{"3h":0.65},"sys":{"pod":"d"},"dt_txt":"2020-04-11 12:00:00"},{"dt":1586617200,"main":{"temp":2.18,"feels_like":-4.71,"temp_min":2.18,"temp_max":2.18,"pressure":1016,"sea_level":1016,"grnd_level":995,"humidity":69,"temp_kf":0},"weather":[{"id":600,"main":"Snow","description":"небольшой снег","icon":"13d"}],"clouds":{"all":95},"wind":{"speed":6.45,"deg":347},"snow":{"3h":0.19},"sys":{"pod":"d"},"dt_txt":"2020-04-11 15:00:00"},{"dt":1586628000,"main":{"temp":-0.57,"feels_like":-6,"temp_min":-0.57,"temp_max":-0.57,"pressure":1018,"sea_level":1018,"grnd_level":997,"humidity":83,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04n"}],"clouds":{"all":54},"wind":{"speed":4.34,"deg":334},"sys":{"pod":"n"},"dt_txt":"2020-04-11 18:00:00"},{"dt":1586638800,"main":{"temp":-1.05,"feels_like":-6.31,"temp_min":-1.05,"temp_max":-1.05,"pressure":1019,"sea_level":1019,"grnd_level":998,"humidity":86,"temp_kf":0},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01n"}],"clouds":{"all":0},"wind":{"speed":4.09,"deg":324},"sys":{"pod":"n"},"dt_txt":"2020-04-11 21:00:00"},{"dt":1586649600,"main":{"temp":-1.26,"feels_like":-6.42,"temp_min":-1.26,"temp_max":-1.26,"pressure":1019,"sea_level":1019,"grnd_level":998,"humidity":88,"temp_kf":0},"weather":[{"id":800,"main":"Clear","description":"ясно","icon":"01n"}],"clouds":{"all":0},"wind":{"speed":3.97,"deg":312},"sys":{"pod":"n"},"dt_txt":"2020-04-12 00:00:00"},{"dt":1586660400,"main":{"temp":-1.49,"feels_like":-6.32,"temp_min":-1.49,"temp_max":-1.49,"pressure":1019,"sea_level":1019,"grnd_level":998,"humidity":88,"temp_kf":0},"weather":[{"id":802,"main":"Clouds","description":"переменная облачность","icon":"03d"}],"clouds":{"all":45},"wind":{"speed":3.45,"deg":310},"sys":{"pod":"d"},"dt_txt":"2020-04-12 03:00:00"},{"dt":1586671200,"main":{"temp":1.46,"feels_like":-4.6,"temp_min":1.46,"temp_max":1.46,"pressure":1019,"sea_level":1019,"grnd_level":998,"humidity":72,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":58},"wind":{"speed":5.24,"deg":318},"sys":{"pod":"d"},"dt_txt":"2020-04-12 06:00:00"},{"dt":1586682000,"main":{"temp":3.72,"feels_like":-2.73,"temp_min":3.72,"temp_max":3.72,"pressure":1018,"sea_level":1018,"grnd_level":997,"humidity":61,"temp_kf":0},"weather":[{"id":600,"main":"Snow","description":"небольшой снег","icon":"13d"}],"clouds":{"all":99},"wind":{"speed":5.79,"deg":325},"snow":{"3h":0.14},"sys":{"pod":"d"},"dt_txt":"2020-04-12 09:00:00"},{"dt":1586692800,"main":{"temp":4.85,"feels_like":-1.09,"temp_min":4.85,"temp_max":4.85,"pressure":1017,"sea_level":1017,"grnd_level":997,"humidity":56,"temp_kf":0},"weather":[{"id":804,"main":"Clouds","description":"пасмурно","icon":"04d"}],"clouds":{"all":99},"wind":{"speed":5.05,"deg":323},"sys":{"pod":"d"},"dt_txt":"2020-04-12 12:00:00"},{"dt":1586703600,"main":{"temp":4.11,"feels_like":-0.44,"temp_min":4.11,"temp_max":4.11,"pressure":1017,"sea_level":1017,"grnd_level":996,"humidity":60,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04d"}],"clouds":{"all":78},"wind":{"speed":3.1,"deg":325},"sys":{"pod":"d"},"dt_txt":"2020-04-12 15:00:00"},{"dt":1586714400,"main":{"temp":0.72,"feels_like":-2.21,"temp_min":0.72,"temp_max":0.72,"pressure":1016,"sea_level":1016,"grnd_level":995,"humidity":77,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04n"}],"clouds":{"all":72},"wind":{"speed":0.81,"deg":279},"sys":{"pod":"n"},"dt_txt":"2020-04-12 18:00:00"},{"dt":1586725200,"main":{"temp":0.05,"feels_like":-3.41,"temp_min":0.05,"temp_max":0.05,"pressure":1015,"sea_level":1015,"grnd_level":994,"humidity":83,"temp_kf":0},"weather":[{"id":801,"main":"Clouds","description":"небольшая облачность","icon":"02n"}],"clouds":{"all":22},"wind":{"speed":1.63,"deg":202},"sys":{"pod":"n"},"dt_txt":"2020-04-12 21:00:00"},{"dt":1586736000,"main":{"temp":0.8,"feels_like":-3.63,"temp_min":0.8,"temp_max":0.8,"pressure":1012,"sea_level":1012,"grnd_level":991,"humidity":81,"temp_kf":0},"weather":[{"id":803,"main":"Clouds","description":"облачно с прояснениями","icon":"04n"}],"clouds":{"all":58},"wind":{"speed":3.08,"deg":187},"sys":{"pod":"n"},"dt_txt":"2020-04-13 00:00:00"},{"dt":1586746800,"main":{"temp":0.5,"feels_like":-4.71,"temp_min":0.5,"temp_max":0.5,"pressure":1008,"sea_level":1008,"grnd_level":988,"humidity":91,"temp_kf":0},"weather":[{"id":600,"main":"Snow","description":"небольшой снег","icon":"13d"}],"clouds":{"all":100},"wind":{"speed":4.44,"deg":188},"snow":{"3h":0.41},"sys":{"pod":"d"},"dt_txt":"2020-04-13 03:00:00"},{"dt":1586757600,"main":{"temp":2.64,"feels_like":-2.79,"temp_min":2.64,"temp_max":2.64,"pressure":1005,"sea_level":1005,"grnd_level":985,"humidity":90,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":5.18,"deg":192},"rain":{"3h":1.51},"sys":{"pod":"d"},"dt_txt":"2020-04-13 06:00:00"},{"dt":1586768400,"main":{"temp":4.21,"feels_like":-1.65,"temp_min":4.21,"temp_max":4.21,"pressure":1002,"sea_level":1002,"grnd_level":982,"humidity":88,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":6.08,"deg":218},"rain":{"3h":0.99},"sys":{"pod":"d"},"dt_txt":"2020-04-13 09:00:00"},{"dt":1586779200,"main":{"temp":5.9,"feels_like":0.45,"temp_min":5.9,"temp_max":5.9,"pressure":1000,"sea_level":1000,"grnd_level":980,"humidity":78,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":5.48,"deg":210},"rain":{"3h":1.21},"sys":{"pod":"d"},"dt_txt":"2020-04-13 12:00:00"},{"dt":1586790000,"main":{"temp":8.5,"feels_like":4.05,"temp_min":8.5,"temp_max":8.5,"pressure":997,"sea_level":997,"grnd_level":977,"humidity":68,"temp_kf":0},"weather":[{"id":804,"main":"Clouds","description":"пасмурно","icon":"04d"}],"clouds":{"all":100},"wind":{"speed":4.19,"deg":197},"sys":{"pod":"d"},"dt_txt":"2020-04-13 15:00:00"},{"dt":1586800800,"main":{"temp":6.94,"feels_like":3.65,"temp_min":6.94,"temp_max":6.94,"pressure":995,"sea_level":995,"grnd_level":975,"humidity":86,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"небольшой дождь","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":3.02,"deg":205},"rain":{"3h":1.93},"sys":{"pod":"n"},"dt_txt":"2020-04-13 18:00:00"}],"city":{"id":564912,"name":"Дружба","coord":{"lat":55.8856,"lon":37.7403},"country":"RU","population":4058,"timezone":10800,"sunrise":1586313640,"sunset":1586362832}} Подскажите пожалуйста, как парсить это? ESP8266 уходит в перезагруз!
  13. Kitsum добрый день. Нас с коллегой заинтересовал ваш проект и мы успешно реализовали несколько станций на платформе как esp, так и на ноде. В процессе эксплуатации у нас возник перечень вопросов и пожеланий, которые хотелось бы обсудить с вами. 1. Почему при наличии свободного места на флеш, статистика датчиков: - хранится всего 1 день. - слетает после потери питания . Хотелось бы реализовать запись в энергонезависимую память данных на длительный срок. 2. Наблюдается проблема такого плана. Esp корректно отрабатывает подключение к wifi сети при обрыве питания, но в случае перезагрузки роутера, плата отказывается повторно подключаться к сети. 3. В связи с особенностью размещения некоторых датчиков встал вопрос их связи с платой посредством радиоканала. Хотелось бы предложить реализовать начинания в эту сторону. Спасибо.
  14. Насколько я понял, проблема с диапазоном 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); }
  15. Приветствую. Появился такой вопрос, собрал схему с RFID все работает но когда подключаю самодельный солинойд на 12 вольт через реле, RFID перестает реагировать на открытие через 3 попытки. Откидываю соленойд, перезагружаю ардуино и опять все работает. Не могу разобраться в чем проблема. Помогите пожалуйста.
  16. приветствую а не подскажете, хотя бы направление , какие шаги нужно выполнить, чтобы можно добавить в метеостанцию работу с nrf24? как понял нужно добавить обработчик сюда void loop() { /* Обработчики */ wifi.handleEvents(); http.handleClient(); cron.handleEvents(); }
  17. передатчик потребляет в режиме сна около 3 мкА, при передаче данных раз в минуту довольно долго должен проработать
  18. в теме про метеостанцию писал про датчик с передатчиком на NRF24L01 и возможность использования с метеостанцией простой код приемника на esp // https://aterlux.ru/article/nrf24l01p #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line, для 20x4 - 0x3F //#include <SPI.h> //#include "nRF24L01.h" #include "RF24.h" int32_t data[5]; RF24 radio(99, 15); // CE, CSN, 99 - это заглушка, чтобы освободить один пин, если передача не предполлагается то можно CE просто подтянуть резистором к питанию, иначе нужно указать вывод void setup(void) { lcd.init(); lcd.backlight(); radio.begin(); radio.setAutoAck(true); // radio.setAutoAck(true); включение и ли отклучение автоподтверждения radio.setChannel(100); radio.setDataRate (RF24_2MBPS); // скорость обмена RF24_2MBPS, RF24_1MBPS, RF24_250KBPS - максимальная чувствительность на 250 кбитс, NRF24L01 без плюса 250 не умеет radio.setPALevel (RF24_PA_MAX); // уровень мощности RF24_PA_MIN -18dBm, RF24_PA_LOW -12dBm, RF24_PA_HIGH -6dBM, RF24_PA_MAX 0dBm radio.openReadingPipe(1, 0xAABBCCDD11LL); radio.startListening(); } void loop(void) { if(radio.available()){ // Если в буфере имеются принятые данные, то получаем номер трубы, по которой они пришли, по ссылке на переменную pipe radio.read( &data, sizeof(data)); } // Читаем данные в массив data и указываем сколько байт читать lcd.setCursor(0,0); lcd.print("Temp "); lcd.print(float(data[3])/100, 2); lcd.print(" "); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0,1); lcd.print("Battery "); lcd.print(float(data[0])/1000,3); lcd.print(" v"); lcd.setCursor(0,2); // на некоторых 4 строчных дисплеях в 3 и 4 строке ноль сдвинут на 4 символа вправо, поэтому нулевой символ это -4 lcd.print("Packet N "); lcd.print(data[1]); delay (100); } код передатчика // тема на форуме - http://forum.ixbt.com/topic.cgi?id=48:12460&r=lYjQSTixmu#2 // библиотека для датчика BME280 - https://github.com/sergeyastakhov/BME280 (чтобы не было конфликтов с другими библиотеками, желательно ее разместить в папке скетча) // потребление всего модуля в power save - 2.0 мкА(из них NRF24 - 0.9 мкА), 1.1 мкА - atmega168 // обязательно параллельно батарейке доп емкость около 2200мкф 6.3 в - падение при передаче 10 мВ, ток утечки конденсатора после подформовки менее 100 нА, - http://forum.ixbt.com/topic.cgi?id=48:11468:3073#3073 // измерение напряжение батарейки с помощью измерения питания atmega // еще можно питать атмегу напрямую от лития и измерять ее напряжение, а NRF и BME280 питается от стабилизатора 3.3 вольта с маленькой утечкой, например mcp1700-3302, ток утечки около 1.5 мкА // I2C преобразователь уровней не нужен, главное чтобы подтягивающие резисторы I2C питались от 3.3 вольт // проблема с вотчдогом - http://arduino.ru/forum/apparatnye-voprosy/ne-mogu-vylechit-vatchdog-na-goloi-atmege328r-s-vnutr-taktirovaniem-8-mgts #include <avr/wdt.h> #include <avr/sleep.h> //#include <avr/power.h> #include "RF24.h" RF24 radio(9, 10); // CE_PIN, CSN_PIN byte count = 0; // счетчик количества просыпаний int32_t data[5]; // на данный момент используется int32_t чтобы иметь возможность получить большие числа счетчика передач, для тестирования продолжительности работы от батарейки, // потом можно обычный int // data 0 - данные АЦП или пересчитанное напряжение питания c тремя знаками(в милливольтах, на стороне приемника переменная float деленная на 1000 // data 1 - счетчик отправленных пакетов, сбрасывается при снятии питания // data 2 - P атмсомферное в мм, можно умножить на 10 если нужны десятые, тогда на стороне приемника делить на 10 и float // data 3 - Т температура умноженное на 100 на стороне приемника float делить на 100 // data 4 - H влажность умноженная на 100 #include "BME280.h" // при таком написании компилятор ищет библиотеку в первую очередь в папке скетча using namespace BME280; class CustomI2CProtocol : public I2CProtocol { public: virtual void init() { I2CProtocol::init(); Wire.setClock(400000); // частота работы I2C, 400 кГц - максимум для BME280, уже чувствительна к качеству и длине линии } // реальная частота I2C зависит от регистра и строки в wire.cpp - TWBR = ((F_CPU / frequency) - 16) / 2 и при частоте 8 МГц она ниже, около 250 кГц // https://www.avrfreaks.net/forum/twi-clock-divider?name=PNphpBB2&file=viewtopic&t=79562 }; BME280Sensor bme280 = BME280Sensor(new CustomI2CProtocol()); //BME280Sensor bme280 = BME280Sensor(new I2CProtocol()) - I2C работает на частоте по умолчанию - 100 кГц ISR (TIMER2_OVF_vect) { // из прерывания по таймеру 2 нельзя выходить слишком быстро, поэтому инкрементирование переменной расположим здесь count++; } void setup() { MCUSR = 0; // необходимо при использовании вотчдога для сброса контроллера при зависании на выпонении кода wdt_disable(); // иначе при первом сбросе вотчдогом, будет установлено минимальное время вотчдога 0.15 с, и мк зависнет на этом цикле PORTC |= (1 << PC1); // включение светодиода, для индикации запуска мк delay(10); DDRB = 0b11000001; // настраиваем неиспользуемые выводы(и порты) на выход DDRC = 0b11111111; DDRD = 0b11111111; //clock_prescale_set(clock_div_2); // деление тактовой частоты для получения 4 МГц для работы atmega168 вплоть до 1.8 вольта bme280.init(false); bme280.setHumidityMode(Over_1); // установка режима измерения влажности, остальные при запуске измерения //bme280.setMode(Forced, Over_1, Over_1, Over_1); // Forced - однократный режим измрения, все оверсемплинги(T, P, Hum) = 1 PRR = (1<<PRTIM1) | (1<<PRUSART0); // отключаем неиспользуемую периферию, (1<<PRTIM2) - работает в асинхронном режиме // (1<<PRTIM0) - так не работает передача, видимо count использует этот таймер // (1<<PRSPI), (1<<PRTWI)- не отключаем, SPI - для NRF24 и TWI(по другому I2C) - для BME280 radio.begin(); radio.setAutoAck(true); // подтверждение приема, true - включено, false - отключено radio.setRetries (2, 1); // количество попыток передачи если включен режим автоподтверждения приема, первая цифра - задержка между передачами, 1 = 250 мкс, вторая - количество попыток передачи radio.setChannel(100); // номер канала, можно перед выбором просканировать эфир чтобы выяснить менее зашумленные каналы(использовать скетч scanner из библ. RF24) radio.setDataRate (RF24_2MBPS); // скорость обмена RF24_2MBPS, RF24_1MBPS, RF24_250KBPS - максимальная чувствительность на 250 кбитс radio.setPALevel (RF24_PA_MAX); // уровень мощности RF24_PA_MIN -18dBm, RF24_PA_LOW -12dBm, RF24_PA_HIGH -6dBM, RF24_PA_MAX 0dBm radio.openWritingPipe (0xAABBCCDD11LL); // уникальный номер передатчика, на приемнике должен быть такой же ADCSRA = 0; // отключаем АЦП ACSR |= (1<<ACD); // отключаем компаратор ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // настраиваем АЦП на измерение собственного напряжения питания, опорное 1.1 вольт DIDR0 = 1; // отключаем цифровой вход выводов АЦП, он тоже немного потребляет ASSR |= (1<<AS2); // Асинхронный режим TCCR2A = (0<<WGM21)|(0<<WGM20); //режим normal TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20); // clk/1024 TCNT2 = 0x00; // начальное значение таймера // OCR2A = 0x00; OCR2B = 0x00; TIMSK2 |= (1 << TOIE2); // разрешаем прерывание по переполнению Т2 SMCR = _BV(SM1) | _BV(SM0); // Power_Save, set_sleep_mode(SLEEP_MODE_PWR_SAVE), set_sleep_mode (SLEEP_MODE_PWR_DOWN) - выбор режима сна radio.powerDown(); PORTC &= ~_BV(PC1); // выключение светодиода } void loop() { if ( count >= 8 ) { // передавая один раз в 64 секунды = 8 radio_(); TCNT2 = 0x00; } while(ASSR&(1<<TCN2UB)){;} //wait to TCNT update!!! TCNT2 = 0x00; sleep_enable(); //SMCR |= _BV(SE); sleep_cpu (); } void radio_() { wdt_enable(WDTO_1S); radio.powerUp(); data[1]++; ADCSRA |= _BV(ADEN); // включаем АЦП Measurement measurement = bme280.readMeasurement(); // опрос датчика и расчет параметров data[2] = (measurement.getPressure32()*1000/133322); data[3] = (measurement.getTemperature()*100); data[4] = (measurement.getHumidity()*100); bme280.setMode(Forced, Over_1, Over_1); // запуск однократного измерения и установка оверсемплингов T, P, без влажности //bme280.setMode(Forced, Over_1, Over_1, Over_1); // запуск однократного измерения и установка оверсемплингов T, P, Hum ADCSRA |= _BV(ADSC); // запуск конверсии while (bit_is_set(ADCSRA,ADSC)); // измерение uint8_t low = ADCL; // сначала читаем ADCL - это расблокирует чтение ADCH uint8_t high = ADCH; int volt = (high<<8) | low; // данные АЦП data[0] = (1135494/volt); // 1135494 подобрано эксперементально и в общем случае равно 1100 милливольт опорное * 1024, но опорное не всегда 1100 мВ ADCSRA = 0; // отключаем АЦП // ******************************************** // код до этого места примерно 1700 мкс, убираем в файле RF24.cpp задержку delay(5) и добавляем перед отправкой данных // задержку в 2.3 мс, чтобы в сумме задежка получилась 4 мс, это минимальная задержка от команды powerUp() до write() // при которой стабильно работает большой модуль на RF24, smd модуль работает и при меньшей задержки, т.к. разные кварцы clock_prescale_set(clock_div_256); // на время задержки снижаем частоту контроллера до минимально возможной, для снижения энергопотребления delayMicroseconds(10); // на этой частоте для получения 2.3 миллисекунд нужно указать задержку в 256 раз меньше ~ 9 мкс // в этом режиме потребляет только atmega, которая работает на частоте 1/256 от номанальной clock_prescale_set(clock_div_1); // перед отправкой данных снова устанавливаем исходную частоту работы контроллера radio.write(&data, sizeof(data)); radio.powerDown(); count = 0; wdt_disable(); }
  19. Странно, но не работает. Попробую тестовый датчик с диапазоном в -1 ... 1
  20. BME280, BME280I2C.h. Сам датчик показывает правильно. Если присмотреться на картинке с графиком на фоне видно отрицательное значение температуры.
  21. @IvAn какой датчик температуры Вы используете и с какой библиотекой?
  22. можете выполнить разработку модуля на BME-280 для нашего манометра МО-05 почта 

    info@gidrogaz.ru

     

  23. Снимать долго. Стоит в доме на чердаке. Проще градусов 10 вычесть, но чистота эксперимента пропадет. Тестовый то датчик правильно заработал.
  1. Load more activity
×
×
  • Create New...