Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Meine ersten Eindrücke des C Programmierens für den Raspi.
peterfido
23.08.2012, 22:48
Hallo,
meine ersten "Programme" auf dem Raspberry waren bash und Shell Scripte. Dann fürs WebIf noch php.
Mit dem Gedanken, dass per gcc compilierte Programme weniger Ressourcen benötigen, habe ich mich entschlossen, die Scripte in "echte" Programme zu wandeln.
Da fingen sie dann an, die Probleme. Hier mal eine Klammer oder Leerstelle anders als im BASH und oder php. Nach und nach die Fehler soweit ausgemerzt. (Zumindest gedacht)
Nun habe ich ein Programm, welches alles gesendete vom AVR entgegen nimmt uns auswertet. Ein weiteres sendet zu diesem hin. Ein drittes überwacht den Mediaplayer Dämonen.
Soweit läuft es. Bis dann plötzlich im Internetradio ein Lied mit Klammern im Titel lief. Das Programm, welches den mpd überwacht sendet den Titel dann mittels dem Sendeprogramm zum AVR. Dieses nimmt alles, was gesendet werden soll aus den Startparametern argv[]. Wenn jetzt eine Klammer darin vorkommt, dann kommt eine Fehlermeldung. Kommt ein & drin vor, nimmt es nur bis zum & an und ignoriert den Rest. Also wird vor dem Aufruf des Sendenprogrammes jetzt auch noch der Text geparst.
Ursprünglich sollte alles ein Programm erledigen. Jedoch habe ich es nicht geschafft, wie im BASH ein Programm im Hintergrund /bzw. unabhängig von meinem aufzufrufen. Im BASH wird einfach ein & am Ende des Aufrufes gehängt. Zur Not noch ein disown hinterher. Alles dies klappt per C-Programm nicht mehr. Selbst, wenn ich eine BASH aufrufe, welches dann das nächste Programm mittels "& disown" startet, wartet mein Programm solange, bis die Kette an Sripten und Programmen dazwischen beendet wurden.
Auch das Sendenprogramm mittels Parameter in "Häkchen" aufzurufen ist, aus welchen Gründen auch immer, gescheitert. In eine Textdatei umgeleitet, erscheinen die Häkchen brav.
Dann sollen vom AVR ankommende Parameter in einer Datei gespeichert werden, damit der php-Code des WebIf diese auslesen kann. Konnte es natürlich nicht. Die Rechte der vom C-Programm angelegten Datei waren mal 600 und dann plötzlich mal 140 oder 104. Also nach dem Erstellen der Datei noch ein system("chmod 644 /tmp/webif.farben"); hinterher.
Stringschiebereien bieten allgemein für eingefleischte BASIC Programmierer (oder zumindest für mich) noch ein paar Fallstricke mehr. Ich habe zwischendurch ja schon C-"Erfahrung" gesammelt, wenn ich mal vorhandenen Code für den AVR an meine Vorstellungen angepasst habe, aber Bewusst geworden, was da so alles lauert ist, ist es mir erst in den letzten 2 Tagen. Ist also doch ein Unterschied, ob man was (Kleinigkeiten) anpasst oder komplett neu erstellt.
Was mir weiter aufgefallen war: Wenn eine Klammer übergeben wurde (werden sollte): Die dann gemeldete Fehlermeldung begann mit "sh:". Quasi so, als ob da im Hintergrund dann wieder die Shell ackert...
Allgemein bietet die Suche im Netz nach der richtigen Syntax auch nicht viel brauchbares. Kann aber auch daran liegen, dass "c" auch recht häufig unabhängig vom Programmieren genutzt wird.
Wenn ich z.B. das Ergebnis einer Funktion in eine Variable speichern möchte, dann wird das in den Beispielen so gut wie nicht gemacht. Die geben gleich immer alles auf der Konsole aus. Ist mir bei C wie auch bei BASH aufgefallen. printf(...) / echo blablub. Dass da mal ein $() drumgehört passt zwar oft, aber doch nicht immer. Da ist es mit den Klammern ja fast schon wieder einfach, auch wenn ich diese aus Flüchtigkeit noch hin und wieder vergesse.
Hey,
klasse das du deine Eindrücke mal schilderst :)
Ich habe direkt mit kleinen C-Programmen angefangen und habe die Skripte quasi übersprungen. Es ist halt doch bischen was anderes als auf so einem 8-Bit Controller und auch ich tu mich noch bisl schwer mit GPIOs, UART usw. aber ich denke das kommt noch mit der Zeit.
Aber das mit dem Radio hört sich gut an :)
Wäre cool wenn du deine weiteren Schritte hier postest, weil ich denke das es auch eine schöne Möglichkeit ist verschiedene Chips miteinander zu verbinden.
peterfido
23.08.2012, 23:14
Hallo,
für mein Radioprojekt habe ich ja schon ein Thema eröffnet gehabt. Da aber Null Resonanz war, habe ich da nicht weiter geschrieben. Wollte ja kein Monolog abhalten. Wenn da Interesse dran besteht, werde dann in dem Topic weiter berichten.
Aber heute nicht mehr. Bin irgendwie müde. Gestern bis Nachts durchgeproggt und heute früh Morgens waren die Handwerker in der Wohnung unter mir am Bohren und Hämmern...
Aber eines kann ich jetzt schon sagen: Der Rasp Pi ist sein Geld allemal wert. Dabei wollte ich erst in WizNets investieren. (~50EUR pro Stück) Die AVR NetIOs kosten etwa das gleiche wie der Rasp Pi, liegen jetzt aber erstmal in der Schublade. (Ich habe 2, genau wie auch vom Rasp Pi, einer immer produktiv und der andere für Tests) Denn der, welcher im Wohnzimmer die Beleuchtung mit übernommen hatte (bzw. "nur" dessen WebIf und Zeitserver), kann halt kein Internetradio. Im Winter wird er in meine Laufschriftanzeige kommen, welche man dann schnell per Broswer konfigurieren können soll. Da braucht es dann kein Radio sowie php und Co.
Also ich hab deinen Radio-Thread gelesen, aber wusste nicht so Recht was ich darauf antworten hätte sollen. Die Resonanz auf Skript-Sprachen ist hier nicht wirklich hoch, da hier hauptsächlich C und BASCOM (Basic) sowie Assembler zum Einsatz kommen. Liegt also nicht an Desinteresse der User, sondern einfach am Schwerpunkt des Forums.
Das mit den Häkchen verstehe ich entweder nicht ganz oder aber du hast erwartet, dass dein Programm von Beginn an weiß wie es mit Pipes und Zeichenketten in " eingeschlossen umgehen kann. Das ist aber in C etwas mühseliger als bei der BASH etc. .
Das mit der Laufschriftanzeige übers Ethernet etc hab ich auch vor in unserer neuen Wohnung zu realisieren. Da wir dort auf die Zugverbindungen angewiesen sind, wollte ich die Abfahrtszeiten der Züge und eventuell die Verspätungen anzeigen. Aber leider muss ich noch ein paar Tage auf die Wohnung und wohl noch einige Wochen auf das Pi warten.
für mein Radioprojekt habe ich ja schon ein Thema eröffnet gehabt. Da aber Null Resonanz war, habe ich da nicht weiter geschrieben. Wollte ja kein Monolog abhalten. Wenn da Interesse dran besteht, werde dann in dem Topic weiter berichten.
Also mich persönlich interessiert das schon, da ich selber noch nicht so tief in Linux drin stecke und jedes funktionsfähige Projekt sehr hilfreich finde :)
Aber eines kann ich jetzt schon sagen: Der Rasp Pi ist sein Geld allemal wert.
Da stimme ich dir voll und ganz zu!
Im Moment läuft auf meinem Pi zwar auch "nur" ein Webserver für GPIOs und ne eigene Cloud aber ich möchte das in der nächsten Zeit noch durch eine Funkstrecke zum einschalten von Lampen usw. nutzen. Ein kleines Platinchen habe ich dazu bereits im Kopf (wird zwar erstmal nur mit Batterie versorgt aber es ist ja noch der allererste Entwurf). Das Pi stellt dann den Webserver und die Anbindung an ein XBee bereit und ein PSoC mit einem XBee und einem Relais soll das schalten übernehmen.
Musste da leider auf einen PSoC zurückgreifen, weil ich keinen Atmelchip mit 8 Beinchen und UART gefunden habe ;)
Aber ich habe es bisher nicht bereut das Geld für das Raspberry ausgegeben zu haben. Hätte ich mein zweites Pi nicht verkauft, könnte ich auch eins für eine feste Aufgabe einplanen ^.^
Aber vielleicht gönne ich mir nochmal ein zweites, sobald die Verfügbarkeit etwas besser geworden ist.
Aber heute nicht mehr. Bin irgendwie müde. Gestern bis Nachts durchgeproggt und heute früh Morgens waren die Handwerker in der Wohnung unter mir am Bohren und Hämmern...
Dann mal guten Schlaf :)
peterfido
24.08.2012, 13:34
Ja, von den Script Sprachen habe ich erstmal wieder Abstand genommen. Außer php dann für das WebIf wird das meiste dann doch wohl in C gemacht werden. Das übt dann halt auch etwas. Wobei es etwas hart ist, gleich mehrere neue aber sehr ähnliche Sprachen zu probieren. Da kommt es dann schon auf Kleinigkeiten an.
Allerdings bleibe ich beim AVR bei BASCOM. Da bin ich zu Hause und Änderungen mache ich da aus dem FF.
Hallo peterfido,
mal vorweg, ich kann deine Probleme und den Frust nachvollziehen, aber ich denke du machst zu Unrecht C dafür verantwortlich.
Alles was du beschreibst, hat mit C wenig zu tun, sondern resultiert aus dem Zusammenwirken oder auch Gegeneinanderwirken von eigenem Programmcode, C-Library und einem Multiuser/Multitasking Betriebssystem. Dazu kommen dann noch andere Programme, gern Kommandos genannt, die man selbst nicht unter Kontrolle hat, und deren Umfang man machmal nicht ahnt.
Ich versuche das mal an einem deiner Beispiele zu erläutern:
Ursprünglich sollte alles ein Programm erledigen. Jedoch habe ich es nicht geschafft, wie im BASH ein Programm im Hintergrund /bzw. unabhängig von meinem aufzufrufen. Im BASH wird einfach ein & am Ende des Aufrufes gehängt. Zur Not noch ein disown hinterher. Alles dies klappt per C-Programm nicht mehr. Selbst, wenn ich eine BASH aufrufe, welches dann das nächste Programm mittels "& disown" startet, wartet mein Programm solange, bis die Kette an Sripten und Programmen dazwischen beendet wurden.
Um ein Programm zu starten (oder im Filesystem zu lesen und zu schreiben, etc), gibt es Systemcalls, die das Betriebssystem veranlassen das zu tun. Die Mechanismen dazu sind auf jedem System und auf jedem Prozessor andere. Eigentlich will der Programmierer das auch garnicht wissen, daher gibt es fertige Funktionen in der C-Library, die das für ihn erledigen (Das gilt natürlich nur, wenn es ein Betriebssystem und/oder ein Filesystem überhaupt gibt). Ein Programm unter Unix zu starten, geht (vereinfacht) so: zuerst wird eine identische Kopie des startenden Programms mit fork() erzeugt. Dann überlädt das erzeugte Programm seinen Code mit dem neuen Programm und setzt möglicherweise noch argv[] auf. Manchmal ist auch noch mehr zu tun. Wenn du das genauer wissen willst, schau dir die man-page von fork() an, und lies dann weiter was unter "SEE ALSO" kommt. Das ganze ist aber nicht Teil von C sondern UNIX, und wird auf einem anderen Betriebssystem anders aussehen.
Da nicht jeder ein Programm schreiben und kompilieren will, nur um den Inhalt einer Datei zu lesen oder ein Programm zu starten, hat sich im Laufe der Zeit ein ganzer Zoo von Utilities und Hilsprogrammen entwickelt. Dies geht los mit so einfachen Dingen wie echo oder cat und endet bei sed oder der Commandshell (von denen die bash nur eine von vielen ist), die dann nicht nur durch Parameter sondern auch durch Textfiles gesteuert werden können. Alles dies sind aber auch nur Anwenderprogramme, die auf der gleichen Ebene funktionieren, wie dein eigenes Programm.
Wenn in einem Steuerfile für die Shell an der richtigen Stelle ein & steht, wird also mittels der oben beschriebenen Systemcalls das Programm geforkt, ... und beide laufen nebeneiander weiter. So haben sich die Shell-Erfinder das ausgedacht. Wenn im richtigen Kontext ein | steht, werden die Programme links und rechts vom | gestartet (wie gehabt) und der Output des linken wird auf den Input des rechten geleitet. Ob ein anderes Programm als die Shell das & oder das | gleich verwendet, ist nicht gesagt.
Für C ist & der "binary and" und | der "binary or" Operator (und innerhalb eines char Arrays, auch gerne String genannt, ist es ein 38 oder 124 und damit nicht mehr als ein gültiger Wert, d.h. 0 <= 38 <= 255).
Dann sollen vom AVR ankommende Parameter in einer Datei gespeichert werden, damit der php-Code des WebIf diese auslesen kann. Konnte es natürlich nicht. Die Rechte der vom C-Programm angelegten Datei waren mal 600 und dann plötzlich mal 140 oder 104. Also nach dem Erstellen der Datei noch ein system("chmod 644 /tmp/webif.farben"); hinterher.
Hier wird ein Missverständniss deutlich. In C ändert man die Dateirechte durch einen Call von chmod() oder fchmod(), am besten kümmert man sich darum, wenn man die Datei mit open() oder creat() erzeugt. Du rufst dagegen via system() das externe Programm chmod auf, und läßt das die Arbeit tun. Ja, und system() startet eine Shell, die dann die Zeile "chmod 644 /tmp/webif.farben" gegebenenfalls nach Ersetzung von Wildcards ausführt.
Für die Sprache C sind das aber nur Funktionsaufrufe: Name, rund Klammer auf, Übergabeparameter, rund Klammer zu, Semikolon. Im passenden Headerfile steht das Format der Parameter, damit der Compiler das checken kann, und der Linker muß die Adresse der Funktion auflösen können. Der Inhalt der Parameter interessiert C kein Stück. Bei deinem Beispiel mit system gilt:
int system(const char *txtptr);
so stehts im Headerfile. Was an der Stelle steht, wo txtptr hinzeigt und was das Betriebssystem dann daraus macht, ist dessen Sache.
Der Text ist ja ganz schön lang geworden, ich will mal versuchen einen Abschluß zu finden. Die Steuerung eines Systems durch direkte Library/Systemcalls kann ganz schön komplex werden. Die Beschreibung der libc umfasst einige tausend Seiten und füllt dazu noch eine ganze Bücherei. Ob du dir das antuen willst, weiß ich nicht. Ich würde eher die Hilfe der anderen verwenden, und eine Scriptsprache verwenden. Unter diesen ist aber die Shell/bash die problematischste. Die Syntax ist durch ewiges Anflicken und kryptische Kürzel von tipfaulen Programmierern alles andere als übersichtlich. Ein Syntaxcheck findet nur beim Ausführen der jeweiligen Zeile statt. Scripte, die lange gut laufen, können plötzlich Syntaxfehler bringen, weil ein if jetzt False statt True liefert. Perl oder PHP sind da die bessere Wahl.
MfG Klebwax
peterfido
24.08.2012, 20:50
Hallo,
danke für die Informationen. auf fork() war ich auch schon gestossen, jedoch habe ich es nicht angewendet, da in der Beschreibung stand, dass mein Programm als Kopie erneut geöffnet wird und auch alle Parameter soweit übernimmt. Da wusste ich dann nicht, ob dann evtl. die ganzen Routinen nochmals ausgeführt werden oder nicht. Meine Motivation es herauszufinden war gleich Null und so habe ich mich für (erstmal) 3 Programme entschieden, welche soweit prima zusammenarbeiten. Oder halt auch mein Programm in drei Teile geteilt, je nachdem, wie man es sehen möchte.
Wenn bei BASH am Ende das & quasi zu einem fork() macht, dann hätte mir das eh nicht weitergeholfen, da ich ja den Umweg über eine BASH ein Programm mittels & Parameter probiert habe, was das ursprüngliche Programm auch blockiert hat.
Die vom gcc compilierten Programme benötigen laut TOP etwas weniger CPU Rechenzeit. BASH wäre auch gegangen, aber das Empfangen über die UART hatte Probleme bereitet. Ich wollte ja solange Empfangen, bis ein CR erkannt wird und dann den String auswerten und nebenbei weiterempfangen. Das Problem am Raspi war, dass bei jedem öffnen der UART ein CHR(255) beim AVR ankam. Was für mich eher nach einem unkontrollieren PIN Zustand aussah.
Durch das C-Programm habe ich das Sympton nicht. Da kommt nur beim allerersten öffnen der ttyAMA0 ein CHR(255) am AVR an und der wird dann einfach ignoriert. Die Dateirechte gleich beim öffnen mit anzugeben, war auch eine meiner Ideen, jedoch die Suche im Netz nach den richtigen Parametern erfolglos. Und da ich bei jeder Suche nach ein paar erfolglosen Treffern keine Motivation zum Fortsetzen dieser habe, breche ich dann irgendwann diese ab, wenn ich schon einen Umweg im Hinterkopf habe.
Hauptsache es funktioniert so, wie ich es mir vorgestellt habe. Ob am Ende mein Programm gleich die Rechte setzt, oder diese Aufgabe an das System delegiert, ist mir dann egal. Hauptsache das php Script kann darauf zugreifen (und auch überschreiben, was aber nicht nötig ist, da der AVR eh jeweils die Änderung zurückmeldet). Denn wenn ich die Lichtfarbe über Fernbedienung per AVR ändere, soll halt im WebIf des Raspi diese auch tatsächlich angezeigt und natürlich auch geändert werden können.
Das parsen konnte ich wieder herausnehmen, denn meine Suche hatte ergeben, dass man "text\"text" in einem String verwenden soll, damit die Hochkommas angezeigt werden. Geholfen hatte dann tatsächlich aber "text 'text.
Hilfetexte und die Möglichkeit eine andere Schnittstelle und Baudrate per Parameter mit zu übergeben hatte ich erst geplant, dann aber wieder herausgenommen. Durch den veröffentlichten Code kann sich dann jeder selbst diese Werte anpassen.
Wobei der Code durchaus Kritikfähig sein kann, ich diese aber wenn, so wie du es gemacht hast, lieber hier bespreche als in dem Internetradio-Thema. Der dort veröffentlichte Quelltext hat bestimmt auch einige #Includes zuviel, meine Tests haben aber ergeben, dass gcc diese dann einfach nicht mit einbindet, da die fertigen Programme die selbe Größe hatte, wenn ich mal probehalber welche auskommentiert hatte.
Was wo in welcher Include zu finden ist, ist mir noch nicht so klar. Da bin ich aber schmerzfrei, wenn es am Ende funktioniert. Die von mir veröffentlichten Quellcodes sehe ich da eher als Inspiration an. Ich meine aber, bei meinen Ausflügen zu c++ etwas mehr Komfort gehabt zu haben. Da lassen sich z.B. Strings einfach per + verbinden, wenn ich mich richtig erinnere. Aber deswegen heisst es ja auch C++ und nicht mehr nur C.
C an sich mache ich nicht dafür verantwortlich. Eher die Vielfalt an doch recht ähnlichen Sprachen, wo ich das dann schon als Dialekt durchgehen lassen würde. Da ist es halt wie überall sonst auch. Jeder hat da seine eigenen Vorstellungen und auch im Programmieren bzw. der Entwicklung der Sprachen dazu ist Bewegung. Was durchaus Sinn macht, denn was ich für einen Webserver an Befehle benötige, brauche ich nicht unbedingt für eine Kaffeemaschine. Hätte ich damals nicht mit C64 Basic(V2), Amiga Basic/V7??), QBasic(V4??) und später Visual Basic (6 ist da mein Favorit) angefangen, sondern gleich mit C und Co, würde ich mich jetzt wohl schwer tun, VB Code an meine Bedürfnisse anzupassen.
Aber die Programme sind soweit fertig und jetzt geht es erstmal wieder an die Hardware. Die Soundqualität des analogen Anschlusses ist irgendwie nicht 100% HiFi tauglich. Jetzt teste ich erstmal die nächsten Tage über HDMI, wie da der Ton so ist und vor Allem, ob ein Bufferunderrun vorkommt, denn der Alsa Takt scheint minimal zu schnell zu sein, da der Buffer nach einiger Zeit leer läuft. Leider habe ich nirgends herausgefunden, wie ich diesen Takt beeinflussen kann. Selbst ein Underclocking nutzt nichts, da der Soundteil wohl separat getaktet wird und ich an diesen Takt einfach nicht rankomme. Da ist meine Hoffnung, dass digital übertragen der Empfänger für das Takten zuständig ist. Rauschen und die kleinen Knackser sind über HDMI jedenfalls nicht vorhanden. Leider kostet ein einfacher HDMI>Analog Adapter soviel wie der ganze Raspi. Es gibt noch einen für 19 EUR, dieser wird aber per HDMI gespeist, das möchte ich dem Raspi nicht antun.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.