• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Баги/глюки/проблемы в каком-то конкретном примере из пакета Sming

Nikita

New member
Добрый день!

Проблема с WDT. Пример Temperature_DS1820. С самим примером все более менее корректно, он выполняется один раз, выбирает первый датчик, выводит температуру с него. В случае если датчиков несколько модифицировал пример так, чтобы выводилась информация не с одного а с нескольких датчиков по таймеру и за один раз. В моем случае имею 3 подключенных датчика. Столкнулся с проблемой, приложение вылетает по wdt reset, уже после чтения данных со второго датчика. Каждая итерация и правда выполняется долго, там задержка на 1 сек перед чтением каждого датчика. В случае, если за одну итерации выполняется чтение только одного датчика, в моем случае 1 - 1, 2 - 2, 3 - 3, 4 -1, и т.д. то проблем нет, все работает. Пожалуйста, подскажите, есть ли варианты решения проблемы с WDT кроме отключения его или разнесения выполнения чтения датчиков DS18B20 в разные итерации?

PS Не уверен, что выбрал правильную тему, прошу модераторов перенести вопрос в правильную, если не прав.
Система: Mac OS, устанавливал по инструкции пару недель назад, после этого обновлял только примеры.

*** Updated ***
Отвечу на свой вопрос сам, помогли расставленные в коде WDT.alive().
 
Последнее редактирование:

Nikita

New member
Пример Pressure_BMP180. Работает, но не понятно, как выбрать другие контакты для I2C? Это актуально для модулей с большим количеством контактов чем у esp-01, в частности, у меня esp-12. По умолчанию, SDA - GPIO2, SCL - GPIO0, но это не прописано в примере.
 

Okadzaki

New member
Пример Pressure_BMP180. Работает, но не понятно, как выбрать другие контакты для I2C? Это актуально для модулей с большим количеством контактов чем у esp-01, в частности, у меня esp-12. По умолчанию, SDA - GPIO2, SCL - GPIO0, но это не прописано в примере.
Wire.pins(SCL,SDA) задаёте, перед Wire.begin()
 

verzi

New member
В примере Temperature_DS1820 если оставить все как есть, то не работает. Или я не успеваю консоль открыть что бы увидеть вывод :(.
Если сделать так
Код:
#include <user_config.h>
#include <SmingCore/SmingCore.h>
#include <Libraries/OneWire/OneWire.h>

#define WORK_PIN 13 // GPIO0

OneWire ds(WORK_PIN);
Timer procTimer;
float heatsinktemp;

void getTemp()
{
        byte i;
        byte present = 0;
        byte type_s;
        byte data[12];
        byte addr[8];

        ds.begin(); // It's required for one-wire initialization!

        if (!ds.search(addr))
        {
            Serial.println("No addresses found.");
            Serial.println();
            ds.reset_search();
            delay(250);
            return;
        }

        Serial.print("Thermometer ROM =");
        for( i = 0; i < 8; i++)
        {
            Serial.write(' ');
            Serial.print(addr[i], HEX);
        }

        if (OneWire::crc8(addr, 7) != addr[7])
        {
          debugf("OneWire CRC is not valid!");
          return;
        }
        Serial.println();

        // the first ROM byte indicates which chip
        switch (addr[0]) {
        case 0x10:
          Serial.println("  Chip = DS18S20");  // or old DS1820
          type_s = 1;
          break;
        case 0x28:
          Serial.println("  Chip = DS18B20");
          type_s = 0;
          break;
        case 0x22:
          Serial.println("  Chip = DS1822");
          type_s = 0;
          break;
        default:
          Serial.println("Device is not a DS18x20 family device.");
          return;
        }

        ds.reset();
        ds.select(addr);
        ds.write(0x44, 1);        // start conversion, with parasite power on at the end

        delay(1000);     // maybe 750ms is enough, maybe not
        // we might do a ds.depower() here, but the reset will take care of it.

        present = ds.reset();
        ds.select(addr);
        ds.write(0xBE);         // Read Scratchpad

        Serial.print("  Data = ");
        Serial.print(present, HEX);
        Serial.print(" ");
        for ( i = 0; i < 9; i++)
        {
            // we need 9 bytes
            data[i] = ds.read();
            Serial.print(data[i], HEX);
            Serial.print(" ");
        }
        Serial.print(" CRC=");
        Serial.print(OneWire::crc8(data, 8), HEX);
        Serial.println();

        // Convert the data to actual temperature
        // because the result is a 16 bit signed integer, it should
        // be stored to an "int16_t" type, which is always 16 bits
        // even when compiled on a 32 bit processor.
        int16_t raw = (data[1] << 8) | data[0];
        if (type_s)
        {
            raw = raw << 3; // 9 bit resolution default
            if (data[7] == 0x10)
            {
              // "count remain" gives full 12 bit resolution
              raw = (raw & 0xFFF0) + 12 - data[6];
            }
        } else {
            byte cfg = (data[4] & 0x60);
            // at lower res, the low bits are undefined, so let's zero them
            if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
            else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
            else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
            //// default is 12 bit resolution, 750 ms conversion time
        }

        heatsinktemp = (float)raw / 16.0;
        Serial.print("  Temperature = ");
        Serial.print(heatsinktemp);
        Serial.println(" Celsius, ");
        return;

}

void init()
{
    Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
    Serial.systemDebugOutput(true); // Allow debug output to serial
    procTimer.initializeMs(2000, getTemp).start();

}
То все ОК. Но терзают меня смутные сомнения по поводу ds.begin(); вроде не место ему тут. А если его оставить в void init(), то вот эта часть срабатывает всегда, т.е. не отследить подключен ли датчик или нет.
Код:
if (!ds.search(addr))
    {
        Serial.println("No addresses found.");
        Serial.println();
        ds.reset_search();
        delay(250);
        return;
    }
Первый скриншот сделан с кодом приведенным выше. Сначала датчик подключен, потом выключен. Все корректно отображается.
1.png
Второй скриншот, когда ds.begin() внутри void init().
2.png
 

verzi

New member
И еще. Попытался объединить два примера. ScreenOLED_SSD1306 и Temperature_DS1820.
Код:
#include <user_config.h>
#include <SmingCore/SmingCore.h>
#include <Libraries/OneWire/OneWire.h>
#include <Libraries/Adafruit_SSD1306/Adafruit_SSD1306.h>

Timer lcdTimer;
Timer tempTimer;
OneWire ds(12);
float heatsinktemp;

/*
* Hardware SPI mode:
* GND      (GND)         GND
* VCC      (VCC)         3.3v
* D0       (CLK)         GPIO14
* D1       (MOSI)        GPIO13
* RES      (RESET)       GPIO16
* DC       (DC)          GPIO0
* CS       (CS)          GPIO2
*/
// For spi oled module
Adafruit_SSD1306 display(0, 16, 2);

//* For I2C mode:
// Default I2C pins 0 and 2. Pin 4 - optional reset
// Adafruit_SSD1306 display(4);

void lcdLoop(){
        display.clearDisplay();
        // text display tests
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(0,0);
        display.println(rand());
        display.display();

}

void tempLoop()
{
    ds.begin(); // It's required for one-wire initialization!

    byte i;
    byte present = 0;
    byte type_s;
    byte data[12];
    byte addr[8];

    if (!ds.search(addr))
    {
        heatsinktemp = -1;
        debugf("No DS18B20 sensor found.");
        ds.reset_search();
        delay(250);
        return;
    }

    // the first ROM byte indicates which chip
    switch (addr[0]) {
    case 0x10:
        type_s = 1; //Chip = DS18S20 or old DS1820
    break;
    case 0x28:
        type_s = 0; //Chip = DS18B20
    break;
    case 0x22:
        type_s = 0; //Chip = DS1822
    break;
    default:
        debugf("Device is not a DS18x20 family device.");
        return;
    }

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1); // start conversion, with parasite power on at the end

    delay(750); // maybe 750ms is enough, maybe not
    // we might do a ds.depower() here, but the reset will take care of it.

    present = ds.reset();
    ds.select(addr);
    ds.write(0xBE); // Read Scratchpad

    for ( i = 0; i < 9; i++)
    {
        data[i] = ds.read(); // we need 9 bytes
    }

    // Convert the data to actual temperature
    // because the result is a 16 bit signed integer, it should
    // be stored to an "int16_t" type, which is always 16 bits
    // even when compiled on a 32 bit processor.
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s)
    {
        raw = raw << 3; // 9 bit resolution default
        if (data[7] == 0x10)
        {
            // "count remain" gives full 12 bit resolution
            raw = (raw & 0xFFF0) + 12 - data[6];
        }
    }
    else
    {
        byte cfg = (data[4] & 0x60);
        // at lower res, the low bits are undefined, so let's zero them
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
        // default is 12 bit resolution, 750 ms conversion time
    }

    heatsinktemp = (float)raw / 16.0;
    Serial.println(heatsinktemp);
}
void init()
{
    Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
    Serial.systemDebugOutput(true); // Allow debug output to serial

    display.begin(SSD1306_SWITCHCAPVCC);

    display.display();
    delay(2000);

    // Clear the buffer.
    display.clearDisplay();

    // draw a circle, 10 pixel radius
    display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
    display.display();
    delay(2000);
    display.clearDisplay();

    // text display tests
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.println("Sming Framework");
    display.setTextColor(BLACK, WHITE); // 'inverted' text
    display.setCursor(104, 7);
    display.println("v1.0");
    //----
    display.setTextColor(WHITE);
    display.println("Let's do smart things");
    display.setTextSize(3);
    display.print("IoT");
    display.display();

    delay(2000);
    lcdTimer.initializeMs(2000, lcdLoop).start();
    tempTimer.initializeMs(1000, tempLoop).start();
}
По отдельности и датчик температуры и дисплей работают корректно. Прямо в этом коде. Если закомментировать одну из последних строчек которые запускают таймер дисплея или датчика. А вот вместе нет. Начальная заставка (та что про "Let's do smart things") на дисплее появляется и все на этом, дисплей не обновляется. При этом даже через последовательный порт было не подцепиться, при попытке законектиться esp вис. Только что скачал последний sming, виснуть перестал. В консоли никаких ошибок, только значения температуры. Пробовал и SPI и I2C дисплеи (разные). Sming как я уже писал последний, UDK v2.0.2. Пробовал запускать другие примеры работы с датчиком температуры (из ардуино), не работают. В общем, моих знаний явно не хватает для того что бы разобраться что тут не так.
 

JustACat

Moderator
Команда форума
verzi, а если вызвать lcdLoop прямо из tempLoop (в конце нее), без второго таймера отдельного?
Может просто они друг другу мешают, т.к. у вас у одного таймера 1 секунда, у второго 2 секунды - кратные интервалы получаются... (это догадки, я вообще без понятия, как оно внутри работает, если честно)
 

verzi

New member
Сами по себе несколько таймеров работают без проблем. Проблема в том, что после того как запускается опрос датчика температуры, дисплей перестает обновляться. Ваш совет проверил, не работает.
 

anakod

Moderator
Команда форума
Пока железа под рукой нет, но попробуйте сменить номера пинов - для I2C вызовом Wire.pins(..) или для DS18B20.
 

Def461

New member
Не получается отловить, что умудряется сбрасывать состояние GPIO

При инициализации 1wire или сбросе шины - получаю полный сброс регистров GPIO, любых.
Т.е. имеем лог."0" на GPIO, провел опрос датчиков - бац! GPIO сброшены.

В какую сторону копать?

P.S. Судя по всему у предыдущего оратора - тот же баг: после вызова 1wire отваливаются настроенные регистры у других протоколов.
 
Последнее редактирование:

Nikita

New member
При инициализации 1wire или сбросе шины - получаю полный сброс регистров GPIO, любых.
Подтверждаю, при инициализации 1wire пропадает соединение с MQTT и больше не поднимается. После исключения из проекта кода относящееся к 1wire, опрос dht22 и bmp180 и публикация их результатов через MQTT работает сутками без проблем и сбоев.
 

Nikita

New member
Еще одна проблема. Пробую использовать функцию system_get_vdd33() для чтения напряжения питания на esp, каждый вызов возвращает результат 1023. Если использую не ту функцию, пожалуйста, напишите корректную.
 

pvvx

Активный участник сообщества
Еще одна проблема. Пробую использовать функцию system_get_vdd33() для чтения напряжения питания на esp, каждый вызов возвращает результат 1023. Если использую не ту функцию, пожалуйста, напишите корректную.
2C-ESP8266__SDK__Programming Guide__EN_v1.1.2.pdf:
Function: system_get_vdd33
Measure the power voltage of VDD3P3 pin 3 and 4, unit:1/1024 V
Note:
• system_get_vdd33 can only be called when TOUT pin is suspended
• The 107th byte in esp_init_data_default.bin(0〜~127byte)is named as “vdd33_const“ , when TOUT pin is suspended vdd33_const must be set as 0xFF, that is 255.
По русски - в зависимости как установлена данная константа (107 байт в esp_init_data_default.bin), то работает или system_get_vdd33() или system_adc_read().
На сегодня, одновременно использовать в одном приложении чтение ADC и VDD можно только в моей Web свалке.
vdd_adc.gif rf_data3.gif adc_vdd.gif
Пробуйте использовать uint32 readvdd33(void) вместо system_get_vdd33() и сами пересчитывайте (калибруйте) коэффициент перевода в Вольты - он зависит от номинала резистора припаянного к ноге TOUT и от типа модуля (у ESP-01 вывод TOUT никуда не подключен)... Процесс измерения VDD в чипе происходит путем подачи на ножку TOUT тока внутренним ключом и замером полученного напряжения на ней.
 
Последнее редактирование:

Def461

New member
Таймер, установленный на 600*1000 ms интервал, срабатывает не раз в 10 минут, а раз в шесть.
Вроде ограничения для таймера быть не должно :(
Таймер на 120 секунд взводится идеально, на 600 - некорректно.
Код:
logserversTSTimer.initializeMs(600*1000, logserversTSUpdate).start();
 
Последнее редактирование:

FGX

Member
Таймер, установленный на 600*1000 ms интервал, срабатывает не раз в 10 минут, а раз в шесть.
Вроде ограничения для таймера быть не должно :(
Таймер на 120 секунд взводится идеально, на 600 - некорректно.
Код:
logserversTSTimer.initializeMs(600*1000, logserversTSUpdate).start();
Так сделайте таймер на 1 минуту, в нем заведите переменную и инкрементируйте ее при каждом вызове, как дойдет до 10 делайте что хотели и сбросьте ее в 0.. Зачем заводить кучу таймеров с разным временем, можно пару завести на 1с и 1 минуту, например, и делать все что хотели в них смотря на доп переменные.
 

Def461

New member
Так сделайте таймер на 1 минуту, в нем заведите переменную и инкрементируйте ее при каждом вызове, как дойдет до 10 делайте что хотели и сбросьте ее в 0.. Зачем заводить кучу таймеров с разным временем, можно пару завести на 1с и 1 минуту, например, и делать все что хотели в них смотря на доп переменные.
Как решать вопрос при одном таймере на всю систему - я знаю.
Не вижу смысла изобретать костыли, если framework подразумевает множественное количество таймеров штатными средствами.

Кстати, вопрос был не в нескольких таймерах, а в том, что период в 120 секунд отрабатывает корректно, а этот же таймер на 600 - нет.
 

FGX

Member
Кстати, вопрос был не в нескольких таймерах, а в том, что период в 120 секунд отрабатывает корректно, а этот же таймер на 600 - нет.
Я думаю, что таймер нельзя задавать на бесконечно большой интервал, на 1 час, например, может просто кончился его предел. Я поэтому и предложил получить 10 минут из таймера на 1 минуту, тем более проверить переменную на мой взгляд проще для системы в целом чем делать кучу таймеров.
 

Def461

New member
В примерах есть гораздо бОльшие интервалы, нежели 10 минут.
Потому я и задал вопрос, что изменилось в коде библиотек, что таймер может не работать на разумном интервале.
 

pvvx

Активный участник сообщества
@anakod не помогает это с WDT в новых SDK https://github.com/anakod/Sming/blob/master/Sming/system/flashmem.c#L100
Стирание в spiffs на 16Mбайт Flash делать в цикле нельзя. Отключается WiFi и т.д. Делал стирание flash блоками по 64к. Без остановки WDT pp_soft_wdt_stop() и рестарта pp_soft_wdt_restart() не катит. Сильно не вдавался, но и остановка не решает проблемы вылета цикла по WDT. Требуется обновление вызова pp_soft_wdt_stop() через некоторое время...
В общем spiffs не подходит к концепции оф. SDK. Надо включать второй процесс по типу RTOS, но простой - всего 2 - SDK и всё остальное :)
PS: NodeMCU это Ад. не берите от туда ничего - смотреть можно, но копировать - нет.
 
Последнее редактирование:

Def461

New member
Еcть продолжение цирка с 1wire
Библиотекой затрагивается именно GPIO14, даже если работа с далласами назначена на другой порт.

Т.е. сегодня перекомпилил работу реле с GPIO14 на GPIO16 - при опросе 18В20 GPIO16 не затрагивается
А вот I2C на "стандартных" GPIO12/14 перестает норально работать ровно после инициализации комплектной библиотеки 1Wire.

UPD: "Обошел" глюк костылём корявой работы с регистрами.
Обнаружил второй интересный глюк: если модуль рестартует после прошивки с зажатым "ресетом", то I2C библиотека не может нормально "дергать" GPIO.
 
Последнее редактирование:
Сверху Снизу