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).
Es war mir schon klar das net durch mein Programm zusätzlich 37,5 % frei geworden sind ..... Habs vielleicht etwas schlecht formuliert
Fakt ist ja nur, dass das Programm im Simulator trotzdem läuft ich kann mir nur leider nicht erklären warum die Schleife immer abschmiert
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
du mußt doch die PROGMEM read funktionen benutzen wenn du einen array progmem definierst ich glaub pgm_read oder so müßte das gewesen sein.
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:
> ((calcticks>>10)-(calcticks>>11))
Dieser Ausdruck lässt sich noch dramatisch vereinfachen, wenn man
bedenkt, dass gilt: a-a/2 = a/2
a/2 = 1/2 = 0.5 das ist aber net der Wert den ich brauche.
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
Als test für die Rechnung habe ich nur das letzte if im prog verändert ( das ist ja der Wert der maximalen Zeit ). 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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.