Ich hoffe es traut sich jemand Ich habe an einem ATmega8 an Port B und D 16 LEDs hängen, die je nach Effekt in irgendeinem Muster (alle an, alle gleichzeitig blinken, zufälliges linken, Lauflicht u.a.) leuchten. Da die Effekte mit verschiedenen Geschwindigkeiten laufen sollen, gibt es an Port C 2 Taster für schneller/langsamer. Intern wird dann eine Variable zwischen 0 und 255 verändert. Wenn ich den Wert direkt ins OCR2 füttere (Timer2 läuft im CTC-Mode), dann ist das Verhalten nicht gerade toll (z. B. von 20 auf 10 => Effekt doppelt so schnell, von 220 auf 210 => fast keine Änderung bemerkbar; beides sind aber zehn Einstellungsschritte). Kleine Anmerkung: ich verwende nachher 256, obwohl nur 255 in die Register passt. Das ist aber zum Rechnen bequemer. Wünschenswert ist ein Verhalten, bei dem sich die Geschwindigkeit exponetiell ändert: s(speed) = wert_für_ocr2 s(0) = 256 s(128) = 16 s(256) = 1 Das lässt sich ganz leicht berechnen: 256 >> (speed >> 5). Das Problem dabei ist: so kommen insgesamt nur 8 unterschiedliche Schritte heraus, wobei sich jedesmal die Geschwindigkeit verdoppelt. Deswegen ist meine nächste Lösung, das 256 vor dem Shiften durch einen anderen Wert zu ersetzen, je nachdem was in Bits 3 und 4 von speed steht. In Assembler sieht das dann so aus: ################### Oh grade gelesen, dass man den anhängen soll. Also siehe Anhang... ################### Das sind schon einige Schritte mehr, aber dafür schon ein ganze Menge Code. Ich habe noch nicht so viel in Assembler gemacht. Gibt es da eine Möglichkeit den selben Effekt übersichtlicher und schneller zu erreichen, ohne gleich eine Tabelle im EEPROM zu verwenden?
Du musst die Tabelle ja nicht ins EEPROM schreiben, sondern kannst auch den Flash verwenden... In so einem Fall ist eine Tabelle wirklich das allereinfachste. Eigentlich brauchst Du eine 1/x - Funktion, wenn ich das richtig durchblicke.
Die Exponentialfunktion ensteht, wenn man die Frequenz von Stufe zu Stufe mit einem konstanten Faktor multipliziert, d.h. den Timerwert durch einen konstanten Wert dividiert. Das kann man mit einer Tabelle machen ,aber auch einfach on-the-fly berechnen: Damit man genug Auflösung hat, bietet sich hier eine 16x16 Fixedpoint-Arithmetik an. Vom 32-Bit-Ergebnis verwendest Du die 8 höchsten Bits für den Timer. Z.B. für 12 Schritte für ein Frequenzverhältnis 10:1 ist die Konstante 1,21153 (wie in der E12-Reihe für Widerstände): für die eine Richtung addierst Du das 0,21153-fache, indem Du mit 0,21153*65536=13863 multiplizierst und zum Grundwert addierst. für die andere Richtung multiplizierst Du mit dem Kehrwert 0,8254*65536=54094 Schritt F 8bitTeiler 0 1,00 255 1 1,21 210 2 1,47 174 3 1,78 143 4 2,15 118 5 2,61 98 6 3,16 81 7 3,83 67 8 4,64 55 9 5,62 45 10 6,81 37 11 8,25 31 12 10,00 25 Eine ganz andere Methode wäre die Erzeugung des Tabellenindexes wie bei der DDS (direkte digitale Synthese) durch regelmäßige (mit z.B. 10kHz) Addition mit einer Konstanten, welche proportional zur gewünschten Frequenz ist.
Danke für die Antworten! Ich habe mir die Lösungen angesehen. Die Fixed-Point-Lösung braucht mir zu viele Register und auch Rechenzeit, obwohl sie eigentlich am sichersten (vor Programmierfehlern) und sehr leicht an andere Raten pro Schritt anpassbar ist. Aber da der speed-Wert auch immer wiedermal direkt gesetzt werden kann und nicht nur um eins nach oben oder unten geht, könnte das im Extremfall 255 Multiplikationen hintereinander bedeuten. Die DDS braucht ja auch eine Tabelle. Wenn ich keine verwende nicht ergibt sich durch Addieren keine a^x sondern nur eine a*x Funktion, was das inverse der 1/x Funktion ist. Und bei beiden ergibt sich nicht das gewünschte Verhalten, dass sich bei gleicher Schrittanzahl (z. B. 5mal + drücken) die Geschwindigkeit immer um den gleichen Faktor ändert. Im Endeffekt werde ich doch eine Tabelle mit 64 Werten, allerdings im Flash, nehmen. Das scheint in dem Fall tatsächlich die beste Lösung zu sein und ist ein guter Kompromiss zwischen Auflösung, Speicherverbrauch und Rechenaufwand zu sein. Außerdem habe ich gemerkt, dass ein OCR2 Wert von 1 sowieso viel zu wenig ist, da dann nur noch alles flackert. Mit einer Tabelle kann ich die speed-to-OCR2-Werte leichter von z. B. 10 bis 255 exponteial verteilen. Aber ich merke mir die Vorschläge, falls eine Vorberechnung mal nicht möglich ist!
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.