Forum: Compiler & IDEs Suche eine kleine LCD library für den ATTiny26


von Bernd E. (edi)


Lesenswert?

Hallo,
stehe gerade vor dem Problem, dass mein hex File für den AtTiny26 obwohl 
im eigentlichen Programm nicht viel getan wird durch die LCD Ausgabe 
viel zu groß wird (9kB), gibt es da eine ganz abgespeckte Version für 
die Ausgabe am LCD (HD44780U komp. 2x16 LCD), die ich im Tiny verwenden 
könnte, oder wie macht ihr das?

von Jens B. (sio2)


Lesenswert?

Selber schreiben ;) ist ja eigentlich auch kein akt. oder du nimmst dir 
aus den sourcen nur das was du brauchst.

von Bernd E. (edi)


Lesenswert?

Hi,
hab meine (die ich normalerweise verwende) selbst geschrieben, aber aus 
Zeitgründen dachte ich, vielleicht hat ja jemand eine abgespeckte 
Version für den Tiny parat!

von Ulrich (Gast)


Lesenswert?

Da kann man nix abspecken. Da kann an nur das rauswerfen was man nicht 
braucht....

von Karl-j. B. (matrixman)


Lesenswert?

was brauchst du denn für Befehle an dein LCD?
und welche Sprache?

mfg Karl

von Bernd E. (edi)


Lesenswert?

Im Grunde brauch ich nur eine Ausgabe von Strings und vielleicht eine 
für int. Das ganze natürlich in C.

von Ulrich (Gast)


Lesenswert?

sowas kommt eh nicht in die lcd-libary. Da werden nur funktionen mit dem 
namen putc und puts nach ausen zur verfügung gestellt....

von Bernd E. (edi)


Lesenswert?

Hi,
das ist schon klar, aber in meiner lcd.c muss ich die Sachen ja auch 
ausprogrammieren!

Habe jetzt einige Sachen auch meiner lcd.h und lcd.c gelöscht, die Größe 
des hex-Files ist jedoch nicht kleiner geworden.

Wie verhält es sich eigentlich mit dem einbinden von Headerfiles, wenn 
ich z.B. nur itoa() aus stdlib verwende, wird dann auch nur der Code 
itoa() ins hexfile aufgenommen, oder alle Funktionen von stdlib?

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>wird dann auch nur der Code itoa() ins hexfile aufgenommen
und das, was itoa() zum wandeln braucht.

von Bernd E. (edi)


Angehängte Dateien:

Lesenswert?

Könnte ich vielleicht übers Makefile noch was rausholen, verwende 
nämlich ein Standard Hex File von MFile generiert, habs mal angehängt!

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

Zeich doch mal deinen Code! Da lässt sich vielleicht an Stellen drehen, 
wo du es selber nicht siehst (ist einfach so, passiert mir und anderen 
genauso).




("Zeich" = Kielerisch/Norddeutsch für "zeig")

von Bernd E. (edi)


Angehängte Dateien:

Lesenswert?

Hier ist mein Code!

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

Float-Berechnung kostet natürlich auch Speicher...
"dtostrf" erscheint mir sehr, sogar zu mächtig...

Und dann schluckt die LCD-Library vermutlich auch eine ganze Menge 
Speicher.

Sehe ich es richtig, dass du eine (Spannung) bzw. zwei (Strom) Stellen 
vor und 2 nach dem Komma darstellen willst?

Das mache ich so:

zehner = '0';
einer = '0';
zehntel = '0';
hundertstel = '0';
f = spg;
while (f>0.0) {f -= 1.0; einer++;)
while (f>0.1) {f -= 0.1; zehntel++;}
while (f>0.01) {f-= 0.01; hundertstel++;)

Die Zehner-Stelle genauso...
Durch '0' wird die float gleich in ASCII-Zeichen gewandelt.
Führende Nullen kann man auch noch herausfiltern...

von Bernd E. (edi)


Lesenswert?

Hi,
es wird in der ersten Zeile einfach ein Stromwert (zur Zeit auch noch 
der dazu gehörige ADC WErt) angezeigt und in der zweiten Zeile der 
Spannungswert.

Entstehen dann in den char Variablen zehner, einer,... die einzelnen 
Ziffern als Character?

Würde das für die Zehnerstelle so aussehen?
while (f>10.0) {f -= 10.0; zehner++;)

Solll ich statt double dann auch lieber float nehmen?

von Karl heinz B. (kbucheg)


Lesenswert?

> Und dann schluckt die LCD-Library vermutlich auch eine ganze Menge
> Speicher.

Das ist aber nicht viel. Die Fleury Lib ist ziemlich einfach
gestrickt:
  Basisfunktionen zur Byte-Ausgabe
  Initialisierung
  Ausgabe eines Charcater
  Ausgabe eines String
Mit ein paar Zig Bytes ist man da dabei.

Das meiste wird wohl durch die floating point Arithmetik +
die Formatierfunktionen draufgehen.

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>Würde das für die Zehnerstelle so aussehen?
>while (f>10.0) {f -= 10.0; zehner++;)

ja.

von Karl heinz B. (kbucheg)


Lesenswert?

> Solll ich statt double dann auch lieber float nehmen?

Das bringt mit gcc nichts.
float und double sind dort gleich gross und haben
daher auch dieselbe Implementierung.

Wenn du die floating point Library wegbekommen willst,
dann musst du komplett auf float bzw. double verzichten.

Ist aber kein Problem:
Deine Berechnung sieht so aus:

  spg = (adc_str * 5.0) / 1024.0;

Das kannst du auch mit Fixkommaarithmetik im long
Bereich machen:

  spg = ( adc_str * 500L ) / 1024;

(spg ist dann eine int Variable. Die long Rechnerei braucht
man nur deshalb, damit adc_str * 500 nicht den int Zahlen-
bereich überläuft).

Anstatt Zahlen im Bereich 0 bis 5 (als float) kommen da
jetzt Zahlen im Bereich 0 bis 500 heraus. Die Zehner- und
Einerstelle sind dabei deine ursprünglichen Nachkommastellen.
D.h. Wenn du jetzt bei der Ausgabe zwischen Hunderterstelle
und Zehnerstelle ein '.' einschmuggelst dann sieht die
Ausgabe aus wie vorher. Nur halt ohne Floating Point
berechnet.

  lcd_putint( spg / 100 );
  lcd_putc( '.' );
  lcd_putint( spg % 100 );

Was ähnliches kann man noch mit der anderen Berechnung machen
und schon fällt die Floting Point Library aus deinem Program
raus.

von Karl heinz B. (kbucheg)


Lesenswert?

Sehe gerade, dass in deiner 2-ten Berechnung auch Tausendstel
vorkommen, und dass die aus spg ausgerechnet werden.

Anstatt '*100' bietet es sich dann an, einfach alles *1000
zu nehmen um überall ganze Zahlen zu haben.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn ich mir die Größe der beiden Module hd44780.o und lcd.o aus
dem stdiodemo der avr-libc ansehe, dann sind das:
1
% avr-size *.o
2
   text    data     bss     dec     hex filename
3
    210       0       0     210      d2 hd44780.o
4
    102       0       1     103      67 lcd.o

Sollte also durchaus auch in einen ATtiny26 passen.

von Bernd E. (edi)


Lesenswert?

Hallo,
danke erstmal für eure super Ratschläge!

Deine Idee gefällt mir sehr gut Karl Heinz, hättest du die das bei der 
zweiten Berechnung so vorgestellt?

strom = ((spg - 2.5) *1000L) / 0.025;

von Bernd E. (edi)


Lesenswert?

Hab das mit dem Strom jetzt mal so gelöst:
strom = ((spg - 250) ) / 0.025;
lcd_gotoxy(11, 0);
lcd_putint( strom / 100 );
lcd_putc( '.' );
lcd_putint( strom % 100 );

Bin jetzt immerhin von 9kB auf 6kB runter gekommen!


Ich benutze  in meiner lcd.c auch noch stdlib für itoa, kann(soll) ich 
das auch noch rausbekommen? Hier mal meine Ausgabe für int am lcd:

void lcd_putint(int value)
{
  char string[4];

  itoa(value, string, 10);
  lcd_puts(string);
}

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>/ 0.025;

Würde ich durch "*40" ersetzen...

von Karl heinz B. (kbucheg)


Lesenswert?

> strom = ((spg - 2.5) *1000L) / 0.025;

Denk nach. Da sind immer noch Kommazahlen drinn!

Ich geh mal davon aus, dass du

  spg = ( adc_str * 5000L ) / 1024;

gemacht hast. spg hat also einen Wertebereich 0 bis 5000

Aus den 2.5 muessen dann klarerweise 2500 werden

   spg - 2500

sind dann Zahlen im Bereich -2500 bis +2500

Die durch 25 dividieren ( 0.025 * 1000) liefert
-100 bis +100.

Wenn ich mich jetzt nicht vertan habe (Chef war am
Telefon), dann sind das -0.1 Ampere bis +0.1 Ampere.
D.h. '.' wieder an der richtigen Stelle einschmuggeln.


von Karl heinz B. (kbucheg)


Lesenswert?

> Bin jetzt immerhin von 9kB auf 6kB runter gekommen!

Wenn du floating point komplett weg hast, müsstest
du nochmal einen grossen Sprung sehen.

itoa()
Ich denke, wenn floating point weg ist, hast du keine
Notwendigkeit mehr darüber nachzudenken. Ausserdem:
itoa() ist nicht soooo teuer. Irgendeine Umwandlung
brauchst du sowieso und ob du die jetzt selbst schreibst
oder ob du itoa() benutzt sollte Jacke wie Hose sein.

von Bernd E. (edi)


Lesenswert?

Hallo,
habe die Änderungen noch übernommen und bin jetzt auf 5kB.

Habe mir jetzt auch einmal die Größe anzeigen lassen, nur in was wird da 
gemessen, Byte?

I:\AVR Programme\UILogger>avr-size *.o
text    data     bss     dec     hex filename
 458       0       0     458     1ca lcd.o
 566      17       3     586     24a uilogger.o

von Karl heinz B. (kbucheg)


Lesenswert?

Ja, Byte

> habe die Änderungen noch übernommen und bin jetzt auf 5kB.
Wo liest du die 5K ab?
Doch hoffentlich nicht von der Größe der .hex Datei.


Wenn ich dein Pgm jetzt durch meinen Compiler jage,
dann lande ich bei
  Program:  1218 bytes (59.5% Full)
  Data:       25 bytes (19.5% Full)

Das reicht dann schon um gebrannt werden zu können.
Mit Floating Point waren die Daten übrigens:
  Program:  5916 bytes (288.9% Full)
  Data:       33 bytes (25.8% Full)

Kleine Umstellung, grosse Wirkung

von Bernd E. (edi)


Lesenswert?

Ich glaube die Ausgaben ans LCD fressen so viel Platz, denn wenn ich 
alle Ausgaben wegmache komme ich auf 3kB runter, wenn ich rein Strom und 
Spannungswert ausgebe bin ich auf 4 kB

von Karl heinz B. (kbucheg)


Lesenswert?

Bernd Edlinger wrote:
> Ich glaube die Ausgaben ans LCD fressen so viel Platz, denn wenn ich
> alle Ausgaben wegmache komme ich auf 3kB runter, wenn ich rein Strom und
> Spannungswert ausgebe bin ich auf 4 kB

Nochmal:
Du darfst nicht nach der Größe des .hex Files gehen.

Dein Program ist zur Zeit 1218 Bytes gross und füllt
den Tiny zu rund 60% aus.

von Bernd E. (edi)


Lesenswert?

Mann bin ich blöd...
Danke für den Hinweis, dann werd ich es gleich mal testen.

Wie sehe ich denn die Größe beim Compiler?

von Karl H. (kbuchegg)


Lesenswert?

Ich benutze den WinAVR im Rahmen des AVR-Studios. Dessen
Build Funktion gibt die Statistik im Abschluss aus.

von Malte _. (malte) Benutzerseite


Lesenswert?

Noch zwei Sachen:
Du verwendest alle globalen Variablen als volatile -soweit OK.
1. Du beschreibst "adc_str" in einem Interrupt - das ist eine 16Bit 
Variable.
Wenn die Anzeige einigermaßen Zuverlässig sein sollte, musst du die 
Interrupts deaktiveren bevor du die an die LCD Libray übergibst. Sonst 
könnte es in seltenen Fällen dazu kommen dass die erste Hälfte es alten 
Wertes mit dr zweiten 8 Bit Hälfte des neuen Wertes auf dem Display 
angezeigt wird.
2. Wenn du volatile Variablen lokal mehrfach verwendet lohnt es sich 
eine lokale Kopie anzulegen um unnötige RAM Zugriffe zu vermeiden.

Also:
1
cli();
2
uint16_t adc_str_l = adc_str;
3
sei();
4
lcd_putint(adc_str_l);
Bei 8 Bit Variablen ist das natürlich nicht unbedingt nötig.

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.