Да как так-то??? (цикл уходит за пределы)

switch
Offline
Зарегистрирован: 07.12.2015

Картинка скажет сама за себя. У кого не отображается - замечу, что банальный цикл выходит за пределы. Неведомым мне образом. Соответственно вся обработка данных (а там структуры и массивы)  уходит в левые области памяти, контроллер уходит в ребут. 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может банально не хватать ОЗУ, например. Это всего лишь предположение.

switch
Offline
Зарегистрирован: 07.12.2015

А как это можно узнать?

просто не очень охота переносить все на MEGA.  Я хотел в итоге программу перенести на NANO, а ее вставить в плату с исполнительными устройствами. Да и мега дороже. Да и зря чтоли я мучался с оптимизацией или рисованием ;)

Памяти в MEGA не на много больше...

Да и по  программной памяти укладываюсь с запасом: провел кое-какие оптимизации. Привожу код целиком, за исключением слегка модифицированных UTFT_buttons


#define YP A2  
#define XM A1 
#define YM  6 
#define XP  7 
 

#define TS_MAXX 92
#define TS_MINX 936
#define TS_MAXY 135
#define TS_MINY 900

// Последним параметром указывается сопротивление между X+ и X-
// Для данных дисплеев 300 подойдет
// От PhOSTU: я сомневаюсь в правильности этого коммента

// Сила нажатия на дисплей
// От PhOSTU: и этого тоже)
#define MINPRESSURE 10
#define MAXPRESSURE 1000
#define ONE_WIRE_BUS 12
#define TEMPERATURE_PRECISION 9
//------------------------------------
#include <avr/pgmspace.h>
#include "TouchScreen.h"
#include <UTFT.h>
#include "buttons.h"
#include <OneWire.h>
#include <DallasTemperature.h>

extern uint8_t Sinclair_S[]; 

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
UTFT myGLCD(31,A2,A1,A3,A4);
UTFT_Buttons  myButtons(&myGLCD, &ts);
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature mySensors(&oneWire); 

#define SENSCOUNT 8
#define ACC_OUT 0
#define RD_IN 1
#define RD_OUT 2
#define HT_IN 3
#define HT_MID 4
#define AIR_IN 5
#define AIR_OUT 6
#define OUTDOOR 7
//структура для хранения данных о датчиках

#define DATASIZE 10       // количество хранимых отсчетов
#define DATAPERIOD 1000   // период отсчетов
//структура для датчиков
typedef struct  
{
  char* name; // имя
  DeviceAddress addr; //адрес
  int x;              //координата Х
  int y;              //координата Y
  byte data[DATASIZE];//история отсчетов
} tSensor;

  
  tSensor sensor[]=
  {
	  {"ACC_OUT",{ 0x28, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },12,2 ,{0}},
	  {"RD_IN",  { 0x28, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },39,30,{0}},
	  {"RD_OUT", { 0x28, 0xFF, 0x4B, 0xF5, 0x01, 0x15, 0x02, 0x25 },15,30,{0}},
	  {"HT_IN",  { 0x28, 0xFF, 0x4B, 0xF5, 0x01, 0x15, 0x02, 0x25 },41,2 ,{0}},
	  {"HT_MID", { 0x28, 0xFF, 0x4B, 0xF5, 0x01, 0x15, 0x02, 0x25 },47,16,{0}},
	  {"AIR_IN", { 0x28, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },15,35,{0}},
	  {"AIR_OUT",{ 0x28, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },39,35,{0}},
	  {"OUTDOOR",{ 0x08, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },56,2 ,{0}},
  };
  // int sensPosX[SENSCOUNT]= {12, 39, 15, 41, 47, 15, 39, 56};
  // int sensPosY[SENSCOUNT]= {2,  30, 30, 2,  16, 35, 35 ,2};

#define acc_out 0
#define rd_in 1
#define rd_out 2
#define ht_in 3
#define ht_mid 4
#define air_in 5
#define air_out 6
#define outdoor 7
  
byte bMain =1; 
byte bSensors = 2; 
int pressed_button; 
//------------------------------------
#define BOXSIZE 40 // Размер кнопки выбора цвета
#define PENRADIUS 1 // Радиус круга для рисования
  int top = 5;
  int left= 10;
  float s=6;
//************************************

//ставим цвета
 #define  COL_C1 31
 #define  COL_C2 10265 //синий ниже
 #define  COL_C3 14357 //синий ниже
 #define  COL_C4 22544 //сине-красный
 #define  COL_C5 28684 //сине-красный
 #define  COL_C6 38917 //красный 
 #define  COL_C7 47104 //темно-красный
 #define  COL_C8 63488 //ткрасный
 #define  COL_GREEN 1504 //зеленый
 
void drawFLine(int x1, int y1, int x2, int y2, word col)
{
  myGLCD.setColor(col); 
  myGLCD.drawLine(x1,y1,x2,y2); 
  myGLCD.drawLine(x1+1,y1,x2+1,y2); 
  myGLCD.drawLine(x1,y1+1,x2,y2+1); 
  myGLCD.drawLine(x1+1,y1+1,x2+1,y2+1); 
}
int h(int val)
{
  int res = (int) val * s + left;
  return res;
}
int v(int val)
{
  int res = (int) val * s + top;
  return res;
}
word setWColor(byte r, byte g, byte b)
{
    word fch=((r&248)|g>>5);
    word fcl=((g&28)<<3|b>>3);
    return (fch<<8) | fcl;
}
void gPrintLn(const char* text, word color,int x, int y)
{
  static int line =0;
  #define line_step 10
  myGLCD.setColor(color);
  myGLCD.print(text, x, y+(line*line_step));
  line++;

}
void checkSensor(int n, int x, int y)
{
  char buf[30];
  delay(200);
  if (!mySensors.isConnected(sensor[n].addr))
  { 
    myGLCD.setColor(VGA_YELLOW);
    sprintf(buf, "Unable to find address for %s", sensor[n].name);
    //myGLCD.print(buf, x, y+(line*line_step)); 
    myGLCD.print(buf, x, y); 
  }
  else
  {
    mySensors.setResolution(sensor[n].addr, TEMPERATURE_PRECISION);
    myGLCD.setColor(VGA_GREEN);
    int tempC =(int) mySensors.getTempC(sensor[n].addr);
    sprintf(buf, "Temperature for %s is %i *C", sensor[n].name, tempC);
    myGLCD.print(buf, x, y*n); 
    
    myGLCD.printNumI (y, 310,n*10);
  } 
}
void setup(void) {
  
  Serial.begin(9600);
  myGLCD.InitLCD();
  myGLCD.setFont(Sinclair_S);
  myButtons.setTextFont(Sinclair_S);
  pinMode(13, OUTPUT);
  
  myGLCD.clrScr(); 
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("System init", CENTER, 1);
  
  myGLCD.setColor(VGA_RED);
  myGLCD.print ("Init temperature sensors...", 10, 20);
  delay(100);
  mySensors.requestTemperatures();
  
  Serial.println("requestTemperatures");
  //обрабатываем все датчики поочереди
  //for(i=0; i<SENSCOUNT; i++)
  for (int i=0; i<=2; i++)
   
  {
    Serial.print("i= ");
    Serial.println(i);
    myGLCD.setColor(VGA_LIME);
    myGLCD.printNumI (i, 340,i*10);
    //checkSensor(i,10,i*5+20);
  }
  myGLCD.setColor(VGA_RED);
  myGLCD.print ("Init temperature sensors...", 10, 200);

  delay(3000);
  drawMainScreen();
  
  
}
void drawMainScreen()
{
  myButtons.deleteAllButtons();
  myGLCD.clrScr(); 
  // Устанавливаем текущий цвет  
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("System control", CENTER, 1);
  
  //вот так вот определяем картинку для экономии памяти
  #define Rect 1
  #define RRect 2
  #define FLine 3
  #define Circle 4//бочка 							            		трубы                       					Радиатор											камин типа      насос
  byte img_type[] PROGMEM =	{RRect,Rect,  Rect,   Rect,   Rect,   RRect,  Rect,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	FLine,	Rect,	Rect,	Rect,	 Rect,		Rect,   Rect,		Rect,	Rect,	Circle,	FLine,	FLine,	FLine,		FLine	};
  int img_x1[]    PROGMEM =	{0,	0,	0,	0,	0,	0,	0,	10,	44,	37,	17,	10,	35,	10,	44,	48,	45,	48,	20,	33,	22,	 22,		22,	22,		42,	42,	27,	27,	27,	26,		26	};
  int img_y1[]    PROGMEM =	{3,	8,	10,	13,	16,	22,	19,	4,	12,	4,	4,	29,	29,	4,	4,	6,	8,	10,	28,	28,	29,	 31,		33,	35,		20,	23,	4,	3,	5,	3,		5};
  int img_x2[]    PROGMEM =	{10,	10,	10,	10,	10,	10,	10,	44,	44,	37,	17,	20,	43,	44,	48,	45,	48,	44,	22,	35,	33,	 33,		33,	33,		49,	49,	10,	28,	28,	27,		27	};
  int img_y2[]    PROGMEM =	{10,	10,	13,	16,	19,	31,	23,	4,	20,	29,	29,	29,	29,	4,	6,	8,	10,	12,	37,	37,	30,	 32,		34,	36,		23,	30,	0,	4,	4,	4,		4		};
  word img_col[]  PROGMEM =	{COL_C1,COL_C2,COL_C3, COL_C4, COL_C5, COL_C7, COL_C6, COL_C1, COL_C6, COL_C5, COL_C6, COL_C7, COL_C8, COL_C1, COL_C2, COL_C3, COL_C4, COL_C5, COL_C7, COL_C8, VGA_GRAY,VGA_GRAY,	VGA_GRAY,VGA_GRAY,	COL_C7, COL_C8, COL_GREEN, 	VGA_BLACK, VGA_BLACK, VGA_BLACK,VGA_BLACK };
    
   
   for (byte i=0; i<32; i++)
   {
     

     if(img_type[i]==Rect)
     {
        myGLCD.setColor (img_col[i]);
        myGLCD.fillRect(h(img_x1[i]),v(img_y1[i]),h(img_x2[i]),v(img_y2[i]));
     }
     if(img_type[i]==RRect)
     {
        myGLCD.setColor (img_col[i]);
        myGLCD.fillRoundRect(h(img_x1[i]),v(img_y1[i]),h(img_x2[i]),v(img_y2[i]));
     }
     if(img_type[i]==FLine)
     { 
        drawFLine(h(img_x1[i]),v(img_y1[i]),h(img_x2[i]),v(img_y2[i]),img_col[i]);
     }
     if(img_type[i]==Circle)
     {
        myGLCD.setColor (img_col[i]);
        myGLCD.fillCircle(h(img_x1[i]),v(img_y1[i]),img_x2[i]);
     }
     //myGLCD.printNumI (i, 320, 10);
     //delay(300);             
   }  
  
  myButtons.deleteAllButtons();
  boolean default_colors = true;
  
  myGLCD.setColor(VGA_WHITE); 
  myButtons.deleteAllButtons();
  myButtons.addButton( 310,  200, 70,  25, "Sensors", bSensors);
  myButtons.drawButtons();
  

}
//печатаем состояние датчиков на  экране
void sensorPrint(byte n) 
{
  

    // предыдущее время сохранения данных
    static long lastTime=0;
    long curtime=millis();
    int tempC=0;
    //получаем адрес по идентификатору
    tempC =(int) mySensors.getTempC(sensor[n].addr);
    if(tempC <= 0)
        myGLCD.setColor(VGA_BLUE);
    if(tempC==-127)
        myGLCD.setColor(VGA_GRAY);
    if(tempC <= 40 && tempC > 0)
        myGLCD.setColor(VGA_GREEN);
    if(tempC <= 60 && tempC > 40)
        myGLCD.setColor(VGA_LIME);
    if(tempC <= 80 && tempC > 60)
        myGLCD.setColor(VGA_YELLOW);
    if(tempC > 80 )
        myGLCD.setColor(VGA_RED);
    //раз в минуту сохраняем данные 
        Serial.print("lastTime= ");
        Serial.print(lastTime);
        Serial.print(" curtime= ");
        Serial.println(curtime);
    if(curtime-lastTime > DATAPERIOD )
    {
        lastTime=millis();
        //byte i=0;
        //сдвигаем все нафиг на  одну позицию
        for (byte i=DATASIZE-1; i>=0; i--)
        {
          Serial.print("di=");
          Serial.print(i);
          Serial.print(" data=");
          Serial.println(sensor[n].data[i]);
          sensor[n].data[i+1]=sensor[n].data[i];
          myGLCD.printNumI (sensor[n].data[i+1], 300, 0);
        }
        sensor[n].data[0]=tempC;
    }
    myGLCD.printNumI (tempC, h(sensor[n].x), v(sensor[n].y));
}
//рисуем цветной график заданного размера
void drawGraph(byte n, int x, int y, byte h, byte count)
{
  byte i;
  if(count > DATASIZE-1)
    count = DATASIZE-1;
    
  for (i=0; i<count; i++)
  {
      int tempC=sensor[n].data[i];
      //если меньше нуля - не показываем ибо пофиг.
      if(tempC<=0)
        tempC=0;
      myGLCD.setColor(100+tempC,255-tempC,0);
      myGLCD.drawLine(x+count-i,y+h,x+count-i,y+h-i/100*h); 
      
    myGLCD.printNumI (tempC, 20*i,30);
  }
}
void drawTemp()
{

    //int tempC=0;
    mySensors.requestTemperatures();
    //обрабатываем все датчики поочереди
    for(int i=0; i<SENSCOUNT; i++)
      sensorPrint(i);
 
   // drawGraph(acc_out, 100, 10, 50, 30);
}
void drawSensorsScreen()
{  

  myGLCD.clrScr(); 
  myGLCD.setColor(VGA_WHITE); 
  myGLCD.print("Sensors control", CENTER, 1);
  boolean default_colors = true; 
  myButtons.deleteAllButtons();
  //выход в основной экран
  myButtons.addButton( 330,  200, 60,  25, "Return", bMain);
  myButtons.drawButtons();
 
}

void loop(void) 
{

  pressed_button = myButtons.checkButtons();
  drawTemp();
  myGLCD.setColor(VGA_GREEN); 
  myGLCD.printNumI (pressed_button, 320, 0);
  if(pressed_button==bMain)
    drawMainScreen();  
  if(pressed_button==bSensors)
    drawSensorsScreen();

  delay(100);
  
 
}
  

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Строка 149, длина буфера 30 байт. Строка формата, 27 байт длиной, плюс имя сенсора, ещё 7 байт, уже 34. Остальное даже не смотрел, с такими плюхами выполнение кода непредсказуемо.

switch
Offline
Зарегистрирован: 07.12.2015

Круто! Спасибо большое!

Я неопытный в сях приплюснутых, делаю тупые ошибки. последние 10..15 лет программировал на интерпретируемых языках, с нечеткой типизацией.

Подскажите, пожалуйста, есть ли методы анализа сколько памяти используется?

switch
Offline
Зарегистрирован: 07.12.2015

Не сочтите за наглость, не могли бы Вы проконсультировать по поводу этой функции?

//печатаем состояние датчиков на  экране
void sensorPrint(byte n) 
{
    // предыдущее время сохранения данных
    static long lastTime=0;
    long curtime=millis();
        Serial.print("lastTime= ");
        Serial.print(lastTime);
        Serial.print(" curtime= ");
        Serial.println(curtime);
    int tempC=0;
    //получаем адрес по идентификатору
    tempC =(int) mySensors.getTempC(sensor[n].addr);
    if(tempC <= 0)
        myGLCD.setColor(VGA_BLUE);
    if(tempC==-127)
        myGLCD.setColor(VGA_GRAY);
    if(tempC <= 40 && tempC > 0)
        myGLCD.setColor(VGA_GREEN);
    if(tempC <= 60 && tempC > 40)
        myGLCD.setColor(VGA_LIME);
    if(tempC <= 80 && tempC > 60)
        myGLCD.setColor(VGA_YELLOW);
    if(tempC > 80 )
        myGLCD.setColor(VGA_RED);
    //раз в минуту сохраняем данные 
    if(curtime-lastTime > DATAPERIOD )
    {
        lastTime=millis();
        //byte i=0;
        //сдвигаем все нафиг на  одну позицию
        for (byte i=DATASIZE-1; i>=0; i--)
        {
          Serial.print("di=");
          Serial.print(i);
          Serial.print(" data=");
          Serial.println(sensor[n].data[i]);
          sensor[n].data[i+1]=sensor[n].data[i];
          myGLCD.printNumI (sensor[n].data[i+1], 300, 0);
        }
        sensor[n].data[0]=tempC;
    }
    myGLCD.printNumI (tempC, h(sensor[n].x), v(sensor[n].y));
}

Если включить блок кода после комментария "раз в минуту сохраняем данные" то после вызова этой фунции ничего не работает. Сама функция - тоже, в последовательный порт не уходят сообщения, которые определены в начале функции. Подозреваю что дело в размере массива данных sensor[n].data[]: сейчас он определяется тупо так: 

  {"OUTDOOR",{ 0x08, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },56,2 ,{0,0,0,0,0,0,0,0,0,0}},//улица

Большое спасибо!

inspiritus
Offline
Зарегистрирован: 17.12.2012

Ну там вообщетто новые IDE после компилляции пишут про память.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

32 строка,, byte - беззнаковые, значит условие i >= 0 выполняется всегда, цикл бесконечный.

switch
Offline
Зарегистрирован: 07.12.2015

kisoft, спасибо! Но не помогло. Исполнение не доходит до этого участка кода вообще

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

У вас lastTime инициализируется в теле функции. Нужно сделать ее глобальной.

rekrut007
Offline
Зарегистрирован: 19.10.2014

switch пишет:

Если включить блок кода после комментария "раз в минуту сохраняем данные" то после вызова этой фунции ничего не работает. Сама функция - тоже, в последовательный порт не уходят сообщения, которые определены в начале функции. Подозреваю что дело в размере массива данных sensor[n].data[]: сейчас он определяется тупо так: 

  {"OUTDOOR",{ 0x08, 0xFF, 0x79, 0xF6, 0x01, 0x15, 0x02, 0xAA },56,2 ,{0,0,0,0,0,0,0,0,0,0}},//улица

Большое спасибо!

Функция millis возвращает значение не того типа, которое Вы определили переменной curtime.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

switch пишет:

Подскажите, пожалуйста, есть ли методы анализа сколько памяти используется?

http://andybrown.me.uk/2011/01/01/debugging-avr-dynamic-memory-allocation/

switch
Offline
Зарегистрирован: 07.12.2015

ЕвгенийП, спасибо, попробую!

Вот что получилось: 

Сейчас смотрю где память можно подрезать.  Хотя бы до 1 тыс. отсчетов увеличить.

Еще пытаюсь решить проблему с мерцанием и фиговым качеством  изображения. Особенно это видно когда рисуешь много линий. Например, графики те же. По экрану мерцают вертикальные линии хаотично...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, не знаю, как мерцает, а в статике красиво выглядит

switch
Offline
Зарегистрирован: 07.12.2015

Товарищи, имейте в виду что библиотека UTFT_Buttons с ходу отжирает около 500 байт ОЗУ. Ибо там одни классы и все в оперативке