Hallo Leutz mit folgendem kleinen Codesnippet habe ich so meine
Probleme. Bei der Simulation bleibt die Schleife hängen. Wenn ich nur
mit j!=54 arbeite läuft das Programm in 1400µs durch. Wenn ich das
komplette Array nehme dann läuft das Programm 7000µs und startet dann
einfach neu ( anfang int main). Im array keine besondere stelle Wert
Umlaufdauer[55] ist 2308. der Wert für für zzp[0-80] ist immer gleich 0.
int zzp_init()
{
for(uint8_t j=0;j!=80;j++)
{
zms[j] =(loadtime +(umlaufdauer[j]/360)*((vorzuendung+zzp[j])/5));
}
return 0;
}
Warum schmiert mir die schleife ab ?
Watchdog ist nicht aktiv.
mfg Jan
Nee, geht auch so... und wenn schon, dann j < 80 :-)
Manax schrieb:
> der Wert für für zzp[0-80] ist immer gleich 0.
Warum addierst Du ihn dann? ;-)
zzp[0-80] würde ja bedeuten, dass das Array 81 Werte hat... aber Du
hörst ja bei 79 auf, da kann also nix überschrieben werden. Es sei denn
vielleicht zms[] oder umlaufdauer[] wären kleiner.
Naja die Werte kann ich dann später noch eintragen die werte für zzp.
Kann das ein Problem mit vollem speicher sein der AVR attestierte mir
137,5% ROM frei. Und im Prinzp wollte ich auch nur umgehen, dass ich den
Wert im Programm ausrechne. Die Berechnung dauert leider 50µs im
Programm gibt es irgendeine Möglichkeit
coilstatus_on = allticks - (loadtime
+(allticks/360)*((vorzuendung+zzp[i])/5));
Diese Rechnung schneller zu meistern ?
mfg Jan
Jan schrieb:
> Naja die Werte kann ich dann später noch eintragen die werte für zzp.> Kann das ein Problem mit vollem speicher sein der AVR attestierte mir> 137,5% ROM frei.
lol
137% vom ROM können nicht frei sein.
Entweder es ist komplett frei, dann ist es zu 100% frei.
Oder es ist komplett belegt, dann ist es zu 100% belegt.
Oder aber dein Programm ist so gross, dass es nicht mehr ins ROM passt.
Dann belegt es 137% vom ROM (was aber nicht geht, denn bei 100% ist
Schluss. Mehr passt nicht rein).
Nein.
Fakt ist, daß du hier nur Fragmente deines Programms zeigt,
eine grottige Beschreibung des Rests und des Verhalten
lieferst und ich nach mehrmaligem Durchlesen nicht weiß,
was hier passiert.
So wird das nichts.
Alles andere ist nicht Fakt sondern Spekulation.
Hilfreich wären:
- ganze Quelltexte
- ganze + verständliche Sätze
- korrekte Aussagen
Hallo Leutz
@ Klaus ich hab mir die komplette Seite nochmal durchgelesen und ich
weiß beim besten Willen nicht wo ich so undeutlich formuliert haben
soll, dass man es beim durchlesen nicht versteht.
int zzp_init()
{
for(uint8_t j=0;j!=80;j++)
{
zms[j] =(loadtime +(umlaufdauer[j]/360)*((vorzuendung+zzp[j])/5));
}
return 0;
}
es geht um diesen bereich Bei dem LOADTIME um eine konstante mit dem
Wert 1600. Bei UMLAUFDAUER handelt es sich um ein Array mit 81 Werten
im Bereich von 15000- 2000. VORZUENDUNG ist ein konstanter Wert (
Range: 0-200).
ZZP ist ein Array mit 81 Werten passendend zur Umlaufdauer ( alle Werte
im Moment 0 Werten ( zu testzwecken)).
Die erste Möglichkeit die ich gefunden habe wäre
zms[j] =(loadtime +((umlaufdauer[j]*(vorzuendung+zzp[j])/1800));
Bringt aber leider keinen Erfolg die Schleife bleibt immer noch hängen.
Die Zweite Möglichkeit ist die Errechnung in Echtzeit.
for(uint8_t i=81,i!=0,i--)
{
if (umlaufdauer[i]>=allticks)
{
Errechnung des Zzps hier im laufenden
Betrieb
test1=umlaufdauer[i] // testweise Ausgabe
break;
}
}
Wenn ich jetzt allerdings allticks = 15000 setze dann nimmt i den Wert
33 an ( der nicht stimmt ) da das Array Umlaufdauer[i] an dieser Stelle
den Wert 3000 hat und das ist ja net größer als 15000 und test1 nimmt
komischerweise den Wert 15000 an obwohl das Array eigentlich als
const uint16_t Umlaufdauer[81] PROGMEM = {
..
3300 // 33igste Stelle.
..
};
Außerdem braucht der Programmteil mit der for-if Schleife ca 220µs bei
20 Mhz. Sodass ich mir sicher bin, dass ich irgendeinen Fehler gemacht
habe.
Nur wo liegt er?
p.s Ich würde auch den kompletten Source posten aber so ist es glaub ich
einfacher, da ihr euch nicht erst komplett einarbeiten müsst ( ist recht
lang ).
Bitte helft mir ^^ ich hab gar keinen Schimmer was ich da jetzt falsch
mache.
mfg Jan
Manax schrieb:
> p.s Ich würde auch den kompletten Source posten aber so ist es glaub ich> einfacher, da ihr euch nicht erst komplett einarbeiten müsst ( ist recht> lang ).
Das Problem ist, dass der Fehler oft nicht dort sitzt, wo du denkst dass
er sitzt. Aus dem bisher geposteten kann man herzlich wenig sagen,
ausser dass du auf PROGMEM Sachen so nicht zugreifen kannst. Aber das
alleine ist kein Grund für eine 'hängende Schleife' (an die ich sowieso
nicht glaube, da passiert mit Sicherheit irgendetwas anderes, du
interpretierst nur die Symptome falsch)
hier mal ein Beispiel wie du deinen array UMLAUFDAUER lesen mußt wenn du
ihn mit Progmem im flash hast.
read_pgm_byte(¨aufdauer[3])
probiere doch mal all deine werte auszugeben auf RS232 (falls vorhanden)
dann siehst du ob deine zugriffe richtig sind oder du nur auf adressen
zugreifst.
wie schon mehrfach vorgeschlagen: Zeig mal (den vollständigen)
Quellcode, ohne geht nichts. Die pgm_read*() brauchts auf jeden Fall,
das dürfte aber wie schon gesagt nicht zum Verrecken beitragen sondern
nur zu falschen Berechnungen.
Zwei klitzekleine Vermutungen hab ich noch: Ist "zms" auch im PROGMEM
(von hinten durch die Brust ins Auge funktioniert das (aber halt nicht
richtig))? Oder: Geht Dir möglicherweise der Ram aus?
Ok jetzt hab ichs mal andersrum gemacht um dieses Problem zu lösen.
((calcticks>>10)-(calcticks>>11)) mit calcticks im bereich von
1667-15000 leider kommt bei dieser Rechnung eine Zahl raus mit der ich
mal so gar nichts anfangen kann. Denn bei dieser division 1/1024-1/2048
kommt mit calcticks ein wert von ca 0,81... raus leider interpretiert
das Programm das als 1.
Wie bekomme ich hier eine erhöhte Genauigkeit hin ( 3-4 Stellen nach dem
Komma) und ohne in der Rechnung zu dividieren( dauert zu lange ) ohne
den Speicher zu sprengen.
mfg Jan
Vielleicht kann Dir der Artikel Festkommaarithmetik weiterhelfen.
Und vielleicht möchtest Du - immer noch - Deinen Programmcode hier
hochladen, so dass man Dir vernünftig helfen kann.
Manax schrieb:
> a/2 = 1/2 = 0.5 das ist aber net der Wert den ich brauche.
Mag sein.
Aber letztenedes ist das genau das was du berechnest
((calcticks>>10)-(calcticks>>11))
ist identisch zu
(calcticks>>11)
egal, wie gut du das versteckst. Und das wiederrum ist identisch zu
calcticks / 2048
(wenn calticks ein unsigned Wert ist). Und genau so (also mit Division)
solltest du das auch schreiben und da nicht lange rumkünsteln. Dann
sieht man nämlich was Sache ist. Wenn die Division durch Schieben
ersetzbar ist, dann macht das der Compiler ohnehin.
Im Anhang hab ich jetzt mal den Source hochgeladen.
Mit dem Beispiel aus der Festkommaritmetik dauert die Schleife wenn ich
1667 als allticks nehme leider 129 µs schöner wären weniger, da es sich
um eine zeitkritische Schleife handelt.
Ich habe schon das Teilen durch 1800 versucht ( 100µs ) .
Das verschieben ( Zahl wird zu klein und zu stark gerundet).
Könnt ihr mir weiterhelfen ?
Erreichen würde ich gerne einen Wert von ca 20-50 µs .
mfg Jan
Puh.
Der Code ist .... nun ja ...
Wenn das beschleunigt werden soll, wäre es vielleicht gut, wenn du
erzählen würdest, was das wird, was die Grundlagen dafür sind und welche
Idee im Programm verfolgt wird.
Das Programm ist nun ja... weils mein erstes ist. Ich geb kurz die
wesentliche Funktion wieder.
Timer triggert alle 4 µs und erhöht tick immer um 1. Wenn der externe
Interrupt triggert wird hall auf 1 geschaltet und in der main schleife
wird das programm checktick ausgeführt. Dieses prüft anhand einer
Routine ob OT des Motors erreicht wurde und speichert die komplette Zeit
der Umdrehung.
Wenn Ot des Motors erreicht wurde dann wird das Programm choosetable
ausgeführt.
Dieses wählt anhand der kompletten Zeit der Umdrehung einen
entsprechenden Zündzeitpunkt aus.
Das Problem ist nun meinen Wert vorzündung ( in Grad ) + den Wert
Zündzeitpunkt (in Grad ) in µs umzurechnen.
Daher die Routine ztimer= allticks -( loadtime +
(allticks/(360*5))*(ZZp+Vorzündung)
Ztimer wird dann in der mainroutine geprüft und wenn er übereinstimmt
dann wird die Zündspule geladen. allticks sind die µs*4 der Umdrehung.
loadtime ist die Ladezeit der Spule in µs/4 (allticks/360*5) rechnet
µs*4 / 0.2 Grad um und verrechnet es dann mit zzp und vorzündung.
Die If-Schleifen in choosetable brauchen alleine 30µs im schlechtesten
Fall.
Leider finde ich keine bessere Möglichkeit das zu Verbessern, da hier ja
immer allticks>= Wert geprüft werden muss.
Die anderen 70µs im schlechtesten Fall gehen für die Rechnung drauf.
Daher hab ich es wie oben schon erwähnt noch nicht verbessern können.
Der Grund warum es möglichst schnell gehen soll ist, dass der Motor ja
nur ca 13µs pro 1 Grad braucht bei ca 13000 Umdrehung. Das lässt sich
natürlich über das Zündkennfeld verrechnen es wäre nur eleganter wenn es
halt möglichst schnell geht.
mfg Jan
Manax schrieb:
> Routine ob OT des Motors erreicht wurde und speichert die komplette Zeit> der Umdrehung.> Dieses wählt anhand der kompletten Zeit der Umdrehung einen> entsprechenden Zündzeitpunkt aus.
OK.
Soweit ist das klar.
Du willst den Zündzeitpunkt an die gemessene Drehzahl anpassen.
> Das Problem ist nun meinen Wert vorzündung ( in Grad ) + den Wert> Zündzeitpunkt (in Grad ) in µs umzurechnen.
Warum musst du das umrechnen?
Kannst du nicht einfach eine Tabelle nehmen, in der der Zündzeitpunkt in
Abhängigkeit von diesem Winkel für, sagen wir alle 4 Grad (4 .. wegen
2-er Potenz), abgelegt ist?
Dann brauchst du so gut wie gar nichts rechnen. Kostet ein wenig
Speicher, aber was solls.
> Leider finde ich keine bessere Möglichkeit das zu Verbessern, da hier ja> immer allticks>= Wert geprüft werden muss.
Ich hab das jetzt nicht kontrolliert ob das geht. Aber wenn du deine
Abhängigkeit von der Drehzahl auf zb vielfache von 256 beschränken
könntest, könnte man dann auch dort wieder eine einfache
Tabellenindizierung machen.
> Der Grund warum es möglichst schnell gehen soll ist, dass der Motor ja> nur ca 13µs pro 1 Grad braucht bei ca 13000 Umdrehung.
Seh ich ehrlich gesagt nicht ganz ein.
Der Motor ändert ja seine Drehzahl nicht wesentlich bei einer einzigen
Umdrehung. Wenn also der veränderte Zündzeitpunkt eine Umdrehung zu spät
kommt, ist das sicherlich auch kein Beinbruch. Vom Zeitpunkt des
Feststellens des OT hast du eine komplette Motordrehung Zeit, den neuen
Zündzeitpunkt auszurechnen und erst im nächsten OT aktivierst du ihn
(und startest die Berechnung erneut mit dem dann gemessenen Wert für die
nächste Umdrehung)
Uiui danke für die schnelle Antwort.
zu 2 )
Die Zeit die der Motor für ein Grad braucht ist ja abhängig von der
Drehzahl.
Ich wüsste jetzt gerade net wie man da nen guten ZZP hinbekommt ohne das
man ausrechnet wieviel µs dem gewollten zzp entsprechen.
zu 3)
könntest du das mit der Tabellenindizierung genauer erklären?
meinste sowas wie
for (uint8_t i=0, i<=Maximalwert, i+256) { mach was ? }
zu 4)
Gemeint ist den ZZp möglichst präzise zu errechnen. Wenn die Rechnung
sehr lange dauert ist es schwieriger den ZZP zu treffen sagen wir von
13° vor OT, 13µs zu spät würde bedeuten man zündet erst 12° vor OT.