Привет.
Самостоятельно потратил уже около двух недель на поиск бага - не могу ничего сам решить… спасайте
Бы ла у меня программа, которая собирала данные с UART и 3х датчиков по i2c и с борта ESP8266 отправляла данные в “народный мониторинг”. OK.
Около 2х лет это работало, но вот я решил что-то доработать в программе и она посыпалась. Я взял скетч за 2021г - компилирую новой IDE - не работает. Переношу код на другую ESP8266 - не работает. Переношу на Arduino nano - не работает.
Физически все датчики подключены. i2c тестер проходят всегда. Осцилофограмма красивая. Адреса казаны правильно.
Думаю, что все дело в программе. Начинаю делить и получаю такой результат:
BME680 - самостоятельно работает
CCS811 - самостоятельно работает
HDC1080 - самостоятельно работает
BME680 + HDC1080 - вместе работает
только подключаю опрос CCS811 - програма крашится. В лучшем случае плюется мусором в порт но может и зависнуть.
Начинаю думать, что или библиотеки конфликтуют или оперативной памяти не хватает.
Но как локализовать проблему и/или ее решить?
void setup() {
pinMode(13,OUTPUT);
Serial.begin(115200);
MyI2Csetup();
Testi2c();
// Serial.println("BME680 test"); Serial.flush(); MyBME680setup();
// Serial.println("CCS811 test"); Serial.flush(); CCS811setup();
Serial.println("HDC1080 test"); Serial.flush(); StartHDC1080();
}
void loop() {
digitalWrite(13, !digitalRead(13));
// TestBME680(); delay(1000);
// CCS811read(); delay(1000);
ReadHDC1080(); delay(1000);
}
b707
12.Апрель.2023 13:13:24
2
Для начала выложите полный код.
А также приведите сообщения об ошибках. И опишите подробнее, чтьо означает “программа не работает”
Полный код состоит из файлов соотвествующих библиотек + “мои файлы” - это код типа Serialprintln(readDatchik()); Причем “мой” код основан на примерах из интернета.
Всего около 15 файлов.
Скетч компилируется и ошибок не выдает. В программе тоже ошибок как таковых нет.
Если программа работает - это опрос датчика один раз в несколько секунд и в терминал выплевывается стандартная "температура = 23 влажность =40 ". Дуешь на датчик - значения меняются.
Если в моем примере расскоментировать только 1 датчик - данные идут непрерывно и логично.
Если расскоментировать датчик CCS811 и еще один, но вместо данных CCS811 начинает идти мусор. Как будто терминал глотает какие то символы. При этом еще один датчик показывает логичные данные.
Если расскоментировать все датчики - программа может зависнуть. Т.е. в терминале видно, что прошла иннициализация i2c, прочитались все адреса, и все. НИЧЕГО нет. Данные в терминал не идут. Светодиод на плате не моргает.
BME680 один отдает данные:
Датчик CC811 один отдает данные:
Датчик HDC1080 один отдает данные:
Датчик HDC1080 и BME680 вместе отдают данные
Датчик CC811 и BME680 вместе работают:
Зависание программы, когда все три датчика раскоментированы.
Прошел мусор с CC811 и программа зависла:
(когда датчик один - работает стабильно)
b707
12.Апрель.2023 14:36:15
10
@Veoramid
Без полного кода я не вижу ни малейшего шанса как-то вам помочь. Может кто-то другой сможет…
Удачи в ваших проектах.
nik182
12.Апрель.2023 17:08:39
12
На сторонние ресурсы здесь не ходят.
Основной скетч
#include "MyI2C.h"
#include "MyHDC1080.h"
#include "MyBME680.h"
#include "MyCCS811.h"
#include <avr/wdt.h>
// Переменные, создаваемые процессом сборки, // http://microsin.net/programming/avr/arduino-determining-amount-free-and-used-ram.html
// когда компилируется скетч
extern int __bss_end;
extern void *__brkval;
// Функция, возвращающая количество свободного ОЗУ (RAM)
int memoryFree()
{
int freeValue;
if((int)__brkval == 0)
freeValue = ((int)&freeValue) - ((int)&__bss_end);
else
freeValue = ((int)&freeValue) - ((int)__brkval);
return freeValue;
}
void setup() {
pinMode(13,OUTPUT);
Serial.begin(115200);
MyI2Csetup();
Testi2c();
wdt_reset();
Serial.println("BME680 test"); Serial.flush(); MyBME680setup(); Serial.print(F("memoryFree1()=")); Serial.println( memoryFree() );
wdt_reset();
Serial.println("HDC1080 test"); Serial.flush(); StartHDC1080(); Serial.print(F("memoryFree2()=")); Serial.println( memoryFree() );
wdt_reset();
Serial.println("CCS811 test"); Serial.flush(); CCS811setup(); Serial.print(F("memoryFree3()=")); Serial.println( memoryFree() );
}
void loop() {
digitalWrite(13, !digitalRead(13));
TestBME680(); delay(1000); Serial.print(F("memoryFree4()=")); Serial.println( memoryFree() );
ReadHDC1080(); delay(1000); Serial.print(F("memoryFree5()=")); Serial.println( memoryFree() );
CCS811read(); delay(1000); Serial.print(F("memoryFree6()=")); Serial.println( memoryFree() );
delay(1);
}
My!2C.h
#include <Wire.h>
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MyI2Csetup(void) {
Wire.begin();
//Wire.begin(cSDA, cSCL); /* задаем i2c мост через контакты SCL=D1 и SDA=D2 на NodeMCU */
//Wire.begin(SCL, SDA); /* задаем i2c мост через контакты SDA=D1 и SCL=D2 на NodeMCU */
delay(500);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Testi2cDevice(byte adress) {
Wire.beginTransmission(adress);
byte n = 1;
byte d;
//Wire.Write(i);
//error = Wire.endTransmission();
for (byte i = 0; i <= 10; i++)
{
Wire.requestFrom(adress, n);
if ( Wire.available() ) { d = Wire.read(); Serial.print(d,HEX); }
else return;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Testi2c(void)
{
byte error, address;
int nDevices;
Serial.println(F("\nI2C Scanner"));
Serial.println(F("Scanning..."));
nDevices = 0;
for(address = 1; address < 127; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(F("I2C device found at address 0x"));
if (address<16) Serial.print(F("0")); Serial.print(address,HEX);
switch (address)
{
case 0x77: Serial.print(F(" BME680")); break;
case 0x40: Serial.print(F(" HDC1080")); break;
case 0x5A: Serial.print(F(" CCS811")); break;
}
Serial.print(" ! "); Testi2cDevice(address); Serial.println();
nDevices++;
}
else if (error == 4)
{
Serial.print(F("Unknow error at address 0x")); if (address<16) Serial.print(F("0")); Serial.println(address,HEX);
}
}
if (nDevices == 0) Serial.println(F("No I2C devices found\n"));
else Serial.println(F("done\n"));
Wire.endTransmission();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MyBME680.h
/*
* https://arduino.ua/ru/prod4512-modyl-datchika-kachestva-vozdyha-bme680-i2c5v
*/
#define cBME680_adress 0x77
// - - - - - - - - - - - - - - - - - - -
// Датчик качества воздуха #1
//
#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h> // Библиотека BME680
#define SEALEVELPRESSURE_HPA (1014.58) // Высота над уровне моря
Adafruit_BME680 bme680; //i2C // Объект
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct struct_BME680 // Структура данных
{
boolean BME680ok = false;
float Temp; // Температура
float Humi; // Влажность
float Alti; // Высота
float pkPa; // Давление кПа
float pmmH; // Давление mmH
float Ohms; // VOC [Ом]
float KOhm; // VOC [КОм]
float VOC0100; // VOC [%]
unsigned long PWM1023; // VOC [AO%]
} var_struct_BME680; // Переменная труктурная
void MyBME680setup(void);
void TestBME680(void);
void OutText(void);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MyBME680setup(void) {
// - - - - - - - - - - - - - - - - -
//Serial.println(F("BME680 test"));
Serial.println(F("BME680: init Begin 1")); Serial.flush();
// var_struct_BME680.BME680ok = bme680.begin(BME680_adress,true);
var_struct_BME680.BME680ok = bme680.begin(cBME680_adress);
Serial.println(F("BME680: init Begin 2"));
if (!var_struct_BME680.BME680ok) {
Serial.println(F("BME680: Could not find a valid BME680 sensor, check wiring!"));
// var_struct_BME680.BME680ok = bme680.begin(BME680_adress,true);
//while (1); // зависание
Serial.println(F("BME680: init fiasko"));
return;
}
if (var_struct_BME680.BME680ok)
{
// Set up oversampling and filter initialization
bme680.setTemperatureOversampling(BME680_OS_8X);
bme680.setHumidityOversampling(BME680_OS_2X);
bme680.setPressureOversampling(BME680_OS_4X);
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme680.setGasHeater(320, 150); // 320*C for 150 ms
}
Serial.println(F("BME680: init End"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TestBME680(void){
static unsigned long OldMillisBME;
unsigned long NewMillisBME = millis();
if ( ((NewMillisBME - OldMillisBME) > 4999) )
{
OldMillisBME = NewMillisBME;
if (! bme680.performReading() ) {
Serial.println(F("BME680: Failed to perform reading :("));
var_struct_BME680.Temp = -9.9;
var_struct_BME680.Humi = -9.9;
var_struct_BME680.pkPa = -9.9;
var_struct_BME680.KOhm = -9.9;
var_struct_BME680.Alti = -9.9;
return;
}
var_struct_BME680.Temp = bme680.temperature; //Serial.print("Temperature = "); Serial.print(bme.temperature); Serial.println(" *C");
var_struct_BME680.Humi = bme680.humidity; //Serial.print("Humidity = "); Serial.print(bme.humidity);Serial.println(" %");
var_struct_BME680.pkPa = (bme680.pressure / 100.0);///1000.0; //Serial.print("Pressure = "); Serial.print(bme.pressure / 100.0); Serial.println(" hPa");
var_struct_BME680.Ohms = bme680.gas_resistance; //Serial.print("Gas = "); Serial.print(bme.gas_resistance / 1000.0);Serial.println(" KOhms");
var_struct_BME680.Alti = bme680.readAltitude(SEALEVELPRESSURE_HPA); //Serial.print("Approx. Altitude = "); Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));Serial.println(" m"); Serial.println();
//var_struct_BME680.pmmH = (var_struct_BME680.pkPa * 760.0) / 101.325; // mmH ????
var_struct_BME680.pmmH = var_struct_BME680.pkPa * 0.75006375541921; // mmH
var_struct_BME680.KOhm = var_struct_BME680.Ohms / 1000.0; //Serial.print("Gas = "); Serial.print(bme.gas_resistance / 1000.0);Serial.println(" KOhms");
var_struct_BME680.VOC0100 = map(var_struct_BME680.Ohms, 0, 300000, 100, 0 ); // Пересчет в проценты 100...0
var_struct_BME680.PWM1023 = map(var_struct_BME680.Ohms, 0, 110000, 0, 1023); // Пересчет в проценты 0...1023
// OutGraph(&var_struct_All);
OutText();
//Serial.println();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OutText(void){
Serial.print(F("BME680: "));
Serial.print(F("Temperature = ")); Serial.print(var_struct_BME680.Temp); Serial.print(" *C ");
Serial.print(F("Humidity = ")); Serial.print(var_struct_BME680.Humi); Serial.print(" % ");
Serial.print(F("Pressure = ")); Serial.print(var_struct_BME680.pkPa); Serial.print(" hPa ");
Serial.print(F("Gas = ")); Serial.print(var_struct_BME680.KOhm); Serial.print(" KOhms ");
Serial.print(F("Approx. Altitude = ")); Serial.print(var_struct_BME680.Alti); Serial.print(" m ");
Serial.println();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OutText(struct_BME680 *BME680){
Serial.print(F("Temperature = ")); Serial.print(BME680->Temp); Serial.println(" *C");
Serial.print(F("Humidity = ")); Serial.print(BME680->Humi); Serial.println(" %");
Serial.print(F("Pressure = ")); Serial.print(BME680->pkPa); Serial.println(" hPa");
Serial.print(F("Gas = ")); Serial.print(BME680->KOhm); Serial.println(" KOhms");
Serial.print(F("Approx. Altitude = ")); Serial.print(BME680->Alti); Serial.println(" m");
Serial.println();
}
MyCC811.h
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
void CCS811setup(void);
void CCS811read(void);
void CCS811setup(void){
Serial.println("CCS811: Begin Setup 1"); Serial.flush();
if(!ccs.begin(0x5A)){
Serial.println("CCS811: Failed to start sensor! Please check your wiring."); Serial.flush();
// ESP.restart();
while(0);
}
Serial.println("CCS811: Begin Setup 2"); Serial.flush();
// Wait for the sensor to be ready
while(!ccs.available());
}
void CCS811read(void){
Serial.println(F("CCS811: Begin")); Serial.flush();
if(ccs.available()){
Serial.println(F("CCS811: Датчик есть ")); Serial.flush();
if(!ccs.readData()){
Serial.println(F("CCS811: ДА прочитали данные ")); Serial.flush();
word vCO2 = ccs.geteCO2();
word vVOC = ccs.getTVOC();
Serial.print(F("CCS811: CO2: ")); Serial.print(vCO2); Serial.print(F("ppm, TVOC: ")); Serial.println(vVOC); Serial.flush();
}
else{
Serial.println(F("CCS811: ERROR!")); Serial.flush();
return;
//while(1);
}
}
else {Serial.println(F("СС811: Датчик не готов")); Serial.flush();}
Serial.println(F("CCS811: End")); Serial.flush();
}
MyHDC1080.h
// - - - - - - - - -
// https://www.youtube.com/watch?v=t1vCKlzr2W8
#include "ClosedCube_HDC1080.h"
#define hdc1080_adress 0x40
ClosedCube_HDC1080 hdc1080;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct struct_HDC1080 // Структура данных
{
boolean HDC1080ok = false;
float Temp = -9.99; // Температура
float Humi = -9.99; // Влажность
} var_struct_HDC1080; // Переменная труктурная
void printSerialNumber(void);
void StartHDC1080(void);
void ReadHDC1080(void);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StartHDC1080(void)
{
// Default settings:
// - Heater off
// - 14 bit Temperature and Humidity Measurement Resolutions
hdc1080.begin(hdc1080_adress);
word m_id = hdc1080.readManufacturerId();
word d_id = hdc1080.readDeviceId();
Serial.println(F("HDC1080: "));
Serial.print(F("Manufacturer ID=0x")); Serial.println(m_id, HEX); // 0x5449 ID of Texas Instruments
Serial.print(F("Device ID=0x")); Serial.println(d_id, HEX); // 0x1050 ID of the device
if (m_id == 0x5449) { var_struct_HDC1080.HDC1080ok = true; }
else Serial.println(F("HDC1080: No Code!!"));
printSerialNumber();
Serial.println(); Serial.flush();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ReadHDC1080(void)
{
static long OldTime = 0;
long NewTime = millis();
if ( (NewTime - OldTime) < 5000 ) return; OldTime = NewTime;
Serial.println(F("HDC1080: Begin")); Serial.flush();
if (!var_struct_HDC1080.HDC1080ok)
{
StartHDC1080();
return;
}
var_struct_HDC1080.Temp = hdc1080.readTemperature();
var_struct_HDC1080.Humi = hdc1080.readHumidity();
Serial.print(F("HDC1080: ")); Serial.print(F("T=")); Serial.print(var_struct_HDC1080.Temp); Serial.print(F(" C, RH=")); Serial.print(var_struct_HDC1080.Humi); Serial.println(F("%")); Serial.flush();
/**/
Serial.println("HDC1080: End"); Serial.flush();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void printSerialNumber(void) {
Serial.print(F("HDC1080: Device Serial Number=")); Serial.flush();
HDC1080_SerialNumber sernum = hdc1080.readSerialNumber();
char format[12];
sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast); Serial.println(format); Serial.flush();
}
char format[12];
sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
Скоко символов в строке ?
3 лайка
sadman41:
char format[12];
СПАСИБО!!!
Похоже это оно
Глаз видел, но мозг не зацепил.
Пример взят 1:1 из примера и на Гитхабе он так (с ошибкой) и висит…
b707
13.Апрель.2023 05:14:19
20
Интересная конструкция…
Veoramid:
while(0);
Почти после каждой печати:
Veoramid:
Serial.flush();
Зачем?
Таймеры должны быть unsigned long
Veoramid:
static long OldTime = 0;
Veoramid:
while(0);
В “оригинальных” примерах было while(1) . Это они так останавливали программу.
Veoramid:
Serial.flush();
Я пытался найти где программа крашится. По описанию flush() это “Функция ожидает завершения процесса отправки всех исходящих данных по последовательному интерфейсу.”
Не помогло.
Спасибо. Недосмотрел.