Конфликт MQTT и I2C в программном коде

Здравствуйте! Прошу помощи с кодом. Ниже приведённый код (для Arduino UNO) реализует следующую задачу: Подключение к MQTT брокеру ( по средством модуля SIM800L) для передачи показаний датчиков на смартфон. Считывающие датчики подключены к другому микроконтроллеру (Arduino Mega) который обрабатывает сигналы датчиков, и выполнят свой программный код. Arduino UNO получает показания датчиков по шине I2C. Передачу данных по шине проверял, все показания в мониторе порта UNO считываются и отображаются. Подключение к брокеру и передача данных на телефон без инициализированной шины I2C работает т.е. если объявленной переменной int присвоено значение int=20, все передаётся и читается, НО стоит инициализировать шину I2C для получения показаний модуль SIM800L отказывается подключаться к интернету. Собственными силами проблему решить не получается т.к. язык начал изучать совсем недавно, перерыл тонну материалов а результата нет уже месяц. Помогите пожалуйста.

#include <Wire.h>
#include <iarduino_I2C_connect.h>
iarduino_I2C_connect I2C2;
// Select your modem:
#define TINY_GSM_MODEM_SIM800

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#ifndef __AVR_ATmega328P__
#define SerialAT Serial1

// or Software Serial on Uno, Nano
#else
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(2, 3);  // RX, TX
#endif

// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS

// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon

// Add a reception delay, if needed.
// This may be needed for a fast processor at a slow baud rate.
#define TINY_GSM_YIELD() { delay(2); }

// Your GPRS credentials, if any
const char apn[]      = "internet.tele2.ru";
const char gprsUser[] = "";
const char gprsPass[] = "";

// MQTT details
const char* broker = "mqtt.by";

#include <TinyGsmClient.h>
#include <PubSubClient.h>

#define PUB_DELAY (5 * 1000) /* 5 seconds */

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm        modem(debugger);
#else
TinyGsm        modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient  mqtt(client);

uint32_t lastReconnectAttempt = 0;

void mqttCallback(char* topic, byte* payload, unsigned int len) 
{
  SerialMon.println(topic);
  SerialMon.write(payload, len);
  SerialMon.println();
}

boolean mqttConnect() 
{
  SerialMon.print("Connecting to ");
  SerialMon.print(broker);

  // Connect to MQTT Broker
  boolean status = mqtt.connect("Test_client",         "???",        "???");

  if (status == false) 
  {
    SerialMon.println(" fail");
    return false;
  }
  SerialMon.println(" success");

  mqtt.subscribe("???/???/???/zapros");
  return mqtt.connected();
}

int VAR_ust_temp_vozduh;
int VAR_temp_vozduh;
int VAR_temp_voda;
int VAR_davl_voda;
float f_temp_vozduh;
float f_davl_voda;
bool zapros= LOW;                   

void setup() 
{
 // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  SerialMon.println("Wait...");

  // Set GSM module baud rate
  SerialAT.begin(9600);
  delay(6000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // modem.init();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);

  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");

  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

  // GPRS connection parameters are usually set after network registration
  SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");

  if (modem.isGprsConnected()) {
    SerialMon.println("GPRS connected");
  }

  // MQTT Broker setup
  mqtt.setServer(broker, 1883);
  mqtt.setCallback([] (char* topic, byte * payload, unsigned int len)  {
    SerialMon.write(payload, len);
    SerialMon.println();
    if ((char)payload[0] == '1')
    {
      zapros = HIGH;
    }
    else 
    {
      zapros = LOW;
    }
  });
}
void I2C_date()
{
  if (zapros = HIGH)
  {
    Wire.begin();
    Wire.requestFrom(2, 5);
    VAR_temp_vozduh = I2C2.readByte(2,0)<<8;
    VAR_temp_vozduh += I2C2.readByte(2,1);
    VAR_temp_voda = I2C2.readByte(2,2);
    VAR_davl_voda = I2C2.readByte(2,3);
    VAR_ust_temp_vozduh = I2C2.readByte(2,4);
  delay(500);
  f_temp_vozduh =(VAR_temp_vozduh * 0.1);
  f_davl_voda = (VAR_davl_voda*0.1); 
  }
}

long last = 0;   
void publishDat() 
{
  long now = millis();
  if (now - last > PUB_DELAY) 
  {
    String ust_temp_vozduh(VAR_ust_temp_vozduh);
    String temp_voda(VAR_temp_voda);
    String temp_vozduh(f_temp_vozduh,1);
    String davl_voda(f_davl_voda,1);
    mqtt.publish("user/Dima_ural/dom/ust/vozduh", String(ust_temp_vozduh).c_str());
    mqtt.publish("user/Dima_ural/dom/temp/vozduh", String(temp_vozduh).c_str());
    mqtt.publish("user/Dima_ural/dom/temp/voda", String(temp_voda).c_str());
    mqtt.publish("user/Dima_ural/dom/davlenie/voda", String(davl_voda).c_str());
    last = now;
  }
}
void loop() 
{
// Make sure we're still registered on the network
  if (!modem.isNetworkConnected()) {
    SerialMon.println("Network disconnected");
    if (!modem.waitForNetwork(180000L, true)) {
      SerialMon.println(" fail");
      delay(10000);
      return;
    }
    if (modem.isNetworkConnected()) {
      SerialMon.println("Network re-connected");
    }

    // and make sure GPRS/EPS is still connected
    if (!modem.isGprsConnected()) {
      SerialMon.println("GPRS disconnected!");
      SerialMon.print(F("Connecting to "));
      SerialMon.print(apn);
      if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
        SerialMon.println(" fail");
        delay(10000);
        return;
      }
      if (modem.isGprsConnected()) {
        SerialMon.println("GPRS reconnected");
      }
    }
  }

  if (!mqtt.connected()) {
    SerialMon.println("=== MQTT NOT CONNECTED ===");
    // Reconnect every 10 seconds
    uint32_t t = millis();
    if (t - lastReconnectAttempt > 10000L) {
      lastReconnectAttempt = t;
      if (mqttConnect()) {
        lastReconnectAttempt = 0;
      }
    }
    delay(100);
    return;
  }
   mqtt.loop();
   publishDat();
//   I2C_date();      
}

Подозреваю что памяти в МК не хватает, для эксперимента запустите этот код на Mega.

1 лайк

Скетч использует 27094 байт (83%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1439 байт (70%) динамической памяти, оставляя 609 байт для локальных переменных. Максимум: 2048 байт.
Предупреждение что недостаточно памяти не выдаёт, за совет спасибо попробую!

Начните с того, что упрячьте все строковые константы в макрос F() - выиграете несколько сот байт оперативы.

1 лайк

Спасибо за совет! после переноса строковых констант в программную память, объём оперативной памяти действительно уменьшился в разы.
Скетч использует 27164 байт (84%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1205 байт (58%) динамической памяти, оставляя 843 байт для локальных переменных. Максимум: 2048 байт.

УРА-УРА-УРА!!! Все заработало!!! Проблема действительно оказалась в нехватке оперативной памяти МК (UNO). Всем ОГРОМНОЕ СПАСИБО!!!

Нальёшь при случае.

как-то “в разы” тут совсем не видно :slight_smile:

Мне кажется 12% для такого объёма памяти это в разы, да и UNO видимо считает также :thinking: , самое главное что всё получилось!