Klaus schrieb:> Kann ich einfach rechnen:
Ja, kannst du. Auch
1
OCR1A+=20;
geht. Das Register hat lesend und schreibend 16 Bit, und man liest auch
den gleichen Wert zurück, den man rein geschrieben hat.
Allerdings würde ich mehrfache Operationen (wie Addition und Vergleich)
dann doch in einer Zwischenvariablen durchführen, denn erstens
produzierst du sonst im ungünstigsten Falle Glitches, zweitens werden
die verschiedenen Operationen dann in CPU-Registern durchgeführt statt
in den (langsameren) IO-Registern.
Klaus schrieb:> Habe das jetzt drin:if (!(PINA & (1<<PINA1))) // links drehen> { // Start bei 275> uint16_t ocr1b = OCR1B;> if(ocr1b < 550)> { // Begrenzung links = 550> ocr1b = ocr1b + 20;> OCR1B = ocr1b;> }> }> Beim betätigen des Tasters geht der Servo sofort auf Endwert (550). Es> gibt keine Zwischenwerte.
Naja, nicht ganz. Kommt drauf an, wie oft die Funktiona ufgerufen wird.
Aber im Prinzip hast du Recht, man sollte schon sowas wie eine
Flankenerkennung und ggf. auch Entprellung einbauen. Dann springt
der Wert nicht zum Anschlag, sondern man kann einzelne Stufen
einstellen.
Klaus schrieb:> sofort auf Endwert (550). Es gibt keine Zwischenwerte.
Wie schnell ist "sofort", womit hast du das getestet?
Ansonsten müsste man halt ein Stück mehr von deinem Programm sehen um zu
wissen, wann/wie oft du diese Rechnung ausführst.
> Beim betätigen des Tasters geht der Servo sofort auf Endwert (550). Es> gibt keine Zwischenwerte.
Doch, die gibt es natürlich. Du merkst bloß nichts davon, weil der Code
ja sehr wahrscheinlich in einer Schleife (z.B. der Hauptschleife des
Programms) aufgerufen wird. Da braucht es dann nur 13
Aufrufe/Schleifendurchläufe und der Endwert ist erreicht. Wenn weiter
kein Code in der Hauptschleife ist, geht das sehr, sehr schnell.
Dazu kommt dann, dass neue Werte in den OCR-Registern in den PWM-Modi
immer nur einmal pro PWM-Zyklus in die Hardware übernommen werden. Von
den 13 Aufrufen des Codes bleiben also bei sonst leerer Hauptschleife 11
bis 12 effektiv unwirksam. Die Hardware sieht nur den Endwert und zuvor
eventuell noch einen Zwischenwert, der dann 20ms später durch den
Endwert ersetzt wird.
Oder anders ausgedrückt: du musst dringend die Architektur deines Codes
überdenken...
c-hater schrieb:> du musst dringend die Architektur deines Codes> überdenken...
Wenigstens solltest du warten, das die Taste wieder losgelassen wird.
Das ist immer noch nicht optimal, weil jeder mechanische Taster prellt,
aber schon mal ein Schritt nach vorne. Als nächstes könntest du dich mit
Tastenabfragen beschäftigen, die wirklich funktionieren:
https://www.mikrocontroller.net/articles/Entprellung
Habe nicht erwartet das der Code so schnell ist. Habe jetzt noch delay
drin und es ist deutlich zu sehen.
Werde eine einfache Entprellung mit _delay(20) erst mal verwenden. Wenn
der Rest läuft kommt die Entprellung von Peter.
Danke für eure Hilfe.
Matthias S. schrieb:> Wenigstens solltest du warten, das die Taste wieder losgelassen wird.> Das ist immer noch nicht optimal, weil jeder mechanische Taster prellt,> aber schon mal ein Schritt nach vorne. Als nächstes könntest du dich mit> Tastenabfragen beschäftigen, die wirklich funktionieren:> https://www.mikrocontroller.net/articles/Entprellung
Wäre eine Möglichkeit, aber eine dramatisch aufwändige und umständliche
für den beabsichtigten Effekt. Sehr viel einfacher wäre es, den
ansonsten unveränderten Code mit einer kleinen Sache zu ergänzen,
nämlich der Abfrage und dem Reset des Overflow-Interruptflags des
Timers.
if (is_ovfflag_set())
{
[bestehender Code]
reset_ovfflag();
}
Schon ist sichergestellt, das der bestehende Code maximal alle 20ms
aufgerufen wird und mit dem berechneten Wert auch tatsächlich etwas
bewirkt wird. Ganz ohne aufwendige und hier auch völlig unnötige
Entprellung.
c-hater schrieb:> Wäre eine Möglichkeit, aber eine dramatisch aufwändige und umständliche> für den beabsichtigten Effekt.
So dramatisch aufwändig und umständlich ist Copy&Paste für dich?
Immerhin ist das ein Stück solider Code für den Baukasten und kann immer
wieder mal benutzt werden. Und lernen kann man immer etwas.
Matthias S. schrieb:> So dramatisch aufwändig und umständlich ist Copy&Paste für dich?
Naja, zwei simple Zeilen Code zu schreiben ist auf jeden Fall schneller
erledigt.
> Immerhin ist das ein Stück solider Code für den Baukasten und kann immer> wieder mal benutzt werden.
Natürlich ist das guter Code und man kann ihn überall dort verwenden, wo
er nützlich ist. In dieser konkreten Anwendung ist er es aber nicht.
> Und lernen kann man immer etwas.
Jepp. Nur gibt es da diese Baustein-C&P-ler, die nix lernen wollen. "Ich
hab' doch schon meinen Hammer, alles andere wird damit zum Nagel
gemacht, koste es, was es wolle..."
c-hater schrieb:> if (is_ovfflag_set())> {> [bestehender Code]> reset_ovfflag();> }
Danke für deine Info. Das kannte ich bisher nicht. Da werde ich mal das
DB genau anschauen, da ich es noch nie gesehen habe.
Klaus schrieb:> Habe jetzt noch delay drin und es ist deutlich zu sehen.
Falls sonst noch irgendetwas in deinem Code ablaufen soll, ist delay()
sicher die schlechteste Möglichkeit. Zum Test mag das ok sein.
Besser steuerst du den Zeitablauf aber z.B. durch Abfrage des
System-Timers, d.h. über millis().
und rufe das in der Hauptschleife auf. So wird ein festes Zeitraster
gemacht - wenn Timer0 läuft. Im Datenblatt steht, wo die Bits liegen.
Hier isses ein Tiny25/45/85.
c-hater schrieb:> if (is_ovfflag_set())> {> [bestehender Code]> reset_ovfflag();> }
Habe zu diesem Code nichts gefunden. ovfflag wurde bei mir als Fehler
angezeigt. Muss ich dazu eine bestimmte Bibliothek laden?