Forum: Mikrocontroller und Digitale Elektronik Speicher voll durch Multiplikation


von S. G. (goeck)


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

von Hannes E. (k1ngarthur) Benutzerseite


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.

von Bernd N (Gast)


Lesenswert?


von fgxn (Gast)


Lesenswert?

Nenne ADC(volts) in ADC(millivolts) und rechne mit Ganzzahlen.

Gast

von Karl H. (kbuchegg)


Lesenswert?

Und dann zeig mal die wesentlichen Teile deines Programms.

von Klaus W. (mfgkw)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

Siehe Festkommaarithmetik

MFG
Falk

von Gunther (Gast)


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

von Peter (Gast)


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)

von Karl H. (kbuchegg)


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 :-)

von Peter (Gast)


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!

von Tropenhitze (Gast)


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 :-)

von Gunther (Gast)


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).

von Karl H. (kbuchegg)


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 :-)

von S. G. (goeck)


Lesenswert?

Oh, reger Zuspruch

Hier also Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/pgmspace.h>
4
5
#include <util/delay.h>
6
#include <stdio.h>
7
#include <inttypes.h>
8
#include <stdlib.h>
9
10
#include "uart.h"
11
#include "mcp2515.h"
12
#include "global.h"
13
#include "defaults.h"
14
#include "ads1234.h"
15
#include "ads1234_defs.h"
16
17
// ----------------------------------------------------------------------------
18
19
#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)
20
21
static int putchar__(char c, FILE *stream) {
22
  uart_putc(c);
23
  return 0;
24
}
25
26
static FILE mystdout = FDEV_SETUP_STREAM(putchar__, 0, _FDEV_SETUP_WRITE);
27
28
29
// -------------------------------------------------------------------------
30
/*!@details This function converts the gathered data from ADC into voltage by
31
 * making use of the following formula
32
 * @f[  ADC{[volts]} = ADC{[counts]} \cdot \frac{0.5 \cdot V_{Ref} / Gain}{2^{23} - 1}@f]
33
 * @return  voltage as float variable
34
 * @see ADS1234 datasheet p. 18
35
 */
36
float counts2voltage(uint32_t AData)
37
{
38
    float vRef = 5.0;
39
    float gain = 1.0;
40
41
    return AData *   ((0.5 * vRef / gain) / 8388607); //8388607 = 2^23 - 1
42
}
43
44
45
// ----------------------------------------------------------------------------
46
// Hauptprogram
47
48
int main(void)
49
{
50
  // Initialisiere die UART Schnittstelle
51
  uart_init(UART_BAUD_SELECT(19200UL, F_CPU));
52
  
53
  // Aktiviere Interrupts
54
  sei();
55
  
56
  // Umleiten der Standardausgabe => ab jetzt koennen wir printf() verwenden
57
  stdout = &mystdout;
58
  
59
  // Versuche den MCP2515 zu initilaisieren
60
  if (!mcp2515_init()) {
61
    PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
62
    for (;;);
63
  }
64
  else {
65
    PRINT("MCP2515 is aktiv\n\n");
66
  }
67
  
68
  PRINT("Erzeuge Nachricht\n");
69
  tCAN message;
70
  
71
  // einige Testwerte
72
  message.id = 0x123;
73
  message.header.rtr = 0;
74
  message.header.length = 2;
75
  message.data[0] = 0xab;
76
  message.data[1] = 0xcd;
77
  
78
  print_can_message(&message);
79
  
80
  PRINT("\nwechsle zum Loopback-Modus\n\n");
81
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));
82
  
83
  // Sende eine Nachricht
84
  if (mcp2515_send_message(&message)) {
85
    PRINT("Nachricht wurde in die Puffer geschrieben\n");
86
  }
87
  else {
88
    PRINT("Fehler: konnte die Nachricht nicht senden\n");
89
  }
90
  
91
  // warte ein bisschen
92
  _delay_ms(10);
93
  
94
  if (mcp2515_check_message()) {
95
    PRINT("Nachricht empfangen!\n");
96
    
97
    // read the message from the buffers
98
    if (mcp2515_get_message(&message)) {
99
      print_can_message(&message);
100
      PRINT("\n");
101
    }
102
    else {
103
      PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
104
    }
105
  }
106
  else {
107
    PRINT("Fehler: keine Nachricht empfangen\n\n");
108
  }
109
  
110
  PRINT("zurueck zum normalen Modus\n\n");
111
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
112
  
113
  // wir sind ab hier wieder mit dem CAN Bus verbunden
114
  
115
  PRINT("Versuche die Nachricht per CAN zu verschicken\n");
116
  
117
  // Versuche nochmal die Nachricht zu verschicken, diesmal per CAN
118
  if (mcp2515_send_message(&message)) {
119
    PRINT("Nachricht wurde in die Puffer geschrieben\n\n");
120
  }
121
  else {
122
    PRINT("Fehler: konnte die Nachricht nicht senden\n\n");
123
  }
124
  
125
  PRINT("Warte auf den Empfang von Nachrichten\n\n");
126
127
128
    /* For CAN board carrying ADS1234 only
129
     */      
130
    PRINT("================ \n");
131
    PRINT("Schalte jetzt Pins durch...\n");
132
    PRINT("ADS1234:  set gain factor to %3d...  ", 1);
133
    if( ADS1234_setGain(1) )
134
        PRINT("[done]\n");   
135
    else
136
        PRINT("[failed]\n"); 
137
138
    PRINT("ADS1234:  set channel to %2d...       ", 4);
139
    if( ADS1234_setChannel(4) )
140
        PRINT("[done]\n");   
141
    else
142
        PRINT("[failed]\n"); 
143
144
    PRINT("ADS1234:  set speed to %2d...         ", 10);
145
    if( ADS1234_setSpeed(10) )
146
        PRINT("[done]\n");   
147
    else
148
        PRINT("[failed]\n");         
149
150
    PRINT("ADS1234:  calibrating...             ");
151
    if ( ADS1234_calibrate() )
152
        PRINT("[done]\n");
153
    else
154
        PRINT("[failed]\n");
155
    PRINT("SetUp beendet.\n==============\n\n");
156
157
    //Let's get us a variable to hold latest data
158
    int32_t AData=0;
159
    int count = 0;
160
    char str[9];
161
162
    while (1) {
163
164
        // warten bis wir eine Nachricht empfangen
165
        if (mcp2515_check_message())
166
        {
167
            PRINT("Nachricht empfangen!\n");
168
169
            // Lese die Nachricht aus dem Puffern des MCP2515
170
            if (mcp2515_get_message(&message)) {
171
                print_can_message(&message);
172
                PRINT("\n");
173
            }
174
            else {
175
              PRINT("Kann die Nachricht nicht auslesen\n\n");
176
            }
177
        }
178
179
        
180
        /* For CAN board carrying ADS1234 only
181
         */ 
182
        if(ADS1234_checkDrdy())
183
        {
184
185
            PRINT("Data waiting ...");
186
187
            if(ADS1234_getData(&AData)) 
188
            {
189
                PRINT("count: %i Value:", count);
190
                float VData = counts2voltage(AData);
191
                ltoa(VData, str, 10);
192
                PRINT("%f V\n",VData);
193
194
            }
195
            else
196
                PRINT("Could not acquire data!\n");
197
        }
198
199
        count += 1;        
200
        _delay_ms(500);
201
    }  
202
    return 0;
203
}
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

von Klaus (Gast)


Lesenswert?

wow, dein Flash ist ja zur Hälfte mit Textstrings voll oO

von MPPT (Gast)


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

von MPPT (Gast)


Lesenswert?

MPPT schrieb:
> printf_P

nehm alles zurück

von Klaus (Gast)


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. :)

von S. G. (goeck)


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:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/pgmspace.h>
4
5
#include <util/delay.h>
6
#include <stdio.h>
7
#include <inttypes.h>
8
#include <stdlib.h>
9
10
#include "uart.h"
11
#include "mcp2515.h"
12
#include "global.h"
13
#include "defaults.h"
14
#include "ads1234.h"
15
#include "ads1234_defs.h"
16
17
// ----------------------------------------------------------------------------
18
19
#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)
20
21
static int putchar__(char c, FILE *stream) {
22
  uart_putc(c);
23
  return 0;
24
}
25
26
static FILE mystdout = FDEV_SETUP_STREAM(putchar__, 0, _FDEV_SETUP_WRITE);
27
28
29
// ---------------------------------------------------------------------------
30
/*!@details This function converts the gathered data from ADC into voltage by
31
 * making use of the following formula
32
 * @f[  ADC{[volts]} = ADC{[counts]} \cdot \frac{0.5 \cdot V_{Ref} / Gain}{2^{23} - 1}@f]
33
 * @return  voltage as float variable
34
 * @see ADS1234 datasheet p. 18
35
 */
36
float counts2voltage(uint32_t AData)
37
{
38
    float vRef = 5.0;
39
    float gain = 1.0;
40
41
    return AData *   ((0.5 * vRef / gain) / 8388607); //8388607 = 2^23 - 1
42
}
43
44
45
// ----------------------------------------------------------------------------
46
// Hauptprogram
47
48
int main(void)
49
{
50
  // Initialisiere die UART Schnittstelle
51
  uart_init(UART_BAUD_SELECT(19200UL, F_CPU));
52
  
53
  // Aktiviere Interrupts
54
  sei();
55
  
56
  // Umleiten der Standardausgabe => ab jetzt koennen wir printf() verwenden
57
  stdout = &mystdout;
58
  
59
  // Versuche den MCP2515 zu initilaisieren
60
  if (!mcp2515_init()) {
61
    //PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
62
    for (;;);
63
  }
64
  else {
65
    //PRINT("MCP2515 is aktiv\n\n");
66
  }
67
  
68
  //PRINT("Erzeuge Nachricht\n");
69
  tCAN message;
70
  
71
  // einige Testwerte
72
  message.id = 0x123;
73
  message.header.rtr = 0;
74
  message.header.length = 2;
75
  message.data[0] = 0xab;
76
  message.data[1] = 0xcd;
77
  
78
  print_can_message(&message);
79
  
80
  //PRINT("\nwechsle zum Loopback-Modus\n\n");
81
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));
82
  
83
  // Sende eine Nachricht
84
  if (mcp2515_send_message(&message)) {
85
    //PRINT("Nachricht wurde in die Puffer geschrieben\n");
86
  }
87
  else {
88
    //PRINT("Fehler: konnte die Nachricht nicht senden\n");
89
  }
90
  
91
  // warte ein bisschen
92
  _delay_ms(10);
93
  
94
  if (mcp2515_check_message()) {
95
    //PRINT("Nachricht empfangen!\n");
96
    
97
    // read the message from the buffers
98
    if (mcp2515_get_message(&message)) {
99
      print_can_message(&message);
100
      //PRINT("\n");
101
    }
102
    else {
103
      //PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
104
    }
105
  }
106
  else {
107
    //PRINT("Fehler: keine Nachricht empfangen\n\n");
108
  }
109
  
110
  //PRINT("zurueck zum normalen Modus\n\n");
111
  mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
112
  
113
  // wir sind ab hier wieder mit dem CAN Bus verbunden
114
  
115
  //PRINT("Versuche die Nachricht per CAN zu verschicken\n");
116
  
117
  // Versuche nochmal die Nachricht zu verschicken, diesmal per CAN
118
  if (mcp2515_send_message(&message)) {
119
    //PRINT("Nachricht wurde in die Puffer geschrieben\n\n");
120
  }
121
  else {
122
    //PRINT("Fehler: konnte die Nachricht nicht senden\n\n");
123
  }
124
  
125
  //PRINT("Warte auf den Empfang von Nachrichten\n\n");
126
127
128
    /* For CAN board carrying ADS1234 only
129
     */      
130
    //PRINT("================ \n");
131
    //PRINT("Schalte jetzt Pins durch...\n");
132
    //PRINT("ADS1234:  set gain factor to %3d...  ", 1);
133
    //if(
134
     ADS1234_setGain(1);
135
     // )
136
        //PRINT("[done]\n");   
137
    //else
138
        //PRINT("[failed]\n"); 
139
140
    //PRINT("ADS1234:  set channel to %2d...       ", 4);
141
    //if(
142
     ADS1234_setChannel(4);
143
     // )
144
        //PRINT("[done]\n");   
145
    //else
146
        //PRINT("[failed]\n"); 
147
148
    //PRINT("ADS1234:  set speed to %2d...         ", 10);
149
    //if(
150
     ADS1234_setSpeed(10);
151
     //)
152
        //PRINT("[done]\n");   
153
    //else
154
        //PRINT("[failed]\n"); 
155
        
156
157
    //PRINT("ADS1234:  calibrating...             ");
158
    //if ( 
159
    ADS1234_calibrate();
160
    // )
161
        //PRINT("[done]\n");
162
    //else
163
        //PRINT("[failed]\n");
164
165
166
    //PRINT("SetUp beendet.\n==============\n\n");
167
168
    //Let's get us a variable to hold latest data
169
    int32_t AData=0;
170
    int count = 0;
171
    char str[9];
172
173
174
    // ----------- built a magnus can message ---------------------
175
    uint8_t dat[8];
176
    dat[0] = 0x23;
177
    dat[1] = 0x23;
178
    dat[2] = 0x23;
179
    dat[3] = 0x23;
180
    dat[4] = 0x23;
181
    dat[5] = 0x23;
182
    dat[6] = 0x23;
183
    dat[7] = 0x23;
184
//    tCAN m;
185
186
    srand(125);  
187
188
    while (1) {
189
190
        // warten bis wir eine Nachricht empfangen
191
        if (mcp2515_check_message())
192
        {
193
            PRINT("Nachricht empfangen!\n");
194
195
            // Lese die Nachricht aus dem Puffern des MCP2515
196
            if (mcp2515_get_message(&message)) {
197
                print_can_message(&message);
198
                PRINT("\n");
199
            }
200
            else {
201
              PRINT("Kann die Nachricht nicht auslesen\n\n");
202
            }
203
        }
204
205
        
206
        /* For CAN board carrying ADS1234 only
207
         */ 
208
        if(ADS1234_checkDrdy())
209
        {
210
211
            PRINT("Data waiting ...");
212
213
            if(ADS1234_getData(&AData)) 
214
            {
215
                PRINT("count: %i Value:", count);
216
                //PRINT("%x\n",AData);
217
                float VData = counts2voltage(AData);
218
                ltoa(VData, str, 10);
219
                PRINT("%f V\n",VData);
220
221
            }
222
            else
223
                PRINT("Could not acquire data!\n");
224
        }
225
226
        count += 1;
227
        
228
        _delay_ms(500);
229
    }
230
  
231
  return 0;
232
}

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

von Peter D. (peda)


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

von Karl H. (kbuchegg)


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.

von S. G. (goeck)


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?

von Karl H. (kbuchegg)


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!

von Karl H. (kbuchegg)


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.

von S. G. (goeck)


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:
1
#define  PRINT(string, ...)    printf_P(PSTR(string), ##__VA_ARGS__)
 durch
1
#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.

von S. G. (goeck)


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?

von Karl H. (kbuchegg)


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.

von Peter D. (peda)


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

von Karl H. (kbuchegg)


Lesenswert?

S. G. schrieb:

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

machs Sicherheitshalber so
1
#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 :-)

von Karl H. (kbuchegg)


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?

von S. G. (goeck)


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.

von S. G. (goeck)


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.

von Karl H. (kbuchegg)


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.

von S. G. (goeck)


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

von S. G. (goeck)


Lesenswert?

Also die Festkommaarithmetik funktioniert beim ersten Ansatz nach dem 
vorgeschlagenen Tutorial gut.

von Karl H. (kbuchegg)


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 ...
1
  if (!mcp2515_init()) {
2
    PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
3
    for (;;);
4
  }
... liest sich natürlich wunderbar. Aber ein simples
1
  if (!mcp2515_init()) {
2
    PRINT("Fehler: MCP2515 nicht gefunden!\n");
3
    for (;;);
4
  }

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

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.

von S. G. (goeck)


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

von Peter D. (peda)


Lesenswert?

Eine sehr schlanke Zahlenausgabe:

Beitrag "Formatierte Zahlenausgabe in C"


Peter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.