Question about sketch size

Hello forum !

I am doing a temperature sensor based on a DS18B20 and a wireless communication using 433mhz channel.
I am using an Arduino Leornardo. Everything works perfectly !

Now I plan to build 5 wireless temperature sensor, so I will use some Attiny45 to replace the Arduino.

My question is about the sketch size: it is 6,5Kb. Unfortunately Attiny45 has only 4,5Kb of flash.

So I am investigating how to reduce the code size.

I found that some function with only few lines of code are about 6-700 bytes. It is too much ! So I tried to comment out the code line by line to understand what are the lines responsible of that. Here is the result of my investigation:

byte readBit(int pin) {
unsigned long start=micros();
noInterrupts();
// Until this line, code is very small, about few bytes
measTime(start,2ul);
// If I add the line above, code size increase approximatively by 600bytes !!!

}

Note that the function measTime() is called in many places in my code, so it is not a compiler optimisation which remove unused function. Event if I replace function call measTime by an Arduino specific command pinMode(pin,OUTPUT) result is the same…

It look like there is a "step-effect" on code size somewhere. I suspect other functions of my code having this situation, leading to an overall memory consumption of 6,5Kb.

Do you have any clues to understand this ?

My IDE version is 1.0.5

Best regards, and happy new years !

Grégoire

We would maybe get more clues if you posted all of your code.

Sure !

Here is the full code, function is readBit(): 694 bytes. Function sendBit() which is quite similar is only 246 bytes.

I also suspect (not confirmed) the same issue for functions:

  • readTemp(): 1400 bytes
  • resetWire(): 1338 bytes

Regards,

Grégoire.
------------ Code ---------

#define NOTEMP 0xFFFF

int pintemp=2;
int pinrfpwr=3;
int pinrfdat=4;

byte tabcrc[256]={
  0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
 35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
190,224,  4, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
 87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107,53
};

void measTime(unsigned long start, unsigned long delay) {
  unsigned long top;
  unsigned long t1,t2;
  unsigned long t;
  
  do {
    top = micros();
    if( top < start ) { // timer loop every 70minutes 
      t1=start-top-1;
      t2=0xFFFFFFFF;
      t=t2-t1;
      start=0;
      top=t;
    }
    t=top-start;
  }
  while( t<delay );
  
  return;
}

void sendBit(byte pin, byte bit) {
  unsigned long start = micros();
  digitalWrite(pin,LOW);
  pinMode(pin,OUTPUT);
  if( bit==1 ) {
    measTime(start,10ul);
    pinMode(pin,INPUT);
    measTime(start,60ul);
  }
  else {
    measTime(start,60ul);
    pinMode(pin,INPUT);
    measTime(start,65ul);
  }
}

byte readBit(int pin) {
  unsigned long start=micros();
  noInterrupts();
  pinMode(pin,OUTPUT);
  measTime(start,2ul);
  pinMode(pin,INPUT);
  measTime(start,10ul);
  byte value = digitalRead(pin);
  interrupts();
  while( digitalRead(pin)==0 );
  measTime(start,60ul);
  return value;
}

void sendByte(byte pin, byte data) {
  byte i,b;
  for( i=0 ; i<8 ; i++ ) {
    b=data&0x01;
    sendBit(pin,b);
    data=data>>1;
  }
}

byte readByte(byte pin) {
  byte data=0;
  byte i,d;
  for( i=0 ; i<8 ; i++ ) {
    d = readBit(pin);
    data = data | (d<<i);
  }
  return data;
}

// Return 1 in cas of success

byte resetWire(byte pin) {
  
  unsigned long start;
  
  // Write 0 for at least 480us. Choose 500us.
  start = micros();
  pinMode(pin,OUTPUT);  
  measTime(start,500ul);
  
  // Slave must answer a 0 between 15 and 60, and goes up between 75 to 300us
  // Choose measure at 65us. 
  start = micros();
  pinMode(pin,INPUT);
  measTime(start,65ul);
  
  byte level = digitalRead(pin);
  byte present=0;
  if( level==LOW ) 
    present=1;
  while( digitalRead(pin)==LOW );
  return present;  
}

int readTemp(byte pin) {
  int temp=NOTEMP;
  byte i,d;
  byte crc,index;
  byte wdata[8];
  byte wcrc;

  d = resetWire(pin);
  if(d==1) {
    sendByte(pin,0xCC);
    sendByte(pin,0x4E);
    sendByte(pin,0); // low threshold
    sendByte(pin,1); // high threshold
    sendByte(pin,31); // 9 bits conversion
    resetWire(pin);
    sendByte(pin,0xCC);
    sendByte(pin,0x44);
    do {
      d=readBit(pin);
    }
    while(d==0);

    resetWire(pin);
    sendByte(pin,0xCC);
    sendByte(pin,0xBE);
    
    for( i=0 ; i<8 ; i++ ) {
      d=readByte(pin);
      wdata[i]=d;
    }
    wcrc=readByte(pin);        
    
    crc=0;
    for( i=0 ; i<8 ; i++ ) {
      index=crc^wdata[i];
      crc=tabcrc[index];
    }
    
    if( crc==wcrc ) {
      
      temp=wdata[1]<<8 | wdata[0];
      boolean neg = wdata[1]>>7 == 1;
      if( neg ) temp = (!temp)-1;
      byte degree=temp>>4;
      byte t=(temp>>2) & 0x03;
      byte values [4]={0,25,50,75};
      byte cdegree=values[t];
      temp = degree*100 + cdegree;
      if( neg ) temp = (!temp)+1;
    }
  }
  
  return temp;
}

void rfsend(byte pin,unsigned int period, byte b0, byte b1, byte b2, byte b3) {
  pinMode(pin,OUTPUT);
  byte synchro=B10101010;
  byte start=B11001100;
  rfsendbyte(pin,period,synchro);
  rfsendbyte(pin,period,start);
  rfsendbyte(pin,period,b0);
  rfsendbyte(pin,period,b1);
  rfsendbyte(pin,period,b2);
  rfsendbyte(pin,period,b3);
}

void rfsendbyte(byte pin,unsigned int micro,byte b) {
  int i=0;
  for( int i=0 ; i<8 ; i++ ) {
    byte data = b&B10000000;
    b=b<<1;
 
    if( data==0 ) {
      digitalWrite(pin,HIGH);
      delayMicroseconds(micro);
      digitalWrite(pin,LOW);
      delayMicroseconds(micro);
    }
    else {
      digitalWrite(pin,LOW);
      delayMicroseconds(micro);
      digitalWrite(pin,HIGH);
      delayMicroseconds(micro);
    }
  }
}

void setup() {

  pinMode(pintemp,INPUT);
  digitalWrite(pintemp,LOW);
  
  pinMode(pinrfpwr,OUTPUT);
  digitalWrite(pinrfpwr,LOW);
  
  pinMode(pinrfdat,OUTPUT);
  digitalWrite(pinrfdat,LOW);
}

void loop() {
  byte tl,th;
  
  int temp = readTemp(pintemp);
  if( temp != NOTEMP ) {
    digitalWrite(pinrfpwr,HIGH);
    delay(10);
    tl = temp & 0xFF;
    th = temp>>8 & 0xFF;
    rfsend(pinrfdat,1000,'d',0, th, tl);
    digitalWrite(pinrfpwr,LOW);
  }
  delay(5000);
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.