Closed vladikas closed 2 years ago
а зачем каждый раз запрашивать адрес датчика?
C одной стороны, как бы и не зачем. Это артефакт остался от поиска проблемы. А с другой стороны каким образом это может влиять на датчик? Я долго искал проблему, изначально в коде этого запроса не было. Проблема в таком варианте возникает стабильно, если что-то убрать с этого кода, то лотерея.
Вроде бы датчик притягивает пин, когда идёт преобразование. Библиотека таймера точно работает корректно? Может можно сделать более минимальный пример, где проявляется бага?
Я попробую, но мне кажется, что вряд-ли получится. И так два дня воевал, а результата ноль. Может это партия датчиков глючная.
Примеры из библиотеки работают?
Да, всё работает. Подозреваю, что это нюансы работы прерываний на ESP8266.
Прерывания запрещаются на период чтения и отправки битов данных, не думаю что в этом дело
Я видел. В меру своих познаний ковырялся в коде библиотеки. Просто у ESP есть свои хитрости с прерываниями. Например, для обслуживания WiFi время выделяется. Или особым образом регламентируются обработчики прерываний.
У 8266 основное обслуживание идёт в yield или в конце луп, на чтение дс18 не должно влиять
Если есть какие-то идеи, что мне попробовать, то пиши. После праздников ещё пару дней поковыряю. Если не найду проблему, то оставлю паразитное питание и всё будет работать.
Хорошо бы локализовать проблему, получить минимальный пример, на котором проявляется бяка
Повоевал сегодня с кодом немного. Так уж получается, что выше как раз минимальный код, когда появляется проблема. Подвигал DS по всем доступным пинам, проблема не исчезает. Попробовал другую библиотеку, она работает отлично. В общем, я либо буду использовать другую библиотеку, либо буду использовать паразитное питание. В любом случае спасибо тебе за то, что откликнулся. Пример с другой библиотекой, где всё ок:
#include <ESP8266WiFi.h>
#include <SimpleTimer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_BME280.h>
SimpleTimer myTimer;
//инициализация датчика температуры
#define ONE_WIRE_BUS D5// GPIO14 пин датчика температуры
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device address
DeviceAddress insideThermometer;
Adafruit_BME280 bme; // use I2C interface D1-GPIO5, D2-GPIO4
Adafruit_Sensor *bme_temp = bme.getTemperatureSensor();
Adafruit_Sensor *bme_pressure = bme.getPressureSensor();
Adafruit_Sensor *bme_humidity = bme.getHumiditySensor();
void setup(void){
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP_TEST");
Serial.print(F("BME connecting... \r\n"));
for (int i = 10; i > 1; i--)
{
Serial.println(i);
if(bme.begin(0x76))
{
break;
}
delay(10);
}
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(insideThermometer, 9);
Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();
sensors.requestTemperatures(); // Send the command to get temperatures
myTimer.setInterval(10000, sendDataToNarodmon);//раз в пять минут посылать данные
myTimer.setInterval(2000, bmeRead); //таймер для измерения BME280
myTimer.setInterval(2000, readTempDS); //таймер для измерения температуры
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
void bmeRead(){
sensors_event_t temp_event, pressure_event, humidity_event;
bme_temp->getEvent(&temp_event);
bme_pressure->getEvent(&pressure_event);
bme_humidity->getEvent(&humidity_event);
Serial.print(F("Temperature = "));
Serial.print(temp_event.temperature);
Serial.println(F(" *C"));
Serial.print(F("Humidity = "));
Serial.print(humidity_event.relative_humidity);
Serial.println(F(" %"));
Serial.print(F("Pressure = "));
Serial.print(pressure_event.pressure);
Serial.println(F(" hPa"));
}
//температура
void readTempDS(void){
Serial.println("readTempDS");
float tempC = sensors.getTempC(insideThermometer);
if(tempC == DEVICE_DISCONNECTED_C)
{
Serial.println("Error: Could not read temperature data");
return;
}
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print("\r\nDevice 0 Address: ");
printAddress(insideThermometer);
Serial.println();
sensors.requestTemperatures(); // Send the command to get temperatures
}
void sendDataToNarodmon(void){
Serial.println(F("sendDataToNarodmon"));
WiFiClient client;
client.connect(F("narodmon.ru"), 8283); //Подключаемся
String line = client.readStringUntil('\n');
}
void loop(void){
myTimer.run();
}
Это всё таки не похоже на минимальный код) там ещё один датчик и куча всего лишнего. Нужно локализовать проблему, и я её решу
Я практически построчно удалял из кода "лишнее". Например, не опрашивал BME по влажности. Проблема исчезает.
Видимо звёзды сошлись, или адафрут опять насрали в библиотеку. Вообще как то странно написан код, может компилятор свинью подсунул? mocrods18b20 работает предельно просто, там digitalRead/write и delay, ломаться абсолютно нечему
Попробую другой вариант, заменю библиотеку для BME280.
А ds18 подключен туда же куда bme280? Так нельзя делать, это не будет работать)
Нет конечно. BME занимает аппаратные выводы i2c D1 и D2. DS изначально был на D5. Это у меня модуль NodeMcu V3.
Так я смотрю у ДС вообще пин не указан
Наводите порядок в скетче, и всё будет работать
static const uint8_t dsPin = D5;// GPIO14 пин датчика температуры и
static const uint8_t dsPin = D5
В microds18 пин не задаётся таким образом
А что за конструкция с запросом адреса в условии, и при else идёт request? Откуда это взято?) Да и с бме280 очень странный код, там в пару строк всё делается без объектов-прослоек
#include <SimpleTimer.h>
SimpleTimer myTimer;
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme;
#include <microDS18B20.h>
MicroDS18B20<D5> sensor;
void setup() {
Serial.begin(9600);
bme.begin();
myTimer.setInterval(2000, bmeRead);
myTimer.setInterval(2000, readTempDS);
}
void loop() {
myTimer.run();
}
void bmeRead() {
Serial.print(bme.readTemperature());
Serial.print(',');
Serial.print(bme.readHumidity());
Serial.print(',');
Serial.println(bme.readPressure());
}
void readTempDS() {
if (sensor.readTemp()) Serial.println(sensor.getTemp());
else Serial.println("DS18 error");
sensor.requestTemp();
}
static const uint8_t dsPin = D5
В microds18 пин не задаётся таким образом
А что за конструкция с запросом адреса в условии, и при else идёт request? Откуда это взято?)
И то и другое взято из твоих уроков https://kit.alexgyver.ru/tutorials/ds18b20/ Ну разве что там было "#define DS_PIN 2", но компилятору без разницы статическая константа или дефайн. Ведь компилируется и работает же.
Работа с BME из примера с гитхаба https://github.com/adafruit/Adafruit_BME280_Library/blob/master/examples/bme280_unified/bme280_unified.ino
тогда я не понимаю как вот это может компилироваться
static const uint8_t dsPin = D5;// GPIO14 пин датчика температуры
MicroDS18B20 tempSensor;
А... Не обратил внимание. Это почему-то гитхаб выкинул что в угловых скобках. Вроде нажал кнопочку "code". Первый раз что-то в гитхаб пишу.
static const uint8_t dsPin = D5;
MicroDS18B20<dsPin> tempSensor;
По моему примеру выше код работает? Если добавить необходимый запрос на народмон
Минимальный с пустым запросом на народмон работает. Если делаю полноценный проект (формирование страницы для локального отображения и прочее), то опять DS валится в это странное состояние.
Не могу найти у ДС ситуацию, в которой он зажимает шину и не отпускает. Может это пин есп шалит?
Поигрался с разными датчиками в итоговом проекте. Упростил запросы к BME. Достаточно не спрашивать адрес датчика DS и вроде всё работает нормально (длительно не проверял). Но самое интересное, что датчик, купленный в другом месте и в другое время работает, там где предыдущие падают в ошибку.
Который нормально работает:
{0x28, 0xAA, 0xA3, 0x65, 0x40, 0x14, 0x1, 0x59}
Падают в ошибку:
{0x28, 0xFF, 0x64, 0x01, 0xB2, 0x19, 0x53, 0x5D}
{0x28, 0xFF, 0x64, 0x01, 0xB2, 0x18, 0x11, 0x63}
{0x28, 0xFF, 0x64, 0x01, 0xBD, 0x68, 0x4A, 0x71}
И ещё раз перепроверил, что именно притягивает к нулю - именно пин DS.
Так что может быть это партия такая глючная (прилагаю фотку). А тот, который работает нормально, тот в герметичном корпусе.
Ну вот я выше кидал минимальный код для опроса и работы системы, ты пишешь
опять DS валится в это странное состояние
В итоге как дела то обстоят?)
Про тот "минимальный минимальный" я же написал, что он работает нормально. Код из самого первого поста в ветке стабильно роняет DS после первого же запроса к народмону. Проще забить болт, чем отлавливать баг, который работает только на определённом датчике. Может закрыть?
Можно
Специфическая, видимо, ситуация. Всё равно решил написать. ESP8266 собирает данные с bme280 и ds18b20 и отсылает данные на narodmon. Если народмон недоступен, то спотыкается на секунду. При этом ds зависает, притянув ногу к нулю и вообще ни на что не реагирует. Помогает только отключение питания или перевод ds на паразитное питание, тогда ds сам перезагружается, потеряв паразитное питание, замкнув пин данных, и проблемы как бы и нет. Ниже код, для получения этой ситуации. ESP тут в режиме точки доступа, но это не важно, главное, чтоб у неё интернета не было.