Pages: [1] 2 3   Go Down
Author Topic: Arduino 1.0 produces 25% larger binary?  (Read 7241 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I upgraded to 1.0 yesterday. It took me a while to adapt the libraries (e.g. ds1307 clock), but I managed to get it compiled. The sketch used about 25k of flash before, now I can't upload it anymore to the Arduino Uno, because it's blown up to 31,5k.

I make use of Ethernet, SD, Wire, OneWire, DallasTemperature, DS1307 and DHT11 (humidity sensor) libraries. If helpfull, I can post the sketch.

Any help greatly appreciated!
Logged

0
Offline Offline
God Member
*****
Karma: 26
Posts: 621
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OneWire 2.1 has an option, if you edit OneWire.h, to use a small but slower CRC algorithm.  For OneWire 2.0, the slow code was the default.  2.1 defaults to the fast code.  The size change should be about 250 bytes.

Unfortunately, some of 1.0's new features, like xyz.print() returning byte counts, simply consume more code space.

If you had posted code, I might have investigated if any one thing was a huge contributor to the size change.  But instead, I'm writing this message..  (hint: your chances of more useful help are always better if you post code that demonstrates your problem).
Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your reply! I'd love some expert have a look at the code in any case! smiley Some of the variable and function names are german, I am afraid. Here it is:
Code:
#include <MemoryFree.h>
#include <EEPROM.h>
#include <SD.h> //SD-Karte
#include <SPI.h> //Kommunikation mit Ethernet-Shield
#include <Ethernet.h>
//#include <dht11.h> //Feuchte-Sensor
#include <OneWire.h> //Kommunikation mit Temperatur-Sensoren
#include <DallasTemperature.h> //Temperatur-Sensoren
#include <Wire.h>  //I2C für Uhr
#include <DS1307.h> //Uhr-Chip
//#include <Arduino.h>

#define DHT11PIN 2 //Digitaler Pin, an dem DHT11 angeschlossen ist
#define ONE_WIRE_BUS 3 //Digitaler Pin für 1-Wire

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 177 };

// Initialize the Ethernet server library (port 80 is default for HTTP)
EthernetServer server(80);
//dht11 feuchtesensor;
OneWire oneWire(ONE_WIRE_BUS); //Instanz für 1-Wire-Device
DallasTemperature tempSensors(&oneWire); //Temperatursensor
int uhrzeit[7];
const int relais1 = 5, relais2 = 6; //Relais für Pumpe auf Pins 5, 6
const char eingabeTaste = 13;
const char tabTaste = 9;
//const char refreshString[] = "<meta http-equiv=\"refresh\" content=\"1; URL=/\">";
boolean nichtGespeichert = true; //fuer minuetliches Speichern

void setup()
{
  Serial.begin(9600); //serielle Verbindung über USB starten

  Ethernet.begin(mac, ip); // start the Ethernet connection
  server.begin(); // Ethernet Server starten
  tempSensors.begin(); // 1-Wire-Temperatursensoren starten
  pinMode(10, OUTPUT); //fuer SD-Karte: Chip select pin als OUTPUT setzen
  while (!SD.begin(4)) {  //nur mit SD-Karte geht's weiter!
    Serial.println("SD-Karte?!");
    delay(200);
  };
  DDRC|=_BV(2) |_BV(3);  // POWER:Vcc Gnd  muss was für I2C sein, für die Uhr
  PORTC |=_BV(3);  // VCC PINC3
  //stelleUhr(); //Uhr nur einmal stellen!!

  pinMode(relais1, OUTPUT); //Pin für relais1
  pinMode(relais2, OUTPUT); //Pin für relais2
}


void loop()
{
  RTC.get(uhrzeit,true); //Uhrzeit einlesen
  if (uhrzeit[0]<30 && nichtGespeichert) {  //einmal in der Minute
    //readDHT11(); //DHT11-Feuchtesenser lesen und schreiben
    tempSensors.requestTemperatures();  // 1-Wire lesen
    werteSpeichern(); //Daten mit Zeitstempel speichern
    nichtGespeichert = false;
  }
  else if (uhrzeit[0]>=30) nichtGespeichert = true;
  webServer();
  controlHeater();
}


void controlHeater()
{
  float tempSollTag = changeTemp("h/tetag.htm",'=');
  float tempSollNacht = changeTemp("h/tenac.htm",'=');
  float tempSollWasser = changeTemp("h/tewas.htm",'=');
  DeviceAddress tempHV={ 0x28, 0x99, 0x88, 0x4A, 0x03, 0x00, 0x00, 0xD3 };
  DeviceAddress tempHR={ 0x28, 0x99, 0x87, 0xAD, 0x02, 0x00, 0x00, 0xD8 };
  DeviceAddress tempSpeicherOben ={ 0x28, 0x86, 0x5A, 0x08, 0x03, 0x00, 0x00, 0x96 };
  DeviceAddress tempSpeicherMitte={ 0x28, 0x71, 0x4C, 0x08, 0x03, 0x00, 0x00, 0x81 };
  DeviceAddress tempSpeicherUnten={ 0x28, 0xCA, 0x75, 0x08, 0x03, 0x00, 0x00, 0x09 };
  DeviceAddress tempAussen={ 0x28, 0xD8, 0xC1, 0xAD, 0x02, 0x00, 0x00, 0xEF };

}

void webServer()
{
  EthernetClient client = server.available();   // listen for incoming clients
  if (client)
  {
    // an http request ends with a blank line
    char* anfrage="h/12345.678";
    int zeichenzaehler=0;
    while (client.available()) {
      char charVomClient = client.read();
      if ((zeichenzaehler++ >= 5) &&(zeichenzaehler <=14))
        anfrage[zeichenzaehler-4] = charVomClient;  //Zeichen 12345.678 nach anfrage
      Serial.print(charVomClient);
    }
    Serial.println();
    Serial.print("Anfrage: ");
    Serial.println(anfrage);
    if (anfrage[2]=='_') //"te*"=temperatur or "ta*"=tag
    {
      if (anfrage[3]=='t') //Temperatur
      {
        char upDown=anfrage[6]; //'+' or '-'
        switch (anfrage[4])
        {
        case 't': //Tag
          anfrage="h/tetag.htm";
          break;
        case 'n': //Nacht
          anfrage="h/tenac.htm";
          break;
        case 'w': //Wasser
          anfrage="h/tewas.htm";
        }
        changeTemp(anfrage, upDown);
        sendFile(client, anfrage);
      }//if
      else //Zeiten
      {
        boolean hour = (anfrage[6]=='h' || anfrage[6]=='i'); // !hour == minute
        boolean up = (anfrage[6]=='m' || anfrage[6]=='h'); // !up == down
        boolean startTime = (anfrage[5]=='s');
        char heizzeit = anfrage[4];
        boolean deleteTime = (anfrage[5]=='x');
        switch (anfrage[3])
        {
        case '1':
          anfrage="h/tamoX.htm";
          break;
        case '2':
          anfrage="h/tadiX.htm";
          break;
        case '3':
          anfrage="h/tamiX.htm";
          break;
        case '4':
          anfrage="h/tadoX.htm";
          break;
        case '5':
          anfrage="h/tafrX.htm";
          break;
        case '6':
          anfrage="h/tasaX.htm";
          break;
        case '7':
          anfrage="h/tasoX.htm";
        }
        anfrage[6]=heizzeit;
        if (deleteTime) setTimeToND(anfrage);
        else changeTime(anfrage, startTime, hour, up);
        sendFile(client, anfrage);
      }
    }
    else
    {
      if (anfrage[2]==' ') anfrage="h/index.htm";
      if (anfrage[8]=='t') anfrage="log.txt";
      sendFile(client, anfrage); //alle sonstigen Anfragen
    };
    delay(1); //Zeit für die TCP-Übermittlung
    client.stop(); // close the connection
  }
}

/*void readDHT11(void)
{
  int chk = feuchtesensor.read(DHT11PIN); //liest DHT11
  switch (chk) //Fehlerbehandlung für DHT11
  {
  case 0:
    break;
  case -1:
    Serial.println("DHT11: C err"); //checksum
    break;
  case -2:
    Serial.println("DHT11: T err"); //timeout
    break;
  default:
    Serial.println("DHT11: err");
    break;
  }
}*/
Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Second half of the code (didn't fit in one message):
Code:
void werteSpeichern(void) //sichert alle Sensordaten in "log.txt"
{
  Serial.print("werteS RAM: ");
  Serial.println(freeMemory());
  File logFile = SD.open("LOG.TXT", FILE_WRITE);
  if (logFile) {
    logFile.print(uhrzeit[4]);  //Datum und Uhrzeit
    logFile.print( ".");
    logFile.print( uhrzeit[5]);
    logFile.print( ".");
    logFile.print( uhrzeit[6]);
    logFile.print( " ");
    logFile.print( uhrzeit[2]);
    logFile.print( ":");
    logFile.print( uhrzeit[1]);
    logFile.print( ":");
    logFile.print( uhrzeit[0]);
    logFile.print( tabTaste);

/*    logFile.print( feuchtesensor.humidity);
    logFile.print( tabTaste);
    logFile.print( feuchtesensor.temperature);
    logFile.print( tabTaste); */

    logFile.print( (int)(tempSensors.getTempCByIndex(0)*100));
    logFile.print( tabTaste);
    logFile.println( (int)(tempSensors.getTempCByIndex(1)*100));

    delay(10);
    logFile.close();
  }
  else Serial.println("Op file err");
}

boolean sendFile(Client& client, char* filename)
{
  File file = SD.open(filename);
  if (file)
  {
    char c=file.read();
    while (c != -1)
    {
      client.write(c);
      c = file.read();
    }
    file.close();
    return true;
  }  
  else return false;
}

float changeTemp(char* filename, const char upDown)
{
  float temperature=0.0;
  File file = SD.open(filename, FILE_WRITE);
  if (file)
  {
    int positionInFile=0;
    char* last="     "; //length 5
    file.seek(0);
    last[4]=file.read();
    while (last[4] != -1)
    {
      if (last[4]=='>' && last[2]=='v' && last[3]=='"')
        positionInFile=file.position();//Start der Var
      //      Serial.print("last: "); Serial.println(last);
      if (positionInFile!=0 && last[4]=='<') //weiterlesen, bis '<' erreicht
      {
        last[4]=0;
        temperature= (last[0]-48)*10 + (last[1]-48) + (last[3]-48)/10.0;
        //        Serial.print("Temperatur: "); Serial.println(temperature);
        if (upDown=='+') temperature += 0.5;
        else if (upDown=='-') temperature -= 0.5;
        last[0]=temperature/10+48;
        last[1]=(int)(temperature-(int)(temperature/10)*10)+48;
        last[2]='.';
        if ((int)(temperature*10) % 10 != 0) last[3]='5';
        else last[3]='0';
        //        Serial.print("last: "); Serial.println(last);
        file.seek(positionInFile);
        for (int i=0;i<=3;i++) file.write(last[i]);
        last[4]=-1;
      }
      else
      {
        for (int i=0;i<4;i++) last[i]=last[i+1];
        last[4] = file.read();
      };
    }
    file.close();
    return temperature;
  }  
  else return -1.0;
}

int getTime(File& file, int& hour, int& minute)
{
  char* last="   "; //length 3
  last[2]=file.read();
  while (last[2] != -1)
  {
    if (last[2]=='>' && last[0]=='v' && last[1]=='"') last[2]=-1;
    else
    {
      for (int i=0;i<2;i++) last[i]=last[i+1];
      last[2] = file.read();
    }
  }
  for (int i=1;i<=2;i++) last[i] = file.read();
  if (last[1]=='N' && last[2]=='D')
  {
    hour=-1;
    minute=-1;
  }
  else
  {
    hour= (last[1]-48)*10 + (last[2]-48);
    for (int i=0;i<=2;i++) last[i] = file.read();
    minute= (last[1]-48)*10 + (last[2]-48);    
  };
  return file.position();
}

boolean setTimeToND(char* filename)
{  
  File file = SD.open(filename, FILE_WRITE);
  if (file)
  {
    file.seek(0);
    for(int i=0; i <= 2; i++)
    {
      int hour, minute;
      int positionInFile=getTime(file, hour, minute);
      if (hour >= 0)
      {
        file.seek(positionInFile-5);
        file.print("ND   ");
        Serial.println("ND geschrieben.");
      }
      else i=3;
    };
    file.close();
    return true;
  }
  else return false;
}


boolean changeTime(char* filename, boolean startTime, boolean isHour, boolean up)
{  
  File file = SD.open(filename, FILE_WRITE);
  if (file)
  {
    int hour, minute;
    file.seek(0);
    int positionInFile=getTime(file, hour, minute);
    if (hour < 0)
    {
      file.seek(file.position()-2);
       file.print('00:00');
      while(file.read()!='N');
      file.seek(file.position()-1);
      file.print('00:00');
    }
    else
    {
      if (!startTime) positionInFile=getTime(file,hour,minute);
      char* timeString="00:00";
      if (isHour)
      {
        if (up) hour += 1;
        else hour -=1;
        if (hour==-1) hour=23;
        if (hour==24) hour=0;
      }
      else
      {
        if (up) minute += 10;
        else minute -= 10;
        if (minute < 0) minute=50;
        if (minute >50) minute=0;
      };
      timeString[0]=hour/10+48;
      timeString[1]=(int)(hour-(int)(hour/10)*10)+48;
      timeString[3]=minute/10+48;
      timeString[4]=(int)(minute-(int)(minute/10)*10)+48;
      file.seek(positionInFile-5);
      for (int i=0;i<=4;i++) file.write(timeString[i]);
    };
    file.close();
    return true;
  }  
  else return false;
}
Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2732
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So why upgrade?
Unless you need the new features of 1.0, it really isn't worth
the work to use it and as you have seen, it breaks literally 100% of the existing libraries
and can cause your code to no longer fit.

Since 1.0 was not well published during the beta/RC period prior to its release, I predict that
many issues will crop up and you will see a flury of updates. So I'd hold off on using it
for a while.

If you still want to use 1.0 there are few easy things that might work in your specific case.

If you are using a pre "uno" board,

- upgrade your bootloader to use the smaller optiboot bootloader top make your board an "uno" board.
Either use optiloader and another Arduino board or use the IDE using the optiboot image.
https://github.com/WestfW/OptiLoader
https://github.com/WestfW/Arduino/tree/master/hardware/arduino/bootloaders/optiboot


You can also save several hundred bytes of code by changing the head and tail pointers
in HardwareSerial to use unsigned chars instead of ints. This is an easy change and should
have been done in the official code. (but we all know how hard it is to get any patches into Arduino)
Simple go edit
hardware/cores/arduino/HardwareSerial.cpp
and change:
Code:
struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  int head;
  int tail;
};
to
Code:
struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  unsigned char head;
  unsigned char tail;
};
Logged

"The old Europe"
Offline Offline
Edison Member
*
Karma: 1
Posts: 2005
Bootloaders suck!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can also shave off a few bytes (50-100), if you use your own main() function.

Instead of:
Code:
void setup(void) {
  // setup-code
}

void loop(void) {
 // loop-code
}

you'd just use:
Code:
int main(void) {

  init(); // this initializes all the timers and so forth

  // your setup() code goes here

 while(1) {
   // your loop() code goes inside the while loop
 }

}

This also disables the 'serial event' code btw.
Logged

• Upload doesn't work? Do a loop-back test.
• There's absolutely NO excuse for not having an ISP!
• Your AVR needs a brain surgery? Use the online FUSE calculator.
My projects: RGB LED matrix, RGB LED ring, various ATtiny gadgets...
• Microsoft is not the answer. It is the question, and the answer is NO!

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Unless you need the new features of 1.0, it really isn't worth
the work to use it and as you have seen, it breaks literally 100% of the existing libraries
and can cause your code to no longer fit.
I come to believe that that's the way to go... Why invest lots of work without the need for new features? Thanks also for the helpful hints! Same to you, madworm! I guess I will need these hints later anyhow, when I'll get to the limits. There's still a lot to do for my little Arduino! ;-)
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can do some analysis, but... nearly every library you're using is giving me compile errors.  Do you happen to have pointers to the 1-compatible versions of onewire, ds1370, dallastemperature, and etc?  (Yeah, I can probably fix them, but then I wouldn't know for sure whether I'm using the same code that you're using.  PM me a zip file if you want.)
Logged

0
Offline Offline
God Member
*****
Karma: 26
Posts: 621
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I also might investigate, but at the risk of repeating myself, it's pointless without having the code to reproduce the problem.

@barish - you posted your sketch, but that is not enough.  Imagine, if you will, that you some random person who might help, but has nothing other that a clean copy of the Arduino IDE.  Try downloading a fresh copies of Arduino, both 1.0 and 0023.  Can you reproduce the exact result in both using only fresh downloads of both Arduino IDEs, and the files you've provided?  If not, you haven't posted enough to reproduce the problem!
« Last Edit: December 03, 2011, 11:48:48 am by Paul Stoffregen » Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Paul, I wasn't aware that you'd like to compile the code and reproduce the problem. Instead I thought you would look over my sketch to see if there was obvious memory waste. I will see if I can upload the modified libraries I use to make them available to you guys. Thanks for your effort so far!

Edit: Here's the zip-file of my "libraries" folder: http://goo.gl/BMGYs
« Last Edit: December 03, 2011, 01:10:15 pm by barish » Logged

0
Offline Offline
Edison Member
*
Karma: 67
Posts: 1652
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

SD.h has grown by almost 2KB for a simple example.  The SD/examples/ReadWrite sketch is 13580 bytes on 1.0 and it is 11686 bytes on 0022.

Most of this is due to new features added to the SD.h wrapper in 1.0.  The base code for SdFat has not been changed much from 0022.

Part is due to something else in 1.0.  For my new version of SdFat  a similar example, SdFatReadWrite, is 12098 bytes on 1.0 and 11682 on 0022.  So there is a 416 byte increase in this example with the same code on both systems.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
look over my sketch to see if there was obvious memory waste.
I'm afraid the "interesting question" is not "how can we fix your sketch?", but rather "why did the sketch get 25% bigger?", so we don't particularly want to look at the source for your sketch, but the size of the binaries of everything involved...
Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Part is due to something else in 1.0.  For my new version of SdFat  a similar example, SdFatReadWrite, is 12098 bytes on 1.0 and 11682 on 0022.  So there is a 416 byte increase in this example with the same code on both systems.
If I understand there's something about 1.0 you don't know yet the cause. Well I hope someone will find out.

@westfw: nothing to be afraid for, I hope you can compile and fix something now. All I want is a smaller binary after all, no matter where the problem lies.
« Last Edit: December 04, 2011, 02:54:09 am by barish » Logged

0
Offline Offline
Edison Member
*
Karma: 67
Posts: 1652
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like most of the increase is in Ethernet.  The Ethernet WebServer example is 10146 bytes on 1.0 but only 5446 bytes on 0022.  That's 4,700 bytes more.   

I didn't look at the library code for Ethernet but the example was not changed much.  Here is the diff for the example in 1.0 and 0022:
Code:
24c24
< IPAddress ip(192,168,1, 177);
---
> byte ip[] = { 192,168,1, 177 };
29c29
< EthernetServer server(80);
---
> Server server(80);
41c41
<   EthernetClient client = server.available();
---
>   Client client = server.available();

The SD library is about 1,500 bytes larger due to new features.  These two libraries add about 6,200 bytes.
Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, fat16lib, so that must be the biggest chunk of my memory increase. But shouldn't there be some options for the lib to use less space? E.g. I don't need to open multiple files. I mean, 5k more or less, that must be important to many users (I imagine).
Logged

Pages: [1] 2 3   Go Up
Jump to: