Hallo,
Habe ein kleines Verständnis Problem. Programmiere momentan eine
Regelung für ein Modelltriebwerk. Gerade bin ich beim Start. Ich lasse
mir sekündlich die Temperatur und die Drehzahl des Triebwerks ausgeben.
Der Anfang des Starts läuft ohne Probleme, komme ich jedoch in meine
zweite while Schleife so bricht das Programm ab und der Mikrocontroller
startet es komplett neu. In dieser Schleife lasse ich mir im gleichen
String auch noch den aktuellen PWM-Wert ausgeben. Lasse ich den PWM-Wert
in einem eigenen String ausgeben funktioniert das Programm wieder ohne
Probleme. Kann es sein, dass der String durch die weiteren Zeichen zu
lang wird und der Controller damit nicht umgehen kann?
Gruß Andreas
1. ist das Programm nicht vollständig; das macht so keinen Spaß.
2. Wie willst du von der ersten in die zweite Schleife kommen, wenn die
erste endlos ist? Hast du soviel Geduld?
PS: sehe gerade, daß die erste while-Schleife ja gar nicht vor der
zweiten endet; mein 2. Punkt ist also Blödsinn.
Dafür könntest du das Programm mal sinnvoll formatieren, damit man es
verstehen kann :-)
Sagt dir das Stichwort "Stack Overflow Reset" irgendwas? Wäre das eine
Möglichkeit. Wie das jetzt genau bei deinem Mikrocontroller heißt weiß
niemand - du sagst ja auch nicht welchen du verwendest.
- gesamter Schaltplan
- gesamter Sourcecode
- alle Fuses
Selbst nach einem Formatieren ist das Programm ziemlich wirr.
Lesbar ist etwas anderes....
So ein Kommentar ist vollkommen sinnlos:
while (1) //Unendliche Schleife
Dafür wären sinnvolle Kommentare hilfreich oder vernünftige Namen statt
i und s.
Etwas wie:
PORTF &= ~(1<<PF7);
könnte mit lesbaren Namen auch ziemlich gewinnen.
Es wäre erstmal dein Job, das Ganze verständlich zu machen, bevor hier
jeder anfängt zu rätseln.
"programmteil 1":
// Wenn Triebwerk über 9000RPM, EGT über 100°C und Zündung erkannt
Kerosinventil auf
bzw. folgendes soll scheinbar zur Programm-Termination führen
// Wenn Taster gedrückt gehe in Schleife
// 15ms warten
// Wenn Taster immernoch gedrückt dann Autostop einleiten
Danach folgt "programmteil 2"
// Wenn Taster gedrückt gehe in Schleife
// 15ms warten
// Wenn Taster immernoch gedrückt dann Autostop einleiten
bzw.
// Sicherung gegen Übertemperatur
o.
// Sicherung gegen hängengebliebenden Start
führen in "programmteil 2" zur Terminierung?!
Vermutung: deine Variable char s[45] wird überrant. Du solltest sie
vielleicht auch mal clearen. Die Vermutung kommt dadurch das du jedesmal
strcat (s ...also jedesmal nur anhängst.
Meine Vermutung wird gestärkt durch:
Andreas H. schrieb:> Lasse ich den PWM-Wert> in einem eigenen String ausgeben funktioniert das Programm wieder ohne> Probleme.
Folglich ->
Lehrmann Michael schrieb:> Sagt dir das Stichwort "Stack Overflow Reset" irgendwas?
Die Anmerkungen, das alles ein wenig übersichtlicher zu machen, haben
etwas für sich.
Ein paar5 Tips:
Es lohnt sich meistens, große Funktionalitätsblöcke in Funktionen
auszulagern.
Du musst keinesfalls erst einmal alle deine Ausgaben in einen einzigen
String zusammenpfriemeln, ehe du dann diese String irgendwo ausgibst.
Die UART hat kein Problem damit, wenn du einfach nacheinander
Einzelstrings ausgibst. Die Anzeige (Terminal) kann sowieso nicht
unterscheiden, ob du jetzt im Programm alles in einem String
zusammengepfercht hast oder ob der Text den es anzeigen soll aus
meherern Ausgaben stammt
1
chara[8]=" Stop1 ";
2
uart_puts(a);
Du brauchst hier kein Zwischenarray. Es ist absolut kein Problem, den
String einfach direkt an uart_puts zu übergeben
1
uart_puts(" Stop1 ");
Aber wenn du solche Arrays hast, dann ist es am besten den Compiler die
Zeichen zählen zu lassen. Die Arraygröße selbst anzugeben, wenn man es
nicht muss, ist erstens langweilig und zweitens fehleranfällig. Der
Compiler kann zuverlässiger zählen als du. Und er macht es bei jedesmal
übersetzen wieder aufs neue.
Funktionen wurden schon angesprochen. Sie sind dein Werkzeug, mit der du
scheinbare Komplexität aus dem Programm rausholen kannst. Wenn zb die
Anzeigesequenz (also das was du ausgibst) immer gleich ist UND dann auch
noch an 2 Stellen vorkommt, dann ist es eine gute Idee, dafür eine
eigene Funktion zu machen. Zb der ganze Teil, der sich damit beschäftigt
eine Temperatur auszugeben.
Brich dein Programm etwas auf, mach es übersichtlicher, keine
Monsterfunktionen. Und du wirst sehen, dass sich einige Probleme durch
die bessere Übersicht ganz von alleine in Luft auflösen. Das eigenartige
ist nämlich: die Programmierer mit den unüberisichtlichsten Programmen
sind oft auch die mit den seltsamsten Fehlern. In diesem Sinne ist ein
optisch schöner und überischtlicher Quelltext nicht einfach nur
Selbstzweck, sondern erfüllt durchaus eine praktische Funktion.
Variablennamen sinnvoll wählen. Je kürzer ein Variablenname, desto
'lokaler' soll die Variable sein.
Ein Variablenname von 'i' ist für eine Variable, die die Drehzahl hält
nicht angemessen. i, j, k, l sind typische Variablennamen, wie man sie
in (kurzen) for-Schleifen benutzt. Dort sind sie die Laufvariable, die
irgendetwas durchzählt.
Erstmal danke für eure Antworten.
Hatte nur einen Ausschnitt des Programms geposted um die Übersicht (ich
weiß, dass die in meinem Programm sowieso schlecht ist) ein wenig besser
zu machen.
An die Sache mit den Zwischenarrays und den Variablennamen hab ich mich
schon gemacht und werde versuchen mich da in Zukunft zu bessern.
Einige Sachen in Funktionen auszulagern hatte ich auch schon geplant,
bzw auch schon angefangen. Wollte nur erst versuchen ob das Programm so
wie ich mir das wünsche überhaupt funktioniert.
Zur Sache mit dem Clearen. Kann mir einer kurz erklären wie das
funktioniert?
Gruß Andreas
So wie ich das stichprobenartig gecheckt habe, ist das Stringproblem
keines. Mit viel Geduld und Spucke findet man raus, dass du in der
Squenz
1
// Drehzahl in String umwandeln
2
ultoa(i,s,10);//Variable in Ascii-Zeichen umwandeln
3
strcat(s,"[1/min] ");//Leerzeichen einfügen
4
5
//Temperatur in String umwandeln
6
if(tc_erkennung==1)
7
{
8
strcpy(temp,"Kein TC");// Fehlermeldung wenn kein Thermoelemant angeschlossen
9
}
10
11
else
12
{
13
temp_to_string(temperature,temp);// In String umwandeln
14
}
15
16
strcat(s,temp);//Temperatur an String anfügen
17
strcat(s,"[C] ");//Leerzeichen einfügen
18
19
uart_puts(s);//Drehzahl und Temperatur ausgeben
20
21
DrehTemp=0;// Bestätigung das Ausgabe erfolgt ist
22
}
als erstes ein ultoa machst, welches implizit dafür sorgt, dass der
String wieder von vorne beschrieben wird. Aber eigentlich ist das
unnötig, wenn du erst mal eine etwas sinnvollere Aufteilung in
Funktionen machst. Ein nicht unerheblicher Teil der Entwicklungsarbeit
besteht darin, sich sinnvolle Hilfsfunktionen zu schreiben.
In deinem Fall macht die Version 1 und 2 keinen Unterschied, aber wenn
z.B.
ein uint16_t array wäre, würdest du ausserhalb des Speicherbereichs
schreiben.
Gruß
Jean Player schrieb:> ich meinte natürlich> memset(s, 0, sizeof(s) / sizeof(char));
Ein sizeof(char) is per Definition immer 1, ist also äquivalent zu dem
oben geposteten.
> In deinem Fall macht die Version 1 und 2 keinen Unterschied, aber wenn> z.B.> ein uint16_t array wäre, würdest du ausserhalb des Speicherbereichs> schreiben.
Nö? sizeof() liefert die Größe des Arrays in Bytes, memset() will die
Größenangabe auch in Bytes, das sizeof(s) klappt also immer, egal ob ein
char-Array oder uint16_t-Array.
> In deinem Fall macht die Version 1 und 2 keinen Unterschied, aber wenn> z.B.> ein uint16_t array wäre, würdest du ausserhalb des Speicherbereichs> schreiben.
Kleiner Tip.
Wenn du das so universell wie möglich haben willst, dann schreib es so
1
memset(s,0,sizeof(s)/sizeof(*s));
dann spielt es keine Rolle, welchen Datentyp s hat (solange es ein Array
ist). Das erledigt dann der Compiler für dich.