What wrong with this code ?

Hi all.
My code ocasionally hangs… or self reset (once per one-two days). Then on oled it is incomplete text.
It seems to me that it is a deficiency of free SRAM. This program uses 690 B of 2048 B SRAM (as indicated by the arduino).
What is the reason for this behavior?
It’s possible that I have a significant error in the code?

#include <SerialGSM.h>
#include <SoftwareSerial.h>
SerialGSM cell(2, 3);
#include <OneWire.h>
OneWire  ds(9);
#define I2C_ADDRESS 0x3C
#include "AvrI2c.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
SSD1306AsciiAvrI2c oled;
#include <EEPROM.h>

unsigned long previousMillis2 = 0;
float celsius;

void setup() {
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(System5x7);
  oled.clear();
  oled.println(F("Wait 20 sec.."));

  //Serial.begin(57600);
  cell.begin(19200);
  cell.Verbose(true);
  cell.Boot();
  cell.DeleteAllSMS();
  cell.FwdSMS2Serial();

  boolean aaa = 0;
  while (cell.ReadLine()) {
    if ( strstr(cell.Message(), "OK") != NULL ) {
      aaa = 1;
      delay(10);
    }
  }
  if (aaa) {
    oled.clear();
    oled.println(F("OK - FOUND"));
    delay(1000);
  }
  else
  {
    oled.clear();
    oled.println(F("Reset.."));
    cell.Boot();
    while (cell.ReadLine()) {
      delay(10);
    }
  }
}


void loop() {
  celsius = temperature();
  delay(10);

  displaytemp();
  delay(10);

  if (cell.ReceiveSMS()) {
    //  Serial.println(cell.Sender());
    //  Serial.println(cell.Message());
    if ( strstr(cell.Message(), "TT.TEMP") != NULL) tttemp();
    if ( strstr(cell.Message(), "TT.ALARM:") != NULL) ttalarm();
    if ( strstr(cell.Message(), "TT.TELTEMP:") != NULL) tttel();
    if ( strstr(cell.Message(), "TT.INTERVAL:") != NULL) ttinterval();
    if ( strstr(cell.Message(), "TT.CHECK") != NULL) ttcheck();
    if ( strstr(cell.Message(), "TT.SETUP") != NULL) ttsetup();
    cell.DeleteAllSMS();
  }
  delay(10);

  alarmtest();

  delay(1000);
}


float temperature() {
  byte data[12];
  byte addr[8];
  if ( !ds.search(addr)) {
    ds.reset_search();
    return -300;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);
  for (byte i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  ds.reset_search();
  float raw = (data[1] << 8) | data[0];
  float cels = raw / 16.0;
  return cels;
}

void tttemp() {

  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Temperature at home: "));
  cell.print(celsius);
  cell.print(F("'C"));
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void ttalarm() {
  char *mess = cell.Message();
  char alarmo[3];
  for (byte i = 0; i < 2; i++) {
    alarmo[i] = *(mess + 9 + i);
  }
  alarmo[2] = '\0';
  byte n = atoi(alarmo);
  EEPROM.write(9, n);
  delay(100);
  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Alarm setup: "));
  cell.print(n);
  cell.print(F("'C"));
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void tttel() {
  char *mess = cell.Message();
  char bufftel[13];
  for (byte i = 0; i < 9; i++) {
    bufftel[i] = *(mess + 11 + i);
    EEPROM.write(i, bufftel[i]);
  }
  bufftel[9] = '\0';
  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Telephone setup: "));
  for (byte i = 0; i < 9; i++) {
    cell.print(bufftel[i]);
  }
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void ttinterval() {
  char *mess = cell.Message();
  char inter[2];
  inter[0] = *(mess + 12);
  inter[1] = '\0';
  byte m = atoi(inter);
  EEPROM.write(10, m);
  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Interval setup: "));
  cell.print(m);
  cell.print(F(" hours."));
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void ttcheck() {
  cell.CheckBalance();
  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Prepaid balance: "));
  cell.print(cell.Stanval());
  cell.print(F("va /"));
  cell.print(cell.Standay());
  cell.print(F("days."));
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void ttsetup() {
  cell.Rcpt(cell.Sender());
  cell.StartSMS();
  cell.print(F("Interval setup: "));
  cell.print(EEPROM.read(10));
  cell.println(F(" hours."));
  cell.print(F("Telephone setup: "));
  for (byte i = 0; i < 9; i++) {
    cell.print(char(EEPROM.read(i)));
  }
  cell.println(F("."));
  cell.print(F("Alarm setup: "));
  cell.print(EEPROM.read(9));
  cell.println(F("'C"));
  cell.EndSMS();
  delay(500);
  cell.ReadLine();
}

void displaytemp() {
  oled.clear();
  oled.println(F("Thermometer GSM"));
  oled.println();
  oled.set2X();
  oled.print(celsius);
  oled.println(F("'C"));
  oled.set1X();
}

void alarmtest() {
  byte alarm = EEPROM.read(9);
  if (celsius < alarm) {
    unsigned long interval2 = EEPROM.read(10);
    interval2 = interval2 * 3600000;
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis2 >= interval2) {
      previousMillis2 = currentMillis;
      char bufftel[13];
      bufftel[0] = '+';
      bufftel[1] = '1';
      bufftel[2] = '1';
      for (byte i = 0; i < 9; i++) {
        bufftel[i + 3] =  EEPROM.read(i);
      }
      bufftel[12] = '\0';
      cell.Rcpt(bufftel);
      cell.StartSMS();
      cell.print(F("Temperature alarm: "));
      cell.print(celsius);
      cell.print(F("'C"));
      cell.EndSMS();
      delay(500);
      cell.ReadLine();
    }
  }
}
  float raw = (data[1] << 8) | data[0];

Is shifting a byte and anding a byte really going to produce a float? Not in my universe.

I find it hard to believe that with an OLED display with fonts, etc., that you are only using 690 bytes of SRAM.

  char inter[2];
  inter[0] = *(mess + 12);
  inter[1] = '\0';
  byte m = atoi(inter);

Or

byte m = *(mess + 12) - '0';

Just to point out another bug:

float raw = (data[1] << 8) | data[0];

Any byte shifted left 8 bits will be 0. Think about it in binary:

00000001  start with 1 as an example
00000010  shift left once
00000100  twice
00001000  three times
00010000  four times
00100000  five times
01000000  six times
10000000  seven times
00000000  eight times - the last bit of the starting number just "fell off" the left side

(Technically, the result is undefined, but this is the practical result).

–Doug

dnwheeler:
Just to point out another bug:

float raw = (data[1] << 8) | data[0];

Any byte shifted left 8 bits will be 0. Think about it in binary:

00000001  start with 1 as an example

00000010  shift left once
00000100  twice
00001000  three times
00010000  four times
00100000  five times
01000000  six times
10000000  seven times
00000000  eight times - the last bit of the starting number just “fell off” the left side




(Technically, the result is undefined, but this is the practical result).

--Doug

The byte will be promoted to int for the arithmetic.
An int is 16 bits on an eight bit Arduino, and 1 can happily be shifted eight places left in a sixteen bit variable.(though a cast to an unsigned type is advisable)

I find it hard to believe that with an OLED display with fonts, etc., that you are only using 690 bytes of SRAM.

This simple code uses only 34 Bytes of SRAM and 2728 Bytes of Flash. More here: http://forum.arduino.cc/index.php?topic=335594.0

#define I2C_ADDRESS 0x3C
#include "AvrI2c.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
SSD1306AsciiAvrI2c oled;

void setup() {                
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(System5x7);
}

void loop() {
  oled.clear();
  oled.println(F("Hello"));
  delay(1000);
}