Помогите найти утечку памяти

Dr.Cat
Offline
Зарегистрирован: 24.07.2017

Добрый день, форумчане!

Процедура занимается генерацией смс-сообщения с последующей передачей его другой функции. 

void timerInterupt() {
   {
    char smsbuf [150];
    smsbuf[0] = '\0';
    char *psmsbuf = &smsbuf[0];
    {
      char *str = "System powered\r";
      while (*str)
      {
        *psmsbuf++ = *str++;
      }
    }
    if (gerconflag == false) {
      *psmsbuf = &smsbuf[15];
      {
        char *str = "Door closed\r";
        while (*str)
        {
          *psmsbuf++ = *str++;
        }
      }
    }
    else
    {
      *psmsbuf = &smsbuf[15];
      {
        char *str = "Door openered\r";
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
    }
    //    Serial.print("2sms ="); for (byte j = 0; j < 30; j++) {
    //      Serial.print(smsbuf[j]);
    //    } Serial.println("!");
    *psmsbuf = &smsbuf[27];
    {
      char *str = "Current t.= ";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
    //    Serial.print("3sms ="); for (byte j = 0; j < 40; j++) {
    //      Serial.print(smsbuf[j]);
    //    } Serial.println("!");
    *psmsbuf = &smsbuf[39];
    {
      char t[4];
      dtostrf(Temperature(Pintemp), 2, 2, t);
      char *str = t;
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
    *psmsbuf = &smsbuf[43];
    {
      char *str = "C\rTemp.history:\r";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
    //    Serial.print("4sms ="); for (byte j = 0; j < 60; j++) {
    //      Serial.print(smsbuf[j]);
    //    } Serial.println("!");
 
 
    *psmsbuf = &smsbuf[59];
    for (byte j = 0; j <= 11; j++)
    {
      {
        char t[4];
        dtostrf(Temp[j], 2, 2, t);
        char *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
        *psmsbuf++ = '\r';
      }
    }
    //    Serial.print("5sms ="); for (byte j = 0; j < 120; j++) {
    //      Serial.print(smsbuf[j]);
    //    } Serial.println("!");
 
    *psmsbuf = &smsbuf[119];
    {
      char *str = "Sys.time:\r";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
 
    //    Serial.print("6sms ="); for (byte j = 0; j < 140; j++) {
    //      Serial.print(smsbuf[j]);
    //    } Serial.println("!");
    //    for (byte j = 0; j < 140; j++) {
    //      if (smsbuf[j] == '\r') Serial.println(j);
    //    }
 
    *psmsbuf = &smsbuf[128];
    {
      {
        char t[1];
        itoa (GetTime('H'), t, 10);
        char *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = ':';
      {
        char t[1];
        itoa (GetTime('M'), t, 10);
        char  *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = ':';
      {
        char t[1];
        itoa (GetTime('S'), t, 10);
        char  *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = '\0';
    }
 
   // Serial.print("7sms ="); for (byte j = 0; j < 150; j++) {
    //  Serial.print(smsbuf[j]);
   // } Serial.println("!");
    //    for (byte j = 0; j < 150; j++) {
    //      if (smsbuf[j] == '\r') Serial.println(j);
    //    }
    Serial.print("sms ="); Serial.println(smsbuf);
 
    sendsms(smsbuf);
 
  }
 Serial.println("continue temp check");
}
 
void sendsms(char *currsms)  //процедура отправки СМС
volatile int GetTime (char ini)  ///GetTime
float Temperature(int Pintemp) //значение температуры
 
Плата зависает на пробегании предпоследней строчки: {
begin interupt
smsbuf=7sms =System powered
Door closed
Current t.= 0.00C
Temp.history:
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
Sys.time:
8194:8194:8194
conti⸮
}
Иногда при повторном вызове функции, хотя переменные инициализируются снова, а может и не зависнуть.
Загрузка:{
Скетч использует 18176 байт (56%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1254 байт (61%) динамической памяти, оставляя 794 байт для локальных переменных. Максимум: 2048 байт.
}
но будет больше, поэтому раскидывться нельзя. Подскажите, пожалуйста, что не так, а то за неделю все мозги сломал((
 
b707
Offline
Зарегистрирован: 26.05.2017

Выложите скетч как положено, чтобы можно было обсуждать. В шапке вверху есть специальная тема с обьяснением, как правильно выкладывать код.

Dr.Cat
Offline
Зарегистрирован: 24.07.2017

Спасибо. Интересующая процедура как раз начинается со строчки 100.

/*

*/
//#include <MemoryExplorer.h>
#include <MsTimer2.h>
#include <SoftwareSerial.h>
#include <OneWire.h>
#include <stdio.h>                          //работа со строчками
#include <Wire.h>                           // Подключаем библиотеку Wire                           
#include <TimeLib.h>                        // Подключаем библиотеку TimeLib
#include <DS1307RTC.h>                      // Подключаем библиотеку DS1307RTC
#include <avr/wdt.h>                        //подключаем сторожевую собаку
#include <string.h>

const byte Pintemp = 2;
const byte Pingercon = 3;
const byte PinVib = 4;
//const byte PinMov = 7;
const char MasterNum[] = {"+7000000000"};
const byte PinLight = 12;
const byte tempinterval = 5;            //в минутах, время между сохранением температуры
const byte tempalarm = 50;               // град. с. при предупредждении о опышении темперутуры

SoftwareSerial mySerial(10, 11); // RX, TX

float Temp[11];
int tempcount;

void setup() {
  Serial.begin(9600);
  pinMode(Pingercon, INPUT);
  pinMode(PinVib, INPUT);
  pinMode(PinLight, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(13, OUTPUT);
  mySerial.begin(9600);
  sim800ini();
 
  MsTimer2::set(60000, timerInterupt); // задаем период прерывания по таймеру в мс
  MsTimer2::start();              // разрешаем прерывание по таймеру
  wdt_enable(WDTO_4S);

}

String currStr;        //переменные для получения смс
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;
int i = 0;

boolean gerconflag = false;
boolean vibflag = false;
boolean UP = true;        //выключен - false (влючен - true) после заливки прошивки
boolean smsflag = true;    //шлем смс, если true

char ini;

void loop() {
  // i++;
  //Serial.println(i);
  //delay (10);
  //////////////////     Обработка геркона     ///////////////////////////

  if (Gercon(Pingercon) == true && gerconflag == false && UP == true)
  {
    gerconflag = true;
    digitalWrite(PinLight, HIGH);  //здесь действие при сработке
    {

    }
  }
  
    //////////////////     Обработка датчика вибрации     ///////////////////////////
  if (Vib(PinVib) == true  && vibflag == false && UP == true) {
    vibflag = true;
    digitalWrite(PinLight, HIGH);  //здесь действие при сработке
    {
     
    }
  }


 
  //////////////////           ОБРАБОТКА КОМАНД СМС           //////////////////////
 {
  volatile  int comand = 0;
  comand = recivesms();
  if (comand == 4) sim800ini(); //и так далее...
  }
  //////////////////// КОМАНДЫ ПО ТАЙМЕРУ///////////////////

  wdt_reset();
}


///////////////////////////////////////////////FUNCTIONS////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////      TIMER       //////////
void timerInterupt() {

  Serial.println("begin interupt");
   {
    char smsbuf [150];
    smsbuf[0] = '\0';
    Serial.print("smsbuf="); Serial.print(smsbuf); //Serial.println("!!");
    char *psmsbuf = &smsbuf[0];
    {
      char *str = "System powered\r";
      while (*str)
      {
        *psmsbuf++ = *str++;
      }
    }
    if (gerconflag == false) {
      *psmsbuf = &smsbuf[15];
      {
        char *str = "Door closed\r";
        while (*str)
        {
          *psmsbuf++ = *str++;
        }
      }
    }
    else
    {
      *psmsbuf = &smsbuf[15];
      {
        char *str = "Door openered\r";
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
    }
    *psmsbuf = &smsbuf[27];
    {
      char *str = "Current t.= ";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
    *psmsbuf = &smsbuf[39];
    {
      char t[4];
      dtostrf(Temperature(Pintemp), 2, 2, t);
      char *str = t;
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }
    *psmsbuf = &smsbuf[43];
    {
      char *str = "C\rTemp.history:\r";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }

    *psmsbuf = &smsbuf[59];
    for (byte j = 0; j <= 11; j++)
    {
      {
        char t[4];
        dtostrf(Temp[j], 2, 2, t);
        char *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
        *psmsbuf++ = '\r';
      }
    }

    *psmsbuf = &smsbuf[119];
    {
      char *str = "Sys.time:\r";
      while (*str)
      {
        (*psmsbuf++ = *str++);
      }
    }

    *psmsbuf = &smsbuf[128];
    {
      {
        char t[1];
        itoa (GetTime('H'), t, 10);
        char *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = ':';
      {
        char t[1];
        itoa (GetTime('M'), t, 10);
        char  *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = ':';
      {
        char t[1];
        itoa (GetTime('S'), t, 10);
        char  *str = t;
        while (*str)
        {
          (*psmsbuf++ = *str++);
        }
      }
      *psmsbuf++ = '\0';
    }

    Serial.print("7sms ="); for (byte j = 0; j < 150; j++) {
      Serial.print(smsbuf[j]);
    } Serial.println("!");
    //    for (byte j = 0; j < 150; j++) {
    //      if (smsbuf[j] == '\r') Serial.println(j);
    //    }
    Serial.print("sms ="); Serial.println(smsbuf);

  
    //массив температур..

        if (GetTime('M') == tempinterval)
        {
          Temp[tempcount] = Temperature(Pintemp);
          tempcount++;
        }
    
    
        if (smsflag == true && GetTime('H') == 10 && GetTime('M') == 10)
        {
          sendsms(smsbuf);
          tempcount = 0;
        }
        if (smsflag == true && GetTime('H') == 22 && GetTime('M') == 10)
        {
          sendsms(smsbuf);
          tempcount = 0;
        }
    
        if (smsflag == true && GetTime('H') == 17 && GetTime('M') == 10)
        {
          sendsms(smsbuf);
          tempcount = 0;
        }
        sendsms(smsbuf);
 
  }


 
  Serial.println("continue temp check");
//  if (Temperature(Pintemp) > tempalarm)
//  {
//    { String currsms, chars;
//      currsms = "Temperature exceed detected!\r";
//      chars = "t.= ";
//      currsms = currsms + chars;
//      currsms = currsms + Temperature(Pintemp);
//      chars = "C\rSys.time:\r";
//      currsms = currsms + chars;
//      chars = GetTime('H');
//      currsms = currsms + chars;
//      chars = ":";
//      currsms = currsms + chars;
//      chars = GetTime('M');
//      currsms = currsms + chars;
//      chars = ":";
//      currsms = currsms + chars;
//      chars = GetTime('S');
//      currsms = currsms + chars;
//      Serial.println(currsms);
//      //    if (smsflag == true) sendsms(currsms);
//    }
//
//  }

  Serial.println("continue switch");

  if (digitalRead(13) == HIGH) {
    digitalWrite(13, LOW);
  } else {
    digitalWrite(13, HIGH);
  }
  
  Serial.println("end interupt");
}

///GetTime

volatile int GetTime (char ini) {
  tmElements_t tm;
  if (RTC.read(tm)) {
    int _var = 0;

    switch (ini) {
      case 'H' :
        _var = tm.Hour;  return (_var);
      case 'M' :
        _var = tm.Minute; return (_var);
      case 'S' :
        _var = tm.Second; return (_var);
      case 'D' :
        _var = tm.Day; return (_var);
      case 'm' :
        _var = tm.Month; return (_var);
      case 'Y' :
        _var = tm.Year; return (_var);

    }
  }
}


///SIM800 Initialization
void sim800ini() {
  mySerial.begin(9600);
  // Настраиваем приём сообщений с других устройств
  // Между командами даём время на их обработку
  mySerial.print("AT+CMGF=1\r");                            //устанавливает текстовый режим смс-сообщения
  delay(500);
  mySerial.print("at+cscs="); mySerial.print(char(34)); mySerial.print("GSM"); mySerial.print(char(34)); mySerial.print("\r"); //кодировка GSM
  delay(500);
  mySerial.print("AT+IFC=1, 1\r");                           //устанавливает программный контроль потоком передачи данны
  // delay(300);
  //mySerial.print("AT+CPBS=\"SM\"\r");                     //открывает доступ к данным телефонной книги SIM-карты
  delay(500);
  mySerial.print("AT+CNMI=1,2,2,1,0\r");                    //включает оповещение о новых сообщениях
  // Serial.print("AT+CNMI=1,2,2,1,0\r");
  // mySerial.print("AT+CMGDA="DEL ALL"\r");                   // удаляем все смски из памяти
  delay(2500);
}

void openport () //активирует usb-uart
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
  {
    while (Serial.available())
    {
      mySerial.write(Serial.read());
    }
    mySerial.println();
  }
}

void infonet() //инфо о сети и пр.
{
  //mySerial.println("at");
  mySerial.println("AT+COPS?");
  delay(500);
  mySerial.println("AT+creg?");
  delay(500);
  mySerial.println("AT+CSQ");
  //mySerial.println("at");
  delay(2000);

}

int recivesms()
{
  volatile int _comand = 0;
  if (!mySerial.available())
    return _comand;

  char currSymb = mySerial.read();
  Serial.print(currSymb);
  if ('\r' == currSymb) {
    if (isStringMessage) {
      //если текущая строка - SMS-сообщение,
      //отреагируем на него соответствующим образом
      if (!currStr.compareTo("On")) {
        _comand = 1;
        //Serial.print (_comand);
      } else if (!currStr.compareTo("Off")) {
        _comand = 2;
      }
      else if (!currStr.compareTo("Temp")) {
        _comand = 3;
      }
      else if (!currStr.compareTo("Net")) {
        _comand = 4;
      }
      else if (!currStr.compareTo("Echo")) {
        _comand = 5;
      }
      else if (!currStr.compareTo("SMS off")) {
        _comand = 6;
      }
      else if (!currStr.compareTo("Status")) {
        _comand = 7;
      }
      isStringMessage = false;
    } else {
      if (currStr.startsWith("+CMT")) {
        //если текущая строка начинается с "+CMT",
        //то следующая строка является сообщением
        isStringMessage = true;
      }
    }
    currStr = "";
  } else if ('\n' != currSymb) {
    currStr += String(currSymb);
  }
  return _comand;
  Serial.print("_comand="); Serial.print(_comand);
}


void sendsms(char *currsms)  //процедура отправки СМС
{
  Serial.println("SMS send started");
  mySerial.println("AT+CMGF=1"); delay(500);
  Serial.println("AT+CMGF=1");
  mySerial.print("AT+CMGS="); mySerial.print(char(34)); mySerial.print(MasterNum) ; mySerial.print(char(34)); mySerial.println();
  Serial.print("AT+CMGS="); Serial.print(char(34)); Serial.print(MasterNum) ; Serial.print(char(34)); Serial.println();

  delay(500);
  Serial.println ("Msg sending:");
  Serial.println(currsms); //Serial.print(char(26));
  mySerial.print(currsms); mySerial.print(char(26));

  Serial.println("SMS send complete");
  delay(2000);
}


boolean Vib (int PinVib) {
  if (digitalRead(PinVib) != HIGH) {
    return true;
  }
  else
  {
    return false;
  }
}

boolean Gercon(int Pingercon) {
  if (digitalRead(Pingercon) != HIGH) {
    return true;
  }
  else
  {
    return false;
  }
}

float Temperature(int Pintemp) {
// код 
  return celsius;
}

 

b707
Offline
Зарегистрирован: 26.05.2017

ой жуть какая.

Признайтесь. сколько дней вы программируете? Один?

Зачем начинать с таких сложных скетчей. помигайте сначала диодами.

Если честно - рука устанет перечислять все ошибки в коде.

Самое главное - функция, вызываемая прерыванием - или аналогичная, вызываемая библиотекой работы с таймерами - должна отрабатывать максимально быстро! Реально - вызвали, проверили одно-два условия. выставили флаг о результате - и ВЫШЛИ. А у вас половина программы запихнута в функцию timerInterupt()

Dr.Cat
Offline
Зарегистрирован: 24.07.2017

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

b707
Offline
Зарегистрирован: 26.05.2017

Dr.Cat пишет:
Признаюсь, довольно долго. Мигать диодами может быть скучно, а нужные проекты требуют усилий. Ваше замечание учту, спасибо, но от проблем генерации массива символов не уйти.

Совет - оставьте в скетче только генерацию текста СМС- без таймеров и интерруптов. И сначала добейтесь, чтобы оно работало. Когда получится - добавляйте в основную программу.

Тот код, что вы привели-  вы явно откуда-то списали и сами не понимаете. Я бы советовал не искать в нем ошибки, а написать свой. заново. самостоятельно.  Код совершенно жуткий и ошибок в нем куча.

Dr.Cat
Offline
Зарегистрирован: 24.07.2017

b707 пишет:

Совет - оставьте в скетче только генерацию текста СМС- без таймеров и интерруптов. И сначала добейтесь, чтобы оно работало. Когда получится - добавляйте в основную программу.

Хорошо. Какой вариант генерации текста оптимальный, если не указатель-массив? Функция strcat в этих же условиях зависает так же, String делает больше проходов, но на второй-третий вызов - зависает.

b707 пишет:

Тот код, что вы привели-  вы явно откуда-то списали и сами не понимаете. Я бы советовал не искать в нем ошибки, а написать свой. заново. самостоятельно.  Код совершенно жуткий и ошибок в нем куча.

Ну да, отсюда: http://cpp.com.ru/kr_cbook/ch5kr.html :)