mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Speicher voll durch Multiplikation


Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein recht vollgestopften Flash durch mein Programm, bin bei 93% 
auf einem ATMega8. Ich kommuniziere über UART und SPI, frage einen ADC 
über SPI ab und schicke die Daten an einen CAN Controller über SPI.
Jetzt möchte ich gerne die Daten vom ADC von counts nach Volt wandeln 
und muss dazu folgende Formel anwenden:
Wenn ich das nun in den Code einpflege wird der sofort um ca 500Byte 
größer und sprengt mir somit den Flash. Ich habe durch Probieren 
rausbekommen, dass es an der Multiplikation von ADC_[counts] mit dem 
Rest hängt. Nehme ich die raus, stehe ich bei 96%. ADC_[counts] ist eine 
uint32_t Variable, der Rest float. Ich wollte daher einen Cast machen 
nach float.

Was kann ich machen oder umstricken, ohne dass ich den Rest des 
Programms rausschmeißen muss?

Danke euch.
Grüße

Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich befürchte da kann man wenig machen. Das Rechnen mit einer 32-bit 
Float-Variable ist verständlicherweise sehr Programmintensiv. Du 
solltest überlegen, ob du wirklich mit float rechnen musst, oder ob ein 
normaler Ganzzahlwert ausreicht.

Ansonsten ist der Atmega168 (glaube ich) Pin-kompatibel und bietet 
doppelt so viel Flash.

Autor: Bernd N (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: fgxn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nenne ADC(volts) in ADC(millivolts) und rechne mit Ganzzahlen.

Gast

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und dann zeig mal die wesentlichen Teile deines Programms.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(oder atmega328 nehmen, und beim nächsten Mal gleich mit Fixkomma 
anfangen :-)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Festkommaarithmetik

MFG
Falk

Autor: Gunther (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo siehst Du eine Multiplikation?

0.5 = rechtsshift um 1
1/(2^23-1) = ca. rechtsshift um 23
VRef/Gain = vermutlich auch links- oder rechtsshift mit glattem Wert

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ich würde gänzlich auf float verzichten und alles mit uint32_t 
rechnen. (dafür alles in mV, falls dies von der Auflösung aussreicht!)

Venwendest Du die Math-Lib für AVR? (Linker Option: -lm), die ist für 
AVR optimirt und wesentlich schlanker als die generische GCC Math-Lib 
(welche unsinnigerweise meistens defaultmässig dazugelinkt wird)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gunther schrieb:
> Wo siehst Du eine Multiplikation?
>
> 0.5 = rechtsshift um 1
> 1/(2^23-1) = ca. rechtsshift um 23
> VRef/Gain = vermutlich auch links- oder rechtsshift mit glattem Wert

Vermutlich   float VRef;
             float Gain;

und damit sind deine ganzen Shiftereien nur noch Makulatur.

Wenn er den ganzen Code (ohne die SPI / UART Funktionen, bei denen kann 
man gar nicht so viel Speicher verbrauchen) herzeigen würde, dann könnte 
man sich das alles mal ansehen und nicht nur generische Vorschläge 
machen. Aber wahrscheinlich ist das wieder mal ein Geheimprojekt :-)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wo siehst Du eine Multiplikation?

(0.5 * VRef/Gain)/(2^23-1) wird eine Konstante sein, mit welcher aber 
ADC[counts] multipliziert werden muss!

Autor: Tropenhitze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bevor ich auf fix-und-fertig Berechnungen umstelle, würde ich lieber den 
Euro für einen 'dickeren' Prozessor spendieren und 'float' anstatt 
Tränen fließen lassen :-)

Autor: Gunther (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Vermutlich   float VRef;
>              float Gain;
>
> und damit sind deine ganzen Shiftereien nur noch Makulatur.

Wäre es bei mir nicht unbedingt, da ich bei der Hardwaredefinition auch 
die Software im Blick habe (und natürlich umgekehrt).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gunther schrieb:
>> Vermutlich   float VRef;
>>              float Gain;
>>
>> und damit sind deine ganzen Shiftereien nur noch Makulatur.
>
> Wäre es bei mir nicht unbedingt, da ich bei der Hardwaredefinition auch
> die Software im Blick habe (und natürlich umgekehrt).

Das passiert des öfteren, wenn Leute float blauäugig einsetzen.
So nach dem Muster: Da denk ich gar nicht lange nach - float muss her.
Besonders interessant wird es dann, wenn der float sich über mehrere 
Berechnungsstufen hinzieht. 6 signifikante Stellen sind nicht viel und 
sind schnell aufgebraucht. Ab dann hätte man geausogut auch würfeln 
können :-)

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, reger Zuspruch

Hier also Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include <util/delay.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>

#include "uart.h"
#include "mcp2515.h"
#include "global.h"
#include "defaults.h"
#include "ads1234.h"
#include "ads1234_defs.h"

// ----------------------------------------------------------------------------

#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)

static int putchar__(char c, FILE *stream) {
  uart_putc(c);
  return 0;
}

static FILE mystdout = FDEV_SETUP_STREAM(putchar__, 0, _FDEV_SETUP_WRITE);


// -------------------------------------------------------------------------
/*!@details This function converts the gathered data from ADC into voltage by
 * making use of the following formula
 * @f[  ADC{[volts]} = ADC{[counts]} \cdot \frac{0.5 \cdot V_{Ref} / Gain}{2^{23} - 1}@f]
 * @return  voltage as float variable
 * @see ADS1234 datasheet p. 18
 */
float counts2voltage(uint32_t AData)
{
    float vRef = 5.0;
    float gain = 1.0;

    return AData *   ((0.5 * vRef / gain) / 8388607); //8388607 = 2^23 - 1
}


// ----------------------------------------------------------------------------
// Hauptprogram

int main(void)
{
  // Initialisiere die UART Schnittstelle
  uart_init(UART_BAUD_SELECT(19200UL, F_CPU));
  
  // Aktiviere Interrupts
  sei();
  
  // Umleiten der Standardausgabe => ab jetzt koennen wir printf() verwenden
  stdout = &mystdout;
  
  // Versuche den MCP2515 zu initilaisieren
  if (!mcp2515_init()) {
    PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
    for (;;);
  }
  else {
    PRINT("MCP2515 is aktiv\n\n");
  }
  
  PRINT("Erzeuge Nachricht\n");
  tCAN message;
  
  // einige Testwerte
  message.id = 0x123;
  message.header.rtr = 0;
  message.header.length = 2;
  message.data[0] = 0xab;
  message.data[1] = 0xcd;
  
  print_can_message(&message);
  
  PRINT("\nwechsle zum Loopback-Modus\n\n");
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));
  
  // Sende eine Nachricht
  if (mcp2515_send_message(&message)) {
    PRINT("Nachricht wurde in die Puffer geschrieben\n");
  }
  else {
    PRINT("Fehler: konnte die Nachricht nicht senden\n");
  }
  
  // warte ein bisschen
  _delay_ms(10);
  
  if (mcp2515_check_message()) {
    PRINT("Nachricht empfangen!\n");
    
    // read the message from the buffers
    if (mcp2515_get_message(&message)) {
      print_can_message(&message);
      PRINT("\n");
    }
    else {
      PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
    }
  }
  else {
    PRINT("Fehler: keine Nachricht empfangen\n\n");
  }
  
  PRINT("zurueck zum normalen Modus\n\n");
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
  
  // wir sind ab hier wieder mit dem CAN Bus verbunden
  
  PRINT("Versuche die Nachricht per CAN zu verschicken\n");
  
  // Versuche nochmal die Nachricht zu verschicken, diesmal per CAN
  if (mcp2515_send_message(&message)) {
    PRINT("Nachricht wurde in die Puffer geschrieben\n\n");
  }
  else {
    PRINT("Fehler: konnte die Nachricht nicht senden\n\n");
  }
  
  PRINT("Warte auf den Empfang von Nachrichten\n\n");


    /* For CAN board carrying ADS1234 only
     */      
    PRINT("================ \n");
    PRINT("Schalte jetzt Pins durch...\n");
    PRINT("ADS1234:  set gain factor to %3d...  ", 1);
    if( ADS1234_setGain(1) )
        PRINT("[done]\n");   
    else
        PRINT("[failed]\n"); 

    PRINT("ADS1234:  set channel to %2d...       ", 4);
    if( ADS1234_setChannel(4) )
        PRINT("[done]\n");   
    else
        PRINT("[failed]\n"); 

    PRINT("ADS1234:  set speed to %2d...         ", 10);
    if( ADS1234_setSpeed(10) )
        PRINT("[done]\n");   
    else
        PRINT("[failed]\n");         

    PRINT("ADS1234:  calibrating...             ");
    if ( ADS1234_calibrate() )
        PRINT("[done]\n");
    else
        PRINT("[failed]\n");
    PRINT("SetUp beendet.\n==============\n\n");

    //Let's get us a variable to hold latest data
    int32_t AData=0;
    int count = 0;
    char str[9];

    while (1) {

        // warten bis wir eine Nachricht empfangen
        if (mcp2515_check_message())
        {
            PRINT("Nachricht empfangen!\n");

            // Lese die Nachricht aus dem Puffern des MCP2515
            if (mcp2515_get_message(&message)) {
                print_can_message(&message);
                PRINT("\n");
            }
            else {
              PRINT("Kann die Nachricht nicht auslesen\n\n");
            }
        }

        
        /* For CAN board carrying ADS1234 only
         */ 
        if(ADS1234_checkDrdy())
        {

            PRINT("Data waiting ...");

            if(ADS1234_getData(&AData)) 
            {
                PRINT("count: %i Value:", count);
                float VData = counts2voltage(AData);
                ltoa(VData, str, 10);
                PRINT("%f V\n",VData);

            }
            else
                PRINT("Could not acquire data!\n");
        }

        count += 1;        
        _delay_ms(500);
    }  
    return 0;
}



Das ist mein gesamtes Programm, ich nutze einen ADS1234 ADC von TI und 
einen MCP2515 für den CAN Bus. Für den CAN Bus nutze ich die Bibliothek 
von Fabian Greif, für den ADC habe ich selbst eine geschrieben.

@Peter: Deine Idee finde ich äußerst interessant. Habe gerade mal mit 
der Linker Option -lm gearbeitet, aber der erzeugte Code scheint genauso 
groß zu sein. Wie kann ich die Anbindung der GCC-Mathe Bibliothek 
unterbinden? Ich habe ja gar keine math.h an sich eingebunden...Aber ich 
sehe grade, dass WinAVR standardmäßig anscheinend -lm schon nutzt.

Ich würde wohl mal die Festarithmetrik ausprobieren, aber es 
interessiert mich schon wieso und vor allem wo die 500Bytes hingehen. 
Hatte lediglich erwartet, dass es eben lange dauert - die Float 
Geschichte...

Grüße

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wow, dein Flash ist ja zur Hälfte mit Textstrings voll oO

Autor: MPPT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> wow, dein Flash ist ja zur Hälfte mit Textstrings voll oO

da er kein progmem nutzt, sind die eigentlich nicht im Flash

Autor: MPPT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MPPT schrieb:
> printf_P

nehm alles zurück

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MPPT schrieb:
> da er kein progmem nutzt, sind die eigentlich nicht im Flash

Ohne PROGMEM wären sie im Ram UND im Flash. Denn irgend woher muss der 
RAM ja initialisiert werden. :)

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> wow, dein Flash ist ja zur Hälfte mit Textstrings voll oO

OK, hab ich mir noch gar keine Gedanken drüber gemacht, aber ich habe 
gerade mit folgender Version eine 87%ige Auslastung des Speichers 
erreicht:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include <util/delay.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>

#include "uart.h"
#include "mcp2515.h"
#include "global.h"
#include "defaults.h"
#include "ads1234.h"
#include "ads1234_defs.h"

// ----------------------------------------------------------------------------

#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)

static int putchar__(char c, FILE *stream) {
  uart_putc(c);
  return 0;
}

static FILE mystdout = FDEV_SETUP_STREAM(putchar__, 0, _FDEV_SETUP_WRITE);


// ---------------------------------------------------------------------------
/*!@details This function converts the gathered data from ADC into voltage by
 * making use of the following formula
 * @f[  ADC{[volts]} = ADC{[counts]} \cdot \frac{0.5 \cdot V_{Ref} / Gain}{2^{23} - 1}@f]
 * @return  voltage as float variable
 * @see ADS1234 datasheet p. 18
 */
float counts2voltage(uint32_t AData)
{
    float vRef = 5.0;
    float gain = 1.0;

    return AData *   ((0.5 * vRef / gain) / 8388607); //8388607 = 2^23 - 1
}


// ----------------------------------------------------------------------------
// Hauptprogram

int main(void)
{
  // Initialisiere die UART Schnittstelle
  uart_init(UART_BAUD_SELECT(19200UL, F_CPU));
  
  // Aktiviere Interrupts
  sei();
  
  // Umleiten der Standardausgabe => ab jetzt koennen wir printf() verwenden
  stdout = &mystdout;
  
  // Versuche den MCP2515 zu initilaisieren
  if (!mcp2515_init()) {
    //PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
    for (;;);
  }
  else {
    //PRINT("MCP2515 is aktiv\n\n");
  }
  
  //PRINT("Erzeuge Nachricht\n");
  tCAN message;
  
  // einige Testwerte
  message.id = 0x123;
  message.header.rtr = 0;
  message.header.length = 2;
  message.data[0] = 0xab;
  message.data[1] = 0xcd;
  
  print_can_message(&message);
  
  //PRINT("\nwechsle zum Loopback-Modus\n\n");
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));
  
  // Sende eine Nachricht
  if (mcp2515_send_message(&message)) {
    //PRINT("Nachricht wurde in die Puffer geschrieben\n");
  }
  else {
    //PRINT("Fehler: konnte die Nachricht nicht senden\n");
  }
  
  // warte ein bisschen
  _delay_ms(10);
  
  if (mcp2515_check_message()) {
    //PRINT("Nachricht empfangen!\n");
    
    // read the message from the buffers
    if (mcp2515_get_message(&message)) {
      print_can_message(&message);
      //PRINT("\n");
    }
    else {
      //PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
    }
  }
  else {
    //PRINT("Fehler: keine Nachricht empfangen\n\n");
  }
  
  //PRINT("zurueck zum normalen Modus\n\n");
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
  
  // wir sind ab hier wieder mit dem CAN Bus verbunden
  
  //PRINT("Versuche die Nachricht per CAN zu verschicken\n");
  
  // Versuche nochmal die Nachricht zu verschicken, diesmal per CAN
  if (mcp2515_send_message(&message)) {
    //PRINT("Nachricht wurde in die Puffer geschrieben\n\n");
  }
  else {
    //PRINT("Fehler: konnte die Nachricht nicht senden\n\n");
  }
  
  //PRINT("Warte auf den Empfang von Nachrichten\n\n");


    /* For CAN board carrying ADS1234 only
     */      
    //PRINT("================ \n");
    //PRINT("Schalte jetzt Pins durch...\n");
    //PRINT("ADS1234:  set gain factor to %3d...  ", 1);
    //if(
     ADS1234_setGain(1);
     // )
        //PRINT("[done]\n");   
    //else
        //PRINT("[failed]\n"); 

    //PRINT("ADS1234:  set channel to %2d...       ", 4);
    //if(
     ADS1234_setChannel(4);
     // )
        //PRINT("[done]\n");   
    //else
        //PRINT("[failed]\n"); 

    //PRINT("ADS1234:  set speed to %2d...         ", 10);
    //if(
     ADS1234_setSpeed(10);
     //)
        //PRINT("[done]\n");   
    //else
        //PRINT("[failed]\n"); 
        

    //PRINT("ADS1234:  calibrating...             ");
    //if ( 
    ADS1234_calibrate();
    // )
        //PRINT("[done]\n");
    //else
        //PRINT("[failed]\n");


    //PRINT("SetUp beendet.\n==============\n\n");

    //Let's get us a variable to hold latest data
    int32_t AData=0;
    int count = 0;
    char str[9];


    // ----------- built a magnus can message ---------------------
    uint8_t dat[8];
    dat[0] = 0x23;
    dat[1] = 0x23;
    dat[2] = 0x23;
    dat[3] = 0x23;
    dat[4] = 0x23;
    dat[5] = 0x23;
    dat[6] = 0x23;
    dat[7] = 0x23;
//    tCAN m;

    srand(125);  

    while (1) {

        // warten bis wir eine Nachricht empfangen
        if (mcp2515_check_message())
        {
            PRINT("Nachricht empfangen!\n");

            // Lese die Nachricht aus dem Puffern des MCP2515
            if (mcp2515_get_message(&message)) {
                print_can_message(&message);
                PRINT("\n");
            }
            else {
              PRINT("Kann die Nachricht nicht auslesen\n\n");
            }
        }

        
        /* For CAN board carrying ADS1234 only
         */ 
        if(ADS1234_checkDrdy())
        {

            PRINT("Data waiting ...");

            if(ADS1234_getData(&AData)) 
            {
                PRINT("count: %i Value:", count);
                //PRINT("%x\n",AData);
                float VData = counts2voltage(AData);
                ltoa(VData, str, 10);
                PRINT("%f V\n",VData);

            }
            else
                PRINT("Could not acquire data!\n");
        }

        count += 1;
        
        _delay_ms(500);
    }
  
  return 0;
}

Ich bekomme auch wundervolle Gleitkommazahlen angezeigt im Terminal.
Kann ich die Textstrings nicht im EEPROM ablegen?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Programm sieht nicht sonderlich groß aus.
Die Flashfresser werden in dem nicht geposteten Code liegen.

Wenn Du es mit den fehlenden *.c und *.h zippen würdest, könnte man es 
mal optimiert compilieren.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:

Ich würde wohl mal die Festarithmetrik ausprobieren, aber es
> interessiert mich schon wieso und vor allem wo die 500Bytes hingehen.
> Hatte lediglich erwartet, dass es eben lange dauert - die Float
> Geschichte...

Na ja.
Die halbe Floating Point Libarry ist dann schon mal ein Wummer.

Dazu dann noch der ganze stream Überbau, den du dir mit der sorglosen 
Verwendung von printf einhandelts, obwohl du ihn nirgend wo wirklich 
brauchst oder auch nur annähernd in seinen Fähigkeiten ausnutzt. Eine 
puts Funktion zusammen mit einer puti (für Integer Ausgaben) hätte es 
auch getan.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann versuch ich mal die PRINTs durch uart_puts zu ersetzen. Wie gut 
oder schlecht is die Nutzung von itoa() im Sinne des Speichers?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:
> Dann versuch ich mal die PRINTs durch uart_puts zu ersetzen. Wie gut
> oder schlecht is die Nutzung von itoa() im Sinne des Speichers?

itoa ist klein.

printf, sprintf, fprintf als eierlegende Wollmilchsäue mit x 
verschiedenen Möglichkeiten zur Zahlenformatierung im Formatstring, sind 
schon nicht ohne.

Sinn macht es allerdings nur, wenn du ALLE printf ersetzt!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja.
Wenn du genauer wissen willst, wie sich der Flash aufteilt: lass dir ein 
Map-File erzeugen. Da stehts genau aufgeschlüsselt drinnen.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Sinn macht es allerdings nur, wenn du ALLE printf ersetzt!

Also ich habe das von mir zuerst gepostete Programm genommen und 
folgendes gemacht:
#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)
 durch
#define  PRINT(string, ...)    uart_puts_p(string)
ersetzt und komme auf 95% Auslastung, was für mich reicht. Ich muss 
überlegen, ob ich dennoch mit der Festkommaarithmetik weiter komme.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ach ja.
> Wenn du genauer wissen willst, wie sich der Flash aufteilt: lass dir ein
> Map-File erzeugen. Da stehts genau aufgeschlüsselt drinnen.

Jetzt muss ich wieder mit Unvermögen prahlen... wie krieg ich das hin?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:
> Karl heinz Buchegger schrieb:
>> Ach ja.
>> Wenn du genauer wissen willst, wie sich der Flash aufteilt: lass dir ein
>> Map-File erzeugen. Da stehts genau aufgeschlüsselt drinnen.
>
> Jetzt muss ich wieder mit Unvermögen prahlen... wie krieg ich das hin?


AVR-Studio?

Bei den Prjekt Einstellungen gibt es Häkchen für Listfile und für Map.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Print-Geschichte isses nicht, Platz kostet immer nur der erste 
Aufruf.
Das Programm müßte bequem in 4kB passen.

Der Flashfresser liegt woanders!


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:

>
#define  PRINT(string, ...)    uart_puts_p(string)

machs Sicherheitshalber so
#define PRINT(string)   uart_puts_p(string)

dann sucht dir der Compiler raus, wo du nicht einfach einen printf 
ersetzen kannst, sondern noch mehr eingreifen musst.

> ersetzt und komme auf 95% Auslastung, was für mich reicht. Ich muss
> überlegen, ob ich dennoch mit der Festkommaarithmetik weiter komme.

Auf jeden Fall.
Lass dir nicht Volt ausrechnen sondern Millivolt. Oder von mir aus 10-er 
Einheiten von Millivolt (wozu hat men denn sonst einen ADC mit sovielen 
Bits, so dass es höchst fragwürdig ist, ob das nach der 5ten 
Nachkommastelle überhaupt noch in irgendeiner Weise mit der zu messenden 
Spannung korreliert :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Die Print-Geschichte isses nicht, Platz kostet immer nur der erste
> Aufruf.

Bischen was ist es auch.
Mit dem ganzen stream Überbau, printf ist auch nicht gerade Schmalhans.

> Das Programm müßte bequem in 4kB passen.

Ähm. Da fällt mir noch was ein.
Nachdem der TO die Projekt Einstellungen anscheinend nicht kennt:
Die Optimierung ist aber eingeschaltet?

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenn schon die Projekteinstellungen, so ist es nicht. Aber ich hab 
mir eben noch nie eine Memory Map vom AVR anschauen müssen. Die Häkchen 
sind übrigens standardmäßig gesetzt.

Ich habe die Optimierung überprüft, steht auf "-Os".

Ich habe zusätzlich mal libm.a dazugelinkt und auf einmal habe ich trotz 
Nutzung von printf jetzt wieder nur noch 70% Auslastung.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:
> Ich habe zusätzlich mal libm.a dazugelinkt und auf einmal habe ich trotz
> Nutzung von printf jetzt wieder nur noch 70% Auslastung.
Fehler: ich habe zusätzlich noch die -libprintf_min dazugelinkt und 
dadurch wurde das Programm so klein, konnte allerdings keine float 
Variablen mehr
 im printf Befehl darstellen -> "?"
Also hab ichs rausgenommen und bin wieder bei meinen knappen 100% wenn 
ich den einen oder anderen String auskommentiere und konsequent auf 
uart_puts() + ltoa() vertraue.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:
> S. G. schrieb:
>> Ich habe zusätzlich mal libm.a dazugelinkt und auf einmal habe ich trotz
>> Nutzung von printf jetzt wieder nur noch 70% Auslastung.
> Fehler: ich habe zusätzlich noch die -libprintf_min dazugelinkt und
> dadurch wurde das Programm so klein, konnte allerdings keine float
> Variablen mehr
>  im printf Befehl darstellen -> "?"

Das ist klar.
Ein Punkt für das 'Minimalversion' in liblrpintf_min ist es eben, dass 
die floating point Unterstützung herausoperiert wurde.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jop! Hab ich verstanden. Jetzt versuche ich mal die 
Festkommegeschichte...

Karl heinz, hast du noch einen Tipp für mich, wie ich Strings im EEPROM 
ablegen kann und dann einfach zur "Anzeige" bringe über UART? Danke dir

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die Festkommaarithmetik funktioniert beim ersten Ansatz nach dem 
vorgeschlagenen Tutorial gut.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. G. schrieb:
> jop! Hab ich verstanden. Jetzt versuche ich mal die
> Festkommegeschichte...
>
> Karl heinz, hast du noch einen Tipp für mich, wie ich Strings im EEPROM
> ablegen kann und dann einfach zur "Anzeige" bringe über UART? Danke dir

Da gibts nicht sehr viel an Tipps.
String im EEPROM ablegen. Mit den EEPROM Funktionen auslesen und ab zur 
UART damit. Alles straightforward.

Aber ehe du dich da jetzt ins Unglück stürzt: Denk mal darüber nach, ob 
deine Texte wirklich so geschwätzig sein müssen.

Ich meine ...
  if (!mcp2515_init()) {
    PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
    for (;;);
  }
... liest sich natürlich wunderbar. Aber ein simples
  if (!mcp2515_init()) {
    PRINT("Fehler: MCP2515 nicht gefunden!\n");
    for (;;);
  }

oder
  if (!mcp2515_init()) {
    PRINT("Error: MCP2515 not found!\n");
    for (;;);
  }

tut's auch. Und in Summe sinds dann auch ein paar Bytes. Ein paar Bytes 
hier, ein paar Bytes da und schon sind wieder 100 oder 200 Bytes 
beisammen.

Autor: S. G. (goeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm...Da hast du Recht Karl Heinz.

Werds mal eindampfen und dann mal schauen, ob ich noch Platz brauche, 
dann ggf. ins EEPROM auslagern.

Dane euch für die Hilfe.
Grüße

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine sehr schlanke Zahlenausgabe:

Beitrag "Formatierte Zahlenausgabe in C"


Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.