Перейти к публикации
iT4iT.CLUB

Kitsum

Пользователи
  • Публикации

    360
  • Зарегистрирован

  • Посещение

  • Дней в лидерах

    184

Последний раз Kitsum выиграл 25 февраля

Публикации Kitsum были самыми популярными!

Репутация

166 Excellent

11 подписчиков

О Kitsum

  • День рождения 2 апреля

Посетители профиля

4 559 просмотров профиля
  1. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Что Вы имеете в виду под фигурирует, связь между двумя контроллерами по Serial? Если да, то оба контроллера подключаются друг к другу через порты RX и TX с общей землей (GND). RX подключается к TX не зависимо от того с какой стороны смотреть. Также необходимо помнить об согласовании уровней сигналов. В программе работаете с контроллерами через Serial, различия будут лишь в том, что в ESP буфер с данными формируется автоматически, а в ATmega данные получаете по одному байту и буфер нужной длинны необходимо формировать самому. Дело в том, что предоставленный пример написан под ESP 8266/32 и для них в объекте Serial есть метод printf, а вот под ATmega данного метода нет, но есть одноименная функция, приводящая к аналогичному результату. Так что для ATmega строки такого вида Serial.printf ("f1: %f\r\nf2: %f\r\n", f1, f2); приведите к такому printf ("f1: %f\r\nf2: %f\r\n", f1, f2); и все должно заработать. Вообще все строки с Serial можно удалить, я добавил их для вывода отладочной информации дабы можно было отследить как выглядит число, записанное в float при разборе на массив из 4-х byte элементов и дальнейший обратный процесс с записью значение в другую переменную. PS: прошу прощение за задержку с ответами.
  2. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @post125 попробуйте такой вариант разбора float на массив byte float f1 = -3.14; float f2 = 0; byte b1[sizeof(float)]; void setup() { Serial.begin(115200); Serial.println(); *(float*)b1 = f1; Serial.printf("f1: %f\r\nf2: %f\r\n", f1, f2); Serial.printf("0x%02X\r\n0x%02X\r\n0x%02X\r\n0x%02X\r\n", b1[0], b1[1], b1[2], b1[3]); f2 = *(float*)b1; Serial.printf("f1: %f\r\nf2: %f\r\n", f1, f2); } void loop() { } Передавайте этот массив и собирайте его в обратном порядке на стороне ESP.
  3. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. @post125 В первую очередь нужно понять, что I2C и NRF это две разные транспортные линии, не рассматривайте их как единую среду передачи данных от беспроводных устройств к ESP, так ничего не выйдет. Со стороны ProMini необходимо организовать систему получения данных по беспроводному каналу их обработку и хранение в оперативной памяти. Допустим Вы получаете данные с 5-и беспроводных устройств, значит ProMini должна держать в памяти 5 разных значений с этими данными, пусть это будет float или, что угодно. Далее ESP, по мере надобности, запрашивает у ProMini данные по конкретному устройству, одному из 5-и. В ответ ProMini передает заранее преобразованное значение float с одного из датчиков в массив из 4-х byte или char и по очереди передает все элементы массива ESP. Далее проводите обратную операцию и получаете значение float. Главное помнить простую вещь, что float имеет размер в 4 byte, обращайтесь к каждому из них как к элементу массива и передавайте значение по одному byte. Таким образом получается, что ProMini является агрегатором данных со всех беспроводных устройств, работающих через NRF и передающих мастеру данные в виде массива из 4-х byte для каждого float.
  4. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. Ограничения есть только в web интерфейсе проекта, в файле index.htm Для проверки SSID применяется следующее регулярное выражение, соответствующее латинским буквам от A до Z без учета регистра, всем цифрам и дополнительным символам "_. -". Общая длинна от 3 до 30 символов включительно. function checkSSID(ssid) { return ssid.match(/^[a-z0-9_. -]{3,30}$/i); } Для пароля все еще проще, это от 5 до 63 любых символов function checkPassw(passw) { return passw.match(/^.{5,63}$/); } Это говорит о том, что Вы проходите проверку на стороне web интерфейса ESP8266. Следовательно, причина кроется на стороне микроконтроллера. В первую очередь будет вызван один из методов web сервера, отвечающий за обработку пользовательских запросов. Файл webserver.h По сути тут будет проведена проверка на авторизацию пользователя и передача новых параметров вашему объекту конфигурации через вызов его метода config::write(String apiSave) Файл config.h Метод перебирает все доступные ему параметры, находящиеся в оперативной памяти и перезаписывает значения для тех из них чьи имена упоминались в списке, переданном web интерфейсом. Далее записывает данные в конфигурационный файл находящийся во Flash памяти. Могу предположить, что причина кроется в обработке некоторых символов библиотекой ArduinoJson в методе config::write(String apiSave), что приводит в отказу от записи конфигурации. json.success() Попробуйте в файле webserver.h добавить код ответа 500 для подобного события в метод http::api_settings(), приведите его к следующему виду void http::api_settings() { this->sendServerHeaders(); this->sendHeader("Cache-Control", "no-store, no-cache"); if (!this->security()) this->send(403); else if (this->authorized()) { if (this->hasArg(F("save"))) { if(!conf.write(this->arg(F("save")))) this->send(500); else this->send(200, headerJson, conf.showSecureConfig()); } else this->send(200, headerJson, conf.showSecureConfig()); } else this->send(401); } В теории, если ошибка происходит на уровне json формата, то она должна появиться с сообщением 500 Internal Server Error Если причина действительно в этом и Вам удастся выловить символ, то дайте мне знать какой он.
  5. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Как мне кажется, эта библиотека не подойдет, но проверить конечно же стоит. Я бы копал в сторону стандартной библиотеки Wire.h как для AVR контроллеров (Atmega ...) так и для ESP, ищите их в вашей Arduino IDE. Также надо учитывать, что для этих контроллеров библиотеки разные. Например, ESP может работать только в качестве Master устройства, что в принципе и требуется, а вот AVR контроллеры могут работать в Master/Slave режиме. Это можно подсмотреть в заголовочных файлах (.h) их библиотек. Также для начала будут очень полезны эти материалы: https://www.arduino.cc/en/Reference/Wire https://www.arduino.cc/en/Tutorial/MasterReader https://www.arduino.cc/en/Tutorial/MasterWriter https://forum.arduino.cc/index.php?topic=336543.msg2321656#msg2321656 (стоит ознакомиться с возможными проблемами, прочтите всю тему) Также помните о подтягивающих резисторах на SDA и SCL т.к они не отражены на схемах. Они понадобятся если Вы соединяете два контроллера между собой, но если на шине установлен какой ни-ть Китайский датчик, то очень велика вероятность, что резисторы уже есть. И еще один важный момент, это согласование уровней сигнала т.к ESP работает от 3.3V, а для ATmega стандартом является 5V, но они могут поддерживать и 3.3V. В любом случае, Вы должны гарантировать, что рассогласования уровней сигнала не будет. Лично мне нравится вариант, когда оба контроллера имеют питание 3.3V, так можно питать Slave от Master и не ставить плату согласования, но это зависит от конкретных задач, этот вариант не всегда приемлем. После того, как Вы научитесь передавать данные между контроллерами, копайте в сторону файла sensors.h в проекте. Вам нужен метод add, а точнее разобраться в параметрах, передаваемых ему. Один из параметров указывает какую функцию нужно вызвать чтобы получить данные от датчика, вот в этой функции и стоит описывать код запроса данных от Slave и дальнейший их разбор. Описание для интерфейса knob_t *sensor_knob_cfg = new knob_t(0, 100, "1", "Что показывает", "Ед. измер."); Функция сбора данных float getSensorData() { float value = 0; /* Тут описываем работу с Slave по i2c, результат записываем в value */ return value; } Добавление датчика sensors.add(sensor_knob_cfg, device::out, "sensor_uid", getSensorData); Это очень грубый пример одного из вариантов. В проекте много примеров реализации и есть некоторое количество комментариев, не стесняйтесь изучать содержимое файлов проекта, таких как sensors.h. Очень велика вероятность, что после изучения их содержимого у Вас появится свое видение как это должно быть реализовано, и это очень хорошо.
  6. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. @Дмитрий Давайте попробуем, но я заранее предупреждаю, что Вам придется самостоятельно проводить все испытания. Я лишь постараюсь помочь с рекомендациями относительно данного проекта. И так. На сколько я понял, общая идея заключается в подсчете импульсов чашечного анемометра. Самый верный путь, это регистрировать импульсы по прерыванию т.к это не тратит драгоценное время ЦП. Далее, опираясь на частоту импульсов вычислять расстояние, которое прошел анемометр как будто это колесо автомобиля, а уже из этих данных выводить скорость. Стоит учитывать, что при расчете частоты нужно брать время между предыдущим и текущим расчетом скорости ветра, а не фиксированный интервал т.к есть и другие задачи время выполнения которых может меняться, а микроконтроллер выполняет код в реальном времени без распараллеливания задач. В первую очередь необходимо определиться, какой порт микроконтроллера будем задействовать. Я возьму за основу порт GPIO14. Он уже был задействован в проекте, поэтому в основном файле необходимо закомментировать вызов функции, которая его занимает. //gpio_14(); // Расхождение расчетной абсолютной влажности между показаниями с двух датчиков, например, BME280 Теперь порт свободен и можно преступать к коду анемометра. Мне не известно какие датчики Вы еще используете поэтому всё дальнейшее описание я буду делать так, как будто у меня только один этот датчик, так будет более понятно. Выберите пользовательский файл в котором будите работать, это любой .h файл начинающийся с префикса users_ или создайте новый файл со своим уникальным именем, например users_wspeed.h. Выбранный Вами файл должен быть подключен через оператор include в основном файле программы, другие пользовательские файлы должны быть закомментированы. Для себя я выбрал вариант с новым файлом users_wspeed.h //#include "users_auto.h"; // Пользовательская конфигурация датчиков, именно тут описывается с какими датчиками работать //#include "users_bme280_x2.h"; // Пример для двух датчиков BME280 (несовместим с users_auto.h) //#include "users_multiple_ds18b20.h"; #include "users_wspeed.h"; Весь код в этом файле должен быть заключен в конструкцию такого вида #ifndef USERS_H #define USERS_H /* Весь код описанный ниже располагается тут */ #endif Это указания для компилятора, на тот случай если в коде окажутся подключены два пользовательских файла. Теперь добавим описание для плагина Knob который отобразит наш сенсор в web интерфейсе. Установим приделы шкалы от 0 до 40 метров в секунду с шагом в одну десятую и соответствующим описанием. /* Параметры индикаторов web интерфейса для плагина Knob Мин Макс Шаг Заголовок Ед. измер. |---------------------|----|------|------|--------------|---------| */ knob_t *S = new knob_t(0, 40, ".1", "Скорость в.", "м/c"); Теперь объявим все необходимые константы. Обязательно укажите значения, подходящие для Вашего датчика. Учтите количество импульсов на один полный оборот, радиус анемометра и коэффициент для калибровки датчика. По сути этот коэффициент равен расхождению в скорости (м/c) между показаниями Вашего датчика и какого ни-ть эталонного, например другого анемометра. Можно собрать анемометр, покататься с ним на машине и сравнить показания, только помним о переводе км/ч в м/c. Я надеюсь, что зависимость линейная и все будет в порядке. /* Параметры конфигурации для расчета скорости ветра */ #define windSpeed_Pin 14 // GPIO микроконтроллера к которому подключен чашечный анемометр #define windSpeed_Pulses 1 // Количество импульсов на один оборот чашечного анемометра #define windSpeed_Correction 0 // Коэффициент поправки. Разница в скорости м/с между измеренным и фактическим значением полученная при калибровки #define windSpeed_Radius 100 // Радиус чашечного анемометра от центра до середины чашечки в милиметрах Объявим переменные для хранения показаний частоты и расчетной скорости. uint32_t windSpeed_Hz = 0; // Тут будет зафиксирована частота за ПЛАВАЮЩИЙ интервал времени float windSpeed = 0; // Тут будет зафиксирована скорость ветра Далее опишем функцию, которая будет вызываться по прерыванию и изменять показания частоты /* Функция, регистрирующая импульсы с чашечного анемометра */ void pulseDetected() { ++windSpeed_Hz; } Переходим к основной функции, отвечающей за расчет скорости ветра. Обязательно все за мной перепроверяйте т.к я мог ошибиться в расчетах или что-то сделать не так. На время расчетов мы выключаем регистрацию новых импульсов. За время мы возьмем интервал между предыдущим вызовом этой функции и текущим. Рассчитаем длину окружности и общий пройденный путь. Полученный результат запишем в одну из объявленных ранее глобальных переменных. /* Функция, производящая расчет скорости ветра */ void pulseCounter() { detachInterrupt(windSpeed_Pin); // Отключаем регистрацию импульсов на время расчета /* Расчет скорости ветра */ if (windSpeed_Hz) { float time = cron.lastRun("Wind Speed Calculation") / 1000; // Время прошедшее с последнего расчета скорости ветра в секундах float circumference = 3.14 * 2 * windSpeed_Radius; // Длинна окружности анемометра в милиметрах float distance = (windSpeed_Hz / windSpeed_Pulses) * circumference; // Пройденое растояние в милиметрах float speed = distance / time / 1000; // Скорость в метрах в секунду (грязная) windSpeed = speed + windSpeed_Correction; // Скорость ветра с учетом коректировки } else windSpeed = 0; /* Сброс частоты */ windSpeed_Hz = 0; attachInterrupt(windSpeed_Pin, pulseDetected, FALLING); // Возобновляем регистрацию импульсов } Опишем функцию возвращающую расчетный результат скорости. /* Функция, возвращающая последнее расчетное значение скорости ветра */ float getWindSpeed() { return windSpeed; } Ну и осталось самое главное, это функция описывающая наши сенсоры. void sensors_config() { pinMode(windSpeed_Pin, INPUT_PULLUP); // Конфигурируем порт микроконтроллера как вход с активным встроенным подтягивающим резистором attachInterrupt(windSpeed_Pin, pulseDetected, FALLING); // Регистрация импульсов с чашечного анемометра по прерыванию на землю cron.add(cron::time_10s, pulseCounter, "Wind Speed Calculation"); // Задача в планировщике для расчета скорости ветра sensors.add(S, device::out, "windSpeed", getWindSpeed); // Добавляем сенсор скорости ветра в web интерфейс } Как мы видим, тут происходит инициализация порта микроконтроллера на вход с подтяжкой к питанию. Объявление прерывания. А также добавление задачи по расчету скорости в планировщик и добавление нашего сенсора. Еще раз напоминаю, что я не могу гарантировать работоспособность данного решения, у меня нет возможности это проверить. Внимательно все просмотрите, я постарался везде указать комментарии. Помните, что импульсы считаются по прерыванию на землю, Вы должны гарантировать, что схема датчика будет их генерировать. На всякий случай прикрепляю готовый файл. users_wspeed.zip
  7. Ничем не отличается. Разницы нет, это просто уникальные идентификаторы для подсетей.
  8. Вроде бы и ничего сложного тут нет, но то параметр забудешь, то еще какая ни-ть мелочь, а по справке бегать как всегда нет особого желания. В общем оставляю лично для себя. find /catalog -type d -exec chmod 755 {} \; find /catalog -type f -exec chmod 644 {} \;
  9. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. Электронных компонентов для проверки у меня нет, но я постараюсь помочь, опираясь на код библиотеки. Все фактические проверки Вам придется произвести самостоятельно. Я буду использовать эту библиотеку https://github.com/bogde/HX711, Вы можете использовать любую другую, просто действуйте по аналогии. В первую очередь необходимо определиться с используемыми портами микроконтроллера. Предлагаю задействовать 12 и 13 порты, но т.к они уже были использованы ранее, то в основном файле проекта необходимо закомментировать вызов функции gpio_12_13(). Я выбрал эти порты для примера, возможно Вы задействуете какие ни-ть другие. /* Инициализация GPIO для управления внешней нагрузкой */ //gpio_12_13(); // Простое превышение температуры или влажности (выставляется в WEB интерфейсе) Теперь мы уверенны, что порты не заняты и можем переходить к реализации весов. Я предположу, что для описания сенсоров Вы используете один из пользовательских файлов имена которых начинаются с users_. В начале файла подключаем выбранную библиотеку. #include "HX711.h" Объявляем объект с помощью которого будем работать с весами. При объявлении мы передаем в качестве параметров номера задействованных портов. HX711 scale(12, 13); Создадим описание для системы визуализации (плагин Knob). knob_t *W = new knob_t(-100, 10000, "1", "Вес", "Гр"); Мне не известно какой датчик Вы будите использовать, поэтому значения я выбрал на свое усмотрение. Минимальный вес равен -100 грамм, максимальный 10000 грамм, шаг шкалы 1, описание сенсора "Вес", ну и "Гр" в качестве единиц измерения. Минимальный вес в -100 грамм взят не случайно, так Вам будет проще найти калибровочный коэффициент. Теперь модифицируем функцию sensors_config() и объявим новый сенсор. /* Добавление датчиков в систему */ void sensors_config() { /* Тут описан код других датчиков */ scale.set_scale(3); // калибровочный коэффициент scale.tare(); // тарирование sensors.add(W, device::in, "in_weight", [&](){ return scale.get_units() * 0.035274; // перевод в граммы }); } В теории, этого должно быть достаточно. Обратите внимание на калибровочный коэффициент, я указал значение 3, у Вас это будет свое значение уникальное для Вашего датчика. scale.set_scale(3); Также обратите внимание, что при запуске микроконтроллера происходит тарирование весов. scale.tare(); Отпишитесь о результатах.
  10. Kitsum

    esp8266 и парсинг погоды с OpenWeatherMap

    Доброе время суток. @Же ка Ваша проблема скорее всего связана с ошибочным значением в переменной appid. Возможно опечатка или Вы не прошли до конца процесс получения ключа. Проверьте все еще раз. Таблицу с кодами ответов можно посмотреть тут https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP#401 А вот тестовый пример для проверки API. https://samples.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=b6907d289e10d714a6e88b30761fae22
  11. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Убедитесь в работоспособности проекта без строки корректировки. Проверьте датчик стандартным скетчем, идущим в примере с библиотекой. Укажите в качестве температуры и влажности какие-нибудь значения, можно статичные. Посмотрите на результат длительной работы.
  12. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. Большинство самостоятельно добавляет необходимый функционал. Как мне кажется, на текущий момент в проекте очень много проблем, думаю, что следующую версию имеет смысл делать для контроллера ESP32. А для всего остального всегда можно получить ответ на форуме. Но, возможно, я ошибаюсь... Это связано с тем, что на одном графике отображается информация с нескольких сенсоров, это сопровождается некоторым описанием для каждого из них. На все это требуется место для визуализации, и только свободная часть используется для вывода данных с сенсоров. В итоге, на маленьком разрешении рассмотреть что-либо практически невозможно. Но если хочется её вернуть, то в файле index.htm найдите следующий фрагмент css кода. @media screen and (max-width:610px) { #graph { display: none; } div.copyright { position: unset; } } И удалите из него строку #graph { display: none; } Не забудьте запаковать файл обратно в .gz формат Это зависит от самого датчика. В проекте данные проходят только через медианный фильтр, класс medianFilter_t в файле tools.h. По сути, это просто накопительный буфер для сглаживания случайных пиков. Больше информации можно посмотреть тут https://ru.wikipedia.org/wiki/Медианный_фильтр В ранних версиях используемой библиотеки это не было реализовано. Интересно посмотреть, как это повлияет на показания. В файле users_auto.h есть пример кода для работы с датчиком #if SENSOR_CCS811 sensors.add(C, device::out, 0x5A, "out_co2", [&](){ ccs811.begin(); ccs811.start(CCS811_MODE_1SEC); }, [&](){ uint16_t eco2, etvoc, errstat, raw; ccs811.read(&eco2, &etvoc, &errstat, &raw); return eco2; }, true); #endif Замените его на этот #if SENSOR_CCS811 sensors.add(C, device::out, 0x5A, "out_co2", [&](){ ccs811.begin(); ccs811.start(CCS811_MODE_1SEC); }, [&](){ uint16_t eco2, etvoc, errstat, raw; ccs811.set_envdata(sensors.get("out_temperature"), sensors.get("out_humidity")); ccs811.read(&eco2, &etvoc, &errstat, &raw); return eco2; }, true); #endif Разница всего в одной строке ccs811.set_envdata(sensors.get("out_temperature"), sensors.get("out_humidity")); Где out_temperature и out_humidity, это имена объявленных Вами сенсоров температуры и влажности.
  13. Kitsum

    esp8266 и парсинг погоды с OpenWeatherMap

    @В К Найдите строку postingInterval = find ? 600L * 1000L : 60L * 1000L; и замените ее на postingInterval = find ? 3600L * 1000L : 60L * 1000L;
  14. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Вы можете воспользоваться решением указанным несколько постов ранее, только внесите одно изменение. Замените запрос температуры по индексному номеру датчика sensors.add(T, device::in, "ds18b20_s0", [&](){ return ds18b20.getTempCByIndex(0); }); на запрос по уникальному серийному номеру sensors.add(T, device::in, "ds18b20_s0", [&](){ return ds18b20.getTempC({ 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 }); }); После этих изменений датчику c идентификатором ds18b20_s0 будет соответствовать DS18B20 с адресом 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0
  15. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Попробуйте провести эксперимент используя только один из двух датчиков по очереди чтобы попытаться исключить неисправность датчиков. Или временно замените датчики на другие. Убедитесь, что сама линия имеет надежные контактные соединения с контроллером и датчиками. Проверьте исправность подтягивающего резистора на шине 1 wire. Попробуйте подключать датчики без использования паразитного питания если конечно последнее используется. Воспользуйтесь одним из стандартных примеров библиотеки DallasTemperature для 10-15 минутного теста.
×
×
  • Создать...