Hallo liebe Community,
Ich würde gerne mal eure Meinung hören. Ich programmiere seit letzten
Jahr Oktober 2018 ein Aquarium Controller.
Da mein Projekt ständig weiter entwickelt wird, wird nun auch langsam
der Programmspeicher meines Mikrocontrollers knapp. Hatte damals schon
den ATMega644 gegen ein ATMega1284P ausgetauscht. Da die 64K des 644
voll waren, nun der ATMega1284P hat 128K Flash und 16K SRAM.
Im Moment sieht es bei mir so aus das ich 100K Flash benutze und 7Kb
SRAM. Von den 128K gehen noch 4K für den Bootloader runter. Mein Projekt
ist jedoch noch nicht fertig und ich habe noch einige Sachen die ich
umsetzten möchte.
Nun für ein Funktionsfähiges Menü verbrauche ich ungefähr 10-15KB Flash,
RAM ist immer Unterschiedlich. Ein großer Teil des Flash Speicher geht
für die Text drauf die ich auf dem ILI9341 TFT Display darstelle.
Ich stelle mir nun aber die Frage was mache ich wenn der Speicher
endgültig voll ist? Es gibt noch den ATMega2560 der den doppeln Speicher
aufweist jedoch dafür nur den halben RAM von ATMega1284P. Naja und ist
halt SMD aber das wäre das kleinste Problem.
Oder vielleicht ein kompletter Umstieg auf ein ganzen anderen Prozessor
wie zum Beispiel den STM32 den gibt es ja bis 2MB Flash und 512kB RAM.
Aber mal ganz abgesehen das ich noch keinerlei Erfahrung mit dem STM32
habe.
Das habe ich so im Moment an Peripherie angeschlossen:
- TFT Display(ILI9341)
- SD Karte(FatFs)
- Netzwerkchip ENC28J60
- Externes EEPROM
- RTC(MCP7940M)
- Rotary Encoder(Bedienung)
Geplant ist noch:
- Akustischer Signalgeber
- Fehlerspeicher(SD Karte)
- SMTP(nicht sicher)
- USV(nicht sicher)
Was würdet ihr machen wenn es bei euch so wäre. Upgrade auf ATMega2560
oder kompletter Wechsel auf einen Prozessor zb. STM32?
Schönen Sonntag noch
Lg
Da müsste man den Code sehen.. wenn das so schnell voll ist für so eine
einfache Aufgabe muss da wohl die Arduino IDE am Werk sein?
Bei Arduino und anderen normalen Librarys kann man eine Menge
optimieren/abspecken..
EDIT: das meisste müsste der ENC28J60 ausmachen.. da sollte man
heutzutage lieber den W5100 oder nen ESP8266 nehmen. ( beim ENC baust Du
die kommunikation im Atmega zusammen, beim w5100 macht das der w5100
schon selbst)
Welche IDE wird denn benutzt?
Mein Vorschlag:
https://www.olimex.com/Products/OLinuXino/A64/A64-OLinuXino/open-source-hardware
Das erschlägt sehr viel von dem, was Du selber mühselig programmieren
musstest:
- TFT Display, wahlweise mit Touch direkt anschließbar, z.B. das hier
https://www.olimex.com/Products/OLinuXino/LCD/LCD-OLinuXino-7/open-source-hardware
- SD-Karte wird direkt vom Linux unterstützt
- Gigabit Ethernet ist direkt da.
- EEPROM brauchst Du wahrscheinlich nicht mehr, ist aber leicht
anschließbar
- RTC ist bereits drin
- Encoder sollte kein Problem sein, aber den könntest Du eventuell mit
Toucheingabe besser in Software implementieren
- Akustischer Signalgeber: Audio 3.5" Stereo-Klinke vorhanden, Beeper
kann einfach über GPIO angeschlossen werden
- SMTP: installier einfach einen postfix auf dem Linux, und gut ist.
- USV: LiPo-Akku anschließbar.
Du wirst das meiste sofort da haben, ohne groß basteln zu müssen.
fchk
PS: Einen Pi würde ich nicht nehmen, da verlierst Du einfach zu viele
IOs, wenn Du ein RGB-TFT anschließen willst. Die Peripherie ist beim PI
viel schlechter als bei Alternativprodukten.
Ver Wunderter schrieb:> Frank K. schrieb:>> Mein Vorschlag:>> Booaaahhhh, einen Quad Core für die Aquariumsteuerung.>> Das ist wirklich die optimale Lösung!
Ja und? Für die AVR-Lösung wird der Fragesteller sicher insgesamt mehr
bezahlt haben als die 36 Oiro, die Olimex für das Board aufruft.
fchk
Hallo,
micha schrieb:> Wenn du eh eine SD-Karte planst eventuell Texte auslagern?
SD Karte ist schon drin, habe ich auch schon gedacht jedoch kann man die
SD Karte aus dem System entfernen um zb. den Fehlermeldungen am PC
auslesen zu können. Die Grundfunktionen sollen erhalten bleiben. Daher
fiel diese Auswahl weg.
Philipp K. schrieb:> Arduino IDE am Werk sein?
Nein, programmiere das Ding in Atmel Studio 7 in C.
Philipp K. schrieb:> Bei Arduino und anderen normalen Librarys kann man eine Menge> optimieren/abspecken..ENC28J60 -> Eine Library von Tuxgraphics welche vom Inhalt her größten
Teils auf der Arduino EtherShield und EtherCard Lib basiert.
ILI9341 -> Hat Ähnlichkeit mit der Adafruit Lib
SD Karte -> FatFs von ELM ChaN
Rotary Encoder -> kommt aus diesen Forum.
Andere Sachen wie Kommunikation wie I2C, SPI, USART, EEPROM sind selbst
geschrieben
Philipp K. schrieb:> das meisste müsste der ENC28J60 ausmachen
Ja ein großen Anteil macht der ENC aus mit der SD Karte zusammen. Der
ENC28J60 ist halt im rohen zustand Dumm wie Brot. TCP/IP HTTP ist halt
in Software gelöst.
Philipp K. schrieb:> lieber den W5100 oder nen ESP8266 nehmen.
Muss mal schauen ob es den W5100 in einzel Ausführung gibt ohne Arduino
Shield.
Frank K. schrieb:> Das erschlägt sehr viel von dem, was Du selber mühselig programmieren> musstest:
Ich hatte am Anfang ein PI in der Hand gehabt, habe mich letzte endlich
aber für den AVR entschieden da dich das ganze gerne selber "klassisch"
programmieren wollte.
Lg
W5100Usa schrieb:> Gibt es. Ganz handlich ...>> Ebay-Artikel Nr. 223614689695
Ah okay du warst schneller als ich :) Danke
Werde ich mal bestellen und ausprobieren.
Crazy H. schrieb:> Wie wäre denn ein XMega384?
Hmm, hörst sich ja auf im ersten Moment nicht schlecht an, weißt du ob
es möglich ist mit bestehen ATMega Kenntnissen den XMega programmieren
zu können. Oder ist der von der Struktur komplett anderes?
Mfg
Eventuell macht hier ein Wechsel auf ein ganz anderes Kaliber Sinn:
Raspberry Pi
Wobei ich mich schon frage, wie man 128kB für ein Aquarium voll bekommt.
Das muss man erstmal schaffen.
Felix N. schrieb:> Ah okay du warst schneller als ich :) Danke
Wenn du erst mal die Last des Ethernet- und TCP-Handling vom
ENC weg hast wirst du schon mal eine ganze Menge Speicher
gewonnen haben.
Und falls du bis jetzt Arduino-Klassen verwendet hast und
auf "normale" Programmierung umsteigst noch mal eine ganze
Menge.
ATXmegas sind meines Wissens nach nicht vom Arduino
Environment unterstützt.
Felix N. schrieb:> ob> es möglich ist mit bestehen ATMega Kenntnissen den XMega programmieren> zu können. Oder ist der von der Struktur komplett anderes?
Die Register heissen ein bisschen anders und es sind viel
mehr, aber sonst kein grosser Umschwung.
W5100Usa schrieb:> Wenn du erst mal die Last des Ethernet- und TCP-Handling vom> ENC weg hast wirst du schon mal eine ganze Menge Speicher> gewonnen haben.
Ich habe kurz die Netzwerk Initialisierung und Anfragen auskommentiert.
Mit ENC verwende ich Aktuell:
Program Memory Usage : 99750 bytes 76,1 % Full
Data Memory Usage : 7001 bytes 42,7 % Full
Und ohne:
Program Memory Usage : 85646 bytes 65,3 % Full
Data Memory Usage : 5746 bytes 35,1 % Full
W5100Usa schrieb:> Und falls du bis jetzt Arduino-Klassen verwendet hast und> auf "normale" Programmierung umsteigst noch mal eine ganze> Menge.
Ich nutze kein Arduino IDE, Ich habe mit Header und C Dateien.
W5100Usa schrieb:> ATXmegas sind meines Wissens nach nicht vom Arduino> Environment unterstützt.
Muss es ja auch nicht. Ich kann den ATXMega in Atmel Studio ja als
Prozessor auswählen.
Lg
Wenn du auf einen ESP8266 oder ESP32 wechselst, hast du Flash ohne Ende
und das Netzwerk Interface auch schon dabei. Allerdings sind deren I/O
Pins nicht ganz so flexibel einsetzbar, wie du es von deinem AVR gewohnt
bist.
Eine Kombination aus einem AVR für die eigentliche Steuerung + einem ESP
8266 für das Benutzerinterface wäre vielleicht eine praktikable Option
für Dich, wenn du bei Mikrocontrollern bleiben möchtest.
Felix N. schrieb:> Ich habe kurz die Netzwerk Initialisierung und Anfragen auskommentiert.
Ob du damt alles wegbekommst? Dazu müsste dein Linker schon
sehr intelligent sein alle unbenutzten Funktionen zu detektieren
und herauszunehmen.
Ich denke um zu einem genaueren Ergebnis zu kommen müsstest du
wirklich die Ethernet- und TCP Lib voll herausnehmen.
Aber es käme auch Code dazu: die W5100 Einbindung kostet
natürlich trotzdem was an Programm-Speicher und RAM ....
Felix N. schrieb:> Ein großer Teil des Flash Speicher geht> für die Text drauf die ich auf dem ILI9341 TFT Display darstelle.
Dann machst Du irgendwas grundlegend falsch.
Mußt Du wirklich ganze Romane an Text anzeigen?
Was belegen denn die vielen Zeichensätze allein?
In der Regel reicht ein Font in 3 Größen völlig aus.
> Ich habe kurz die Netzwerk Initialisierung und Anfragen auskommentiert.>> Mit ENC verwende ich Aktuell:> Program Memory Usage : 99750 bytes 76,1 % Full> Data Memory Usage : 7001 bytes 42,7 % Full>> Und ohne:> Program Memory Usage : 85646 bytes 65,3 % Full> Data Memory Usage : 5746 bytes 35,1 % Full
Sehr gut. Nun machst die selbe Datenerhebung für jeden anderen
Teilbereich deines Aquariumprogramms auch und führst Buch.
(wenn deine FW sauber modularisiert ist, solltest du bis runter auf eine
"leere" main(..)-Funktion gelangen. Wobei: man kann alles
übertreiben...)
Dann steckst Du Hirnschmalz erstmal in die 3 Speicherintensivsten
Bereiche, mit Fokus auf Verkleinerung.
Danach vergleichst Du die Bereiche untereinander und suchst
Code-Doppelspurigkeiten. Da wo's nur ähnlich ist arbeitest solange daran
rum bis es gleich wird. Dann ausfaktorieren .
Wenn Du echt viele Präsentationstexte (Anzeige) hast, überlege ob ALLE
diese in was anderem als ASCII codierbar wären. Schliesslich belegt 1
Buchstabe 1Byte, ASCII hat aber nur 127 wovon du auch nicht alle
benötigst.
Code welcher das dann handhaben würde, müsste dann aber die
Platzersparnis nicht auffressen...
(ich habe in Konditional geschrieben...)
Viel Erfolg!
Wenn Du ein intelligentes Display verwendest hast Du plötzlich eine
Menge Speicher über, Touch läuft dann nebenbei und Anzeige und Bedienung
werden viel flüssiger, weil die Bildrate sehr viel höher sein kann bei
einem
Bruchteil an zu übertragenden Daten.
Sowas wie das hier:
https://www.matrixorbital.com/ftdi-eve/eve-bt815-bt816/eve3-43g
Das hat Zeichensätze eingebaut und einen FLASH Chip den man mit u.a.
Bildern, UTF-8 Zeichensätzen und Texten füllen kann.
Die Kapazitiv-Touch Version habe ich ausgewählt, weil Resistiv-Touch im
Vergleich einfach nur eklig ist.
Resistiv-Touch werde ich mir hoffentlich nie wieder antun müssen.
Die haben eine SPI Schnittstelle die mit 3,3V Pegeln läuft und benötigen
ein 3,3V Netzteil, je größer das Display, desto mehr Strom.
Das sind so ~200mA bei 3,5", ~300mA bei 4,3", ~500mA bei 5" und ~750mA
bei 7".
Ja, die Größen habe ich alle schon mit AVR benutzt, bei 40+ Bildern pro
Sekunde hat der Controller auch noch nicht wirklich was zu tun.
Aber sowas wie eine Animation für z.B. eine Pumpe läuft schön flüssig,
so mit Drehung des Bildes durch den Grafik-Chip.
BerAVRter schrieb:> Sehr gut. Nun machst die selbe Datenerhebung für jeden anderen> Teilbereich deines Aquariumprogramms auch und führst Buch.
Man könnte aber auch die Größe der einzelnen Programmteile im MAP-File
ablesen.
Ein Klassiker: Wenn du Strings einfach "normal" (wie beim PC) in
Anführungsstriche schreibst, dann belegen sie doppelt Speicher, nämlich
Flash und RAM. Wenn du die gleichen Strings in mehreren
Quelltext-Dateien hast, dann wird auch Speicherplatz vergeudet.
Kennst du die Makros PSTR und PROGMEM?
Felix N. schrieb:> Frank K. schrieb:>> Das erschlägt sehr viel von dem, was Du selber mühselig programmieren>> musstest:>> Ich hatte am Anfang ein PI in der Hand gehabt, habe mich letzte endlich> aber für den AVR entschieden da dich das ganze gerne selber "klassisch"> programmieren wollte.
Was heißt für Dich "klassisch"? Unter Unix haben schon Generationen vor
Dir in C und C++ entwickelt. Und solche Sachen wie TCP/IP, USB,
Filesysteme usw. muss man heute nicht mehr selber entwickeln, das kann
man ruhig einem Betriebssystem überlassen. Das ist jedenfalls der Weg,
über den Du mit minimaler Arbeit das Maximum an Möglichkeiten bekommst.
Alternativ:
http://www.ti.com/tool/EK-TM4C1294XL
Da bekommst Du auch eine ganze Menge an Rechenleistung und Speicher,
dazu 10/100 MBit Ethernet MAC+PHY im Chip, USB und was man sonst noch
alles so braucht. Und dazu gibts ein schönes RTOS und eine umfangreiche
Treiberbibliothek.
fchk
Hm. Wieviel Speicher belegen denn die Texte?
Es gibt Techniken um den Speicher dafür zu verringern. Angefangen von
Kompression bis zur Zerlegung in kleinere Textbautsteine.
Ob sich das im konkreten Fall lohnt, hängt natürlich von der Menge an
Text ab, denn im Austausch ist Code für die Dekompression bzw. das
zusammensetzen der Textbausteine nötig.
Eine etwas schwieriger zu realisierende Möglichkeit ist, die Texte zu
kürzen bzw. entfallen zu lassen. Schwieriger, weil es dazu nötig ist,
gewisse Wünsche und Vorstellungen zu verändern. Dabei steht man sich
mitunter selbst im Weg. :-)
Theor schrieb:> Eine etwas schwieriger zu realisierende Möglichkeit ist, die Texte zu> kürzen bzw. entfallen zu lassen.
Werden denn überhaupt so viele Texte verwendet, bzw. können Deine Fische
lesen?
Ich vermute eher, ungeschickte Programmierung uneinheitlicher Menüs
benötigt zu viel Speicher.
Um nicht den µC komplett zu wechseln, würde ich Funktionen in einen 2.
AVR auslagern und über IIC ankoppeln. Der Hauptprozessor erledigt dabei
die Bedienung.
Genaueres kann man nur sagen, wenn man sieht, was jetzt vorhanden und
wie es umgesetzt ist.
Es gibt auch neuere AVRs mit deutlich mehr Speicher. Sie lösen das
Problem der Optimierung nur bedingt ;).
Im wirklichen Leben wäre das der Gau, da man sich im Vorfeld keine
Gedanken über die richtige Plattform für sein Projekt gemacht hat.
Der ESP32 wäre die Lösung allerdings muss dein Code auch für ein OS
geeignet sein. Das heißt sich mit Threads und einem völlig anderen
Framework beschäftigen zu müssen.
Wie viel Aufwand es ist den Code auf einer anderen Plattform zum laufen
zu bringen hängt von deinem Programmierstil ab.
Felix N. schrieb:> Da mein Projekt ständig weiter entwickelt wird,
[...]
> Das habe ich so im Moment an Peripherie angeschlossen:> - TFT Display(ILI9341)> - SD Karte(FatFs)> - Netzwerkchip ENC28J60
Schau nach vorne, mach einen Plattformwechsel, aber richtig.
Vermutlich tust Du Daten loggen und die Daten irgendwie mit Netzwerk
abrufbar machen oder irgendwohin speichern etc.
Es wird nicht lang gehen, und Du willst evtl. schöne Webseiten mit
Messwerten etc. darstellen. Vielleicht soll das auch per MQTT etc. an
einen Cloud-Hoster angebunden werden etc.
Tu' Dir den Gefallen und rüste auf. Ich vermute, es wird Dir weiterhin
viel Spaß machen neue Funktionen einzubauen und auszuprobieren. Lass Dir
den Tag von Kleingeistern nicht versauern. Die Zeit ist zu Schade, um
sich mit Beschränkungen der Plattform rumärgern zu müssen.
- Willst Du mehr in Richtung Netzwerk und Daten machen, nimm etwas
in der Raspi-Klasse.
- Wenn das Netzwerk wirklich nur ganz trivial bleiben soll, nimm
einen richtig fetten Controller mit viel RAM und richtig Flash
und mehr Bits.
Das Aquarium selbst benötigt so sehr viel mehr Energie und Wartung, da
brauchst Du nicht am Controller sparen.
Nicht kleckern, sondern klotzen.
Felix N. schrieb:> - SMTP(nicht sicher)
Ach, das hatte ich überlesen. Nimm einen Raspi. Die Wahrscheinlichkeit
dass Du zwingend TLS brauchst, ist hoch.
Erfahrener Entwickler schrieb:> Das Aquarium selbst benötigt so sehr viel mehr Energie und Wartung, da> brauchst Du nicht am Controller sparen.
Als ob der Preis des µC das Problem wäre ;-)
> Tu' Dir den Gefallen und rüste auf.
Ja was denn nun: aufrüsten oder umrüsten?
Durch geschickte Programmoptimierungen kann man immer ein paar Bytes
heraus schinden (z. B fixed point statt floating point nutzen)
Kann man die Texte oder Fonts komprimiert abspeichern? (z. B. nur 7 bit
statt 8 verwenden, würde schon 12,5% sparen)
Hast du denn schon heraus gefunden, was den meisten Speicher braucht?
Gruß Roland
Vielleicht hat er die Texte alle als Bitmap abgelegt.
Felix, bist du noch da? Ich glaube es wäre Sinnvoll, wenn du dich an der
Diskussion beteiligen würdest.
Ansonsten können wir unser Urteil gegen Dich in Abwesenheit sofort
fällen :-)
Felix N. schrieb:> Da mein Projekt ständig weiter entwickelt wird, wird nun auch langsam> der Programmspeicher meines Mikrocontrollers knapp. Hatte damals schon> den ATMega644 gegen ein ATMega1284P ausgetauscht.
Hossa, du schaffst es, 128k Flash und 16k SRAM mit der Steuerung eines
Aquariums zu füllen?
Das ist doch nicht etwa ein Aquarium mit der Komplexität etwa von dem in
Manly Beach, Sydney, NSW, Australia? Weil: ich kann mir kaum vorstellen,
dass man sich SOWAS mal eben zu Hause hinstellen kann...
Wie auch immer: die Jungs dort kommen jedenfalls mit ca. 4k SRAM und 48K
ROM klar. SPS und HMI zusammengezählt...
Mir scheint, du musst ein wenig an deiner Programmierkompetenz arbeiten,
statt nach mehr Hardware zu schreien...
W5100Usa schrieb:> Ob du damt alles wegbekommst?
Nein ich habe die #includes ja nicht auskommentiert. Es sollte ja auch
nur verdeutlichen das der ENC28J60 circa. 20Kbyte an Speicher frisst.
W5100Usa schrieb:> die W5100 Einbindung kostet> natürlich trotzdem was an Programm-Speicher und RAM ....
logisch.
Peter D. schrieb:> Mußt Du wirklich ganze Romane an Text anzeigen?
Sorry, habe mich vertan ich die Texte liegen im RAM und nicht im Flash.
Ich habe im Moment ja nur die Grundlegende Menüs fertig(Hauptmenü,
Uhrzeit, Co2, pH Elektrode, SD Karte, Netzwerk und Lichtsteuerung) die
Texte die da drin sind brauche ich so wie sie sind.
BerAVRter schrieb:> Dann steckst Du Hirnschmalz erstmal in die 3 Speicherintensivsten> Bereiche, mit Fokus auf Verkleinerung.
Ich weiß zb. das die ENC Lib auch UDP und NTP vorhanden sind und auch
benutzt werde diese Funktionen mal entfernen da ich diese nicht verwende
und auch nicht vor habe zu verwenden.
Rudolph R. schrieb:> intelligentes Display
Hört sich auf jeden Fall interessant an, gut die FPS bei dem ILI9341 mit
8 MHz Clock Speed sind jetzt nicht sonderlich hoch aber ich hatte bis
jetzt noch nicht vor Grafiken zu verwenden. Aber werde ich auf jeden
Fall im Hinterkopf behalten.
m.n. schrieb:> Ich vermute eher, ungeschickte Programmierung uneinheitlicher Menüs> benötigt zu viel Speicher.
Ich habe jetzt mal mein letztes Menü angehängt in diesem wird die
Lichtsteuerung gehandelt.
m.n. schrieb:> Um nicht den µC komplett zu wechseln, würde ich Funktionen in einen 2.> AVR auslagern und über IIC ankoppeln. Der Hauptprozessor erledigt dabei> die Bedienung.
Also würde ein Prozessor als Externer Speicher arbeiten? Würde SPI nicht
besser sein weil dort höhere Geschwindigkeiten erreicht werden als max.
400KHz bei I2C?
Erfahrener Entwickler schrieb:> Die Wahrscheinlichkeit> dass Du zwingend TLS brauchst
Ja deswegen steht da auch hinter (nicht sicher) ...
Roland P. schrieb:> Hast du denn schon heraus gefunden, was den meisten Speicher braucht?
Ja der ENC und die SD Karte. Der ENC ca. 20Kb die SD ca. 15kb. Und der
Rest geht wahrscheinlich auf die sprintf's drauf, habe gehört die sollen
auch nicht so speicher Schonend sein.
Mfg
Ui.
Menues zu Fuß programmiert, wie es aussieht.
Das braucht natürlich Code noch und nöcher.
Und häufig doppelter Code. (Vermutlich z.T. durch die Optimierung
abgefangen).
Und, wie zu vermuten war, reichlich mehrfache Kopieen von Texten.
Das sowas sich so (aus-)wächst ist bei einem Anfänger der dann noch
dieses oder jenes Feature haben will normal (und auch nichts Schlimmes),
Aber, das macht die Entwicklung auf die Dauer immer schwieriger und
schwieriger.
Also, falls Dein einziges großes Projekt (im Leben) überhaupt sein soll,
dann lass es so und hör auf, wenn der FLASH-Speicher voll ist.
Ansonsten, gehe den nächsten Schritt zur Meisterschaft und überarbeite
den Code gründlich.
Felix N. schrieb:> die Texte liegen im RAM und nicht im Flash
Warum? Schau Dir mal in der Doku der AVR C Library die Beschreibung der
PSTR und PROGMEM Makros an. Ich habe dafür zwar ein -1 bekommen, aber
ich bin zuversichtlich, dass du damit eine große Menge RAM frei bekommen
wirst. Statt sprintf nutzt du dann sprintf_P.
Theor schrieb:> Das sowas sich so (aus-)wächst ist bei einem Anfänger der dann noch> dieses oder jenes Feature haben will normal (und auch nichts Schlimmes),> Aber, das macht die Entwicklung auf die Dauer immer schwieriger und> schwieriger.
Hallo,
Gut das ich ein guter Programmier bin habe ich nie gesagt, ich habe mir
mein gesamtes Programmier wissen aus YouTube Videos, Code Schnippels,
teilweise Bücher und Foren zusammen gesammelt. Habe Beruflich nix damit
zutun. Nur Hobby.
Das was funktioniert hat habe ich am Anfang erst mal auch nicht mehr
verändert. Warum? Es hat ja funktioniert da habe ich mir kein Kopf
gemacht ob dieses nun maximal Optimiert ist oder nicht. Gut das mag
vielleicht nach einer schlechten Einstellung klingen. So soll es aber
nicht rüber kommen.
Ich bin jeder Zeit bereit aus meinen Fehlern zu lernen und diese zu dann
zu verhindern/verbessern. Schließlich siehst Du den Code ja ganz anderen
Augen als Ich, mag vielleicht an deiner Erfahrung liegen.
Stefanus F. schrieb:> Warum? Schau Dir mal in der Doku der AVR C Library die Beschreibung der> PSTR und PROGMEM Makros an. Ich habe dafür zwar ein -1 bekommen, aber> ich bin zuversichtlich, dass du damit eine große Menge RAM frei bekommen> wirst. Statt sprintf nutzt du dann sprintf_P.
Hi,
Wenn ich mich nicht irre werden Texts die man direkt übergibt im RAM
ausgelagert. Ich kenne die PSTR und PROGMEM Makros. Ich weiß auch das
Sie Texte in den Flash auslagern und so Platz im RAM Schaffen. Nur ich
habe 16K RAM und belege 7K zurzeit. Wenn die die ganzen Texte in den
Flash Schiebe wird mein Programmspeicher doch noch weniger. Und gerade
der Flash Speicher ist ja mein Problem. Oder habe ich jetzt da was
falsch verstanden?
MaWin schrieb im Beitrag #5966040:
> Poste mal bitte deinen Sourcecode
Hi, ich habe jetzt mal eine rar Datei angehängt wo mein ganzer Source
Code drin ist.
Mfg
Felix N. schrieb:> Ich bin jeder Zeit bereit aus meinen Fehlern zu lernen
Ich hab nur kurz in den Anzeigecode geschaut, aber was mir sofort
auffaellt ist der Mangel an Abstraktion bzw. die Wiederholung von (fast
oder) identem Code, e.g.
Und Du benutzt float. Das ist meistens vermeidbar.
Wenn ich Bruchteile von Volt messen will, dann nehme ich einfach die
passende Einheit. Nicht Volt, sondern mV oder uV. Zack, schon kann ich
mit Ganzzahlen rechnen. Floats brauchst DU nur, wenn Du einen hohen
Dynamikbereich brauchst, d.h. gleichzeitig sehr kleine und sehr große
Zahlen und dazwischen 10 oder mehr Zehnerpotenzen.
Ohne float wird auch stdio sehr viel kleiner.
Das ist mir nach 30s aufgefallen.
Auf dem vomn mir vorgeschlagenen Olimex-Board wäre das völlig egal. Da
brauchst Du Dich auch nicht um Menüs oder Strings im ROM zu kümmern. Als
Programmierumgebung nimmst Du Qt, das nimmt Dir alles ab.
In der richtigen Welt würde niemand mehr den von Dir gewählten Weg
nehmen. Zu viele Einschränkungen, zu aufwändig zu programmieren, zu
aufwändig zu warten. Schlicht zu teuer in der Entwicklung.
fchk
Felix N. schrieb:> Wenn ich mich nicht irre werden Texts die man direkt übergibt im RAM> ausgelagert. Ich kenne die PSTR und PROGMEM Makros. Ich weiß auch das> Sie Texte in den Flash auslagern und so Platz im RAM Schaffen. Nur ich> habe 16K RAM und belege 7K zurzeit. Wenn die die ganzen Texte in den> Flash Schiebe wird mein Programmspeicher doch noch weniger. Und gerade> der Flash Speicher ist ja mein Problem. Oder habe ich jetzt da was> falsch verstanden?
Die Texte sind doch sowieso im Flash. Müssen sie auch. Von wo anders als
auch dem Flash sollen sie denn nach dem Einschalten herkommen? Klar, aus
einem .data-Segment, das von der Compiler-Runtime noch vor main() ins
RAM kopiert wird. Und DAS ist vermeidbar.
Ja, nun hast DU auch eine Architektur (AVR) gewählt, wo Programm- und
Daten in getrennten Adressräumen liegen. Bei anderen Architekturen wie
ARM oder MIPS (PIC32) oder x86 ist das nicht so. Bei AVR, 8051 und 8-Bit
PIC muss halt der Programmierer entsprechend Grips in der Birne haben.
fchk
Frank K. schrieb:> Und Du benutzt float. Das ist meistens vermeidbar.
Ja, das stimmt. Aber es ist nur ein Funktionsaufruf, traegt kaum zur
Codegroesse bei, nur viel zur Laufzeit.
leo
Frank K. schrieb:> Nicht Volt, sondern mV oder uV
ich nehme cV centi Volt oder dV dezi Volt als Ganzzahl und füge das
Komma per Stringmanipulation ein.
mal als Beispiel..
im code sind 34 mal "ili9341_drawRect(277, 17, 36, 32,BLABLA); und auch
andere doppelt und dreifach..
dann lieber komprimieren mit:
void RechteckBLA(uint32_t color){
ili9341_drawRect(277, 17, 36, 32,color)
}
an der richtigen stelle dann ersetzen rechteckBLA(ORANGE);
Felix N. schrieb:> Theor schrieb:>> Das sowas sich so (aus-)wächst ist bei einem Anfänger der dann noch>> dieses oder jenes Feature haben will normal (und auch nichts Schlimmes),>> Aber, das macht die Entwicklung auf die Dauer immer schwieriger und>> schwieriger.>> Hallo,>> Gut das ich ein guter Programmier bin habe ich nie gesagt,> [...]
Und ich habe auch nicht behauptet, dass Du das von Dir gesagt hättest.
:-)
Darum ging es mir nicht. Du brauchst Dich auch nicht zu rechtfertigen.
Es geht darum, wie bestimmte Dinge entstehen. Es geht um Erklärungen,
nicht um Vorwürfe. Es darum, was die Folge bestimmter Vorgehensweisen
ist und wie man, meiner Ansicht nach, reagieren sollte, wenn einem diese
Folgen auf die Füsse fallen. Mehr nicht.
> Das was funktioniert hat habe ich am Anfang erst mal auch nicht mehr> verändert. Warum?> Es hat ja funktioniert da habe ich mir kein Kopf> gemacht ob dieses nun maximal Optimiert ist oder nicht. Gut das mag> vielleicht nach einer schlechten Einstellung klingen. So soll es aber> nicht rüber kommen.
Im Prinzip ist das sinnvoll. Aber es macht doch einen Unterschied, ob
man weiß, dass es bestimmte Entwurfsmuster gibt und ob man zur rechten
Zeit das Entwurfsmuster wechselt oder ob man das nicht weiß oder nicht
wechselt.
> Ich bin jeder Zeit bereit aus meinen Fehlern zu lernen und diese zu dann> zu verhindern/verbessern. Schließlich siehst Du den Code ja ganz anderen> Augen als Ich, mag vielleicht an deiner Erfahrung liegen.
Gerade so möchte ich von Dir verstanden werden. Ich gebe Dir Urteile
über Deinen Code ab - nicht über den Wert Deiner Person. (Von Deiner
Einstellung habe ich ja auch garnichts geschrieben. Das mag aber in
manchen Fällen durchaus ein sinnvolles Thema sein. Sagt aber immer noch
nichts über den Wert Deiner Person).
Also nochmal in Kürze, da Du darauf nicht eingangen bist:
1. Benutze datengetriebene Menuesysteme, wenn der explizite Code für
jeden Menuepunkt groß wird. Ab, über den Daumen gepeilt, mal so 5 bis 8
Menupunkten sind datengetriebene Systeme meist kleiner als "zu Fuß"
programmierte. Das äussert sich auch darin, dass Du häufig gleiche
Sequenzen von Funktionsaufrufen hast. Siehe:
Beitrag "Re: ATMega Flash wird langsam knapp. Upgrade o. Plattformwechsel?"
2. Da Du sehr häufig gleiche Texte oder Textteile verwendest, kannst Du
Speicher sparen, wenn Du diese Texte nicht als Literale im Code
verwendest, sondern nur einmal hinschreibst und anschliessend Zeiger
darauf verwendest.
In diesem Zusammenhang solltest Du wissen, dass Texte in jedem Fall im
Flash gespeichert werden, denn von irgendwo müssen sie ja auch dann
herkommen, wenn sie in das RAM geschrieben werden (also kopiert werden).
Insofern ist PSTR resp. PROGMEM sinnvoll.
Zusätzlich: Ich habe das vorher nicht erwähnt.
3. Vermeide die Verwendung von Literalen, insbesondere von
Zahlenliteralen im Code. Halte sie lieber an einer zentralen Stelle,
falls möglich.
Gleiches gilt für String-Literale (mal unabhängig davon, ob Du nun ein
Menuesystem verwendest). So sind Änderungen, insbesondere wenn wegen der
Änderung eines Wertes auch andere Werte geändert werden müssen,
einfacher.
Ich hoffe ich habe meine Absichten und Haltung Dir gegenüber klarer
gemacht und Du entscheidest Dich dafür, meine Einwände zu überdenken.
Jedenfalls, auch wenn Du es nicht tust, wünsche ich Dir Erfolg.
Stefanus F. schrieb:> Wenn du auf einen ESP8266 oder ESP32 wechselst, hast du Flash ohne Ende> und das Netzwerk Interface auch schon dabei.
Ich habe einen Aufbau mit Arduino AT328 und ENC28J60, der im Prinzip
läuft, aber das RAM nicht mehr ausreicht. Die Idee war, auf den ESP32 zu
wechesln. Aber: Jegliche Suche nach Libraries für Ethernet als
UDP-Server endete ohne Erfolg. Du schreibst immer, wie toll Ethernet vom
ESP unterstützt würde, nachvollziehen kann ich das nicht.
Manfred schrieb:> wie toll Ethernet vom> ESP unterstützt würde, nachvollziehen kann ich das nicht.
mindestens jede ENC oder W5100 Arduino library kann das..
praktischerweise ist das bestimmt Via WLAN gemeint.
Frank K. schrieb:> Und Du benutzt float. Das ist meistens vermeidbar.
Diese Angst ist unbegründet, die float Lib kostet nur einmal Flash (~1kB
ohne printf, scanf).
Bei einem AVR mit 4kB Flash würde ich überlegen, aber nicht bei 128kB.
Felix N. schrieb:> Wenn die die ganzen Texte in den> Flash Schiebe wird mein Programmspeicher doch noch weniger.
Nein. Denn ohne PSTR und PROGMEM müssen sie beim Start vom Flash ins RAM
kopiert werden. Wo sollen die Texte sonst liegen, in den Elkos?
Felix N. schrieb:> SD Karte ist schon drin, habe ich auch schon gedacht jedoch kann man die> SD Karte aus dem System entfernen um zb. den Fehlermeldungen am PC> auslesen zu können. Die Grundfunktionen sollen erhalten bleiben. Daher> fiel diese Auswahl weg.
Dann schliess parallel am SPI noch einen kleinen SPI-Flash-Baustein an.
Kein Grund für reine Daten einen uC mit größerem Flash zu nehmen. Gibts
für wenig Geld bis in MByte-Größen und kannst du einfach im Programm von
der SD-Karte aus befüllen.
Theor schrieb:> Zusätzlich: Ich habe das vorher nicht erwähnt.>> 3. Vermeide die Verwendung von Literalen, insbesondere von> Zahlenliteralen im Code. Halte sie lieber an einer zentralen Stelle,> falls möglich.
Das ist Quatsch bzw. stimmt nur für C-Strings (bei AVR). Zahlliterale
(als core-constant) werden vom Compiler immer direkt in den generierten
Code eingebaut.
Andreas B. schrieb:> Wenn Du doch sowieso schon ein externes Eeprom hast: Warum nicht dort> die Strings ablegen?
Die paar Texte sind doch überhaupt nicht das Problem, zumal der Compiler
gleiche Texte in der Regel erkennt und nur einmal anlegt.
Die wiederholten, nahezu gleichen Abläufe fressen Platz. Geschickter ist
es, mit Strukturen für die Bedienfelder zu arbeiten. Das ist einmaliger
Aufwand aber danach sehr effizient und transparent.
Für einen Anfänger ist das aber zunächst ein mächtiger Happen, der zu
schlucken ist, zumal es auch anfangs an der Einsicht dafür fehlen wird.
Und auch nur so, behält man bei unkommentiertem Code den Überblick.
Aber da muß man durch, egal wie "fett" der verwendete µC ist.
m.n. schrieb:> Andreas B. schrieb:>> Wenn Du doch sowieso schon ein externes Eeprom hast: Warum nicht dort>> die Strings ablegen?>> Die paar Texte sind doch überhaupt nicht das Problem, zumal der Compiler> gleiche Texte in der Regel erkennt und nur einmal anlegt.
Ich sehe eine ganze Menge Strings. 10% Einsparung würde ich schätzen.
>> Die wiederholten, nahezu gleichen Abläufe fressen Platz. Geschickter ist> es, mit Strukturen für die Bedienfelder zu arbeiten. Das ist einmaliger> Aufwand aber danach sehr effizient und transparent.
Das ist allerdings wahr. Das ganze Bediengedöns sieht recht ineffektiv
aus.
ich vermisse eine Angabe der Compileroptimierung
Stand das schon irgendwo?
Ansonst ja ... man kann immer etwas einsparen
alternativ die Discovery boards ...
gibt ja welche mit LCD + touch + ethernet + sdCard
Felix N. schrieb:> Ich weiß auch das> Sie Texte in den Flash auslagern und so Platz im RAM Schaffen.
Nein, sie werden nicht ins Flash ausgelagert. Da stehen sie sowieso. Sie
werden mit Progmen/PSTR nur nicht ins RAM geschoben beim Start des uCs.
Ich hab mir den Thread jetzt nicht genau durchgelesen, nur überflogen.
Aber generell würde ich mir über Optimierungen mal Gedanken machen wenn
ich sehe, dass 128 kB Flash nicht reichen.
Felix N. schrieb:> Hallo,>> Gut das ich ein guter Programmier bin habe ich nie gesagt, ich habe mir> mein gesamtes Programmier wissen aus YouTube Videos, Code Schnippels,> teilweise Bücher und Foren zusammen gesammelt. Habe Beruflich nix damit> zutun. Nur Hobby.
Naja, da haben wir schon deutlich schlimmere Dinge gesehen ;-)
1
voidgetTempCompensation(void){
2
if(temperature>=20&&temperature<=21){
3
reAmpDiff=TEMP_20*3;
4
}
Diese Funktion ist maximal albern, wenn gleich sie sicher nicht
wahnsinnig viel Flash braucht.
Naja, theoretisch korrekt, praktisch eher ungünstig. Du hast so oder so
nur wenig Speicher, da reicht es, eine lokale, temporäre Variable
(Array) anzulegen. Mit ein wenig Nachdenken kommt diese Funktion sogar
ohne Zwischenspeicher aus, wenn man einfach die Lücke im Originalstring
vor dem Austausch passend zurecht schiebt.
1
voidili9341_init(void)//set up display using predefined command sequence
Auch hier wieder sinnlose, endlose Funktionsaufrufe, die nur einen
anderen Parameter haben! Sowas macht man mit einem Array, idealerweise
liegt der im Flash (PROGMEM) und einer Schleife. Das ergibt nicht nur
deutlich weniger Quelltext, der deutlich übersichtlicher ist, sondern
auch deutlich weniger Flashverbrauch.
1
sprintf(buffer,"pH: %-.2f",phValue);
Du hast viele sprintf() Funtkionen drin. Nimm sprintf_P, dann liegt der
Formatstring direkt im FLASH und verbraucht keinen RAM!
Denk dran, konstante Strings und Array, welche "normal" benutzt werden,
verbrauchen beim AVR Flash UND RAM in gleicher Größe. Erst wenn man sie
mittels der passenden Funktionen in den Flash schiebt und entsprechend
anspricht, entfällt der RAM-Verbrauch.
Auch hier das Gleiche. Du musst deine Funktion auf PROGMEM-Strings
umbauen. Dann sparst du massiv RAM.
1
voidgetTimeBasedInformation(void){
2
ontime_co2_hour=readEEPROM(0x0F);
3
ontime_co2_min=readEEPROM(0x10);
4
offtime_co2_hour=readEEPROM(0x11);
5
offtime_co2_min=readEEPROM(0x12);
Gleiches Problem wie oben. Du spricht direkte, absolute Adressen im
EERPOM an. Das ist Low Level Programmierung, wie man sie nicht mal in
Assembler machen will. Man will Variablen mit gescheitem Namen
ansprechen! Denn sonst sieht man irgendwann nicht mehr durch.
1
uint8_tcompare_float(floatf1,floatf2){
2
floatprecision=0.00001;
Hier hast du schon eines der Probleme bei Fließkommazahlen erkannt. Ein
direkter Vergleich auf Gleichheit geht meist schief. Vermutlich ist für
deine Anwendung Festkommaarithmetik ausreichend und macht dir nicht
solche Probleme.
1
strcpy(smallBuffer,"Manuell")
Auch hier bringt die Funktion strcpy_P RAM-Ersparnis.
Allgemein sieht man in deinem Ansatz zum Menuaufbau tonnenweise
Funktionsaufrufe zum Zeichnen. Vermutlich ist da sehr viel doppelt und
dreifach drin, das kostet schon einiges an Flash. Das kann man mit einem
besseren Ansatz lösen. Man muss ja nicht gleich eine GUI-Menu-Bibliothek
programmieren. Aber man sollte mit deutlich mehr Datenstrukturen
arbeiten, welche die einzelnen Menus beschreiben. Ein kleine, kompakte
Funktion kann diese dann auswerten und ja nach Menu zeichnen. Außerdem
sollte man mehr mit universellen Hilffunktionen arbeiten, damit
wiederholende Aufgaben nicht mehrfach aufgedröselt hingeschrieben werden
müssen. Das spart FLASH, Tipparbeit und minimiert Fehlerquellen.
Strukturierte Programmierung auf Mikrocontrollern
1
switch(dayOfTheWeek()){
2
case1:
3
strcpy(buffer,"Mo.");
4
break;
5
case2:
Ist auch maximaler Unsinn. Das macht man mit einem PROGMEM-Array!
Etwa so
Falk B. schrieb:> Ist auch maximaler Unsinn. Das macht man mit einem PROGMEM-Array!
Das zum einem, es zeigt aber noch etwas weiteres: So eine Woche hat ja
nur 7 Tage: Ein Case hätte man sich auch hier sparen können.
Auch ein ENUM hätte hier wahrscheinlich besser gepasst als das
Switch-Statement.
Aber es wurde ja schon festgestellt, dass in dem Code enorm viel
Optimierungspotential steckt.
Das ist Unsinn und macht im Extremfall nicht das, was du willst. Eine 0
durch die Gegend schieben ist sinnlos. Das funktioniert hier nur, weil
die Bits im Register nach dem Reset sowieso schon auf Null stehen. Wenn
man sicherstellen will, daß diese Pins Eingänge werden, dann eher so,
siehe Bitmanipulation.
MaWin schrieb:>> Autor: MaWin (Gast)>> Datum: 08.09.2019 20:47>> Noch so ein Trollbeitrag vom Psychopathen...
Und du Plinse schaffst es seit Jahren nicht, dir einen Login zuzulegen.
Selber Schuld! Aber was wäre die Welt ohne Paranoia?
Genau SO macht man das eben nicht! Der Witz der Funktion encode_read4()
ist es ja, daß man sie relativ langsam und selten in einer Schleife im
Hauptprogramm aufrufen kann und als Ergebnis die Anzahl der Schritte
seit dem letzten Aufruf nach links oder rechts bekommt. Ein Aufruf in
der ISR ist sinnlos und kontraproduktiv! Die Beispiele hier im Wiki
machen das auch nicht!
Falk B. schrieb:> CODER_DDR |= (0<<CODER_PINA) | (0<<CODER_PINB) | (0<<CODER_BUTTON);> Eine 0 durch die Gegend schieben ist sinnlos.
Kostet allerdings auch keinen Speicherplatz. Der Compiler reduziert das
auf eine simple Zuweisung: CODER_DDR |=0
Stefanus F. schrieb:> Falk B. schrieb:>> CODER_DDR |= (0<<CODER_PINA) | (0<<CODER_PINB) | (0<<CODER_BUTTON);>> Eine 0 durch die Gegend schieben ist sinnlos.>> Kostet allerdings auch keinen Speicherplatz. Der Compiler reduziert das> auf eine simple Zuweisung: CODER_DDR |=0
Wenn der Compiler schlau ist, macht er dabei gar nichts (was ich mal
stark vermute). Mit 0 verodern gibt immer noch das gleiche wie vorher.
Andreas B. schrieb:> Wenn der Compiler schlau ist, macht er dabei gar nichts (was ich mal> stark vermute). Mit 0 verodern gibt immer noch das gleiche wie vorher.
Alle Register sind volatile, ich glaube dass der Compiler die Zugriffe
daher nicht weg optimieren darf.
Wilhelm M. schrieb:> Theor schrieb:>>> Zusätzlich: Ich habe das vorher nicht erwähnt.>>>> 3. Vermeide die Verwendung von Literalen, insbesondere von>> Zahlenliteralen im Code. Halte sie lieber an einer zentralen Stelle,>> falls möglich.>> Das ist Quatsch bzw. stimmt nur für C-Strings (bei AVR). Zahlliterale> (als core-constant) werden vom Compiler immer direkt in den generierten> Code eingebaut.
Lieber Wilhelm. du zitierst nur einen Teil meines Textes und
unterstellst dann, ohne dass ich dafür einen vernüfntigen Grund erkennen
kann, dass ich den von Dir zitierten Teil geschrieben habe, weil ich
annehme, dass damit Speicherplatz gespart wird.
Ich zitiere mich selbst und hebde der Deutlichkeit halber die von mir
genannte Begründung für meine Aussage, die zu zitieren Du unterlassen
hast.
(Die Hervorherbung geschieht hier, in dem die Zitatzeichen '>' von dem
Satz entfernt wurden. Eine andere Möglichkeit, den Satz etwa mit
Unterstreichung hervorzuheben und ihn dabei weiter als Zitat zu
kennezeichen, habe ich leider nicht gefunden). Das Original kann hier
Beitrag "Re: ATMega Flash wird langsam knapp. Upgrade o. Plattformwechsel?" nachgelesen werden.
Theor schrieb:>[...]> 3. Vermeide die Verwendung von Literalen, insbesondere von> Zahlenliteralen im Code. Halte sie lieber an einer zentralen Stelle,> falls möglich.> Gleiches gilt für String-Literale (mal unabhängig davon, ob Du nun ein> Menuesystem verwendest).
_So sind Änderungen, insbesondere wenn wegen der
Änderung eines Wertes auch andere Werte geändert werden müssen,
einfacher._
> [...]
Es mag sein, dass Du das nicht gesehen hast. Dann ist das sicher nur ein
Mißverständnis. Ich hoffe, nun ist klarer, was ich sagen wollte.
Falk B. schrieb:> MaWin schrieb:>>> Autor: MaWin (Gast)>>> Datum: 08.09.2019 20:47>>>> Noch so ein Trollbeitrag vom Psychopathen...>> Und du Plinse schaffst es seit Jahren nicht, dir einen Login zuzulegen.> Selber Schuld! Aber was wäre die Welt ohne Paranoia?
Lasst uns einen MaWin-Day einführen an dem alle mit seinem Namen posten
:)
Hallo,
Theor schrieb:>> Hallo,>>>> Gut das ich ein guter Programmier bin habe ich nie gesagt,>> [...]>> Und ich habe auch nicht behauptet, dass Du das von Dir gesagt hättest.> :-)>> Darum ging es mir nicht.
Okay, dann hatte ich das falsch aufnehmen. Sorry!
leo schrieb:> Das wird dann noch gemacht mit nur anderem Text. Du findest sowas zuhauf> im Code.
Ja weil ich zuvor den bestehen Text überschreiben muss mit einem
schwarzen Rechteck um da sonst wildes Zeug raus kommt wenn ich es weg
lasse.
Andreas K. schrieb:> Dann schliess parallel am SPI noch einen kleinen SPI-Flash-Baustein an.Andreas K. schrieb:> kannst du einfach im Programm von> der SD-Karte aus befüllen.
Das heißt wenn ich das richtig verstehe ich schreibe 1x die meine ganzen
Strings auf die SD Karte und schreibe sie dann in den SPI Flash und dort
bleiben sie ja bis ich sie wieder lösche.
Muss ich dann nicht massig Zugriffe machen, um die Strings dort wieder
raus zubekommen?
M. K. schrieb:> Sie> werden mit Progmen/PSTR nur nicht ins RAM geschoben beim Start des uCs.
Achso.
Falk B. schrieb:> Diese Funktion ist maximal albern, wenn gleich sie sicher nicht> wahnsinnig viel Flash braucht.
500 Bytes hat Sie verbraucht. War noch eine alte Funktion um die
Temperatur Korrektur zu machen für die pH Elektrode ist aber
Mittlerweile nicht mehr in Gebrauch.
Falk B. schrieb:> Schon mal was von einer Schleife gehört?
Ja habe. Ich habe jetzt eine for Schleife eingefügt.
Falk B. schrieb:> Auch hier wieder sinnlose, endlose Funktionsaufrufe, die nur einen> anderen Parameter haben! Sowas macht man mit einem Array, idealerweise> liegt der im Flash (PROGMEM) und einer Schleife. Das ergibt nicht nur> deutlich weniger Quelltext, der deutlich übersichtlicher ist, sondern> auch deutlich weniger Flashverbrauch.
Also ich habe das mal versucht umzusetzen, doch ist der Flash verbrauch
nicht gesunken sondern um 0,2%(256Bytes) gestiegen. Möglicherweiße habe
ich es auch falsch gemacht, habe den Quellcode von ili9341_init() als
Datei angehängt.
Falk B. schrieb:> Nimm sprintf_PFalk B. schrieb:> direkt im FLASH und verbraucht keinen RAM!Falk B. schrieb:> Du musst deine Funktion auf PROGMEM-Strings> umbauen. Dann sparst du massiv RAM.
Irgendwie stehe ich gerade auf den Schlauch. Es wurde ja bereits öfters
geschrieben das ich mit PSTR und PROGMEM oder _P Strings aus dem RAM ins
Flash lege.
Aber erhöhe ich nicht zwangsweise dadurch den Flash Verbrauch? RAM habe
ich ja 16K wovon ich nicht mal 50 % im Moment benutze oder habe ich da
was falsch verstanden?
Falk B. schrieb:> Du spricht direkte, absolute Adressen im> EERPOM an. Das ist Low Level Programmierung> Man will Variablen mit gescheitem Namen> ansprechen!
Was heißt den jetzt Low Level? Und wieso ist es schlecht das ich der
Variable direkt den Wert aus dem EEPROM zuweiße? Wüsste jetzt nicht wie
ich es sonst machen sollte.
Was meinst du genau mit gescheitem Namen? Ich mein ich weiß ja warum die
Variable zb. ontime_co2_hour heißt oder ist damit gemeint das ich besser
ein Array erstelle wie zb.
1
uint8_t co2ONTime[4];
Und dann dem Array 0 bis 4 die Adressen zuweiße?
Falk B. schrieb:> Sieht du in den Massen an Schreibzugriffen selber noch durchFalk B. schrieb:> Denn sonst sieht man irgendwann nicht mehr durch.
Naja manchmal ist es schon ein bisschen speziell. Aber ich habe ein
Excel Dokument wo ich Eintragen habe wie und wo welche Adresse und Wert
abgespeichert ist und was das macht.
Falk B. schrieb:> Schon mal was von einem struct gehört?
Gehört schon aber noch nie benutzt.
Falk B. schrieb:> Allgemein sieht man in deinem Ansatz zum Menuaufbau tonnenweise> Funktionsaufrufe zum Zeichnen.
Ich rufe die Menüs ja schon in der buttonpressed() Funktion auf die in
der Menu Funktion vorhanden ist. Somit lade ich ja die Menüs schon vor.
Wäre es besser wenn ich dort zb. ein Integer als Menü Index setze und
ein Wechsel Boolean so das in der Menu geschaut wird ob gerade ein
Wechsel erforderlich ist zb. vom Hauptmenü aufs RTC Menu und wenn das
der Fall dann wechseln. Somit würde ich die Menüs ja unter ein anderer
nicht mehr aufrufen sondern nur noch 1x Zentral von der main.c
Falk B. schrieb:> Das ist Unsinn und macht im Extremfall nicht das, was du willst.
Ah gut zu wissen das nicht alles gewonnenes wissen richtig ist habe das
mal so aufgeschnappt in einem Online Artikel über die AVR Programmierung
... Deswegen habe ich das so gemacht. Bis jetzt hat es mich auch noch
nicht im Stich gelassen.
Falk B. schrieb:> Genau SO macht man das eben nicht!Falk B. schrieb:> Die Beispiele hier im Wiki> machen das auch nicht!
Da war mal irgendwas warum ich das gemacht habe. Werde mir nochmal den
Wiki Artikel durchlesen.
Lg
Felix N. schrieb:> leo schrieb:>> Das wird dann noch gemacht mit nur anderem Text. Du findest sowas zuhauf>> im Code.>> Ja weil ich zuvor den bestehen Text überschreiben muss mit einem> schwarzen Rechteck um da sonst wildes Zeug raus kommt wenn ich es weg> lasse.
Du verstehst offensichtlich das Problem nicht. Du hast die selben 3
Zeilen Code x mal, nur mit anderem Text anstatt den Code genau 1 mal in
einer Funktion zu haben, der du den unterschiedlichen Text uebergibst.
leo
leo schrieb:> Du hast die selben 3> Zeilen Code x mal, nur mit anderem Text anstatt den Code genau 1 mal in> einer Funktion zu haben, der du den unterschiedlichen Text uebergibst.
Hallo, ich glaube ich weiß jetzt wie du das meinst. Ich beziehe mich mal
auf ein Code Schnippel aus der Co2Menu.c Datei Zeile 118-119 dort habe
ich zwei Zeilen Code
In Zeile 126-127 und 133-134 wiederholt sich der Code nur mit einem
anderen Text. Ich habe mir jetzt folgende Funktion überlegt die halt das
fillrect macht und den Text mittels PSTR übergibt:
Wenn ich die Zeilen die ich oben genannt habe durch die Funktion ersetze
habe ich 46 Bytes Flash wieder frei.
Stefanus F. schrieb:> Ich kann das auch gerne 100 mal schrieben, wenn es Dir hilft:
Nein. Aber ich glaube ich habe es jetzt verstanden. Ich habe mir den
Link mal durchgelesen und mal mich erkundigt wie das mit dem RAM und
Flash ungefähr funktioniert.
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Speicherzugriffe
Wenn ich das nun richtig verstanden habe belegt ein normaler String
Flash und RAM. Wobei der String beim Start zusätzlich in den RAM kopiert
wird. Das ist der Grund warum ich direkt drauf zugreifen kann. richtig?
Wenn ich jetzt den String mit PSTR oder PROGMEM anlege je nach dem, wird
er erst gar nicht in den RAM kopiert. Er wird also nur im Flash anlegt.
Wenn ich jetzt ein direkten Zugriffe drauf mache versucht das Programm
die Adresse der Variable im RAM zu finden, wird es aber nicht da sie mit
PSTR oder PROGMEM gar nicht erst ins RAM geladen wurde und ich bekomme
irgendwas zurück.
Daher muss ich mit den Makros pgm_read_byte/word/... arbeiten damit das
Programm nicht die Adresse des Strings aus dem RAM ließt sondern nach
der Adresse im Flash.
Somit würde ich den doppelten Speicher belegen wenn ich ein String ohne
PROGMEM anlege, das würde ja auch bedeuten das wenn ich einen normalen
String anlege ohne PROGMEM das im RAM zwar eine Kopie liegt aber sie
jedoch nur auf die Adresse des Strings im Flash verweist oder?
Lg
Felix N. schrieb:> Wenn ich die Zeilen die ich oben genannt habe durch die Funktion ersetze> habe ich 46 Bytes Flash wieder frei.
Sehr gut. Ich denke da sind noch viel mehr Wiederholungen, auch mit
leicht anderen Koordinaten oder anderen Texten. Du kannst noch viel mehr
in Funktionen zusammenfassen.
leo
Felix N. schrieb:> Somit würde ich den doppelten Speicher belegen wenn ich ein String ohne> PROGMEM anlege, das würde ja auch bedeuten das wenn ich einen normalen> String anlege ohne PROGMEM das im RAM zwar eine Kopie liegt aber sie> jedoch nur auf die Adresse des Strings im Flash verweist oder?
Eine Kopie ist genau das: eine Kopie und kein Zeiger/Verweis. Ein Zeiger
würde bei einem 16 Bit Adressraum nur 2 Byte brauchen, egal wie groß das
Original ist. Eine Kopie braucht exakt so viel Platz wie das Original.
Das Problem bei AVR ist, dass Du einmal Adressen von 0...65535 fürs
Flash hast und einmal Adressen von 0...65535 fürs RAM. Diese beiden
Adressen sind nicht miteinander kompatibel, d.h. Du hast einmal eine wie
strcpy für RAM-Adressen und einmal eine Spezialversion strcpy_P für
Flash-Adressen. Bei ARM, MIPS und den meisten anderen Architekturen hast
Du diese Unterscheidung nicht. Da hast Du nur einen Satz von Adressen
von 0 bis 4G-1, und da ist alles drin: Flash, RAM, IO-Ports usw. Ist
damit einfacher zu programmieren und ermöglicht es auch, Code aus dem
RAM ablaufen zu lassen. Das ist auch etwas, was bei AVR grundsätzlich
nicht geht.
fchk
Felix N. schrieb:> Wenn ich das nun richtig verstanden habe belegt ein normaler String> Flash und RAM. Wobei der String beim Start zusätzlich in den RAM kopiert> wird. Das ist der Grund warum ich direkt drauf zugreifen kann. richtig?
... und was du danach geschrieben hast
ja alles richtig.
pgm_read_byte/word/...nutze ich nur sehr selten.
Denn für viele String Funktionen gibt es noch die _P Varianten, die aus
dem Flash lesen, anstatt aus dem RAM. Zum Beispiel sprintf_P().
Was Falk geschrieben hat ist richtig auch wenns nicht besonders
diplomatisch war. Lass Dich nicht von diesen Helden mit den ESP- oder
WIZ-Zeugs beeindrucken. Damit schaffts Du nur neue Baustellen.
Mein eigenes Projekt nutzt fast die gleiche Peripherie aber als
FBH-Steuerung. Auch bei mir ist Speicher irgendwann knapp geworden. Habe
dann auf den 2560 + 64k XMEM aufgerüstet - damit lebt es sich ganz
entspannt. Das läuft 24/7 seit ein paar Jahren äußerst zuverlässig.
Felix N. schrieb:> > [...]> Falk B. schrieb:>> Du musst deine Funktion auf PROGMEM-Strings>> umbauen. Dann sparst du massiv RAM.>> Irgendwie stehe ich gerade auf den Schlauch. Es wurde ja bereits öfters> geschrieben das ich mit PSTR und PROGMEM oder _P Strings aus dem RAM ins> Flash lege.
Es ist vielleicht noch nicht klar genug beschrieben worden:
Nach dem Reset des Prozessors geschieht in Bezug auf literale, also
konstante, Strings, u.A. Folgendes:
1. Der FLASH-Speicher enthält grundsätzlich Dein gesamtes Programm
inklusive aller in Deinem Programm verwendeten konstanten Strings
(Zeichenketten), egal ob Du nun PSTR verwendest oder nicht.
2. Das RAM enthält nach dem Reset (sozusagen) Nichts. Soweit es Dich im
Moment angeht, enthält es keine sinnvollen Werte, keine Strings oder
Zahlen aus Deinem Programm.
(Genau genommen stimmt das nur, falls zuvor der Strom ausgeschaltet war,
aber zunächst mal kommt es für Dich auf das selbe hinaus, ob der Strom
vor dem Reset an war oder nicht).
3. Ein Teil der ersten Befehle nach dem Reset, kopiert Deine Strings,
die Du in dem Programmtext hingeschrieben hast, aus dem FLASH-Speicher
in das RAM. Das geschieht, weil Zugriffe auf das RAM schneller gehen als
Zugriffe auf Daten im FLASH-Speicher. D.h. wird auf Strings im Programm
mehr als zwei- oder dreimal zugegriffen, dann geht das aus dem RAM
insgesamt schneller als aus dem FLASH. Dieser Vorgang des kopierens wird
durch Programmcode beschrieben, den Du normalerweise nicht zu sehen
bekommst. Man nennt das den "Startup-Code".
D.h. mit der Verwendung von PSTR und PROGRMEM (usw.) legst Du nicht
Strings aus dem RAM ins FLASH! Nicht so, wie Du das vermutlich meinst.
Die Strings sind eben nicht von vorne herein (beim Reset) im RAM. Wie
sollten sie da hinkommen?
Es ist wichtig, dass Dir klar wird, was Du im Programmtext eigentlich
beschreibst und zu welchem Zeitpunkt es eine Wirkung hat.
Wenn Du im Programmtext PSTR hinschreibst und das Programm kompilierst,
dann erzeugt der Compiler für diese Variable, vor der PSTR steht,
keinen Code, der sie in das RAM kopiert. PSTR wirkt sich auf den Code
aus und der Code tut gewisse Dinge dann nicht.
In Deinem Fall ist nun eine Maßnahme (von mehreren, die Dir hier
vorgeschlagen wurden), dass Du (fast) alle Strings ausschliesslich im
FLASH-Speicher vorhälst. Deswegen sollst Du PSTR vor (fast) alle Strings
schreiben.
> Aber erhöhe ich nicht zwangsweise dadurch den Flash Verbrauch? RAM habe> ich ja 16K wovon ich nicht mal 50 % im Moment benutze oder habe ich da> was falsch verstanden?
Nein. Eben nicht.
Wie oben beschrieben, sind Strings immer_ und _grundsätzlich im FLASH
Speicher enthalten. Denn das ist der Speicher, der auch nach dem
Abschalten des Stroms erhalten bleibt. RAM verliert seinen Inhalt.
Du bewirkst also mit PSTR nicht, das der FLASH-Speicher voller wird,
denn die Strings stehen da auch dann drin, falls Du PSTR nicht
verwendest. Woher sollen sie sonst kommen, wenn sie ins RAM kopiert
werden?
Mit der Verwendung von PSTR bewirkst Du aber, dass die Strings nicht
ins RAM kopiert werden und sparst dadurch, weil Du soviel Text hast,
viel RAM.
Eine Folge der Verwendung von PSTR ist aber, dass sich die
Ausführungszeit des Programmes insgesamt etwas erhöht, denn wie gesagt,
dauert es länger, die Strings aus dem FLASH zu laden, als aus dem RAM.
Nur macht das in Deinem Fall nicht viel aus, da die Anzeige nicht
zeitkritisch ist. Du würdest nur bei extrem langen Texten (vielleicht ab
etwa 100Bytes oder mehr etwas davon merken.
Klar? Oder hast Du noch Fragen?
Felix N. schrieb:> Das heißt wenn ich das richtig verstehe ich schreibe 1x die meine ganzen> Strings auf die SD Karte und schreibe sie dann in den SPI Flash und dort> bleiben sie ja bis ich sie wieder lösche.>> Muss ich dann nicht massig Zugriffe machen, um die Strings dort wieder> raus zubekommen?
Naja, soo viel ist das nicht, kann man relativ einfach in eine Funktion
packen. Aber soweit musst du gar nicht gehen, du hast noch VIEL Luft
nach oben. Erstens durch eine gescheite Umstruktuerierung deines Codes
(neudeutsch Refactoring) und 2. durch den großen Bruder mit 256kB Flash.
>Also ich habe das mal versucht umzusetzen, doch ist der Flash verbrauch>nicht gesunken sondern um 0,2%(256Bytes) gestiegen.
Darf nicht sein.
> Möglicherweiße habe>ich es auch falsch gemacht, habe den Quellcode von ili9341_init() als>Datei angehängt.
Naja, schon mal besser, wenn gleich noch ausbaufähig. Vor allem schreibt
man nicht eine supermegalange Zeile! Viel mehr als 100-120 Zeichen
gehören nicht in eine Zeile. Ein Array darf problemlos über mehrere
Zeilen gehen.
Ich hätte aber aber anders, gemacht, damit wird es kompakter. Kodiere
die Befehle mit 16 Bit und nutze die oberen Bits zur Unterscheidung von
Befehl und Daten. Das verschwendet zwar 7 Bit, macht das in Summe aber
wieder wett (ein Maschinenbefehlt hat beim AVR auch 16 Bit). Siehe
Anhang, ist aber nur beispielhaft, den Rest must du ergänzen.
>Aber erhöhe ich nicht zwangsweise dadurch den Flash Verbrauch? RAM habe>ich ja 16K wovon ich nicht mal 50 % im Moment benutze oder habe ich da>was falsch verstanden?
Ja hast du, immer noch.
Wenn man beim AVR "normale", konstante Strings benutzt, liegen die im
Flash und werden vor dem Start von main() in den RAM kopiert. Mit denen
arbeitet dann dein Programm. Die Strings im Flash werden danach nie
wieder angesprochen.
Mit dem _P Funktionen etc. entfällt die Kopie in den RAM und die Strings
werden DIREKT aus dem Flash gelesen und verarbeitet. Capice?
>Was heißt den jetzt Low Level?
Du kriechst im IT-Urschleim!
> Und wieso ist es schlecht das ich der>Variable direkt den Wert aus dem EEPROM zuweiße?
Weil das Hacker und Amateurmurks ist und du ganz schnell nicht mehr
durchsiehst. Warum wohl wurden selbst beim Assembler Namen für Variablen
verwendet und keine Adressen? Weil der Mensch mit NAMEN deutlich besser
klar kommt!
> Wüsste jetzt nicht wie>ich es sonst machen sollte.
Richtig? Solche Sache packt man in ein struct.
1
typedefstruct{
2
uint16_t:max_temperature;
3
uint16_t:min_temperature;
4
long:Fish_counter
5
}my_setting_t;// Datentyp als struct definieren
6
7
my_setting_tmy_settingsEEMEM;// Variable vom Typ my_setting_t im EEPROM anlegen.
Ist das nicht DEUTLICH lesbarer und vor allem selbsterklärend?
>Naja manchmal ist es schon ein bisschen speziell. Aber ich habe ein>Excel Dokument wo ich Eintragen habe wie und wo welche Adresse und Wert>abgespeichert ist und was das macht.
AUA! Genau SO macht man es NICHT! Denn dieser Job gehört dem COMPILER!
Der verwaltet die Adressen! Du legst Variablen mit gescheiten Namen an,
ggf. als Struct zusammengefaßt.
>Wäre es besser wenn ich dort zb. ein Integer als Menü Index setze und>ein Wechsel Boolean so das in der Menu geschaut wird ob gerade ein>Wechsel erforderlich ist zb. vom Hauptmenü aufs RTC Menu und wenn das>der Fall dann wechseln.
JA!
> Somit würde ich die Menüs ja unter ein anderer> nicht mehr aufrufen sondern nur noch 1x Zentral von der main.c
Das ist der Witz der Sache!
Felix N. schrieb:> Wenn ich die Zeilen die ich oben genannt habe durch die Funktion ersetze> habe ich 46 Bytes Flash wieder frei.
hi
und so geht das durch den gesammten code weiter.
ABER ...
Alle haben mal angefangen und gelernt das jede Architektur seine eigene
Programmierweise hat...
siehe AVR mit PROGMEM und das er nunmal variablen > 8bit nicht so mag
Ich selbst arbeite momentan viel mit Cortex M7
Da dieser Cache hat und immer 32byte aligned arbeitet muss man auch
"komisch" programmieren.
Ebenso der "ART" ist ein 128byte Cache für den Flashzugriff. Alle
Funktionen >128bytes brauchen deutlich mehr Zeit.
Ergo... alles zerhackstücken das man lieber viele viele kleine
funktionen hat. 8bit ist hier eher kontraproduktiv weil trotzdem 32bit
verbraucht werden... usw ...
Wenn ich manchmal code durchschaue den ich vor 2-3 Jahren mal
geschrieben habe erkenne ich sofort optimierungspotenzial.
Das wird mir in 2-3 Jahren bei einem aktuellen Projekt sicher auch so
gehen ^^
Aber zumindest macht man keine grunsätzlichen fehler mehr... nicht mehr
so doll ^^ Man muss halt nur immer dazulernen.
Habe selbst ein Aquarium ( meerwasser ) und mir damals was gebaut.
funktioniert bis heute. Habe dazu aber kein LCD eingebaut und nur den
Netzwerkanschluss genutzt.
Das Ding hat eine Webseite die alle Daten liefert und ggf. auch von
"Außen" Zugriff gewährt.
Vieleicht als Idee für dich ...
Da ein Handy ja auch ein LCD ist ..
und man mit CSS / HTML sicherlich mehr grafische Möglichkeiten hat als
auf dem ILI ..
Encoderbedienung brauch man auch nicht mehr.. gibt ja
Eingabemöglichkeiten auf der Seite.
Die webseite wird komplizierter... dafür wird die Blackbox einfacher
:-)
gdgddfgdfd schrieb:> hi>> und so geht das durch den gesammten code weiter.>> ABER ...> Alle haben mal angefangen und gelernt das jede Architektur seine eigene> Programmierweise hat...> siehe AVR mit PROGMEM
Sicher, ist halt eine Besonderheit. Wenn man sie kennt ist es aber kein
echtes Problem, nur ein wenig mehr Aufwand.
> und das er nunmal variablen > 8bit nicht so mag
UNSINN!!!
> Ich selbst arbeite momentan viel mit Cortex M7> Da dieser Cache hat und immer 32byte aligned arbeitet muss man auch> "komisch" programmieren.> Ebenso der "ART" ist ein 128byte Cache für den Flashzugriff. Alle> Funktionen >128bytes brauchen deutlich mehr Zeit.> Ergo... alles zerhackstücken das man lieber viele viele kleine> funktionen hat. 8bit ist hier eher kontraproduktiv weil trotzdem 32bit> verbraucht werden... usw ...
Quark^3. Kein Mensch optimiert C-Funktionen, damit sie in den Cache der
CPU passen. Das macht man, wenn überhaupt, in Assembler, und auch nur
dort, wo es ULTIMATIV nötig ist.
https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung
Die Grundlagen gelten ganz allgmein.
https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Was
Falk B. schrieb:>> und das er nunmal variablen > 8bit nicht so mag>> UNSINN!!!
Zugriffe auf 16/32bit sind also weiter in einem Takt möglich?
Ich glaube nicht ...
Es geht auch nicht darum das man jetzt bei einer Tasateneingabe
optimiert.
Aber , wenn man in der summe etwas darauf achtet ist so ein AVR lange
nicht am limit .. auch wenn hier oft solche threads erscheinen.
Oft werden "int" oder "short" sogar "float" variablen genutzt ohne das
diese sinn machen. da werden dann zahlen im bereich 0-10 übergeben.
Die funktion wird im code 100x aufgerufen und jedesmal speicher
verbraten.
Sowas meine ich damit.
Das man beim programmieren etwas auf die architektur achtet.
Auch wenn die compiler recht intelligent sind.
Falk B. schrieb:> Quark^3. Kein Mensch optimiert C-Funktionen, damit sie in den Cache der> CPU passen. Das macht man, wenn überhaupt, in Assembler, und auch nur> dort, wo es ULTIMATIV nötig ist.
Ich habe ein Projekt mit einem M7 der (nebenbei) mjpeg decodiert.
Ohne diese Anpassung auf 32bit alianing oder kleinere Funktionen liegt
die Bildrate bei QVGA bei ca 10-13fps , mit dieser Optimierung bei ca
22-25fps.
Die Anpassung ist im C code und damit auch wieder für andere M7
portabel.
(getestet auf STM F7 H7 und NXP RT1060 )
Generell ist der M7 etwas tricky. durch die diversen Speicherbereiche
und deren verhalten ( caching , BUSse )
Man kann es ruhig auf die Spitze treiben. Alle ähnlichen Codesequenzen,
die an 2 oder mehr Stellen auftreten, macht man zu einer Funktion, der
nur die Unterschiede übergeben werden.
Es schaded auch nicht, wenn diese Funktionen nur aus 1 oder 2 Zeilen
bestehen.
Der große Vorteil neben der Codeersparnis ist, man macht auch alle
Fehler immer nur an einer Stelle, muß also nur eine Stelle korrigieren.
Falk B. schrieb:>> siehe AVR mit PROGMEM>> Sicher, ist halt eine Besonderheit. Wenn man sie kennt ist es aber kein> echtes Problem, nur ein wenig mehr Aufwand.
richtig.
Bezieht sich darauf das der TE den Unterschied zwischen RAM und Flash
Nutzung bei Strings jetzt ja kennt.
Wenn er in zukunft darauf achtet .. ist das kein thema mehr.
Wenn er mal mit Cortex M zu tun hat wird er der einfachheit halber auf
schreiben. Damit sind gleiche Strings auch nur einmal im Flash, der
Zugriff ist gekapselt, man kann kein _P mehr bei irgendeiner Funktion
vergessen.
Daher der Ratschlag: bevor er die Plattform wechselt, was sicher bei der
Auquariensteuerung völlig unnötig ist, erstmal mit dem Thema
Softwareentwicklung intensiv befassen. Und das nicht auf dem µC, sondern
in einer komfortableren Umgebung, etwa ein PC mit geeigneter IDE.
gdgddfgdfd schrieb:> Falk B. schrieb:>>> und das er nunmal variablen > 8bit nicht so mag>>>> UNSINN!!!>> Zugriffe auf 16/32bit sind also weiter in einem Takt möglich?> Ich glaube nicht ...
War das die Frage? Ist das für einen Aquariumcontroller wichtig?
> Aber , wenn man in der summe etwas darauf achtet ist so ein AVR lange> nicht am limit .. auch wenn hier oft solche threads erscheinen.
EBEN!
>> Quark^3. Kein Mensch optimiert C-Funktionen, damit sie in den Cache der>> CPU passen. Das macht man, wenn überhaupt, in Assembler, und auch nur>> dort, wo es ULTIMATIV nötig ist.>> Ich habe ein Projekt mit einem M7 der (nebenbei) mjpeg decodiert.> Ohne diese Anpassung auf 32bit alianing oder kleinere Funktionen liegt> die Bildrate bei QVGA bei ca 10-13fps , mit dieser Optimierung bei ca> 22-25fps.
Eben DAS ist so eine Anwendung, wo sich so eine Optimierung lohnt. Das
sollte man aber schon dazu sagen!
Peter D. schrieb:> Es schaded auch nicht, wenn diese Funktionen nur aus 1 oder 2 Zeilen> bestehen.
Das ist ein Punkt, der mich anfangs überraschte, da ich vor
Mikrocontroller überwiegend PC's programmierte.
Beim PC sind Funktionsaufrufe oft (nicht immer) wesentlich teurer, als
beim AVR. Insbesondere dann, wenn die angesprungene Funktion in einem
anderen Speicherberbereich liegt, der sich gerade nicht im CPU Cache
befindet.
Bei AVR kosten Funktionsaufrufe hingegen fast keinen Overhead. Dazu
kommt, dass der Compiler einige Funktionen durch inline-Code ersetzt,
wenn er das für vorteilhaft hält.
Das alles in summe betrachtet führt dazu das der flash nicht so schnell
voll ist.
auch funktionen mit vielen übergabeparametern frisst nicht nur zeit und
ram .. sondern auch flash.
Die sichtweise wie man sachen verallgemeinert oder modularisiert ohne
groß aufzublähen fehlt oft am anfang.
Aber nur durch fehler lernen wir , oder?
Falk B. schrieb:> gdgddfgdfd schrieb:>> Aber nur durch fehler lernen wir , oder?>> Viele nicht mal dadurch. Das geht schon bei der Groß/Kleinschreibung los> . . .
Stimmt.
Bei mir liegts nur an der Faulheit.
Hat sich seit 30 Jahren nicht gebessert.
Peter D. schrieb:> Der große Vorteil neben der Codeersparnis ist, man macht auch alle> Fehler immer nur an einer Stelle, muß also nur eine Stelle korrigieren.
Und die positive Kehrseite ist, daß Änderungen nur an einer zentralen
Stelle vorgenommen werden müssen. Wenn man viele Änderungen vornimmt,
dann wirkt sich das enorm zeitsparend aus.
Ich muß aber gestehen, daß ich manchmal auch Programmteile kopiere,
wodurch sich dann zwangsläufig redundante Codeteile ergeben, weil das
einfacher ist als eine Funktion zu schreiben. Wenn genügend Speicher da
ist, kann ich mir diesen Luxus erlauben...
gdgddfgdfd schrieb:> ich vermisse eine Angabe der Compileroptimierung> Stand das schon irgendwo?
Ich möchte nochmal auf diese Frage hinweisen - ob mit -O0 oder -Os
kompiliert wird, dürfte die Programmgröße massiv beeinflussen.
Genauso die Linker-Optionen überprüfen, ob zum Beispiel LTO aktiv ist.
Und diese andere Option, deren Name mir gerade nicht einfällt, dass
nicht die ganze Bibliothek dazu gelinkt wird, wenn nur eine einzelne
Funktion daraus benötigt wird. Sollte zwar standardmäßig aktiv sein,
aber besser mal nachsehen...
Falk B. schrieb:>>Also ich habe das mal versucht umzusetzen, doch ist der Flash verbrauch>>nicht gesunken sondern um 0,2%(256Bytes) gestiegen.>> Darf nicht sein.
Vielleicht, weil durch die Änderung eine/mehrere der _P-Funktionen mit
gelinkt wird, die vorher nicht benötigt wurde(n)? Die "normalen"
Funktionen (ohne _P) werden ja für die ungeänderten Teile nach wie vor
gebraucht.
MfG, Arno
Ich habe gerade gesehen das er in seiner main.c ganz viele Infos zum
Start ausgibt. Das ist als Anfänger schön wenn da was steht , ist aber
oft auch totaler nonsins^^...
Es belegt Speicher und man baut künstliche delays ein damit man Zeit hat
das zu lesen.
Ich hab beim AVR damals immer eine eigene Datei für alle Strings
angelegt.
Diese war entsprechend formatiert.
texte_de.txt
1
"Hauptmenü",
2
"Submenü1",
3
"Version",
4
.....
im quelltext dann irgendwo:
1
constchar*strings_de[]PROGMEM={
2
#include"texte_de.txt"
3
};
im source gab es dazu passend eine liste
1
typedefenum{
2
TXT_MAIN=0,
3
TXT_SUB1,
4
TXT_VERSION,
5
....
6
}texte_e;
damit lies sich verhindern das texte vlt doppelt im flash landen.
und bei mehreren Sprachen brauch man nur den pointer (strings_de)
verändern.
1
voidfoo(texte_etext){
2
sprintf_P(buffer,strings_de[text]);
3
}
auch Lesbarkeit:
1
if(menuSelector==2)
ist nichtssagend.
mach dir dafür defines
#define MAIN_MENUE 1
#define RTC_MENUE 2
oder eine enumeration
enum{
MENUE_NONE = 0,
MENUE_MAIN,
MENUE_RTC,
...
};
Noch was.
Die One Wire Kommunikation ist NICHT solide, denn während der
Übertragung eines Bits müssen die Interrupts gesperrt sein, damit das
Timing wasserdicht ist! Außerdem braucht man auch hier für die
Temperatur keine Fließkommazahlen. Außerdem fehlt die CRC-Prüfung, das
kann bisweilen auch mal daneben gehen. Was macht deine Steuerung dann?
So geht es sicher und besser.
Beitrag "Onewire + DS18x20 Library"
Auch das hier ist Unsinn. Hier werden echte Variablen angelegt, die
echten RAM verbrauchen. Das braucht keiner, denn das sind alles
Konstanten. In C nutzt man hier eher #define
Falk B. schrieb:> uint8_t MCP7940_ADDRESS = 0x6F; //> Device address, fixed value //> uint8_t MCP7940_RTCSEC = 0x00; //> Section 1: timekeeping //> uint8_t MCP7940_RTCMIN = 0x01; //> //> uint8_t MCP7940_RTCHOUR = 0x02; //> //> [/c]>> Auch das hier ist Unsinn. Hier werden echte Variablen angelegt, die> echten RAM verbrauchen. Das braucht keiner, denn das sind alles> Konstanten. In C nutzt man hier eher #define>>
Frank K. schrieb:> Oder static const uint8_t, wenn es typsicher sein soll.>> fchk
Das wird dann aber in C auch eine echte Variabel mit RAM-Verbrauch,
oder?
Frank K. schrieb:> Falk B. schrieb:>>> uint8_t MCP7940_ADDRESS = 0x6F; //>> Device address, fixed value //>> uint8_t MCP7940_RTCSEC = 0x00; //>> Section 1: timekeeping //>> uint8_t MCP7940_RTCMIN = 0x01; //>> //>> uint8_t MCP7940_RTCHOUR = 0x02; //>> //>> [/c]>>>> Auch das hier ist Unsinn. Hier werden echte Variablen angelegt, die>> echten RAM verbrauchen. Das braucht keiner, denn das sind alles>> Konstanten. In C nutzt man hier eher #define>>>>
Falk B. schrieb:> Frank K. schrieb:>> Oder static const uint8_t, wenn es typsicher sein soll.>>>> fchk>> Das wird dann aber in C auch eine echte Variabel mit RAM-Verbrauch,> oder?
Das ist eine read-only Variable (constexpr gibt es nur in C++), die auch
ein schlechter Compiler sicher gut wegoptimieren kann.
Falk B. schrieb:> Die One Wire Kommunikation ist NICHT solide, denn während der> Übertragung eines Bits müssen die Interrupts gesperrt sein, damit das> Timing wasserdicht ist!
Das muss nicht Wasserdicht sein, da der AVR nicht im Aquarium ist ;-)
W5100Usa schrieb:> Armin K. schrieb:>> Das muss nicht Wasserdicht sein, da der AVR nicht im Aquarium ist ;-)>> Aber die Quad-Core Lösung mit 64-Bit ARM ist nach heutigem> Diskussions-Stand Pflicht!
Der Zweck des Forums und dieser Diskussion ist meiner Ansicht nach,
Empfehlungen zu ggeben und vernünftige Gründe dafür zu nennen.
Ausserdem, nach Möglichkeit konkrete Informationen darüber, wie diese
Empfehlungen realisiert werden können.
Welche Diskussion zwischen welchen Diskussionsteilnehmern meinst Du?
Die Diskussion hier fokussiert sich, meiner Meinung nach zu Recht, auf
eine Überarbeitung des Codes und hat, wiederum meiner Meinung nach zu
Recht, die Voraussetzung, dass bei Umsetzung der Ratschläge der AVR (der
vom TO genannte Typ resp. der nächstgrössere) völlig ausreicht.
Wer oder was verpflichtet hier den TO oder sonstwen und mit welcher
Rechtfertigung tut er oder es das?
"Pflicht" ist hier gar Nichts.
Der TO hat das Recht jede Lösung zu nehmen, die er möchte - sogar wenn
dies von Anderen als unvernünftig betrachtet wird.
Hallo,
Arno schrieb:> Ich möchte nochmal auf diese Frage hinweisen - ob mit -O0 oder -Os> kompiliert wird, dürfte die Programmgröße massiv beeinflussen.
Habe mal unter AVR/GNU C Compiler -> Optimization nach geschaut dort
steht drin: Optimization Level: Optimize(-O1).
Ich habe es mal testweise umstellt bei -O0 kann ich erst gar nicht
kompilieren dort kommt der Fehler: "region `text' overflowed by 14018
bytes"
Ja -O1 wird ja benutzt dort habe ich im Moment 98952 Bytes an Flash und
6853 Bytes an SRAM. Mit -Os habe ich 89932 Bytes Flash und 6893 Bytes an
SRAM.
Habe ich dadurch irgendwelche Nachteile wenn ich das auf -Os umstelle?
Arno schrieb:> Genauso die Linker-Optionen überprüfen, ob zum Beispiel LTO aktiv ist.
Kann ich nicht finden. Weder als Checkbox noch in der Command Zeile.
Falk B. schrieb:> gescheite Umstruktuerierung deines Codes
Ja da bin ich im Moment noch am Überlegen was mehr Sinn macht. Das
Projekt neu Anlegen und den alten Code Schritt weiße übernehmen und
dabei überarbeiten. Zb. Floats weg lassen ... oder im bestehenden Code
überarbeiten.
Falk B. schrieb:> Capice?Frank K. schrieb:> Eine Kopie ist genau das: eine Kopie und kein Zeiger/Verweis.Stefanus F. schrieb:> ja alles richtig.Theor schrieb:> Klar? Oder hast Du noch Fragen?
Habe es mittlerweile kapiert^^. Danke euch :)
Falk B. schrieb:> Weil der Mensch mit NAMEN deutlich besser> klar kommt!Falk B. schrieb:> Denn dieser Job gehört dem COMPILER!> Der verwaltet die Adressen!
Moment mal. Das heißt ich definiere gar nicht die Adressen fürs EEPROM,
sondern die werden dann Zufällig zugewiesen, oder wie muss ich das
verstehen?
In deinem Struct Beispiel bezieht sich die 16 Bit
Variable(min_temperature) ja nicht auf den gelesen Wert vom EE sondern
auf die Adresse im EE wo der Wert liegt.
Oder muss ich die Variablen einmal mit einer Adresse definieren?
1
my_struct.irgendwas = eeprom_adresse;
Falk B. schrieb:> Ist das nicht DEUTLICH lesbarer und vor allem selbsterklärend?
Ja auf jeden Fall. Aber eine Frage habe ich dazu noch du legt ja eine
Variable von der Struktur im EEMEM an wobei sich EEMEM wahrscheinlich
auf das Interne EEPROM des uC bezieht. Ich benutze ja ein externes
EEPROM, reicht es dann wenn ich es nur mit
1
my_struct my_ee;
initialisiere?
Falk B. schrieb:> Hier der Anhang.
Clever auf jeden Fall. Wäre ich aber im Leben nie drauf gekommen mit Bit
Operatoren da zu arbeiten ...
Falk B. schrieb:> Ist das für einen Aquariumcontroller wichtig?
Zeitkritisches habe ich eigentlich nix in meinem Projekt drin und wenn
der pH Wert mal unter 6.80 sinken wird werden meine Fischis auch nicht
davon sterben.
Das einzige wovor ich immer Angst hatte war das sich mein Controller
aufhängt während gerade das Magnetventil für die Co2 Zufuhr geöffnet
ist, konnte ich aber relativ einfach mit dem Watchdog Timer beheben.
Zudem hat er sich bis jetzt auch noch nie aufgehängt.
gdgddfgdfd schrieb:> Das ist als Anfänger schön wenn da was steht , ist aber> oft auch totaler nonsins^^
Es hatte am Anfang wirklich mal ein Sinn gehabt, mein Controller hatte
sich durch nicht ganz korrekte Verdrahtung und scheinbar Kapazitive
Einkopplung der SCL und SCK Leitungen zu System Hängen geführt hat. Habe
ich ein Start Up Bildschirm gemacht um zu sehen wo er sich aufhängt, es
war auch mal eine Startzeit Messung drin aber das ist alles mittlerweile
nicht mehr nötig.
Hatte die Texte damals dennoch drin gelassen, können aber raus. Muss die
main eh mal aufräumen und ein paar Funkionen entfernen und auslagern.
gdgddfgdfd schrieb:> auch Lesbarkeit:if(menuSelector == 2)> ist nichtssagend.
Ja ich weiß menuSelector, menuPointer, menuInlinePointer ... mir war
damals nix besseres eingefallen.
Falk B. schrieb:> Außerdem fehlt die CRC-Prüfung, das> kann bisweilen auch mal daneben gehen. Was macht deine Steuerung dann?
Die sollte weiterlaufen liefert mir nur dann eine Temperatur von
-0.06°C. Den Link werde ich mir mal anschauen.
Falk B. schrieb:> In C nutzt man hier eher #define
Ah ok. Ja die Lib kommt aus dem I-Net. Werde ich abändern. Schaue mir
dann auch gleich mal die anderen Libs an ob es da noch sowas gibt.
Theor schrieb:> Die Diskussion hier fokussiert sichTheor schrieb:> auf> eine Überarbeitung des Codes und hat
Jor das wahr zwar eigentlich nicht mein Ziel. Aber der Richtung wechsel
in die Code Optimierung finde gut. Bin gar nicht erst auf die Idee
gekommen. Das der Flash wegen vielleicht falscher Programmierung voll
ist.
Da habe ich am Ende mehr von als wenn ich mir jedesmal ein neuen uC
kaufen mit mehr flash/ram etc.
Lg
Armin K. schrieb:> as muss nicht Wasserdicht sein, da der AVR nicht im Aquarium ist ;-)
Wäre aber möglich. Wir haben schon einen µC in Epoxyd eingegossen und
unter Wasser betrieben. (Meine Idee war das nicht!) Wegen der
Wärmeentwicklung (läuft an 24V) wurde aber ein Schaltregler eingesetzt.
Funktioniert tatsächlich. ;-)
Felix N. schrieb:>> Genauso die Linker-Optionen überprüfen, ob zum Beispiel LTO aktiv ist.> kann ich nicht finden. Weder als Checkbox noch in der Command Zeile.
Ich empfehle diese Optionen:
FLAGS = -Wall -O1 -fshort-enums -ffunction-sections -fdata-sections
CFLAGS = -std=c99
CPPFLAGS = -fno-exceptions
LDFLAGS = -lm -Wl,--gc-sections
Zum Compilieren für *.c Dateien: FLAGS und CFLAGS
Zum Compilieren für *.cpp Dateien: FLAGS und CPPFLAGS
Zum Linken: FLAGS und LDFLAGS
Erklärung:
-Wall Aktiviert alle empfohlenen Warnungen (es gibt noch mehr, deswegen
ist das Wort "all" irreführend).
-O0 Optimiert gar nicht
-O1 Optimiert auf Performance, geringfügig zu Lasten der Größe
-O2 Optimiert auf Performance, mehr zu Lasten der Größe
-O3 Optimiert auf Performance, ohne Rücksicht auf die Größe
-Os Optimiert auf Größe, geringfügig zu Lasten der Performance
-Og optimiert ein bisschen, soweit es den Debugger nicht stört
-fshort-enums Die numerischen Werte von enums sind 8bit groß - Normal
wären es 16bit
-ffunction-sections -fdata-sections Diese beiden Optionen ermöglichen es
dem Linker (nach dem Compilieren), den Code auseinander zu nehmen und
unbenutzte Funktionen zu entfernen.
-std=c99 Aktiviert Erweiterungen der Sprache C, die ich gerne benutze
-fno-exceptions Deaktiviert das Exception-Handling in C++, was
kompakteren Code ergibt. Dann kann man aber eben keine Exceptions mehr
nutzen. Macht man auf µC eh nur selten.
-lm Bindet die Math Library ein, für Fließkommazahlen
--gc-sections Diese Optionen sagen dem Linker, dass er nicht verwendeten
Code weg schmeißen soll.
Wenn du in printf() Fließkommazahlen brauchst, dann brauchst du noch die
LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
Für Fließkommazahlen in scanf(): LDFLAGS += -Wl,-u,vscanf -lscanf_flt
Stefanus F. schrieb:> Ich empfehle diese Optionen:>> FLAGS = -Wall -O1 -fshort-enums -ffunction-sections -fdata-sections> CFLAGS = -std=c99
zusätzlich:
-mrelax -mcall-prologues
und natürlich -Os statt -O1.
Stefanus F. schrieb:> -fshort-enums Die numerischen Werte von enums sind 8bit groß - Normal> wären es 16bit
Das ist allerdings keine Optimieruns-Option, sonder wählt ein anderes
ABI.
> -lm Bindet die Math Library ein, für Fließkommazahlen
Braucht man schon seit X Jahren nicht mehr.
Felix N. schrieb:> Ja da bin ich im Moment noch am Überlegen was mehr Sinn macht. Das> Projekt neu Anlegen und den alten Code Schritt weiße übernehmen und> dabei überarbeiten.
Ja! neu anlegen und gründlich überarbeiten, da sind locker 30% code
reduction drin, hinweise gab es hier doch reichlich und mal klartext -
dein code ist sehr "bescheiden" so im sinne von level two auf einer
scala von 1-10. mit 128k kannst du bei dem project lange bis ewig leben,
wenn du sinnig programmierst.
und wenn noch nicht geschehen tausche auch die gcc version, gute
erfahrung habe ich mit v8.3 bzgl. optimization.
und für die ferne zukunft würde ich vielleicht mal esp32 mit micropython
andenken, python macht richtig spass braucht aber auch einige zeit bis
man das halbwegs drauf hat und pythonkenntnisse kann man immer
gebrauchen auf allen plattformen als schweizer-messer oder als die
eierlegende wollmilchsau!
mt
Felix N. schrieb:> Habe ich dadurch irgendwelche Nachteile wenn ich das auf -Os umstelle?
Nein.
> Falk B. schrieb:>> Denn dieser Job gehört dem COMPILER!>> Der verwaltet die Adressen!>> Moment mal. Das heißt ich definiere gar nicht die Adressen fürs EEPROM,
Ja.
> sondern die werden dann Zufällig zugewiesen,
Nicht ganz, aber im Normalfall ist die exakte Adresse einer Variable
vollkommen egal. Das kann der Compiler zusammenbasteln wie er will. Es
gibt Ausnahmen, logisch.
> oder wie muss ich das> verstehen?
Bei Structs legt der Compiler die Daten exakt so in der Reihenfolge an,
wie sie aufgeschrieben sind. Aber er darf bisweilen Lücken einfügen,
wenn es die Architektur verlangt oder es Vorteile bringt.
> In deinem Struct Beispiel bezieht sich die 16 Bit> Variable(min_temperature) ja nicht auf den gelesen Wert vom EE
Aber sicher!
> sondern> auf die Adresse im EE wo der Wert liegt.>> Oder muss ich die Variablen einmal mit einer Adresse definieren?> my_struct.irgendwas = eeprom_adresse;
NEIN!
Ok, hier gibt es ein Mißverständnis. Beim internen EEPROM übernimmt der
Compiler die Adressverwaltung, genauso wie im RAM oder ROM (Flash). Bei
externem, seriellen Speicher ist der Compiler nicht beteiligt, dort muss
man alles "zu Fuß" organisieren. Aber auch dort ist man gut beraten,
zumindest teilweise die Funktionen des Compilers zu nutzen. Eben indem
man einen Struct definiert und die Daten struc(block) weise in den
externen Speicher schreibt bzw. von dort liest.
> Falk B. schrieb:>> Ist das nicht DEUTLICH lesbarer und vor allem selbsterklärend?>> Ja auf jeden Fall. Aber eine Frage habe ich dazu noch du legt ja eine> Variable von der Struktur im EEMEM an wobei sich EEMEM wahrscheinlich> auf das Interne EEPROM des uC bezieht. Ich benutze ja ein externes> EEPROM, reicht es dann wenn ich es nur mitmy_struct my_ee;initialisiere?
Nein, das geht leider nicht, siehe oben. Aber auch dann arbeitet man
nicht derartig mit absoluten Adressen.
> Falk B. schrieb:>> Ist das für einen Aquariumcontroller wichtig?>> Zeitkritisches habe ich eigentlich nix in meinem Projekt drin und wenn> der pH Wert mal unter 6.80 sinken wird werden meine Fischis auch nicht> davon sterben.
Deine CPU wird so oder so tödlich gelangweilt sein, ganz egal wie
ineffizient dein Programm ist.
> Jor das wahr zwar eigentlich nicht mein Ziel. Aber der Richtung wechsel> in die Code Optimierung finde gut. Bin gar nicht erst auf die Idee> gekommen. Das der Flash wegen vielleicht falscher Programmierung voll> ist.
Vor allem. Wenn du sie meisten (alle?) konstanten Strings in den Flash
verlagerst (PROGMEM und so), dann wird massiv RAM frei und du kanst
problemlos mit dem großen Bruder 2561 (aka Arduino Mega) mit 256kB Flash
und 8kB RAM arbeiten, ohne ins Schwitzen zu kommen.
Apollo M. schrieb:> Ja! neu anlegen und gründlich überarbeiten
Ja glaubig auch. Werde ich auch machen.
Apollo M. schrieb:> nd wenn noch nicht geschehen tausche auch die gcc version, gute> erfahrung habe ich mit v8.3 bzgl. optimization.
Nein ich benutze die GCC Version 5.4.0 die Version 8.3.0 kann ich nicht
finden habe nur die AVR-GCC 9.2.0 gefunden zum Downloaden:
http://blog.zakkemble.net/avr-gcc-builds/
Jedoch scheint da irgendwas faul zu sein. Beim Kompilieren meckerte er
erst bei der Zusatz Option "unrecognized debug output level
'c-sections'" habe dann -gc-sections entfernt dann konnte ich
Kompilieren jedoch habe ich nun 0 Bytes Flash und 0 Bytes RAM Belegung.
Yeah! Oder auch irgendwie nicht. Er lädt zumindest immer mein altes
Programm hoch welches ich mit GCC 5.4.0 Kompiliert habe.
Habe nur die neuen Daten der Toolchain in den bestehen Ordner der
Toolchain im Atmel Studio Ordner geschoben und halt 5.4.0(Ordner)
gelöscht.
Falk B. schrieb:> Aber sicher!
OK?
Falk B. schrieb:> eeprom_write_word(&my_settings.max_temperature, max);
Da ich die interen EEPROM Funktion des AVRs nicht nutze habe ich mir mal
kurz die Funktion angeschaut und der erste Parameter ist die Adresse im
EEPROM der zweite Parameter der Wert.
Das heißt doch folglich dann wenn du als erstes die Variable aus der
Struktur(max_temperature) übergibt als 1en Paramter das in dieser
Variable(max_temperature) nicht Wert steht sondern nur die EEPROM
Adresse die vom Kompiler vergeben wird steht. Und das der zweite
Parameter(max) die Variable ist welchen den eigentlichen Wert enthält
der ins EEPROM geschrieben werden soll. Oder nicht?
Falk B. schrieb:> Ok, hier gibt es ein Mißverständnis. Beim internen EEPROM übernimmt der> Compiler die Adressverwaltung, genauso wie im RAM oder ROM (Flash). Bei> externem, seriellen Speicher ist der Compiler nicht beteiligt, dort muss> man alles "zu Fuß" organisieren.
Sorry habe mit diesen Strukturen noch nie gearbeitet. Absolutes Neuland
für mich.
Wenn ich das Interne EEPROM nutze brauch ich mir keine Gedanken machen
um die Adressen im EEPROM. Nutze ich(wie jetzt) ein externes EEPROM muss
ich diese ihm einmal Mitteilen. Würde das jetzt so machen:
1
typedef struct { //Struktur definieren
2
uint8_t: karbonathaerte;
3
uint8_t: benutzeDimmung;
4
uint8_t: pHSoll;
5
...
6
} my_eepromAddress;
7
8
void setEEEPROMAddress(void) { //EEPROM Adressen einmal während des Startup laden
9
my_eepromAddress.karbonathaerte = 0x01;
10
my_eepromAddress.benutzeDimmung = 0x02;
11
my_eepromAddress.phSoll = 0x03;
12
...
13
}
Falk B. schrieb:> Nein, das geht leider nicht
Muss ich dieses Struktur überhaupt initialisieren, ich meine du hast
dort ja ein Datentyp im EEPROM anlegt. Kann ich dann direkt damit
arbeiten sprich wie im meinem Beispiel oben?
Joachim B. schrieb:> und warum 4K für den Bootloader wo 512 Byte reichen?
Der Controller liegt schon seit ein paar Jahren bei mir(so 2016) den
habe ich damals fertig mit Bootloader bei unserem ehemaligen
Elektronikshop um der Ecke gekauft, für glaubig 10 Eur. Dort sagte man
mir es ist schon ein Bootloader drauf der würde ca. 4 Kb vom Flash in
Anspruch nehmen. Aber gut zu wissen dann kann ich den neuen ja mal bei
Gelegenheit drauf brennen.
Mfg
Felix N. schrieb:> Nein ich benutze die GCC Version 5.4.0 die Version 8.3.0 kann ich nicht> finden habe nur die AVR-GCC 9.2.0 gefunden zum Downloaden:
Warum nimmst du nicht einfach Atmelstudio? Dort ist alles fix und fertig
drin. Dieses Rumgehacke mit Kommandozeile und Dutzenden Parametern ist
gerade für Anfänger wie du schlicht Unsinn.
>> eeprom_write_word(&my_settings.max_temperature, max);>> Da ich die interen EEPROM Funktion des AVRs nicht nutze habe ich mir mal> kurz die Funktion angeschaut und der erste Parameter ist die Adresse im> EEPROM der zweite Parameter der Wert.
Ja.
> Das heißt doch folglich dann wenn du als erstes die Variable aus der> Struktur(max_temperature) übergibt als 1en Paramter das in dieser> Variable(max_temperature) nicht Wert steht sondern nur die EEPROM> Adresse die vom Kompiler vergeben wird steht. Und das der zweite> Parameter(max) die Variable ist welchen den eigentlichen Wert enthält> der ins EEPROM geschrieben werden soll.
Ja sicher. Wo liegt das Problem?
> Wenn ich das Interne EEPROM nutze brauch ich mir keine Gedanken machen> um die Adressen im EEPROM. Nutze ich(wie jetzt) ein externes EEPROM muss> ich diese ihm einmal Mitteilen.
So einfach ist es nicht. Weig gesagt, bei externem EEPROM muss man
vieles manuell machen. Man kann es nur dahingehend vereinfachen bzw. dem
"Normalfall" angleichen, indem man z.B. beim Start einen Datenblock aus
dem externen EEPROM in ein struct vom gleichen Typ in den RAM kopiert.
Dann hat man alle Einstellungen im RAM und kann dort beliebige
Schreib/Lesezugriffe machen. Irgendwann muss man dann aber die Daten vom
RAM wieder in den EEPROM kopieren, damit sie dauerhaft erhalten bleiben.
Auch das macht man meist sinnvoll als Datenblock und nicht mit
Einzeldaten.
Würde das jetzt so machen:
> typedef struct { //Struktur definieren> uint8_t: karbonathaerte;> uint8_t: benutzeDimmung;> uint8_t: pHSoll;> ...> } my_eepromAddress;
Das ist nicht ganz richtig. typedef definiert einen Datentyp, keine
Variable. Und schon gar nicht eine Adresse! Solche Namen sind maximal
irreführend! Die Variable muss dann im 2. Schritt normal definiert
werden, wie in meinem Beispiel. Man kann zwar auch direkt eine Variable
als struc anlegen, ohne einen Typ zu definieren, das ist aber meistens
ungünstig. Näheres erklärt dir ein C-Buch.
> void setEEEPROMAddress(void) { //EEPROM Adressen einmal während des> Startup laden
Falsch. Adressen werden nicht geladen. Gewöhn dir eine klare, saubere
Sprache bzw. Beschreibung/Namensgebung an, sonst wurschtelst du nur rum.
Strukturierte Programmierung auf Mikrocontrollern> my_eepromAddress.karbonathaerte = 0x01;> my_eepromAddress.benutzeDimmung = 0x02;> my_eepromAddress.phSoll = 0x03;
Was du meinst ist das Laden der EEPROM-Werte mit einem Startwert oder
Standardwert. Das kann der Compiler selber.
struct my_settings EEMEM = {1, 2, 3};
Damit wird vom Compiler ein .eep File (Intel-HEX) erzeugt, daß ebenso
wie der Flash einfach in den AVR programmiert wird. Damit hast du im
internen EEPROM initialisierte Daten stehen. Beim externen EEPROM geht
das freilich nicht. Da ist wieder Handarbeit angesagt.
Felix N. schrieb:> Da ich die interen EEPROM Funktion des AVRs nicht nutze habe ich mir mal> kurz die Funktion angeschaut und der erste Parameter ist die Adresse im> EEPROM der zweite Parameter der Wert.
ich greife das nochmal auf.
Wenn er immer den externen nutzt. muss er es eh anders machen.
der compiler kennt den externen nicht
hier muss man dieses struct bei der init auf die startadresse des
externen eeprom setzen.
bei einem neugerät kann man am anfang des struct ein flag setzen
default sind die externen auf 0xFF gesetzt.
wenn 0xFF im ersten byte an adresse 0x0000 steht kann der µC seine
default werte in den externen EEPROM schreiben
also auch das erste byte auf einen anderen wert setzen
Felix N. schrieb:> Arno schrieb:>> Ich möchte nochmal auf diese Frage hinweisen - ob mit -O0 oder -Os>> kompiliert wird, dürfte die Programmgröße massiv beeinflussen.>> Habe mal unter AVR/GNU C Compiler -> Optimization nach geschaut dort> steht drin: Optimization Level: Optimize(-O1).>> Ich habe es mal testweise umstellt bei -O0 kann ich erst gar nicht> kompilieren dort kommt der Fehler: "region `text' overflowed by 14018> bytes"
Also statt 98kB 142kB (128kB plus 14kB, die nicht mehr in den Speicher
passen).
> Ja -O1 wird ja benutzt dort habe ich im Moment 98952 Bytes an Flash und> 6853 Bytes an SRAM. Mit -Os habe ich 89932 Bytes Flash und 6893 Bytes an> SRAM.>> Habe ich dadurch irgendwelche Nachteile wenn ich das auf -Os umstelle?
Es wird an der einen oder anderen Stelle ein bisschen langsamer sein.
Hast du gerade ein Zeit- oder ein Speicherplatzproblem? (rhetorische
Frage)
> Arno schrieb:>> Genauso die Linker-Optionen überprüfen, ob zum Beispiel LTO aktiv ist.>> Kann ich nicht finden. Weder als Checkbox noch in der Command Zeile.
Das, was ich meinte, ist:
Stefanus F. schrieb:> Erklärung:>> -ffunction-sections -fdata-sections Diese beiden Optionen ermöglichen es> dem Linker (nach dem Compilieren), den Code auseinander zu nehmen und> unbenutzte Funktionen zu entfernen.>> --gc-sections Diese Optionen sagen dem Linker, dass er nicht verwendeten> Code weg schmeißen soll.
Wichtig bei --gc-sections: Das muss direkt nach -Wl, stehen, ohne
Leerzeichen. Denn damit weiß der Compiler, dass er das einfach so an den
Linker weiterreichen soll (sonst kommt die Fehlermeldung, die du gesehen
hast, denn der Compiler versteht --gc-sections nicht).
Also genau wie von Stefan geschrieben:
-Wl,--gc-sections
MfG, Arno
Hab das bei mir mal durchlaufen lassen mit meinen Standardoptionen
(-Os):
avr-size release/aqutest.elf
text data bss dec hex filename
86024 3410 3597 93031 16b67 release/aqutest.elf
Ist natürlich komplett ungetestet. Arbeitest du mit Debugger und
Debuginfos im Code? Ich helfe mir da immer so, dass ich in meinem
makefiles den Code in 2 Gruppen teile. Einmal den der mit -Os optimiert
bleibt und der andere der mit -O0 zum Debuggen von der Optimierung
befreit ist. Aber schon Ewigkeiten nicht mehr mit AVRs sondern mit
Cotexen. Höchstens mal noch einen tiny841.
Das meiste im bss dürften deine Strings belegen wie schon gesagt wurde,
in soweit hast du da noch Optimierungsmöglichkeiten wenn du auf den
größeren AVR umsteigst. Auf den Flash hat das kaum Auswirkung. Wenn du
den RAM nicht anderweitig brauchst ist es verschenkte Lebenszeit das nur
zur Optik anders zu machen. Ob du mit Änderungen am eigenen Code 30%
sparen kannst wie hier behauptet wird, wage ich zu bezweifeln da der
Verhältnis zu den Libs schon nicht mehr als 30% ist. Wenn du 10 Leute
fragst wie guter Code aussieht kriegst du 10 Meinungen und jeder findet
seinen Stil am besten. Traue auch keinen der großspurige Behauptunge in
der Form: "das macht man doch nicht!" von sich gibt. Das ist in der
Regel nur nachgeplappertes Geschwätz.
Für ein komplettes Redesign würde ich dir den Umstieg auf einen Cortex
Mx empfehlen. Allerdings nur wenn dir die Lernphase einen Zusatznutzen
bringt. Die Zeit die du bis jetzt darauf verwendet hast dürfte nochmal
draufgehen. Auf alle Fälle gibt es in diesem Bereich mehr fertige Boards
als für große AVRs. z.B.
https://www.hotmcu.com/lpc1768minidk2-development-board-28-tft-lcd-p-12.html?cPath=1_21&zenid=tdo7s5kaoj499q667hl9du1rl7
Auch wenn die ESPxxxx Controller massiv Flash und Ram haben und auch
schnell sind, die bescheidenen Debugmöglichkeiten wären für mich ein
NoGo für größere Projekte. Höchstens als Interface für BLE oder WLAN in
einer Mehrcontrollerumgebeung.
Moin,
also ICH würde zunächst einige der Verbesserungsvorschläge einarbeiten,
z.B. Texte ins EE, Menüstruktur, Funktionen und Unterprogramme mehr
nutzen.
Dann ergibt sich wahrscheinlich eine deutliche Reduktion der Codegröße,
zumindest für das RAM, aber wahrscheinlich auch für das Flash.
Und zu lernen, wie man effizienter programmiert, kann grundsätzlich
nicht schädlich sein, egal für welches System.
Der Ruf nach stärkerer Hardware ist immer die Nullösung für schlechte
Programmierung.
Und wenn es wirklich zu knapp werden sollte, dann umsteigen auf eine Art
"Mega256 als Nano", der sich auch in eigene Platinen per THT einlöten
läßt:
https://www.mikrocontroller-elektronik.de/mini-controllerboard-mit-atmel-atmega2560-und-usb/
Und wenn 256 kB für eine Aquariensteuerung nicht ausreichen, dann sollte
man das wirklich ganz lassen, denn dann muß die dermaßen mit Funktionen
oder Gimmicks überfrachtet sein, daß die Regelung vermutlich viel zu
unzuverlässig wird... ;-))
svensson schrieb:> Und wenn es wirklich zu knapp werden sollte, dann umsteigen auf eine Art> "Mega256 als Nano", der sich auch in eigene Platinen per THT einlöten> läßt:> https://www.mikrocontroller-elektronik.de/mini-controllerboard-mit-atmel-atmega2560-und-usb/
Schönes Marketinggefasel!
>Leistungsstarker Controller ATMega2560 (einer der wohl leistungsfähigsten> 8 Bit AVR-Controller überhaupt), 100 Pins am Gehäuse,
BlaBla. Der CPU-Kern ist bei allen AVRs praktisch gleich und damit
gleich leistungsfähig. Nur die Speichergröße sowie IO-Module variieren
>256.000 Bytes Flash Speicher
Jaja, große Zahlen braucht das Land! Warum nicht gleich 2048000 Bit?
Außerdem sind es 256KiB, was 262144 Bytes entspricht.
https://de.wikipedia.org/wiki/Binärpräfix>8000 Byte RAM>4000 Bytes EEPROM
Dito.
svensson schrieb:> Und wenn 256 kB für eine Aquariensteuerung nicht ausreichen, dann sollte> man das wirklich ganz lassen, denn dann muß die dermaßen mit Funktionen> oder Gimmicks überfrachtet sein, daß die Regelung vermutlich viel zu> unzuverlässig wird... ;-))
Bevor du weiter faselt, lade dir das Programm mal runter. Bei ihm machen
im Moment die Libs den meisten Teil aus. Ethernet, Filesystem, Grafik
und Kommunikation belegen da schon eine ganze Menge. Und was er für sich
für Funktionen und Gimmicks einbaut war weder die Frage noch geht es
dich was an. Und wieso sollte der Flashverbrauch irgendwelchen
Einfluss auf die Geschwindigkeit einer Temperaturregelung haben?
@Falk
Mir ging es auch nicht um den Inhalt der Seite (den habe ich mir gar
nicht angesehen), sondern um die Bauform (Bilder). Das einzig
entscheidende Kriterium ist, daß der Mega256 eben 256 kB Flash hat, was
einer Verdoppelung zur jetzigen Situation gleichkäme.
Wenn ich es richtig verstanden habe, nutzt der TE jetzt die DIL-Bauform,
d.h. er lötet das Dingens irgendwo ein oder nutzt ein Steckbrett. Bei
dem gezeigten Beispiel wäre das eben, sogar relativ einfach, auch so
möglich.
@temp
Nun aus langjähriger Erfahrung kann ich sagen, KISS (keep it simple and
stupid) gilt immer, läßt sich sogar mathematisch beweisen.
Es gäbe auch noch die Möglichkeit, das ganze Projekt in Teilbereiche
aufzuteilen, z.B. Regelaufgaben und Datenlogging/Aufbereitung der
Meßwerte zu trennen.
ili9341_combo_flash(5,tftline+=10,WHITE,BLACK,1,3,0,0,PSTR("EEPROM initialized. Addr=0xA1 InitCode on 0x00"));
24
25
ili9341_combo_flash(5,tftline+=10,WHITE,BLACK,1,3,0,0,PSTR("Initialized Timers/Counters and Enable Interrputs!"));
26
ili9341_combo_flash(5,tftline+=30,ORANGE,BLACK,1,3,0,0,PSTR("Startup done. Took 405ms"));
dann kann er die _delay_ms(1500); auch entfernen
Das sind infos zum start die anfangs zum debugging vlt brauchbar sind ..
aber am gerät später keinen nutzen haben
Felix N. schrieb:> Nein ich benutze die GCC Version 5.4.0 die Version 8.3.0 kann ich nicht> finden habe nur die AVR-GCC 9.2.0 gefunden zum Downloaden:>> http://blog.zakkemble.net/avr-gcc-builds/
... die gcc v8.3 findest du auch bei zakkemble, du nimmst den link der
9.2 und ersetzt entsprechend auf 8.3.0.
ich benutze atmelstudio und kann bei mir via script mit einem klick
zwischen den versioen 5.4-9.2 wechseln.
ABER! ... du musst immer die 5.4 avr_size.exe nehmen sonst wird dir
bzgl. used code size müll angezeigt.
UND! ... zum debuggen eher auch die 5.4 nehmen, weil atmel studio sonst
ein problem hat beim anzeigen mit den variables/symboles.
mt
temp schrieb:> Auch wenn die ESPxxxx Controller massiv Flash und Ram haben und auch> schnell sind, die bescheidenen Debugmöglichkeiten wären für mich ein> NoGo für größere Projekte.
der esp32 lässt sich z.b. unter vsc einfach/vollständig debuggen, also
kein problem, wenn man ahnung hat!
Der AVR-GCC hat eine CommandLineOption
-mcall-prologues
mit der er (gegen minimalste Extralaufzeit) die Push/Pop-Orgien am
Anfang/Ende von Funktionen optimiert.
Wenn man also die 128k Flash nicht nur mit Bitnaps, sondern auch mit
ausführbarem Code belegt hat, dann spart das eventuell die
entscheidenden 5%.
Oder man versucht mal mit
-flto
in der Compiler-CommandLine Link-Time-Optimization. Dabei wird der ganze
Code über alle C-Files hinweg optimiert.
Letzteres muß nicht auf Anhieb funktionieren, aber das deutet dann eher
auf Ungereimtheiten im Code hin, ganz so wie "das Programm läuft nur mit
-O0".
"Call-Prologs" ist aber völlig transparent und dürfte keine Probleme
machen.
Wenn man LTO nicht probieren will/kann, dann auf alle Fälle alle
Funktionen die nicht von außerhalb ihres Source-Files gerufen werden,
als "static" definieren. Dann spart sich der Compiler den Call eventuell
ganz. Schneller und kleiner!
Hallo alle miteinander,
Falk B. schrieb:> Warum nimmst du nicht einfach Atmelstudio?
Nutze ich doch. Ich habe mal ein Bild angehängt um nun die Frage zgl.
welche IDE ich benutze hochgeladen.
Falk B. schrieb:> Ja sicher. Wo liegt das Problem?
Weil ich oben gefragt ob sich die Variable(min_temperature) nicht auf
den gelesen Wert vom EE bezieht sondern nur auf die Adresse.
Falk B. schrieb:>> In deinem Struct Beispiel bezieht sich die 16 Bit>> Variable(min_temperature) ja nicht auf den gelesen Wert vom EE>> Aber sicher!
Ich habe jetzt unter "Aber sicher" verstanden, das sie doch den gelesen
Wert enthält und nicht die Adresse. Aber das hat sich ja nun geklärt.
Falk B. schrieb:> Näheres erklärt dir ein C-Buch.
Irgendwie check das immer noch nicht mit den Strukturen. Aber ich habe
mal in mein Buch rein geschaut dort wird es so erklärt:
1
struct person { //Struktur definieren
2
char name[50]; //Inhalt der Struktur
3
int alter;
4
} peter; //Variable der Struktur anlegen
5
6
//Alternativ ohne direkt eine Variable der Struktur anzulegen:
7
struct person dieter; //Variable der Struktur anlegen.
8
9
int main() {
10
11
peter.alter = 50; //Person 'peter' das Alter 50 zuweisen
12
dieter.alter = 25; //Person 'dieter' das Alter 25 zuweisen
13
14
printf("Peter ist: %d Jahre alt", peter.alter);
15
printf("Dieter ist: %d Jahre alt", dieter.alter);
16
17
return 0;
18
}
Falk B. schrieb:> Gewöhn dir eine klare, saubere> Sprache bzw. Beschreibung/Namensgebung an
Werde ich versuchen.
gdgddfgdfd schrieb:> muss er es eh anders machen.> der compiler kennt den externen nicht
Das heißt ich muss einmal beim Programmstart die Variablen in der
Struktur die passenden EEPROM Adressen zuweisen, zb. im EEPROM steht
unter der Adresse 0x0A der Wert der Karbonathärte also muss ich einmal
struktur.karbonathaerte = 0x0A machen?
Arno schrieb:> Wichtig bei --gc-sections: Das muss direkt nach -Wl, stehen, ohne> Leerzeichen.
Ah danke jetzt tut es.
svensson schrieb:> Wenn ich es richtig verstanden habe, nutzt der TE jetzt die DIL-Bauform,> d.h. er lötet das Dingens irgendwo ein oder nutzt ein Steckbrett.
Früher Steckbrett hat aber zu viele Probleme mit Kapazitive
Einkopplungen gemacht habe mir dann eine Platine ätzen lassen.
Wenn ich wirklich auf den 2560 umsteige mache ich eh wieder eine neue
Platine da teile der jetzigen Platine nicht mehr gebraucht werden. Dann
kann ich auch gleich den IC in SMD drauf löten.
gdgddfgdfd schrieb:> Das sind infos zum start die anfangs zum debugging vlt brauchbar sind ..> aber am gerät später keinen nutzen haben
Es war mal zum Debuggen nötig:
Felix N. schrieb:> Es hatte am Anfang wirklich mal ein Sinn gehabt, mein Controller hatte> sich durch nicht ganz korrekte Verdrahtung und scheinbar Kapazitive> Einkopplung der SCL und SCK Leitungen zu System Hängen geführt hat. Habe> ich ein Start Up Bildschirm gemacht um zu sehen wo er sich aufhängt, es> war auch mal eine Startzeit Messung drin aber das ist alles mittlerweile> nicht mehr nötig.
Ist aber nun entfernt.
Apollo M. schrieb:> ... die gcc v8.3 findest du auch bei zakkemble, du nimmst den link der> 9.2 und ersetzt entsprechend auf 8.3.0.
Habe es gefunden.
Apollo M. schrieb:> ABER!Apollo M. schrieb:> UND!
Ich lasse es erstmal bei 5.4.0 und werde mich erstmal um mein Programm
kümmern. Das wird mir sonst alles zu kompliziert.
Mfg
Ich würde dir empfehlen:
Code optimieren, aber nicht komplett neu anlegen, auch nur die
wichtigsten Sachen optimieren, keine riesigen Sachen, dann auf den mit
256kb umsteigen. Auf gar keinen Fall würde ich die Plattform wechseln,
da investierst du locker mal 100h nur fürs umprogrammieren, einlesen,
Entwicklungsumgebung aufsetzen, etc. musst du noch draufrechnen.
Wirklich hübschen Code würde ich beim nächsten Projekt von Anfang an
schreiben, das jetzt groß umändern, kostet einfach viel Zeit.
Falk B. schrieb:> So einfach ist es nicht. Weig gesagt, bei externem EEPROM muss man> vieles manuell machen.
... eigentlich nicht, wenn man es sinnig angeht. z.b.
- zuerst mal die extEEprom read/write byte/word/block functionen
schreiben, die i2c oder spi oder parallel angetrieben sind.
- dann ein struct z.b. extEE definieren wo ALLE anderen struct's ,
variablen drin sind. also die struct extEE ist ein "data container"
- nun einen ptr pExtEE mit z.b. addr=0 (ext eeprom start addr) auf die
extEE struct definieren und dann entsprechend mit pExtEE-> und den extEE
read/write functions drauf zugreifen.
so what?
Felix N. schrieb:> Irgendwie check das immer noch nicht mit den Strukturen. Aber ich habe> mal in mein Buch rein geschaut dort wird es so erklärt:
Ist OK.
>> muss er es eh anders machen.>> der compiler kennt den externen nicht>> Das heißt ich muss einmal beim Programmstart die Variablen in der> Struktur die passenden EEPROM Adressen zuweisen,
Nein! Du musst die Daten vom externen EEPROM in eine Kopie im RAM laden.
Man könnte auch immer direkt mit dem Zugriff auf den externen EEPROM
arbeiten, aber das ist meist deutlich ungünstiger.
> zb. im EEPROM steht> unter der Adresse 0x0A der Wert der Karbonathärte also muss ich einmal> struktur.karbonathaerte = 0x0A machen?
Du verwechselt irgendwie permanent die Adresse mit dem Inhalt einer
Variablen.
> Wenn ich wirklich auf den 2560 umsteige mache ich eh wieder eine neue> Platine da teile der jetzigen Platine nicht mehr gebraucht werden. Dann> kann ich auch gleich den IC in SMD drauf löten.
Naja, kauf dir lieber einen Arduino Mega und bastel dir einen passenden
"Shield" dafür.
> Ich lasse es erstmal bei 5.4.0 und werde mich erstmal um mein Programm> kümmern. Das wird mir sonst alles zu kompliziert.
Gute Wahl! Einen Vielfrontenkrieg gewinnt man nicht! (Urdeutsche
Erkenntnis . . .)
Felix N. schrieb:> svensson schrieb:>> Wenn ich es richtig verstanden habe, nutzt der TE jetzt die DIL-Bauform,>> d.h. er lötet das Dingens irgendwo ein oder nutzt ein Steckbrett.>> Früher Steckbrett hat aber zu viele Probleme mit Kapazitive> Einkopplungen gemacht habe mir dann eine Platine ätzen lassen.>> Wenn ich wirklich auf den 2560 umsteige mache ich eh wieder eine neue> Platine da teile der jetzigen Platine nicht mehr gebraucht werden. Dann> kann ich auch gleich den IC in SMD drauf löten.
Der 2560 hat ein External Bus Interface. Da kannst Du z.B. extern noch
ein 32kb RAM anschließen. Z.B.
https://www.reichelt.de/sram-32-kb-4-k-x-8-4-5-5-5-v-tsop-28-62256-70-m-p40086.html?r=1
Das liegt dann direkt im Adressraum des Prozessors wie das interne RAM
auch, und für 1.45€ kann man das ruhig auf Vorrat verbauen.
Und Du kannst zusätzlich ein TFT-Display daran anschließen, z.B.:
https://www.buydisplay.com/default/serial-spi-3-2-inch-tft-lcd-module-display-ili9341-power-than-sainsmart
Das könnte zwar auch SPI, aber die Ansteuerung über das External Bus
Interface geht VIEL schneller (Faktor 5 und mehr), weil jeder
TFT-Registerzugriff nur ein einziger Speicherzugriff ist. Schneller kann
man keine Daten in das Display reinbekommen.
fchk
tschut tschut schrieb:> Wirklich hübschen Code würde ich beim nächsten Projekt von Anfang an> schreiben, das jetzt groß umändern, kostet einfach viel Zeit.
... das klingt nach blümchen sex!
wir reden hier über neudeutsch refactoring! und das ist immer sinnvoll.
coding ist art ... ich habe kein project/program wo ich nicht gefüllt
den code 2-3mal fast neugeschrieben habe - in teilen sogar x-mal neu.
und da ging es nicht darum wie z.b. in c sinnig programmiert wird,
sondern wie ein problem/aufgabe sinnvoll abgebildet wird bzgl.
structure, algorithm, data abstruction, use of rtos, ...
mit jeder itteration lernt man dann fett was dazu (hoffentlich).
mt
tschut tschut schrieb:> Auf gar keinen Fall würde ich die Plattform wechseln,> da investierst du locker mal 100h nur fürs umprogrammieren, einlesen,> Entwicklungsumgebung aufsetzen, etc. musst du noch draufrechnen.
Autsch. Da könnte man ja was bei lernen. Das Denken ist zwar allen
Menschen erlaubt, aber vielen bleibt es erspart.
Mal ein Schwank aus meiner Kindheit: Ich habe 1981 mit Z80 Assembler
angefangen (C existierte zwar, war aber wenig verbreitet). Nach 6
Monaten war ich soweit, dass ich die wichtigsten der 300 Opcodes im Kopf
hatte und meine Programme direkt als hexdumps eingeben konnte. An der
Wand hingen seitenweise Spickzettel mit Befehlslisten und Codierungen.
Mein Rechner hatte keinen Assembler, nur einen Disassembler. Als ich
dann einige Jahre später 6502 angefangen hhabe, brauchte ich nur noch 6
Wochen, um genauso produktiv zu sein.
Genauso ist es hier: Kennst Du einen, kennst Du alle. Ja, Register,
Bitbelegungen und andere Details sind zwar anders, aber Technik,
Vorgehensweise und Grundlagen bleiben. Und bei Dir wird sogar noch die
Programmiersprache die gleiche bleiben. Mann, hast Du es heute gut. Wir
früher...
fchk
Frank K. schrieb:> Mal ein Schwank aus meiner Kindheit:
Im Sandkasten habe ich eine kleine Schaufel gehabt. Heute nehme ich zum
Blumenumtopfen einen Bagger. Meintest Du das?
Die Tage hat hier jemand eine Möglichkeit gesucht, eine LED mit einem I7
blinken zu lassen:Beitrag "LED blinken mit Intel core i7"
Hattest Du ihm dazu geraten?
Mal (eine) ganz simple Frage(n) an den TO:
Gibt es einen Grund den Debug-Build zu benutzen?
Wird ein Sourcecode-Debugger benutzt?
Falls die letze Frage nicht mit eindeutigem JA beantwortet werden kann:
Ein Release-Build mit -Os kommt auf 97017 Byte Flash. Da ist noch Luft.
Und es ist nicht erkennbar, daß irgend ein Code vom Makro "DEBUG"
abhängen würde. Wie auch immer man so einen Berg Code zu laufen bekommt,
ohne irgendwie zu debuggen. Ich könnte es nicht.
Nachtrag:
Die SD-Lib braucht viel Flash für die Benutzung langer Filenamen
inclusive Unterstützung der Codepage 1250. Wird das wirklich gebraucht?
WCHAR (16bit) Zeichenverarbeitung paßt einfach besser zum i7 als zum
AVR.
Carl D. schrieb:> [...]> Wie auch immer man so einen Berg Code zu laufen bekommt,> ohne irgendwie zu debuggen. Ich könnte es nicht.
Was man mal lobend hervorheben könnte.
Es muss ungeheure Energie dazu gehören, mit den verwendeten
unzureichenden Methoden und geringen Kenntnissen so weit zu kommen. Ein
Paradebeispiel für "die harte Tour".
Hut ab und alle Achtung. Auch wenn es doch etwas tragisch ist.
m.n. schrieb:> Frank K. schrieb:>> Mal ein Schwank aus meiner Kindheit:>> Im Sandkasten habe ich eine kleine Schaufel gehabt. Heute nehme ich zum> Blumenumtopfen einen Bagger. Meintest Du das?>> Die Tage hat hier jemand eine Möglichkeit gesucht, eine LED mit einem I7> blinken zu lassen:Beitrag "LED blinken mit Intel core i7"> Hattest Du ihm dazu geraten?
Nein, davon distanziere ich mich.
Ich bin kein Bastler, ich mach das beruflich. Und ich nehme dazu das,
was am besten für die jeweilige Aufgabe geeignet ist, was
Rechenleistung, Verlustleistung, Platzbedarf, Bauteilekosten,
Leiterplattenkosten, Entwicklungsaufwand, Kundenwünsche usw usw angeht.
Bei einem Bastler ist der Weg das Ziel. Von mir werden Ergebnisse
erwartet, und meine Zeit ist teuer. Sehr teuer. Da ist es oft unterm
Strich sinnvoller, bei der Hardware etwas größer als unbedingt notwendig
zu dimensionieren, um dafür Entwicklungs-Zeit und damit -Kosten zu
sparen. Ja, in diesem Forum gibts auch Spezialisten, die am liebsten
alles in Assembler machen würden, um alles optimal und auf der
kleinstmöglichen Hardware erledigen zu können. Im Echten Leben™ würde
die gefeuert werden, weil die ihre Abgabetermine nicht einhalten würden
und das kein Kunde bezahlen wollen würde.
Dazu kommt: Ein 8-Bit Controller wie z.B. der ATMEGA2561-16AU für 10.83€
(aktueller Digikey-Preis) ist heutzutage kommerziell nur noch
interessant, wenn man an die Architektur gebunden ist. Selbst wenn 5V
VCC und 5V IO gefordert sind, gibts beispielsweise den 16 Bit
DSPIC33EV256GM106-I/PT mit mehr und besserer Peripherie, mehr RAM und
wesentlich mehr Rechenleistung im gleiche Gehäuse (TQFP64 im 0.5mm
Raster) für 3.82€.
Jetzt erklär mir mal jemand, warum ich unbedingt eine technisch
schlechtere Alternative zum 3-fachen Preis nehmen soll, wenn
Binärkompatibilität keinerlei Rolle spielt.
Die Aquariumsteuerung hätte ich mit dem von mir anfangs erwähnten
Olimex-Board und einem passenden TFT-Touch-Display und einer
Implementation in Phython in ein paar Tagen fertig gehabt. Das mal als
Vergleich, was die Produktivität angeht. Klar, Webservice, Mail,
SD-Karten-Unterstützung und das Malen von Pixeln auf ein Display sind
Sachen, die dann einfach da sind und funktionieren. Um schnell zu
Ergebnissen zu kommen, ist das der bessere Weg. Ja, ich weiß, dass es
viele Leute gibt, die da anderer Meinung sind, aber das ist halt so.
fchk
PS: Irgendwelche Argumente von wegen Open Source, GPL, Community sind
mir egal. Ich habe es nicht so mit Ideologien, und GPL-Code darf ich in
meinen beruflichen Projekten eh im Allgemeinen nicht verwenden.
Frank K. schrieb:> Ich bin kein Bastler, ich mach das beruflich. Und ich nehme dazu das,> was am besten für die jeweilige Aufgabe geeignet ist, was> Rechenleistung, Verlustleistung, Platzbedarf, Bauteilekosten,> Leiterplattenkosten, Entwicklungsaufwand, Kundenwünsche usw usw angeht.
Das klingt sinnvoll.
> Bei einem Bastler ist der Weg das Ziel.
Das ist Unsinn. Meine Hobbyprojekte verfolgen ein Ziel: Ich habe eine
Idee und ich will ein funktionierendes Gerät mit überschaubarem Aufwand.
Es ist sicher nicht in meinem Sinne, möglichst lange daran zu pruckeln.
Da es Einzelstücke sind, jucken mich ein paar Euro mehr an
Bauteilekosten meist nicht.
> Von mir werden Ergebnisse> erwartet, und meine Zeit ist teuer. Sehr teuer. Da ist es oft unterm> Strich sinnvoller, bei der Hardware etwas größer als unbedingt notwendig> zu dimensionieren, um dafür Entwicklungs-Zeit und damit -Kosten zu> sparen.
So pauschal klingt das falsch: Ich habe früher Prüf- und Meßtechnik
gemacht, individuelle Einzelstücke, da waren Materialkosten kein Thema.
Geht man aber in die Entwicklung von Serienprodukten, sieht das deutlich
anders aus. Da darf der Entwicklungsaufwand gerne ein paar Mannwochen
größer werden, wenn die Hardware bei xxxxxx-Stück pro Jahr ein paar cent
billiger zu fertigen ist.
Frank K. schrieb:> Der 2560 hat ein External Bus Interface. Da kannst Du z.B. extern noch> ein 32kb RAM anschließen.
Das hätte der Mega1280-V auch, aber der dürfte nicht auf die vorhandene
Platine passen ohne Anpassungsarbeiten.
Frank K. schrieb:> Dazu kommt: Ein 8-Bit Controller wie z.B. der ATMEGA2561-16AU für 10.83€> (aktueller Digikey-Preis) ist heutzutage kommerziell nur noch> interessant ...
Den Arduino 2560 PRO MINI bekommt man schon für ca. 7,50 und braucht
nicht einmal SMD-Teile zu löten.
Außerdem handelt es sich um ein privates Hobbyprojekt, also ein
Einzelstück, an dem jetzt schon fast ein Jahr programmiert wird. Da
spielt diese Summe doch nun wirklich keine Rolle.
Wahrscheinlich wird das alles aber gar nicht notwendig werden, sofern
der TE nicht noch weitere große Libs einbindet, denn 20kB sind ja noch
frei. Und nach Optimierung wahrscheinlich eher 30-40kB.
Manfred schrieb:> So pauschal klingt das falsch: Ich habe früher Prüf- und Meßtechnik> gemacht, individuelle Einzelstücke, da waren Materialkosten kein Thema.>> Geht man aber in die Entwicklung von Serienprodukten, sieht das deutlich> anders aus. Da darf der Entwicklungsaufwand gerne ein paar Mannwochen> größer werden, wenn die Hardware bei xxxxxx-Stück pro Jahr ein paar cent> billiger zu fertigen ist.
Klar, bei den Stückzahlen ist das klar. Bei meinem aktuellen Arbytegeber
sind das aber nie mehr als xxx-Stück für etwa xxxxxx€ pro Stück.
fchk
svensson schrieb:> Außerdem handelt es sich um ein privates Hobbyprojekt, also ein> Einzelstück, an dem jetzt schon fast ein Jahr programmiert wird. Da> spielt diese Summe doch nun wirklich keine Rolle.
Siehst Du. Mir der gleichen Begründung hätte ich selber zu dem
Olimex-Board für 36€ gegriffen und wäre innerhalb weniger Tage fertig
gewesen.
fchk
Frank K. schrieb:> svensson schrieb:>>> Außerdem handelt es sich um ein privates Hobbyprojekt, also ein>> Einzelstück, an dem jetzt schon fast ein Jahr programmiert wird. Da>> spielt diese Summe doch nun wirklich keine Rolle.>> Siehst Du. Mir der gleichen Begründung hätte ich selber zu dem> Olimex-Board für 36€ gegriffen und wäre innerhalb weniger Tage fertig> gewesen.
Es geht aber nicht um Dich oder einen anderen erfahrenen Entwickler
hier, sondern allein um den TO.
Mancheiner hätte sich auch jede weitere Anschaffung sparen können und
die Hardware einfach aus der Schublade gekramt - LIBs für den Rest
inklusive.
Frank K. schrieb:> Von mir werden Ergebnisse> erwartet, und meine Zeit ist teuer. Sehr teuer.
Eventuell zu teuer?
;-)
Hallo nochmal,
Apollo M. schrieb:> so what?
Ich werde es mal versuchen umzusetzen.
Falk B. schrieb:> Du verwechselt irgendwie permanent die Adresse mit dem Inhalt einer> Variablen.
Ich werde es mir versuchen abzugewöhnen.
Frank K. schrieb:> Der 2560 hat ein External Bus Interface. Da kannst Du z.B. extern noch> ein 32kb RAM anschließen. Z.B.
Das ist dieses XMEM Interface. Für 1,45 Euro kann ich das wohl mit in
einbauen. Anschlüsse habe ich ja so oder so genug am Ende.
Muss nach der Code Optimierung mal einen neuen Schaltplan erstellen für
den 2560.
Carl D. schrieb:> Gibt es einen Grund den Debug-Build zu benutzen?> Wird ein Sourcecode-Debugger benutzt?
Der Debug Build wahr voreingestellt und habe ihn auch nie umstellt. Nein
es wird auch kein Sourcecode Debugger benutzt. Das einzige was ich mal
zum "Debuggen" nutze sind Textnachrichten die ich an den UART sende.
Carl D. schrieb:> Ein Release-Build mit -Os kommt auf 97017 Byte Flash. Da ist noch Luft.
Ich habe mal das ganze auf Release umstellt jedoch habe ich keine
vergrößern von Flash/RAM im Vergleich zu dem Debug Build. Habe alles im
Release Build wieder eingestellt(-Wl,-gcc-section, -Os ...).
Oder muss ich da noch was einstellen?
Theor schrieb:> Hut ab und alle Achtung. Auch wenn es doch etwas tragisch ist.
Soll ich das jetzt positiv oder negativ verstehen?
Theor schrieb:> Es muss ungeheure Energie dazu gehören, mit den verwendeten> unzureichenden Methoden und geringen Kenntnissen so weit zu kommen.
Puff naja, ich arbeite an diesem Projekt halt dann wann ich Lust und
Laue dazu habe. Ja es steckt viel Arbeit drin jedoch kam es auch schon
vor das ich am meinem Aquarium Controller Wochenlang nicht weiter
programmiert habe.
Und mit den geringen Kenntnissen naja je nach dem mit wem man mich nun
vergleich oder? Ich habe 2014 das Programmieren in Java angefangen für
ein Jahr habe ich mich mit Bukkit Plugins(Minecraft) versucht später
dann ein bisschen Java an sich ohne Bezug auf Plugins. Seit 2016 habe
ich mit den Mikrocontrollern angefangen.
Kann mir gut vorstellen das wenn sich ein richtiger Programmier der eine
Ausbildung gemacht hat und Beruflich damit zutun, sich mein Code
anschaut das er fast vom Stuhl fällt. Habe mir halt alles selber erlernt
das einzige Buch was ich über C habe ist "Grundlagen C von Jürgen Wolf".
svensson schrieb:> ofern> der TE nicht noch weitere große Libs einbindet, denn 20kB sind ja noch> frei. Und nach Optimierung wahrscheinlich eher 30-40kB.
Neue Libs sind erstmal nicht geplant. Ich werde jetzt die nächsten Tagen
mein Projekt neu anlegen und den Code überarbeiten. Werde auf jeden Fall
die ganzen Strings mit PSTR und PROGMEM überarbeiten. Floats entfernen
und mit Integers arbeiten und mal schauen was ich noch verbessern kann.
Frank K. schrieb:> wäre innerhalb weniger Tage fertig> gewesen.
Das Ziel war für mich natürlich auch klar das es am Ende funktionieren
soll. Ich habe dieses jedoch als langes Projekt geplant. Am Anfang war
es nur ein Temperatur Messgerät mit Serieller Ausgabe dann kam ein 16x2
LC Display dann eine pH Messer wo man die Kalibrierten Spannung in den
Code direkt eintragen musste. Und so hat sich das dann weiter
entwickelt. ...
Es war nicht Ziel dieses Projekt innerhalb von wenigen Tagen
abzuschließen. Spaß an diesem Projekt habe ich besonders an der Software
Entwicklung und auch an der Konstruktion an sich(Gehäuse, Bauteile,
Platine, Kühlung etc..)
Möchte mich aber bei euch allen bedanken für eure Hilfe und euren vielen
Tipp und Ratschläge. Werde es die nächsten Tage angehen!
Vielen Dank :)!
Mfg
Felix N. schrieb:> das einzige Buch was ich über C habe ist "Grundlagen C von Jürgen Wolf".
kannst du halbwegs in english was lesen/verstehen, dann schick ich dir
ein "pdf-buchpacket" mit guten bookz zu C und mehr drumrum. wenn
interesse pm an mich mit email.
mt
Felix N. schrieb:> Hallo nochmal,>> Apollo M. schrieb:>> so what?>> Ich werde es mal versuchen umzusetzen.>> Falk B. schrieb:>> Du verwechselt irgendwie permanent die Adresse mit dem Inhalt einer>> Variablen.>> Ich werde es mir versuchen abzugewöhnen.>> Frank K. schrieb:>> Der 2560 hat ein External Bus Interface. Da kannst Du z.B. extern noch>> ein 32kb RAM anschließen. Z.B.>> Das ist dieses XMEM Interface. Für 1,45 Euro kann ich das wohl mit in> einbauen. Anschlüsse habe ich ja so oder so genug am Ende.>> Muss nach der Code Optimierung mal einen neuen Schaltplan erstellen für> den 2560.>> Carl D. schrieb:>> Gibt es einen Grund den Debug-Build zu benutzen?>> Wird ein Sourcecode-Debugger benutzt?>> Der Debug Build wahr voreingestellt und habe ihn auch nie umstellt. Nein> es wird auch kein Sourcecode Debugger benutzt. Das einzige was ich mal> zum "Debuggen" nutze sind Textnachrichten die ich an den UART sende.>> Carl D. schrieb:>> Ein Release-Build mit -Os kommt auf 97017 Byte Flash. Da ist noch Luft.>> Ich habe mal das ganze auf Release umstellt jedoch habe ich keine> vergrößern von Flash/RAM im Vergleich zu dem Debug Build. Habe alles im> Release Build wieder eingestellt(-Wl,-gcc-section, -Os ...).>> Oder muss ich da noch was einstellen?>
Release-Build bedeutet hauptsächlich, daß nicht -O0,
sondern -Os oder -O1/2/3
Größer als Debug-Builds werden die Release-Build (praktisch) nie.
Wie schon geschrieben, im konkreten Fall ca. 97kB statt 142kB.
>> Es war nicht Ziel dieses Projekt innerhalb von wenigen Tagen> abzuschließen. Spaß an diesem Projekt habe ich besonders an der Software> Entwicklung und auch an der Konstruktion an sich(Gehäuse, Bauteile,> Platine, Kühlung etc..)
Wenn man die "extremen" Realtime-Anforderungen der aktuellen Version
anschaut, nämlich praktisch keine, dann könnte man natürlich schon auf
die Idee kommen, eine Raspi-Zero zu verwenden. Der hat Disk/Filesystem,
Netzwerk, WLAN (wenn aktuelle Version), unmengen Speicher und
Rechenleistung, komfortables OS, Python als relative einfache und doch
mächtige Implementierungssprache, Webinterface inclusive und seinen
Pinheader lassen sich die benutzten IO-Bausteine auch betreiben, wobei
auf ein EEPROM nicht nötig ist, die Daten schreibt man einfach in ein
File. Man braucht auch beim Rechnen keine Klimmzüge machen, denn das
Ding kann Floatingpoint mit double Genauigkeit berechnen. AVR kann das
nicht.
Wenn also "Spaß" ein wesentlicher Faktor ist, dann kann man was anderes
ausprobieren. Wobei so Raspi-Zero mit WLAN und Flas-Karte wenn überhaupt
kaum mehr kostet, als ein Mega256n-Board mit ENC, ...
Von fehlenden Nervenkitzel eines "selbstgeschriebenen" Filesystems oder
Netzwerkstacks mal ganz abgesehen.
Carl D. schrieb:> Wenn man die "extremen" Realtime-Anforderungen der aktuellen Version> anschaut, nämlich praktisch keine, dann könnte man natürlich schon auf> die Idee kommen, eine Raspi-Zero zu verwenden.
... und selbst wenn man "Realtime-Anforderungen" hat, dann flanscht man
per UART, SPI, etc. irgendeinen 08/15 Controller à la ATTiny dran und
fertig.
Christopher J. schrieb:> Carl D. schrieb:>> Wenn man die "extremen" Realtime-Anforderungen der aktuellen Version>> anschaut, nämlich praktisch keine, dann könnte man natürlich schon auf>> die Idee kommen, eine Raspi-Zero zu verwenden.>> ... und selbst wenn man "Realtime-Anforderungen" hat, dann flanscht man> per UART, SPI, etc. irgendeinen 08/15 Controller à la ATTiny dran und> fertig.
Notfalls, aber nachdem ich den aktuellen AVR-Code gesehen hab: etwas
Zeitsteuerung, das man locker mit cron machen kann und was schneller
reagieren muß, wie z.B. der Drehgeber, ist im Python machbar. Es gibt
das sogar fertig auf
https://thepihut.com/blogs/raspberry-pi-tutorials/how-to-use-a-rotary-encoder-with-the-raspberry-pi.
BTW, habe ich weiter oben ganz vergessen: ein ordentliches Display kann
man natürlich per HDMI auch dran hängen. Und sollte man keine Lust/Zeit
für Frischfisch haben, kann ein größerer Monitor auch gleich eine
Aquqrium-Simulation anzeigen. ;-)
Wenn das Projekt auch eine Regelung des Aquariums ist, also Pumpen,
Heizungen, Beleuchtung, Belüftung, Filtration, Denitrifikation usw.
betreibt, dann würde ich unbedingt beim µC bleiben, weil das alles
absolut zuverlässig funktionieren muß, sonst gehen die Tiere hops.
Wenn es sich lediglich um die Darstellung von Meßwerten handelt, dann
ist man natürlich völlig frei. Für animierte Grafiken per WLAN aufs
Smartphone wäre ein Kleinstcomputer wie Raspi&Co sicherlich die bessere
Wahl.
svensson schrieb:> Wenn das Projekt auch eine Regelung des Aquariums ist, also Pumpen,> Heizungen, Beleuchtung, Belüftung, Filtration, Denitrifikation usw.> betreibt, dann würde ich unbedingt beim µC bleiben, weil das alles> absolut zuverlässig funktionieren muß, sonst gehen die Tiere hops.
Auch Unix-/Linux-System können jahrelang störungsfrei funktionieren,
wenn Hardware, Betriebssystem und Anwendungssoftware von Leuten mit
Ahnung entwickelt wurden. Das ist kein Entscheidungskriterium, sondern
universelle Grundvoraussetzung.
Andersrum: Der Linux-Code ist inzwischen so gut getestet und debuggt,
dass die Wahrscheinlichkeit für Bugs um Zehnerpotenzen geringer ist als
Code, den irgend so ein Anfänger aus Bruchstücken aus dem Netz
zusammengerührt hat. Das gilt vor allem, wenn Fehler auftreten und
beispielsweise die SD-Karte keine Lust mehr hat. Eine richtige
Fehlerbehandlung hab ich in DEM Code hier nicht gesehen. Oder
beispielsweise ein Watchdog. Nee, so wird das nix mit SIL.
Und die zugrunde liegenden physikalischen Prozesse sind so träge, dass
die Echtzeitanforderungen sehr gering sind. 1000 Liter Wasser haben so
viel thermische Kapazität, da ändert sich die Temperatur nicht eben mal
von einer Sekunde zur anderen. Solltest Du auch nur einen Hauch von
physikalischem Verständnis haben, kannst Du gerne mal die kWh
ausrechnen, die Du brauchst, um das Becken von 18°C auf 28°C aufzuheizen
und dann mal schauen, wie lange Du dafür mit einem normalen Heizstab
brauchst. Und als Bonus kannst Du dann noch ausrechnen, wie viel Reboots
Du in dieser Zeit machen kannst.
fchk
Frank K. schrieb:> Andersrum: Der Linux-Code ist inzwischen so gut getestet und debuggt,> dass die Wahrscheinlichkeit für Bugs um Zehnerpotenzen geringer ist als> Code, den irgend so ein Anfänger aus Bruchstücken aus dem Netz> zusammengerührt hat. Das gilt vor allem, wenn Fehler auftreten und> beispielsweise die SD-Karte keine Lust mehr hat. Eine richtige> Fehlerbehandlung hab ich in DEM Code hier nicht gesehen. Oder> beispielsweise ein Watchdog. Nee, so wird das nix mit SIL.
Dafür ist es in der Summe Zehnerpotenzen mehr Code der für das
zusammenspielen aller Teile dazugehört. Aus der Sicht also Patt. Viele
Libs und gerade die von ChaN für das Filesystem sind wenigstens genauso
gut oder besser getestet wie Treiber für exotische Hardware in Linux.
Code ohne Fehlerbehandlung kann man in Linux auch schreiben. Raspberry
Zero scheidet ja wohl aus weil Ethernet fehlt. 5W rund um die Uhr sind
auch fast 45kWh im Jahr. Ne, dann lieber beim Avr o.ä. bleiben.
svensson schrieb:> würde ich unbedingt beim µC bleiben, weil das alles> absolut zuverlässig funktionieren muß
Mein Raspberry Pi läuft genau so stabil, wie meine AVR und ESP8266
Projekte. Jahrelang ohne Aussetzer halt ich für vollkommen normal.
Gut, ich habe nur Welse und Gildfische im Aquarium, daher brauche ich
mir um die nicht vorhandene Heizung keinen Kopf machen. Aber wenn da
eine wäre, würde ich zumindest die Heizung durch eine unabhängige
Schaltung (nämlich dem darin eingebauten Thermostaten) absichern.
Die Pumpe darf ruhig mal einen halben Tag ausfallen, davon geht die Welt
nicht unter.
temp schrieb:> Raspberry Zero scheidet ja wohl aus weil Ethernet fehlt.
Stimmt, die WLAN-Kabel sind zu teuer.
> 5W rund um die Uhr sind> auch fast 45kWh im Jahr. Ne, dann lieber beim Avr o.ä. bleiben.
Dann am besten auf Kaltwasserfische umstellen.
> 5W rund um die Uhr sind sind auch fast 45kWh im Jahr
Im Ruhezustand nimmt der Raspberry Pi weniger Strom auf, rechne mal mit
ca. 2W + 1W Verlust im Netzteil.
Klar, das ist immer noch mehr, als ein AVR. Die Frage ist, wo man sonst
noch so kleine Leistungen vergeudet ohne darüber nachzudenken.
> Dann am besten auf Kaltwasserfische umstellen.
Eben, deswegen habe ich zwei Goldfische, wo früher 15 andere kleinere
waren.
Felix N. schrieb:> Werde auf jeden Fall die ganzen Strings mit PSTR und PROGMEM> überarbeiten.
Ja, und am besten sich wiederholende Sequenzen nach Möglichkeit
datengetrieben aufbauen. Wenn du bestimmte Dinge in einer Tabelle
organisieren kannst, dann brauchst du keinen zusätzlichen Code.
> Floats entfernen und mit Integers arbeiten und mal schauen> was ich noch verbessern kann.
Das ist nicht unbedingt nötig. Die Kosten für float (den Bibliothekscode
für die Funktionen) bezahlst du nur einmal, ab dann sind das nur normale
Funktionsaufrufe. Da das nicht zeitkritisch ist, ist die Rechenzeit
nicht so wichtig - aber mit Float kannst du natürliche Einheiten ohne
Skalierung benutzen. Das macht es einfacher, Werte auf Plausibilität zu
prüfen.
Ansonsten: Übung macht den Meister. Hier wurden viele gute Ideen
genannt, und wenn du jetzt das Projekt passend umstrukturierst, wirst du
hoffentlich genug gelernt haben, um die Fehler zu vermeiden. Du wirst
dafür viele neue Fehler machen, aber genau dadurch lernt man. Viel
Erfolg und Spaß!
Stefanus F. schrieb:> Mein Raspberry Pi läuft genau so stabil, wie meine AVR und ESP8266> Projekte. Jahrelang ohne Aussetzer halt ich für vollkommen normal.
hahaha,
mir sind schon 3 SD und µSD Karten im PI gestorben, die werden durch das
swap oder cache Dateien einfach kaputtgeschrieben.
Ohne Nennung von OS und wie du Schreibvorgänge auf der SD abschaltest
ist deine Aussage wertlos.
Die 2 Transcend microSD wollten nicht mal am PI2 und PI3 laufen,
einigermaßen durchgehalten haben Samsung SD Karten, aber 2 hat das Kodi
auf dem PI auch kaputtgeschrieben, eine steht kurz vor dem Lebensende
mit raspbian jessiePIXEL. Mittlerweile habe ich swap und chromium cache
auf das NAS ausgelagert, wie gesagt um die Schreibvorgänge auf die SD zu
minimieren.
Joachim B. schrieb:> Ohne Nennung von OS und wie du Schreibvorgänge> auf der SD abschaltest ist deine Aussage wertlos.
Ich wüsste jetzt nicht, warum deine Inkompetenz die Aussage von
Stefanus ungültig machen sollte.
Aber fürs Topic:
Mein Raspberry Pi hat auch noch keine SD-Karte gefressen.
S. R. schrieb:> warum deine Inkompetenz
wieder nur Geschwafel
S. R. schrieb:> Mein Raspberry Pi hat auch noch keine SD-Karte gefressen.
schaffe ich auch, wenn man den PI im Schrank liegen lässt :)
Joachim B. schrieb:> Ohne Nennung von OS und wie du Schreibvorgänge auf der SD abschaltest> ist deine Aussage wertlos.
Rasbian ohne GUI ansonsten in Standard-Konfiguration.
Anwendungen: Fileserver samba (kaum genutzt), sowie ein Shell-Script das
alle 10 Sekunden eine Logmeldung ausgibt.
Wenn die SD Karte frühzeitig ablegt, dann entweder wegen schlechter
Qualität oder ein Anwendungsprogramm hat sie überfordert.
Joachim B. schrieb:> Stefanus F. schrieb:>> Rasbian ohne GUI>> installiert raspbian jetzt nicht mehr serienmäßig eine SWAP Partition> oder macht das nur die mit GUI?
Ich weiß nicht was es "jetzt" macht, denn meiner ist ja schon über 2
Jahre alt. Der hat jedenfalls eine swap Partition. Da sie kaum verwendet
wird, habe ich mir keinen Kopf darum gemacht.
Stefanus F. schrieb:> Ich weiß nicht was es "jetzt" macht, denn meiner ist ja schon über 2> Jahre alt.
na denn.....
2 Jahre mit wenig Schreiben ist eine recht kurze Zeit.
ich nutze den PI seit 6 Jahren und habe 5 PIs und Kodi sowie Chromium
schreiben recht viel auf die SD Karten und Kartenausfall gab es nicht
nur bei mir, auch im PI Forum waren einige betroffen.
Die Karten gehen in den write protect Modus, da ist dann nichts mehr zu
"löten" die lassen sich nicht mehr löschen oder initialisieren.
Mein Webserver auf AVR 1284p Basis läuft seit 2008
Hallo Felix,
ich habe nicht den ganzen Thread Wort für Wort gelesen, aber das
Problem, denke ich, verstanden.
Erst mal Hut ab für Deinen unbedarften Einstieg in die Sache. Genau so
habe ich vor Jaaaahren (80er) gelernt, Software zu schreiben. Die vielen
Fehler und Ungelenkigkeiten in meinen Entwicklungen waren der
gründlichste Weg, dazu zu lernen.
Deine Sources habe ich überflogen. Wenn Du hier so etwas postest,
bekommst Du von 20 Softwerkern natürlich mindestens 30 andere Lösungen
für jedes Einzelproblem. Hinzu kommt, dass manche Protagonisten sich
gegenseitig mit "noch besseren" Lösungen überhäufen, was Dir aber am
Ende wenig nützt. Also lass Dich nicht entmutigen, das ist normal. ;-)
Ich möchte mich nicht unbedingt dazu gesellen, weil es einfach Dutzende
Ansätze gibt, den Code übersichtlicher zu strukturieren und weniger
redundant zu machen.
Um aber Deine Eingangsfrage zu beantworten:
- Wenn Du einfach nur mehr reinpacken willst, und die Dir die
Optimierung Deines Werks nicht so wichtig ist, nimm was Größeres. Dann
hast Du vermutlich schneller Ergebnisse. Allerdings ist der Umstieg auf
(z.B.) einen STM32 nicht trivial. Der ATMEGA2560 hätte vermutlich genug
Flash für das, was Du noch machen möchtest. Und hinsichtlich der
Optimierung des SRAMs dürfte es auch noch genügend Raum geben.
- Wenn Du aber dazu lernen möchtest und es Dir nicht primär auf "viel
drin, schnell fertig" ankommt, rate ich Dir zu einer grundlegenden
Reorganisation Deines Projektes, einschließlich der damit verbundenen
Erarbeitung der entsprechenden Grundlagen. Dann hast Du alles richtig
gemacht, klassisches "learning by doing".
Ich persönlich bin am Ende immer den zweiten Weg gegangen. Zuweilen war
aber auch mir das "viel drin/schnell fertig" wichtig. Nur endete das
dann in aller Regel in schwer wartbaren und final neu zu schreibenden
Programmen. Fehlersuche, Optimierung und Erweiterung der Software waren
am Schluss aufwändiger als es die Neuorgansiation bzw. ein Neustart
gewesen wäre.
Letztlich eine Frage der Geduld.
Ernsthafte Software-Entwicklung ist nach meiner Erfahrung immer ein
iterativer Prozess, der häufig ein gründliches Refactoring verlangt,
und, wenn man einfach so hineingestolpert ist, i.d.R. auch ein
umfassendes Neudesign. Siehe majortom: "ich habe kein project/program wo
ich nicht gefüllt den code 2-3mal fast neugeschrieben habe - in teilen
sogar x-mal neu.". Kann ich unterschreiben. Und auch das hier "und da
ging es nicht darum wie z.b. in c sinnig programmiert wird, sondern wie
ein problem/aufgabe sinnvoll abgebildet wird".
Da offenbart sich der Unterschied zwischen Design und Koden. Du hast
kodiert. Das ist nichts Schlimmes, aber auf Dauer reicht das eben nicht,
jedenfalls nicht bei nicht-trivialen Aufgaben, Und das, was Du da
machst, ist durchaus nicht trivial. Vor dem Koden steht daher die
Isolierung und Formulierung des Problems bzw. der Aufgabe und verbunden
damit der Einzelprobleme und -aufgaben. Ist das geschafft, lassen sich
solche Blöcke viel einfacher handhaben.
Was ich machen würde: Viel Papier auf den Tisch legen, die einzelnen
Aufgaben definieren und als Meta-Code aufschreiben, den Code
reorganisieren (sowohl "physisch", also in Einzeldateien zerlegen, als
auch logisch) und dann mit einem klaren Konzept neu aufsetzen. Zu diesem
Zeitpunkt sollten dann neben den aktuellen Features auch die für die
Zukunft angedachten bekannt und eingeplant sein.
So sollte Dein vorhandener Prozessor noch für einiges mehr tauglich
sein, als Du vermutest.