Простой вызова функции увеличивает код на 150 байт

dvanto
Offline
Зарегистрирован: 26.12.2019

Беда...
Написал программу управления насосом


Стал прикручивать EEPROM - пишет, но как-то не понятно (читает мусор)

Для отладки добавляю вызов функции read_flash();, которая читает EEPROM и пишет, что записалось



Внезапно беда....

Без вызова код помещается в Arduino Pro mega168 16mhz:

Скетч использует 14288 байт (99%) памяти устройства. Всего доступно 14336 байт.
Глобальные переменные используют 802 байт (78%) динамической памяти, оставляя 222 байт для локальных переменных. Максимум: 1024 байт.

с одним дополнительным вызовом вырастает на 150 байтов:

Скетч использует 14438 байт (100%) памяти устройства. Всего доступно 14336 байт.
Глобальные переменные используют 802 байт (78%) динамической памяти, оставляя 222 байт для локальных переменных. Максимум: 1024 байт.

Что не так?
Как исправить?

 

void PumpOff()
{
  Log.notice( FF("Pump OFF - done: %i seconds" CR), pump_last_time );

  //noInterrupts();
  digitalWrite(SW_VALVE, LOW);
  digitalWrite(SW_MOTOR, LOW);
  //interrupts();

  pump = PUMP_OFF;

    lcd_on(true);
  lcd_status();

  // stat
   
  fv_pump.total_time += pump_last_time;
  fv_pump.total_volume += pump_last_volume;
    write_flash();

  // Log.notice( FF( "done: %i seconds" CR), pump_last_time );

   read_flash(); // <--- ПРОБЛЕМА ТУТ


  FlowTimeout.stop();
  TankTimeout.stop();

}

#define EEPROM_f(f, e_offset, v)        { EEPROM.f( e_offset, v ); e_offset += sizeof(v); }

bool read_flash()
{
    int e_offset = FLASH_OFFSET;
    uint16_t sign;

    EEPROM_f( get, e_offset, sign );
    e_offset += sizeof(sign);
    // Log.notice(STR_SXd_CR, FF("sign = "), sign, __LINE__);

    if ( sign == FLASH_SIGNATURE )
    {
        // Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
        EEPROM.get( e_offset, fv_pump );
        e_offset += sizeof(fv_pump);
        EEPROM.get( e_offset, fv_errors );
        EEPROM_f( get, e_offset, fv_pump.cnt );
        EEPROM_f( get, e_offset, fv_pump.owfl );
        EEPROM_f( get, e_offset, fv_pump.total_time );
        EEPROM_f( get, e_offset, fv_pump.total_volume );

        for(byte i=0; i<sizeof(fv_errors); i++ )
            EEPROM_f( get, e_offset, fv_errors[i] );
   
        // Log.notice(FF("read_flash done %d %d" CR), FLASH_OFFSET, e_offset);
   
        print_flash(__LINE__);
        return true;
    }
    else
    {
        Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
        for (byte i=0; i<sizeof(fv_errors); fv_errors[i++]=0);
        print_flash(__LINE__);
        write_flash(FLASH_SIGNATURE);
        return false;
    }

}


 

Полный скетч тут

/*
   Управление колодезным насосом

   Закачка воды в бак с двумя датчиками - нижний уровень и верхний
   Ограничение по времени заполнения бака
   Переход в аварийный режим при "непредсказуемом" поведении датчиков
   Вывод диагностической информации на LCD 1602 (16 символов, 2 строки)

   Рабочий режим
   | 1234567890123456 |
   | ABRLHO 000s 0000
   | STA msg456789012

   Доп режм - вкл по кнопке, возврат к рабочему режиму через 10 сек
   mode  0
   | 1234567890123456 |
   | T 0000s L 000000
   | C 00000 OF 00000

*/

// #include <avr/wdt.h>
#include <LowPower.h>               //  https://github.com/rocketscream/Low-Power
#include <EEPROM.h>
#include <ArduinoLog.h>             // https://github.com/thijse/Arduino-Log/
#include <avr/pgmspace.h>
#include <DebounceEvent.h>          // https://github.com/xoseperez/debounceevent
#include "Chrono.h"
#include <LiquidCrystal_PCF8574.h>
//#include <LiquidCrystal_I2C_OLED.h>


// #define DISABLE_LOGGING
// * 0 - LOG_LEVEL_SILENT     no output 
// * 1 - LOG_LEVEL_FATAL      fatal errors 
// * 2 - LOG_LEVEL_ERROR      all errors  
// * 3 - LOG_LEVEL_WARNING    errors, and warnings 
// * 4 - LOG_LEVEL_NOTICE     errors, warnings and notices 
// * 5 - LOG_LEVEL_TRACE      errors, warnings, notices & traces 
// * 6 - LOG_LEVEL_VERBOSE    all 
#define LOG_LEVEL			LOG_LEVEL_TRACE

#define SETFLAG(x) ( ++(x)?(x):(++(x)) )  // если увеличение дало 0, то увеличиваем еще раз


/* для работы со сторками из ПЗУ */
typedef const __FlashStringHelper* fchar;
//const char LOG_AS[] PROGMEM =

//#define FF(a) 			(a)
#define FF(a)       F(a)

// const char STR_D_CR[] PROGMEM  = ("%s (line:%d)" CR);
fchar STR_sd_CR;
fchar STR_SXd_CR;


/* настройки экарнчика */
#define	LCD_PORT 						0x27
#define LCD_WIDTH						16
LiquidCrystal_PCF8574 			lcd(LCD_PORT);


//*******************************************************************************************

#define PIN_OVERFLOW        PD5
#define PIN_HIGHMARK        PD6
#define PIN_LOWMARK         PD7

#define SW_OVERFLOW         5
#define SW_HIGH_MARK        6
#define SW_LOW_MARK         7

#define SW_MOTOR            8
#define SW_VALVE            9

/* 
#define LOWMARK_TIMEOUT     10 // s
#define HIGHMARK_TIMEOUT    427 // s = 0,468л/с 200 литров
#define SPEED_LPS           0.468 // liters per second
#define LCD_TIMEOUT         (LCD_STAT_TIME+10) // s
#define LCD_STAT_TIME       10 // s
#define STAT_DELAY			 		500 // ms
 */
 
#define LOWMARK_TIMEOUT     3 // s
#define HIGHMARK_TIMEOUT    30 // s = 0,468л/с 200 литров
#define SPEED_LPS           0.468 // liters per second
#define LCD_TIMEOUT         (LCD_STAT_TIME+5) // s
#define LCD_STAT_TIME       5 // s
#define STAT_DELAY			 		1000 // ms


//******************************************************************************************
//  EVENT_NONE EVENT_CHANGED EVENT_PRESSED EVENT_RELEASED
//  BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH | BUTTON_SET_PULLUP);
//  DebounceEvent button = DebounceEvent(BUTTON_PIN, BUTTON_SWITCH | BUTTON_SET_PULLUP);

volatile uint8_t f_Overflow = 0;
volatile uint8_t f_LowMark = 0;
volatile uint8_t f_HighMark = 0;

void btn_Overflow(uint8_t pin, uint8_t event, uint8_t count, uint16_t length);
void btn_LowMark(uint8_t pin, uint8_t event, uint8_t count, uint16_t length);
void btn_HighMark(uint8_t pin, uint8_t event, uint8_t count, uint16_t length);

DebounceEvent sw_Overflow  = DebounceEvent(SW_OVERFLOW,   btn_Overflow, BUTTON_PUSHBUTTON );
DebounceEvent sw_LowMark   = DebounceEvent(SW_LOW_MARK,   btn_LowMark,  BUTTON_PUSHBUTTON );
DebounceEvent sw_HighMark  = DebounceEvent(SW_HIGH_MARK,  btn_HighMark, BUTTON_PUSHBUTTON );

Chrono TankTimeout(Chrono::SECONDS);
Chrono FlowTimeout(Chrono::SECONDS);
Chrono LCD_Timeout(Chrono::SECONDS);
Chrono StatDelay(Chrono::MILLIS);


volatile uint8_t f_WDT = 0;

void _P_ShutdownMode() {} // просто отметка в редакторе

//******************************************************************************************
typedef enum : char { POWEROFF = 0,
											STANDBY,
											ABORT = -127,
											ERR_OVERFLOW,
											ERR_WATHCDOG,
											
											ERR_NO_FLOW,
											ERR_TANK_TIMEOUT,
											
											ERR_START_ABORTED_PUMP,
											ERR_INVALID_SENSORS,
											ERR_INV_LOWMARK_STATUS,
											ERR_INV_HIGHMARK_STATUS,
											ERR_HIGHMARK_UNATTENDED_RELEASE,
											ERR_LAST
											
										} t_ShutdownMode;
						
// ErrorNames[t_ShutdownMode-ABORT]			
																	// 1234567890123456
const  char ErrorMsg_1[] PROGMEM 	= "FATAL ABORT!";
const  char ErrorMsg_2[] PROGMEM 	= "OVRFLW DETECTED!";
const  char ErrorMsg_3[] PROGMEM 	= "WATCHDOG ALERT!";
const  char ErrorMsg_4[] PROGMEM 	= "NO FLOW! Chk WTR";
const  char ErrorMsg_5[] PROGMEM 	= "Tank Timout!";
const  char ErrorMsg_6[] PROGMEM 	= "Start failed!!!";
const  char ErrorMsg_7[] PROGMEM 	= "INVALID sensors!";
const  char ErrorMsg_8[] PROGMEM 	= "LM FTL! Chk SENS";
const  char ErrorMsg_9[] PROGMEM 	= "HM FTL! Chk SENS";
const  char ErrorMsg_10[] PROGMEM = "HM ERR! Chk SENS";

				
const  char* const  ErrorMsg[] PROGMEM = {
										ErrorMsg_1, ErrorMsg_2, ErrorMsg_3, ErrorMsg_4, ErrorMsg_5,
										ErrorMsg_6, ErrorMsg_7, ErrorMsg_8, ErrorMsg_9, ErrorMsg_10
};


//******************************************************************************************
typedef enum : byte { PUMP_OFF = 0,  PUMP_ABORT = 1, PUMP_ON = 2, PUMP_STANBDY = 3} t_PumpStatus;

t_PumpStatus pump 		= PUMP_OFF;

// statistic
struct t_flash_var_pump {
				int 						cnt;
				int     				owfl;
				unsigned long 	total_time;
				unsigned long		total_volume;
			};
								
t_flash_var_pump				fv_pump 							= {0,0,0,0};
t_flash_var_pump				fv_saved;
byte										fv_errors[ERR_LAST-ABORT];

unsigned 								pump_last_time        = 0;
unsigned								pump_last_volume      = 0;

char 										buf[20];

//******************************************************************************************

void Shutdown(t_ShutdownMode mode);
void Shutdown(t_ShutdownMode mode, fchar s1); //,fchar s2,);
// void Shutdown(t_ShutdownMode mode = POWEROFF, fchar s1 = NULL); //,fchar s2,);
// void Shutdown(t_ShutdownMode mode, fchar s1); //,fchar s2,);
// void Shutdown(t_ShutdownMode mode = POWEROFF, const char* s1 ); //, const char*  s2,

void log_internal_state();

//******************************************************************************************

inline char sw(bool f, char c ='F') 
{
  return f ? c : '_';
}

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

#define FLASH_SIGNATURE	0xADB4
#define FLASH_OFFSET		0x20

void print_flash(int l)
{
	sprintErrors(buf);
	Log.warning(FF("flash(%d): %x %x %x %x err=|%s|" CR), l,
		(int)fv_pump.cnt, (int)fv_pump.owfl, (int)fv_pump.total_time, (int)fv_pump.total_volume, buf);
		// fv_errors[0], fv_errors[1], fv_errors[2], fv_errors[3], fv_errors[4], fv_errors[5],
		// fv_errors[6], fv_errors[7], fv_errors[8], fv_errors[9]);
	
}

#define EEPROM_f(f, e_offset, v)		{ EEPROM.f( e_offset, v ); e_offset += sizeof(v); }

void write_flash(uint16_t sign = FLASH_SIGNATURE);
bool read_flash()
{
	int e_offset = FLASH_OFFSET;
	uint16_t sign;
	
	EEPROM_f( get, e_offset, sign );
	e_offset += sizeof(sign);
	// Log.notice(STR_SXd_CR, FF("sign = "), sign, __LINE__);
	
	if ( sign == FLASH_SIGNATURE )
	{
		// Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
		EEPROM.get( e_offset, fv_pump );
		e_offset += sizeof(fv_pump);
		EEPROM.get( e_offset, fv_errors );
		EEPROM_f( get, e_offset, fv_pump.cnt );
		EEPROM_f( get, e_offset, fv_pump.owfl );
		EEPROM_f( get, e_offset, fv_pump.total_time );
		EEPROM_f( get, e_offset, fv_pump.total_volume );
	
		for(byte i=0; i<sizeof(fv_errors); i++ ) 
			EEPROM_f( get, e_offset, fv_errors[i] );
		
		// Log.notice(FF("read_flash done %d %d" CR), FLASH_OFFSET, e_offset);
		
		print_flash(__LINE__);
		return true;
	}
	else 
	{
		Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
		for (byte i=0; i<sizeof(fv_errors); fv_errors[i++]=0);
		print_flash(__LINE__);
		write_flash(FLASH_SIGNATURE);
		return false;
	}
	
}


void write_flash(uint16_t sign)
{
	int e_offset = FLASH_OFFSET;
	
	Log.warning(STR_SXd_CR, FF("write flash: free mem = "), freeRam(), __LINE__);
	
	EEPROM_f( put, e_offset, sign );
	
	EEPROM_f( put, e_offset, fv_pump.cnt );
	EEPROM_f( put, e_offset, fv_pump.owfl );
	EEPROM_f( put, e_offset, fv_pump.total_time );
	EEPROM_f( put, e_offset, fv_pump.total_volume );
	
	for(byte i=0; i<sizeof(fv_errors); i++) 
		EEPROM_f( put, e_offset, fv_errors[i] );
	
	Log.notice(FF("write_flash done %d %d" CR), FLASH_OFFSET, e_offset);
	print_flash(__LINE__);
	
}


void lcd_on(bool timeout = false)
{
  lcd.setBacklight(255);
  lcd.clear();

// #if (LOG_LEVEL == LOG_LEVEL_VERBOSE)
	Log.trace(FF("lcd_on %d restart = %c" CR), __LINE__, timeout?'R':'-' );
// #endif
	
  if (timeout)
    LCD_Timeout.restart();
	else
		LCD_Timeout.stop();

}


char* sprintTime4(char* s, unsigned long v)
{
  if (v < 1000)
    sprintf(s, "%03lus", v);            // 000s
  else if (v < 100*60)
    sprintf(s, "%03lum", v/60);         // 000m
  else if (v < (unsigned long)10*60*60)
    sprintf(s, "%3.1fh", (float)v/3600);// 0.0h
  else
    sprintf(s, "%03luh", v/3600);       // 000h

  return s;
}


char* sprintTime5(char* s, unsigned long v)
{
  if (v < 10000)
    sprintf(s, "%04lus", v);            // 0000s
  else if (v < 100*60)
    sprintf(s, "%4.1fm", (float)v/60);  // 00.0m
  else if (v < (unsigned long)10*60*60)
    sprintf(s, "%4.2fh", (float)v/3600);// 0.00h
  else if (v < (unsigned long)100*60*60)
    sprintf(s, "%4.1fh", (float)v/3600);// 00.0h
  else
    sprintf(s, "%04luh", v/3600);       // 0000h

  return s;
}


char status_msg[]="INV\0OFF\0ABR\0ON!\0INV";

void lcd_status()
{
  char *s, c1, c2, c3;
  char s_time[5];
  char s_vol[5];
	char buf[LCD_WIDTH+1];

	// update stat
	pump_last_time = TankTimeout.elapsed();
  pump_last_volume = SPEED_LPS * pump_last_time;
	
  lcd.setCursor(0, 0);
  switch (pump)
  {
    case PUMP_OFF:
		case PUMP_STANBDY:
      s = status_msg+4;
      break;
    case PUMP_ABORT:
      s = status_msg+8;  // Abort
      break;
    case PUMP_ON:
      s = status_msg+12;
      break;
    default:
      s = status_msg;  // INVALID
  }
	
	sprintf(buf, "%s%c%c%c %s %04u", 
					s, 
					c1 = sw(sw_Overflow.pressed(), 'O'),
					c2 = sw(sw_HighMark.pressed(), 'F'),
					c3 = sw( sw_LowMark.pressed(), 'E'),
					sprintTime4(s_time, pump_last_time),
					pump_last_volume
					);
	lcd.print(buf);
	Log.notice( STR_sd_CR, buf, __LINE__);
	
  lcd.setCursor(0, 1);
}

int sprintErrors(char* buf)
{		
		char *s = buf;
		for(char i=0; i<sizeof(fv_errors); s+=sprintf(s, "%X", fv_errors[i++]));
		for(char* t = buf; *t; t++) 
			if (*t=='0') *t=' ';
		
		return s-buf;
}

void lcd_statistic(uint8_t mode=0)
{
														//12    34567890123456
	// char buf[LCD_WIDTH+5] = "T ";//00000 V 000000";
	int sh;
	
  switch (mode)
  {
    case 0:
    default:  // пока так
			
      lcd.setCursor(0, 0);
			*buf = 'T';
			*(buf+1)=' ';
			sprintTime5(buf+2, fv_pump.total_time);
			sprintf(buf+7, " V %06d", fv_pump.total_volume);
			
      lcd.print(buf);
			Log.notice( STR_sd_CR, buf, __LINE__);

      lcd.setCursor(0, 1);
			
			sh = sprintf( buf, "%03dE", fv_pump.cnt);
			sprintErrors( buf + sh );; //fv_pump.owfl);
			
			lcd.print(buf);
			Log.notice( FF("stat (%d): %i sh %i buf %s" CR), __LINE__, sh, buf);
			break;
  }

  //lcd_on(true);
}

//******************************************************************************************

void PumpOff()
{
  Log.notice( FF("Pump OFF - done: %i seconds" CR), pump_last_time );

  //noInterrupts();
  digitalWrite(SW_VALVE, LOW);
  digitalWrite(SW_MOTOR, LOW);
  //interrupts();

  pump = PUMP_OFF;
	
	lcd_on(true);
  lcd_status();
	
  // stat
		
  fv_pump.total_time += pump_last_time;
  fv_pump.total_volume += pump_last_volume;
	write_flash();

  // Log.notice( FF( "done: %i seconds" CR), pump_last_time );
	
	read_flash();
	

  FlowTimeout.stop();
  TankTimeout.stop();
  
}


// включает двигатель, если все нормально и запускает таймеры переполнения и нижнего датчика
void PumpOn()
{

  if (pump == PUMP_ABORT)
  {
    Shutdown(
      //  1234567890123456
      // FF("Start failed!!!" ),
      ERR_START_ABORTED_PUMP);
    return;
  }

  Log.notice( FF("Pump ON - " ) );

  // stat
  fv_pump.cnt++;

  digitalWrite(SW_VALVE, HIGH);
  digitalWrite(SW_MOTOR, HIGH);

  Log.notice( FF( "done" CR) );

  FlowTimeout.restart();
  TankTimeout.restart();
  StatDelay.restart();
	
  pump = PUMP_ON;

	lcd_on();
  lcd_status();
}


// уснуть - до следующего поплавка (POWEROFF) или навсегда
void _shutdown(t_ShutdownMode mode = POWEROFF)
{

#ifdef DEBUG
  return;
#endif

	// log_internal_state(-1);

  if (mode == POWEROFF)
  {
		// выключить свет и все
    lcd.setBacklight(0);
  }
  else {
    // FULL Shutdown !!!
    pump = PUMP_ABORT;

    // не просыпаться никогда
    // сделать блокировку до полного отключения
		PCICR = 0;
    PCMSK2 = 0;
	
  }

#if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
  Log.verbose(FF("powerDown %d (%d)" CR), mode, __LINE__);
#endif

  delay(100); // чтобы байтики через serial прошли ...перед глубоким сном
	
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
	
#if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
  Log.verbose(FF("wakeup %d" CR), __LINE__);
#endif
}

										
// печатает текст и останавливает устройство
// void Shutdown(t_ShutdownMode mode = POWEROFF, fchar s1 = NULL)

void Shutdown(t_ShutdownMode mode)
{
	char buf[20] = "empty";
	
	if ( !(mode == POWEROFF || mode == STANDBY) && mode > ERR_LAST) mode = ABORT;
	if (mode < POWEROFF)
	{
		byte &err = fv_errors[mode - ABORT];
		err += ((err&0x0f)<0x0f)?0x01:0;
		
		pump = PUMP_ABORT;
		
		sprintErrors(buf);
		Log.notice( FF("Shutdown mode %d %X %X %d %s (%d)" CR), mode, &err, fv_errors, sizeof(fv_errors), buf, __LINE__);

	}
	
	if (mode == STANDBY)
		mode = POWEROFF;
	else
	{
		PumpOff();
		
		// lcd_on(pump != PUMP_ABORT);
		lcd_on();
		lcd_status();
		
		strcpy_P(buf, (char*)pgm_read_word(&(ErrorMsg[mode-ABORT])));
		
		lcd.print( buf );
		Log.fatal( STR_sd_CR, buf, __LINE__);
	}
	
#ifdef WatchDog_h
  WatchDog::stop();
#endif
  f_WDT = 0;

  _shutdown(mode);
}

/* 
void A_Watchdog()
{
  wdt_disable();
  //f_WDT = 1;
  SETFLAG(f_WDT);
  //PumpOff();
}
 */
 
//***********************************************************************************************************************************************************

void btn_LowMark(uint8_t pin, uint8_t event, uint8_t count, uint16_t length)
{
// #if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
  Log.trace( FF(CR "LowMark: %i %x" CR), f_LowMark, event);
// #endif	
  //f_LowMark = 0;

  switch (event)
  {
    case EVENT_PRESSED:
      if (sw_HighMark.pressed()) {
#ifdef WatchDog_h
        WatchDog::start();
#endif
        PumpOn();
      } else {
        Shutdown(
          //  1234567890123456
          // FF("INVALID sensors!"),
          ERR_INVALID_SENSORS);
      }
      break;
    case EVENT_RELEASED:
      FlowTimeout.stop();
      break;
    default:
      Shutdown(
        //  1234567890123456
        // FF("LM FTL! Chk SENS" ),
        ERR_INV_LOWMARK_STATUS);
  }

}

void btn_HighMark(uint8_t pin, uint8_t event, uint8_t count, uint16_t length)
{
// #if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
  Log.trace( FF(CR "HighMark: %i %x" CR), f_HighMark, event);
// #endif 
	//f_HighMark = 0;

  //  must be pressed before
  switch (event)
  {
    case EVENT_PRESSED:
      // вода начала кончаться
			// игнорим
			lcd_on(true);
			lcd_status();
			lcd.print(FF("waiting....")); 
			pump = PUMP_STANBDY; // типа выключить экран, но текст не обновлять
      break;
    case EVENT_RELEASED:
      if (pump != PUMP_ON)
      {
        Shutdown(
          //  1234567890123456
          // FF("HM ERR! Chk SENS"),
          ERR_HIGHMARK_UNATTENDED_RELEASE);
      }
      else {
        PumpOff();

        // Shutdown(
        // FF("FULL TANK!" ),
        // FF("Success! :)" ));
      }
      break;
    default:
      Shutdown(
        //  1234567890123456
        // FF("HM FTL! Chk SENS"),
        ERR_INV_HIGHMARK_STATUS);
  }
}

void btn_Overflow(uint8_t pin, uint8_t event, uint8_t count, uint16_t length)
{
// #if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
  Log.trace(FF(CR "OVERFLOW: %i %x" CR), f_Overflow, event);
// #endif

  fv_pump.owfl++;

  // any change is dangerous!!!
  Shutdown(
    //  1234567890123456
    // FF("OVRFLW DETECTED!" ),
    ERR_OVERFLOW);
}

//***********************************************************************************************************************************************************

volatile uint8_t portBhistory = 0x00;     // default is high because the pull-up
volatile uint8_t portChistory = 0x00;
volatile uint8_t portDhistory = 0x00;     // не pool-up
volatile long t = 0;

ISR(PCINT2_vect)
{
  // t = millis();
  uint8_t changedbits;

  //PCIMSK2
  changedbits = PIND ^ portDhistory;
  portDhistory = PIND;

  if (changedbits & (1 << PIN_OVERFLOW))
  {
    SETFLAG(f_Overflow);
  }

  if (changedbits & (1 << PIN_HIGHMARK))
  {
    SETFLAG(f_HighMark);
  }

  if (changedbits & (1 << PIN_LOWMARK))
  {
    SETFLAG(f_LowMark);
  }

}
/* 
ISR(PCINT0_vect)
{
  t = millis();
  uint8_t changedbits;

  // PCIMSK0
  changedbits = PINB ^ portBhistory;
  portBhistory = PINB;

   // if (changedbits & (1 << PIN_OVERFLOW))
   // {
     // SETFLAG(f_Overflow);
   // }
  
   // if (changedbits & (1 << PIN_HIGHMARK))
   // {
     // SETFLAG(f_HighMark);
   // }
  
   // if (changedbits & (1 << PIN_LOWMARK))
   // {
     // SETFLAG(f_LowMark);
   // }

}
 */
 
 /* 
ISR(INT1_vect)
{

}
 */

#ifdef WatchDog_h
//volatile uint8_t  = 0;
ISR(WDT_vect) {
#ifdef WatchDog_h
  if (Wdog1.active())   {
    if (WatchDog::ovfCounter < WatchDog::ovfTop) {
      WatchDog::ovfCounter++;
    } else {
      WatchDog::ovfCounter = 0;
      Wdog1.isrCallback();
    }
  } else
#endif
    wdt_disable();
  //if (++f_WDT == 0) ++f_WDT;
  SETFLAG(f_WDT);
}
#endif

void log_internal_state(int l_cnt)
{
#if (LOG_LEVEL == LOG_LEVEL_VERBOSE)
    unsigned long e1 =   FlowTimeout.elapsed();
    unsigned long e2 =   TankTimeout.elapsed();
		unsigned long e3 =   LCD_Timeout.elapsed();
		unsigned long e4 =   StatDelay.elapsed();
						
    Log.trace( FF("l_cnt = %d, t = %l f_WDT %i, f_Overflow %i, f_LowMark %i, f_HighMark %i, " CR
									"        portBhistory %X, portChistory %X, portDhistory %X, " CR
									"        FlowTimeout = %c %l, TankTimeout = %c %l, LCD_Timeout = %c %l, StatDelay = %c %l" CR),
               l_cnt, t, f_WDT, f_Overflow, f_LowMark, f_HighMark,
               portBhistory, portChistory, portDhistory, 
							 sw( FlowTimeout.isRunning(), 'R') , e1, sw( TankTimeout.isRunning(), 'R'), e2, 
							 sw( LCD_Timeout.isRunning(), 'R'), e3, sw( StatDelay.isRunning(), 'R'), e4
		);
#endif
}


//***********************************************************************************************************************************************************


void setup() 
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println(FF(CR "In the begining...") );

  // lcd.init();
  lcd.begin(16, 2);
  lcd.noAutoscroll();
  lcd_on(true);
  lcd.print(FF("Starting..."));
  //  lcd.setCursor(0,1);
  //  lcd.print("Starting...");

	STR_sd_CR = FF("%s (line:%d)" CR);
	STR_SXd_CR = FF("%S %X (line:%d)" CR);
	
  Log.begin(LOG_LEVEL, &Serial);
  Log.notice( FF(CR "******************************************" CR) );                     // Info string with Newline

#ifdef WatchDog_h
	Log.notice( FF("WatchDog::init(A_Watchdog, OVF_8000MS, STOP);" CR) );
  WatchDog::init(A_Watchdog, OVF_8000MS, STOP);
#endif
	
	// write_flash(0); // только один раз для платы
	read_flash();

  pinMode(SW_MOTOR, OUTPUT);
  pinMode(SW_VALVE, OUTPUT);
	
  PumpOff();

  lcd_status();
  lcd.print( FF("READY!!!") );
	StatDelay.start();

	PORTD |= (1 << PORTD5) | (1 << PORTD6) | (1 << PORTD6);
  
  // разрешение прерываний INT0 и INT1
  //  EIMSK  =  (1<<INT0)  | (1<<INT1);
	
  // настройка срабатывания прерываний на любому изменению
  //EICRA  =  (0<<ISC11) | (1<<ISC10) | (0<<ISC01) | (1<<ISC00);
	
  // разрешение прерываний с портов B (PCINT[7:0]) и D (PCINT[23:16]), и запрет с порта C (PCINT[14:8])
  PCICR  |= (1 << PCIE2) | (0 << PCIE1) | (0 << PCIE0);
	
  // маскирование всех ног, кроме PB0 и PD7 - по одной на PCINT0 и PCINT2
  //PCMSK0 |= (0 << PCINT7)  | (0 << PCINT6)  | (0 << PCINT5)  | (0 << PCINT4)  | (0 << PCINT3)  | (0 << PCINT2)  | (0 << PCINT1)  | (1 << PCINT0);
  //PCMSK1 |=                (0 << PCINT14) | (0 << PCINT13) | (0 << PCINT12) | (0 << PCINT11) | (0 << PCINT10) | (0 << PCINT9)  | (0 << PCINT8);
  PCMSK2 |= (1 << PCINT23) | (1 << PCINT22) | (1 << PCINT21) | (0 << PCINT20) | (0 << PCINT19) | (0 << PCINT18) | (0 << PCINT17) | (0 << PCINT16);

}

//***********************************************************************************************************************************************************
uint8_t l_cnt = 0;
#define CNT_DIV 3

void loop() 
{

#ifdef LowPower_h
	// дремать если мотор выключен
  if ( (pump == PUMP_OFF || pump == PUMP_STANBDY) && 
			!LCD_Timeout.isRunning() &&
			!StatDelay.isRunning() &&
			!TankTimeout.isRunning() &&
			!FlowTimeout.isRunning()
		  )
  {
#if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
    Log.verbose(FF("Sleep %d" CR), __LINE__);
#endif		
		delay(10);	// чтобы байтики через serial прошли ...перед сном
		LowPower.idle(SLEEP_2S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_ON, SPI_OFF, USART0_OFF, TWI_OFF);
    //LowPower.idle(SLEEP_2S, ADC_OFF, TIMER2_ON, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_ON, TWI_OFF);
    //LowPower.idle(SLEEP_2S, ADC_OFF, TIMER2_ON, TIMER1_ON, TIMER0_ON, SPI_OFF, USART0_OFF, TWI_OFF);
#if (LOG_LEVEL == LOG_LEVEL_VERBOSE)	
    Log.verbose(FF("wakeup %d" CR), __LINE__);
#endif		
  }
#else
	delay(100); // если нет LowPower
#endif

	l_cnt++;

  if ( StatDelay.hasPassed(STAT_DELAY, true) )
  {
		// log_internal_state(l_cnt);
					
		if (pump == PUMP_ON) 
		{
			lcd_status();
			// дописать текущий тайминг
		}
  }

/* 
  if (0 & f_WDT) 
  {
    Shutdown(
      //  1234567890123456
      // FF("WATCHDOG ALERT!" ),
      ERR_WATHCDOG);
  }
 */


	if (LCD_Timeout.hasPassed(LCD_TIMEOUT)) 
	{
		// if (pump == PUMP_OFF)
		{
			// lcd_off:
			lcd.clear();
			lcd_status();
			lcd.print(("READY! cnt=")); lcd.print(fv_pump.cnt);
			pump = PUMP_STANBDY;		
		}
		
		LCD_Timeout.stop();
		LCD_Timeout.add( -LCD_Timeout.elapsed() );
		lcd.setBacklight(0);
			

		Shutdown(STANDBY);

	}
	else if ((pump == PUMP_OFF) && LCD_Timeout.hasPassed(LCD_STAT_TIME))
	{
		pump = PUMP_STANBDY;
		lcd_statistic();
	}


  if (FlowTimeout.hasPassed(LOWMARK_TIMEOUT)) 
  {
    Shutdown(
      //  1234567890123456
      // FF("NO FLOW! Chk WTR" ),
      ERR_NO_FLOW);
  }

  if (TankTimeout.hasPassed(HIGHMARK_TIMEOUT)) 
  {
    Shutdown(
      //  1234567890123456
      // FF("Tank Timout!" ),
      ERR_TANK_TIMEOUT);
  }

  // put your main code here, to run repeatedly:

  sw_Overflow.loop();
  sw_HighMark.loop();
  sw_LowMark.loop();

  if (sw_LowMark.pressed() && !sw_HighMark.pressed()) 
  {
    Shutdown(
      //  1234567890123456
      // FF("Sensors error!" ),
      ERR_INVALID_SENSORS);
  }

}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

А что не так? Объем должен был уменьшиться?

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

Тип float притянут на ровном месте, только для вывода. Во-первых это жирно, а во-вторых, работать не должно, не работает здесь sprint с float (разве что у Вас нестандартная библиотека) - оно Вам что предупреждений не писало?

Уберите всякое упоминание о float и напишите вывод руками - сэкономите килобайта полтора.

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

dvanto - а что вы хотели? - вы добавили процедуру длиной 40 строчек - и у вас код увеличился всего на 150 байт? - считайте повезло...

dvanto
Offline
Зарегистрирован: 26.12.2019

функция read_flash() вызывается из setup(), т.е. ее код уже есть в бинарнике

но!

почему-то добавление еще одного вызова приводит к росту кода на 150б

здесь asm без вызова

000013aa <PumpOff()>:

        	80 91 f3 01 	lds	r24, 0x01F3	; 0x8001f3 <pump_last_time+0x1>
        	8f 93       	push	r24
        	80 91 f2 01 	lds	r24, 0x01F2	; 0x8001f2 <pump_last_time>
        	8f 93       	push	r24
        	81 e4       	ldi	r24, 0x41	; 65
        	91 e0       	ldi	r25, 0x01	; 1
        	9f 93       	push	r25
        	8f 93       	push	r24
        	1f 92       	push	r1
        	84 e0       	ldi	r24, 0x04	; 4
        	8f 93       	push	r24
        	80 e9       	ldi	r24, 0x90	; 144
        	93 e0       	ldi	r25, 0x03	; 3
        	9f 93       	push	r25
        	8f 93       	push	r24
        	0e 94 3e 0d 	call	0x1a7c	; 0x1a7c <void Logging::printLevel<__FlashStringHelper const*>(int, __FlashStringHelper const*, ...) [clone .constprop.42]>
        	60 e0       	ldi	r22, 0x00	; 0
        	89 e0       	ldi	r24, 0x09	; 9
        	0e 94 44 10 	call	0x2088	; 0x2088 <digitalWrite>
        	60 e0       	ldi	r22, 0x00	; 0
        	88 e0       	ldi	r24, 0x08	; 8
        	0e 94 44 10 	call	0x2088	; 0x2088 <digitalWrite>
        	10 92 c4 02 	sts	0x02C4, r1	; 0x8002c4 <pump>
        	81 e0       	ldi	r24, 0x01	; 1
        	0e 94 99 09 	call	0x1332	; 0x1332 <lcd_on(bool)>
        	0e 94 71 08 	call	0x10e2	; 0x10e2 <lcd_status()>
        	e9 ed       	ldi	r30, 0xD9	; 217
        	f2 e0       	ldi	r31, 0x02	; 2
        	20 91 f2 01 	lds	r18, 0x01F2	; 0x8001f2 <pump_last_time>
        	30 91 f3 01 	lds	r19, 0x01F3	; 0x8001f3 <pump_last_time+0x1>
        	84 81       	ldd	r24, Z+4	; 0x04
        	95 81       	ldd	r25, Z+5	; 0x05
        	a6 81       	ldd	r26, Z+6	; 0x06
        	b7 81       	ldd	r27, Z+7	; 0x07
        	82 0f       	add	r24, r18
        	93 1f       	adc	r25, r19
        	a1 1d       	adc	r26, r1
        	b1 1d       	adc	r27, r1
        	84 83       	std	Z+4, r24	; 0x04
        	95 83       	std	Z+5, r25	; 0x05
        	a6 83       	std	Z+6, r26	; 0x06
        	b7 83       	std	Z+7, r27	; 0x07
        	20 91 f0 01 	lds	r18, 0x01F0	; 0x8001f0 <pump_last_volume>
        	30 91 f1 01 	lds	r19, 0x01F1	; 0x8001f1 <pump_last_volume+0x1>
        	80 85       	ldd	r24, Z+8	; 0x08
        	91 85       	ldd	r25, Z+9	; 0x09
        	a2 85       	ldd	r26, Z+10	; 0x0a
        	b3 85       	ldd	r27, Z+11	; 0x0b
        	82 0f       	add	r24, r18
        	93 1f       	adc	r25, r19
        	a1 1d       	adc	r26, r1
        	b1 1d       	adc	r27, r1
        	80 87       	std	Z+8, r24	; 0x08
        	91 87       	std	Z+9, r25	; 0x09
        	a2 87       	std	Z+10, r26	; 0x0a
        	b3 87       	std	Z+11, r27	; 0x0b
        	0e 94 82 0f 	call	0x1f04	; 0x1f04 <write_flash(unsigned int) [clone .constprop.33]>
        	8f ea       	ldi	r24, 0xAF	; 175
        	93 e0       	ldi	r25, 0x03	; 3
        	0e 94 00 07 	call	0xe00	; 0xe00 <Chrono::stop()>
        	8d b7       	in	r24, 0x3d	; 61
        	9e b7       	in	r25, 0x3e	; 62
        	08 96       	adiw	r24, 0x08	; 8
        	0f b6       	in	r0, 0x3f	; 63
        	f8 94       	cli
        	9e bf       	out	0x3e, r25	; 62
        	0f be       	out	0x3f, r0	; 63
        	8d bf       	out	0x3d, r24	; 61
        	8a eb       	ldi	r24, 0xBA	; 186
        	93 e0       	ldi	r25, 0x03	; 3
        	0c 94 00 07 	jmp	0xe00	; 0xe00 <Chrono::stop()>

вот код с вызовом

0000153e <PumpOff()>:
        	80 91 f3 01 	lds	r24, 0x01F3	; 0x8001f3 <pump_last_time+0x1>
        	8f 93       	push	r24
        	80 91 f2 01 	lds	r24, 0x01F2	; 0x8001f2 <pump_last_time>
        	8f 93       	push	r24
        	8c e6       	ldi	r24, 0x6C	; 108
        	91 e0       	ldi	r25, 0x01	; 1
        	9f 93       	push	r25
        	8f 93       	push	r24
        	1f 92       	push	r1
        	84 e0       	ldi	r24, 0x04	; 4
        	8f 93       	push	r24
        	80 e9       	ldi	r24, 0x90	; 144
        	93 e0       	ldi	r25, 0x03	; 3
        	9f 93       	push	r25
        	8f 93       	push	r24
        	0e 94 d3 0d 	call	0x1ba6	; 0x1ba6 <void Logging::printLevel<__FlashStringHelper const*>(int, __FlashStringHelper const*, ...) [clone .constprop.42]>
        	60 e0       	ldi	r22, 0x00	; 0
        	89 e0       	ldi	r24, 0x09	; 9
        	0e 94 d9 10 	call	0x21b2	; 0x21b2 <digitalWrite>
        	60 e0       	ldi	r22, 0x00	; 0
        	88 e0       	ldi	r24, 0x08	; 8
        	0e 94 d9 10 	call	0x21b2	; 0x21b2 <digitalWrite>
        	10 92 c4 02 	sts	0x02C4, r1	; 0x8002c4 <pump>
        	81 e0       	ldi	r24, 0x01	; 1
        	0e 94 99 09 	call	0x1332	; 0x1332 <lcd_on(bool)>
        	0e 94 71 08 	call	0x10e2	; 0x10e2 <lcd_status()>
        	e9 ed       	ldi	r30, 0xD9	; 217
        	f2 e0       	ldi	r31, 0x02	; 2
        	20 91 f2 01 	lds	r18, 0x01F2	; 0x8001f2 <pump_last_time>
        	30 91 f3 01 	lds	r19, 0x01F3	; 0x8001f3 <pump_last_time+0x1>
        	84 81       	ldd	r24, Z+4	; 0x04
        	95 81       	ldd	r25, Z+5	; 0x05
        	a6 81       	ldd	r26, Z+6	; 0x06
        	b7 81       	ldd	r27, Z+7	; 0x07
        	82 0f       	add	r24, r18
        	93 1f       	adc	r25, r19
        	a1 1d       	adc	r26, r1
        	b1 1d       	adc	r27, r1
        	84 83       	std	Z+4, r24	; 0x04
        	95 83       	std	Z+5, r25	; 0x05
        	a6 83       	std	Z+6, r26	; 0x06
        	b7 83       	std	Z+7, r27	; 0x07
        	20 91 f0 01 	lds	r18, 0x01F0	; 0x8001f0 <pump_last_volume>
        	30 91 f1 01 	lds	r19, 0x01F1	; 0x8001f1 <pump_last_volume+0x1>
        	80 85       	ldd	r24, Z+8	; 0x08
        	91 85       	ldd	r25, Z+9	; 0x09
        	a2 85       	ldd	r26, Z+10	; 0x0a
        	b3 85       	ldd	r27, Z+11	; 0x0b
        	82 0f       	add	r24, r18
        	93 1f       	adc	r25, r19
        	a1 1d       	adc	r26, r1
        	b1 1d       	adc	r27, r1
        	80 87       	std	Z+8, r24	; 0x08
        	91 87       	std	Z+9, r25	; 0x09
        	a2 87       	std	Z+10, r26	; 0x0a
        	b3 87       	std	Z+11, r27	; 0x0b
        	0e 94 17 10 	call	0x202e	; 0x202e <write_flash(unsigned int) [clone .constprop.33]>
        	0e 94 0c 0a 	call	0x1418	; 0x1418 <read_flash()>
        	8f ea       	ldi	r24, 0xAF	; 175
        	93 e0       	ldi	r25, 0x03	; 3
        	0e 94 3a 07 	call	0xe74	; 0xe74 <Chrono::stop()>
        	8d b7       	in	r24, 0x3d	; 61
        	9e b7       	in	r25, 0x3e	; 62
        	08 96       	adiw	r24, 0x08	; 8
        	0f b6       	in	r0, 0x3f	; 63
        	f8 94       	cli
        	9e bf       	out	0x3e, r25	; 62
        	0f be       	out	0x3f, r0	; 63
        	8d bf       	out	0x3d, r24	; 61
        	8a eb       	ldi	r24, 0xBA	; 186
        	93 e0       	ldi	r25, 0x03	; 3
        	0c 94 3a 07 	jmp	0xe74	; 0xe74 <Chrono::stop()>

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Я бы не стал гадать имея включенной опцию оптимизации компилятора...

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

dvanto - вам тут и на Амперке посоветовали. как уменьшить ваш код на 1.5 -2 Кб, а все о каких-то 150 байт переживаете

Уберите для начала float и sprintf из кода

dvanto
Offline
Зарегистрирован: 26.12.2019

b707 пишет:

dvanto - вам тут и на Амперке посоветовали. как уменьшить ваш код на 1.5 -2 Кб, а все о каких-то 150 байт переживаете

Уберите для начала float и sprintf из кода

это сделал

вопрос остается

 

хочется понимать причины роста, иначе вся оптимизация коту под хвост

типа, ты все оптимизировал, убрал последние лишние 10 байт, и тут - хлоп - у тебя один вызов +150 ((

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

Вы бы ещё больше использовали шаблонные функции :)

А хотите разобраться - возьмите ассемблерный текст полностью и сравните вызовы один и второй.

dvanto
Offline
Зарегистрирован: 26.12.2019

ЕвгенийП пишет:

Вы бы ещё больше использовали шаблонные функции :)

А хотите разобраться - возьмите ассемблерный текст полностью и сравните вызовы один и второй.

 

сравнил уже - разница 8 байт

где-то компилятор что-то лишнее пихает, но где и причина не понято

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

dvanto пишет:

сравнил уже - разница 8 байт

где-то компилятор что-то лишнее пихает, но где и причина не понято

все излишки сдать на общественный склад под роспись!