• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Умный дом для чайника

Сергей_Ф

Moderator
Команда форума
@Alexey N с чего Вы взяли, что код не срабатывает? Все отработало как написано в коде, как я вижу. Вы чего хотели добиться своим кодом? У вас получилось что если датчик не запустился, то esp уходит в бесконечный цикл (и срабатывает сторожевой таймер). Все так и работает.
 

Alexey N

Member
@Сергей_Ф, Вы правы. А я неверно описал свою проблему. Код срабатывает, датчик не запускается и esp уходит в бесконечный цикл. Так и есть. Но мне-то надо, чтобы датчик запустился. И причину, по которой он не запускается я не могу найти.
Пробовал запустить код из примера для библиотеки Adafruit-BMP085-Library-master без подключения других библиотек. Результат такой же. Датчик то запускается, то не запускается. Причем, если он не запустился, то больше не запустится даже после многочисленных ресетов. После отключения DS3231 все сразу начинает работать. Путем отсоединения отдельных проводов установил, что можно отключить только пин SDA на модуле времени, и тогда датчик давления будет прекрасно запускаться. Но мне то надо, чтобы и часы были.
 

Сергей_Ф

Moderator
Команда форума
@Alexey N а Вы свой код не хотите показать? Что бы не заниматься гаданием на кофейной гуще.
А случаем адреса i2c не совпадают?
 

Сергей_Ф

Moderator
Команда форума
@Alexey N судя по всему на SDA у Вас "зависает" низкий уровень, а значит шина занята. И держит его модуль часов, если при отсоединении его шина SDA освобождается.
Тут либо Вы не закончили обмен с модулем часов, либо баг библиотеки (мало вероятно), либо адрес одинаков и "кто первый встает, того и тапки".
 

Alexey N

Member
Если бы кто-то согласился посмотреть код, было бы замечательно. Просто на данный момент это уже простыня на 400 строк и мне неудобно просить копаться в этом. Приведу начало кода, где инициализируются библиотеки и переменные и сетап. И где, собственно, и вываливается ошибка. Надеюсь, что этого хватит. Про обмен с часами не очень понятно, ведь ошибка происходит на самом старте при запуске датчика давления, еще до запуска часов.
Вот результат работы I2C сканнера. Вроде все видит нормально и по разным адресам.
Scanning...
I2C device found at address 0x57 !
I2C device found at address 0x68 !
I2C device found at address 0x77 !
done



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

Код:
#include <Wire.h>
#include "DHT.h"
#include <Adafruit_BMP085.h>
#include "RTClib.h"
#include "FS.h"
#include <ESP8266WiFi.h>

//+++++++++++++++++++++++++++++++++++++++++++++++++++

//переменные

#define DHTTYPE DHT22  // тип датчика - DHT22
#define DHTPIN 13     // на ногу D7 повесим датчик.

// объявим глобальные переменные влажности и температуры
float humidity_room = 0.0; // глобальная переменная влажность

float temp_room = 0.0; // глобальная переменная температура

//  Инициируем датчик DHT22. С него будем снимать влажность
// и температуру
DHT dht(DHTPIN, DHTTYPE);

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Теперь добавим датчик давления.
// Пин SDA подключаем к D2, пин SDL - к D1

Adafruit_BMP085 bmp;
float pressure = 0.0; // глобальная переменная давления
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Добавляем часы реального времени
// Пин SDA подключаем к D2, пин SDL - к D1

RTC_DS3231 rtc;
// Массив для вывода дня недели
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Все необходимое для WiFi
const char* ssid = "**************";                //  имя WiFi сети
const char* password = "**************";        //  пароль от WiFi
IPAddress ip(192, 168, 0, 8);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
const int port = 80;                           //  port to serve pages through
WiFiServer server(port);

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void setup() {
  Serial.begin(9600); // Откроем сом порт

//  Wire.begin();

  // Запускаем датчик давления
  if (!bmp.begin()) {
    Serial.println("Problem with sensor bmp180!");
    while (1) {}
  }

  // Запускаем датчик температуры
  dht.begin();

  // Запускаем часы
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  // Запускаем файловую систему
  SPIFFS.begin();

  // Запускаем сервер и подключаемся к беспроводной сети
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);                    //  connect to WiFi network
  WiFi.config(ip, gateway, subnet);
  while (WiFi.status() != WL_CONNECTED) {        //  wait until connected
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  server.begin();                                // Start the server
  Serial.println("Server started");
  Serial.println(WiFi.localIP());                // Print the servers IP address
}
 
Последнее редактирование:

=AK=

New member
Я не вижу, каким образом библиотеки узнают, какой пин SDA, а какой SCL. Это должно где-то задаваться. Если это зашито намертво прямо в библиотеку, то непонятно, годится ли такая библиотека для ESP.

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

Сергей_Ф

Moderator
Команда форума
@Alexey N попробуйте сначала часы проинициализировать. Получить всё что от них нужно при старте, затем прекратить общение с RTC и инициализировать датчик давления.
Надо библиотеки смотреть какие пины используются для I2C для каждого устройства - может там конфликт. Тогда надо библиотеку(ки) править. Как вариант, посадить на разные пины i2c RTC и датчика.
P/S/ Если сканер работает, значит дело в библиотеках 99%. Ведь тогда не зависает ничего, не так ли?
 
Последнее редактирование:

tretyakov_sa

Moderator
Команда форума
А вот код, который должен запускать датчик давления:

if (!bmp.begin()) {
Serial.println("Problem with sensor bmp180!");
while (1) {}
}
И вот он-то и не срабатывает. Я пробовал менять очередность инициализации часов и датчика давления - без результата. Пробовал ставить другой модуль часов, на тот вариант, что глюк в самом модуле. Не могу понять, что вызывает ошибку и где ее искать.
while (1) {}
Вот этот цикл зачем? Он и валит всю систему.
 

tretyakov_sa

Moderator
Команда форума
Не могу найти в интернете описание похожей проблемы. У людей прекрасно одновременно работают и датчик давления и часы и еще куча всего на I2C. И просто не могу даже понять, что вообще может в моем случае не работать.
// Wire.begin(); Почему запуск I2C за комментирован ?
 

Alexey N

Member
Что-то вообще ничего не понимаю. @Сергей_Ф, после Вашего PS еще раз вгрузил скетч сканера и получил ошибку:
I2C Scanner
Scanning...
Unknow error at address 0x01
и т.д. ...


После очередного дурацкого передергивания модуля часов все заработало, и работает стабильно даже после перезагрузки О_0.
Если часы в сетапе инициализировать первыми, то тогда еще интереснее. Они тоже не инициализируются, и ЕСП уходит в бесконечную перезагрузку. Но код старта датчика давления все равно выполняется (неудачно):

RTC lost power, lets set the time!
Problem with sensor bmp180!

Soft WDT reset

ctx: cont
sp: 3fff0210 end: 3fff0420 offset: 01b0


Про библиотеки. Я готов разбираться в библиотеках, править их, только знать бы с чего начинать.
Вот на странице библиотеки для часов GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC library есть таблица совместимости библиотеки с разными микроконтроллерами. Для ESP8266 следующее примечание: SDA/SCL default to pins 4 & 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL). То есть используются стандартные ЕСПшные пины для i2c. Для NodeMCU они выведены на пины Д2 и Д1. Для библиотеки датчика давления я не нашел какие пины используются, но в ней просто написано, что используется i2c.
Вот код для функции bmp.begin(). Вроде вернуть ошибку она может только в том случае, если не выполняется условие в строке 8. А что это за условие я уже не могу разобраться.
Код:
boolean Adafruit_BMP085::begin(uint8_t mode) {
  if (mode > BMP085_ULTRAHIGHRES)
    mode = BMP085_ULTRAHIGHRES;
  oversampling = mode;

  Wire.begin();

  if (read8(0xD0) != 0x55) return false;

  /* read calibration data */
  ac1 = read16(BMP085_CAL_AC1);
  ac2 = read16(BMP085_CAL_AC2);
  ac3 = read16(BMP085_CAL_AC3);
  ac4 = read16(BMP085_CAL_AC4);
  ac5 = read16(BMP085_CAL_AC5);
  ac6 = read16(BMP085_CAL_AC6);

  b1 = read16(BMP085_CAL_B1);
  b2 = read16(BMP085_CAL_B2);

  mb = read16(BMP085_CAL_MB);
  mc = read16(BMP085_CAL_MC);
  md = read16(BMP085_CAL_MD);
#if (BMP085_DEBUG == 1)
  Serial.print("ac1 = "); Serial.println(ac1, DEC);
  Serial.print("ac2 = "); Serial.println(ac2, DEC);
  Serial.print("ac3 = "); Serial.println(ac3, DEC);
  Serial.print("ac4 = "); Serial.println(ac4, DEC);
  Serial.print("ac5 = "); Serial.println(ac5, DEC);
  Serial.print("ac6 = "); Serial.println(ac6, DEC);

  Serial.print("b1 = "); Serial.println(b1, DEC);
  Serial.print("b2 = "); Serial.println(b2, DEC);

  Serial.print("mb = "); Serial.println(mb, DEC);
  Serial.print("mc = "); Serial.println(mc, DEC);
  Serial.print("md = "); Serial.println(md, DEC);
#endif

  return true;
}
 
Последнее редактирование:

Alexey N

Member
// Wire.begin(); Почему запуск I2C за комментирован ?
Потому что в каждой функции bmp.begin() и rtc.begin() уже есть вызов этой функции. И я решил, что эта строка лишняя. Хотя я пробовал и с этой строкой. Результат один и тот же.
while (1) {} эту строку я взял из примера, идущего к библиотеке датчика давления. И опять же тогда непонятно почему при убранных часах ничего не валится? А такая же строка в коде

if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}

ничего не валит. И while (1) выполняется только в том случае, если датчик давления не запустился. То есть при нормальном запуске она и не должна выполняться.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@Alexey N а не думаете что RTC просто глючный? Заменить не пробовали?

попробуйте заменить ваши конструкции для всех устройств i2c
Код:
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
на
Код:
while (! rtc.begin()) {
Serial.println("Couldn't find RTC");
delay (500);
}
может так прорвется.
 

Alexey N

Member
@Сергей_Ф, код заменил. Снова бесконечный цикл, только не с перезагрузкой, а с выводом ошибки. То есть функция bmp.begin() так и возвращает ошибку.
Снова, возвращаясь к коду из библиотеки для датчика давления. Простенький код, в котором есть только инициализация датчика и считывание показаний. Не срабатывает, если к i2c подключены часы. Они никак не упоминаются в коде, к ним нет никаких обращений. Они просто подключены. Датчик давления не запускается. Если опять подумать, что пин sda с модуля часов постоянно что-то выдает? Можно это как-то проверить? Скетчем или просто тестером? И еще остается вариант перейти на более низкий уровень и обращаться к датчикам не через библиотеки, а через wire.transmission. Но я пока не знаю как это сделать.
 

Сергей_Ф

Moderator
Команда форума
что пин sda с модуля часов постоянно что-то выдает? Можно это как-то проверить? Скетчем или просто тестером?
просто тестером (лучше осцилографом) - низкий уровень == шина занята. Попробуйте замерить до и после инициализации модуля. Всё кроме RTC выкиньте, оставьте скетч с часами только. Если до обращений низкий, после высокий - то нужно инициализировать первым. Если всегда низкий - брак. Если всегда высокий и низкий тоько во время обмена данными - застрелиться. Шутка.
Также проверьте работу модуля без библиотеки со скетчами из примеров.
По поводу низкого уровня можно почитать Kolban’s book on the ESP8266 | Neil Kolban Tech + datasheet на устройства, но лучше библиотеку найти правильную, если RTC живой.
 

=AK=

New member
Если бы кто-то согласился посмотреть код, было бы замечательно.

Код:
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Теперь добавим датчик давления.
// Пин SDA подключаем к D2, пин SDL - к D1

Adafruit_BMP085 bmp;
float pressure = 0.0; // глобальная переменная давления
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Добавляем часы реального времени
// Пин SDA подключаем к D2, пин SDL - к D1

RTC_DS3231 rtc;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void setup() {
  Serial.begin(9600); // Откроем сом порт

//  Wire.begin();

  // Запускаем датчик давления
  if (!bmp.begin()) {
    Serial.println("Problem with sensor bmp180!");
    while (1) {}
  }

  // Запускаем часы
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
Посмотрел библиотеку часов. Она базируется на I2C библтотеке Wire, которая работает на выделенных I2C пинах.

Функция rtc.begin() всегда возвращает true, поэтому проверка не имеет никакого смысла. В самой функции только вызывается Wire.begin(), больше ничего не делается.

Код:
boolean RTC_DS3231::begin(void) {
Wire.begin();
return true;
}
Скорей всего bmp.begin() делает то же самое. Получается, что вызывая bmp.begin() и rtc.begin() вы дважды вызываете Wire.begin(), что может быть не очень хорошо.

Проблема может быть в том, что библиотеки часов и датчика давления используют одну и ту же библиотеку Wire. А библиотека Wire, насколько я вижу, обладает собственной памятью, т.е. что-то хранит после того, как ею пользовались.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@=AK= если я правильно понял, датчик не работает и в том случае, если библиотеки rtc нет вообще. Просто параллельно подключен модуль rtc и работа сбивается.
 

Сергей_Ф

Moderator
Команда форума
В самой функции только вызывается Wire.begin(), больше ничего не делается.
В таком случае, вызов rtc.begin() просто не нужен, если перед этим была инициализация bmp.begin().
А вот там выполняется условие
if (read8(0xD0) != 0x55) return false;
Как я понял из регистра d0 считывается значение, и если оно равно 0х55 то считается, что датчик работает. Что это за регистр, надо курить даташит. Но мне кажется, что дело не в нем, а в модуле rtc, который шину блокирует.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@Alexey N а покажите схему, как rtc подключен. Очень похоже что глбк аппаратный. Может что то не так полцепили. И описание посмотрите на него, там некоторые ножки подтягивать надо к земле или +.
 

Alexey N

Member
@=AK= если я правильно понял, датчик не работает и в том случае, если библиотеки rtc нет вообще. Просто параллельно подключен модуль rtc и работа сбивается.
Совершенно верно. И я тоже склоняюсь все больше к тому, что глюк в железе. Писал уже выше, что пробовал менять модули RTC. Я их в свое время заказывал пять штук, так вот вчера попробовал прогнать все пять штук. Результат одинаковый. Менял провода, ЕСП, макетную плату. Результат одинаковый.
Прикрепил картинку со схемой. Накидал за пару минут, поэтому она не очень красивая, но надеюсь понятная. Там вроде все сильно просто.
А вот про подтяжку ног это похоже в правильном направлении мысль. Курю интернеты и натолкнулся на такую информацию, что у bmp180 и ds3231 разные логические уровни. 3,3 и 5,0 вольт соответственно. Это если я правильно понимаю английский. Пока непонятно относится ли это только к "голым" микросхемам. У меня эти датчики в виде шилдов с уже имеющейся обвязкой. И питаются от 3,3 вольт с NodeMCU. Нужно ли в таком случае согласование уровней или подтягивающие регистры, или наоборот надо удалять лишние пока не разобрался.

 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@Alexey N
Как подключить часы реального времени к Arduino
Код:
Часы подключаются по протоколу I2C всего двумя проводами. Необходимо дополнительно подтянуть выводы, к которым подключаются часы к рельсе питания с помощью резисторов 2 КОм.
Где у Вас подтяжка ???!!!! Поставьте резисторы и будет всё работать.
SCL -> 2кОм-> +3.3v и SDA ->2кОм-> +3.3v
 
Сверху Снизу