РЕКЛАМА НА ФОРУМХАУС Раньше делали ОВ-215 там тоже один порт, один датчик Судя по поисковику Novatek-electro Санкт-Петербург их по прежнему производит. Один датчик потому что это не шлюз для гирлянды на 1-wire, а конфигурируемый порт под разные датчики и счетчик импульсов.
Она работает правильно. Обратите внимание, что цикл while выполняется только тогда, когда дельта становится больше 950. Там в начале строки стоит оператор if. В ESP нужно использовать uint64_t. ESP отличается от Ардуино разрядностью. int в ESP и Ардуино имеют разную разрядность. Процедуры вызываются с периодичностью 1 сек. Если не делать проверку на переполнение, то при переполнении процедуры могут быть вызваны чаще. Проверка, это скорее перестраховка. В Arduino IDE преобразование типов для плат Ардуино и ESP отличается. Кода который работает на Ардуино, на ESP работает не верно. Я стараюсь сразу всего этого избегать.
Возможно, код работает правильно с вашей точки зрения. Но если это именно кусок вашего кода, то несложно заметить, что это условие (и много чего рядом) не влияет на результат. Если бы взглянули на него свежим взглядом, то я думаю, и сами бы заметили. Я пытался показать вам, как добиться того же результата проще и красивее. За этим многословием вы опять потеряли суть моего замечания. Про то, как нужно работать с переполняющимися unsigned счетчиками (работающими только на увеличение значения). Но если вы сами ничего знать не хотите, то я не могу вас заставить.
Есть у wirenboard. Ну вообще-то именно так и тянут, а в чем проблема? Хоть и есть теоретическая возможность на одной шине 1-wire работать многим устройствам, но это не рекомендуется особенно если до датчика более 3-5 метров. Кабель от датчика до 1-wire порта должен быть как можно более короткий. А вот шину RS-485 можно на сотни метров растянуть.
Кем не рекомендуется? Это штатная работа, по спецификации на протокол. До 127 если правильно помню устройств (причем любых 1wire, не только термодатчиков), расстояние там ограничено ёмкостью и сопротивлением линии. А минимальным должно быть расстояние от устройства до шины. Не рекомендуется теми, кто не разобрался в электрической части или в программной обработке ответов, потому что в общем случае на некоторые команды они отвечают хором, и нужно суметь их разделить. А так прекрасно работают по витой паре, особенно если стоит задача контроля температур на какой-то линии (труба, кабельная трасса, воздуховоды). Вот звездой их подключать не рекомендуется, да, но скорее из-за того что сигналы будут по времени накладываться, т. е. при заведомо разной длине лучей можно
Не поленился, нашел Wemos D1 mini (не отдельный модуль F12, чтобы максимально близко к вашей ситуации), попытался повторить ваш код. С отправкой UDP на свой собственный сервер, с чтением аналогового пина. Результаты следующие: Спойлер: кому интересно 1. Как и ожидалось, назначение "периода тишины" совершенно непонятно, аналоговый пин успешно читается как просто в теле цикла (коммент "вот так работать не будет"), так и по условию раз в секунду (коммент "так работает"). И там и там читается. 2. Период тишины - тупо циклит процессор без права делать что-то еще. И как сказано в п. 1. практического смысла в этом нет. 3. Выбранная схема запуска "раз в секунду" действительно работает раз в секунду, но благодаря именно такому решению всё остальное время кроме этого "раза в секунду" процессор молотит циклы, не имея возможности обрабатывать WiFi. Единственное некоторое поле свободы - обработка OTA и возможно что-то внутри ваших процедур, если они не жестко лимитированы. 4. Как следствие п. 3 - отправка UDP не работает, в то время как отправка по Serial работает успешно. Но Serial - синхронный, а Wifi c UDP - нет. Допускаю, что у вас он каким-то чудом все-таки работает, возможно за счет ОТА или хоть небольших delay в ваших процедурах. 5. Если убрать всё до чтения пина, и организовать запуск "раз в секунду" стандартным для Ардуино способом, из чуть менее чем любого примера Код: if((millis() - timer) > MY_PERIOD){ timer = millis(); // где timer - unsigned long ... } а в самом цикле задать delay (500), разрешив в это время обработку WiFi - то всё чудесным образом работает. Присылая по UDP считанные значения аналогового пина, например, как первый так и второй раз, см. п. 1. Код: void loop() { char buf[255]; int v = analogRead(A0); if((millis() - timer) > 1000){ timer=millis(); // задержка 25мс - на результаты никак не влияет == timeAbs=0; timeOld=timer; while(timeAbs<=25) { timeNew=millis(); if(timeNew>timeOld) {timeAbs=timeNew-timeOld; } else {timeAbs=0; timeOld=timeNew; } } // ================================================= xi++; int v1 = analogRead(A0); sprintf(buf,"a0=%d, a1=%d, i=%d",v,v1,xi); sendUDP(buf); } delay(500); } Никаких других "известных особенностей ESP" не обнаружил.
а обратно, от UDP, пакеты на устройство передаете? Они без пропусков приходят? Все приблуды WIFI компилятор вставляет в конце цикла loop. Как раз все, что связано с WIFI отрабатывается постоянно. Если в тело программы вставить delay(), то компилятор и туда влупит вызов кода wifi.
А надо было, обмен двухсторонний? Использовал UDP когда-то для отправки логов - вот оттуда кусок взял, там однонаправленная связь. Обычно сейчас MQTT использую, вот там двухсторонний обмен. Компилятор никуда сам ничего не вставляет. Логика работы заключается в том, что delay задерживает исполнение текущей процедуры, но во время его выполнения могут обрабатываться другие процедуры, в том числе связанные с обработкой сетевого стека. Можно и свою написать, назвав ее yield - она будет вызываться во время, когда где-то выполняется delay. Но если вы delay не задаете - промежутка не будет, просто выполняется непрерывный цикл (кроме прерываний, которые его могут прерывать, например для Serial) В вашем примере delay мог быть где-то внутри ваших же процедур, или внутри обработчика OTA, в самом цикле loop его нет.
Доработал, да, приходят. Там счетчик, видно что без пропусков. Спойлер: Код тупо из примера взят: Код: int rcv=Udp.parsePacket(); if (rcv) { Serial.print("Received packet of size "); Serial.println(rcv); Serial.print("From "); IPAddress remoteIp = Udp.remoteIP(); Serial.print(remoteIp); Serial.print(", port "); Serial.println(Udp.remotePort()); int len = Udp.read(buf, 255); if (len > 0) { buf[len] = 0; } Serial.println("Contents:"); Serial.println(buf); } ЗЫ: оно все еще работает исправно. Вот теперь буду думать куда же такую полезную штуку применить можно.
Интеграторами из практики. Ну если несколько датчиков и метров до 5, может и будет нормально работать, а штук 10 и метров по 50 - уже как повезет. Эти конвертеры 1-wire->RS485 ведь не просто так придумали... Чаще всего именно RS-485 шину тянут везде, а уже от нее где нужно на пару датчиков ставят такие конверторы.
Около 150 метров тянули, например - змейкой на высоте в складском ангаре, мониторинг температур хранения по нескольким зонам. Делают 485 скорее всего потому что техники ее любят, она у них стандартная и для разного, а 1wire все-таки специфическая. Много вы управляемых выключателей на базе 1wire видели? А они ведь есть, но в основном сейчас либо термометры, либо "таблетки" локально рядом с контроллером доступа. Но тащить домой еще дополнительно кусок 485 без необходимости - ну то такое...
Обмен двухсторонний. Потерю связи я определяю по пакетам идущих от udp сервера. Они просто не приходили. В каждом пакете есть маркер, На сервере он меняется раз в секунду, и передается устройствам. Если маркер до устройства не дошел, то его значение в массиве не меняется. А от UDP какое количество байте передается? delay вообще не использую. Только перед перезагрузкой esp. Если откроете C:\Users\user\AppData\Local\Arduino15, там туча файлов. В одном из них (не помню каком) будет конструкция, в которую переводится программный код. Окончательный вариант программы примерно такой: main { setup(); while (true) { loop(); WIFI(); / процедуры и функции работы с wifi } } Именно этот код и компилируется. Каждый раз, после окончания loop() начинается работа с wifi.
После, а не в конце, это немного разное. Над будет посмотреть. Но результат в общем такой что у меня работает, а если пытаться сделать такой код как на том скриншоте - то не работает, хотя и пытается отправлять раз в секунду. Один пакет даже дошел, но и всё. Значит что-то тут не то. И лечится это добавлением всего одного delay. Туда - строка типа "a0=12 a1=12 i=1234", обратно она же с добавлением IP адреса модуля.