Hallo zusammen,
wie geht das?
Hier sind 3-Dateien, mit denen es gehen sollte :
Beitrag "Re: Tasterverarbeitung mit ARDUINO-C"
Habe mal alles in eine Datei im Anhang zu sehen gepackt.
Ich bekomme jedoch diese Fehlermeldung :
In file included from
C:\Users\Ich\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6
\cores\arduino/Arduino.h:30:0,
from G:\AVR-Projekte\Arduino\MEGA2560 Board\GLCD_ST
7920\Entprellen\GLCD_entprellen\GLCD_entprellen.ino:1:
G:\AVR-Projekte\Arduino\MEGA2560 Board\GLCD_ST
7920\Entprellen\GLCD_entprellen\GLCD_entprellen.ino: In function 'void
loop()':
GLCD_entprellen:76:1: error: expected unqualified-id before string
constant
ISR( TIMER1_COMPA_vect ) { // every 10ms
^
GLCD_entprellen:76:26: error: a function-definition is not allowed here
before '{' token
ISR( TIMER1_COMPA_vect ) { // every 10ms
^
GLCD_entprellen:96:26: error: a function-definition is not allowed here
before '{' token
void init_entprell(void) {
^
GLCD_entprellen:112:43: error: a function-definition is not allowed here
before '{' token
uint8_t get_key_press( uint8_t key_mask ) {
^
GLCD_entprellen:128:41: error: a function-definition is not allowed here
before '{' token
Bernd_Stein
Steve van de Grens schrieb:>> Unter LED_PORT = i; gehört eine zweite geschlossene Klammer "}". Danach> bekommst du die nächsten Fehler angezeigt.
1400 Beitraege und nie diesen Satz gelesen und verstanden:
Und immer schön hierdrann denken, so wie in diesem Fall, an *Punkt 4.*
"Die fünf universellen Forenregeln ;-)"
1. Threadüberschrift lesen
2. Evtl. Datum beachten
3. Posting verstehen
4. Falls nicht drittens, dann nachfragen oder Klappe halten.
5. Auf die Fragen eingehen und / oder Alternativen bzw. Verbesserungen
nennen.
Die Punkte kann man an einer Hand abzählen, man sollte also in der Lage
sein, bis fünf zählen zu können.
Deshalb sind sie evtl. gut zu merken, falls nicht dann nur Punkt 3 und
Punkt 4 merken.
Bernd_Stein
Bernd S. schrieb:> Hier sind 3-Dateien, mit denen es gehen sollte :>> Beitrag "Re: Tasterverarbeitung mit ARDUINO-C">> Habe mal alles in eine Datei im Anhang zu sehen gepackt.
Du bist echt selbst mit Kopieren überfordert. Geh zum Teich die Enten
füttern.
Es geht um einen Hand-Encoder in Verbindung mit PeDa's
Komfort-Entprell-Routine.
Warum wird der Text " Spur_A & Spur_B " angezeigt, wenn doch nur Spur_A
eine 1 vorweist?
Wie muss ich es richtig schreiben, damit nur bei Spur_A & Spur_B = 1 der
Text angezeigt wird?
Bernd_Stein
Bernd S. schrieb:> Ich hab es so wie hier gelöst, aber danke für deine Hilfestellung die> ich nicht verstehe, aber egal ich hab ja eine Lösung.
Du hast keine Lösung, du hast auch keine Ahnung. Und daran wird sich
auch zu deinen Lebzeiten nichts mehr ändern. Du stolperst nur vollkommen
planlos durch die Gegend in der irrigen Annahme, auch nur ansatzweise
was Sinnvolles zu programmieren.
Falk B. schrieb im Beitrag #7496114:
> Und täglich grüßt das Murmeltier. Unser Exemplar hier hat ordentlich was> an der Murmel!
Warum so unfreundlich zu einem unerfahrenen Newbie?
Bernd S. schrieb:> Michael P. schrieb:>> Versuch mal "&" (binär) anstatt von "&&" (logic)>>> Ich hab es so wie hier gelöst, aber danke für deine Hilfestellung die> ich nicht verstehe, aber egal ich hab ja eine Lösung.>> Beitrag "Re: Abfrage ob bits gesetzt in "C"">>> Bernd_Stein
Nei, in deiner originalen Abfrage testet du ob eine Variable gleich
einem Wert ist und gleichzeitig (logisches &&) ob das Ergebnis einer
Schiebeoperation ungleich Null ist. Letzteres ist bei dir immer der
Fall.
Im zitierten Beitrag wird getestet ob zwei Bits einer Variable (binär
'ver-und-tete'(&) mit Bitmaske) gleichzeitig (logisches &&) gesetzt
sind.
Georg schrieb:> gibt ja trotzdem Leute die nur alle Jubeljahre was programmieren> ...>
Das verstehen die nicht, die sind krank und lassen sich nicht helfen,
also ignorieren.
Bernd_Stein
Georg schrieb:> Falk B. schrieb:>> Und täglich grüßt das Murmeltier. Unser Exemplar hier hat ordentlich was>> an der Murmel!>> Warum so unfreundlich zu einem unerfahrenen Newbie?
Der einzige unerfahrene Anfänger (aka Newbie) bist du.
Falk B. schrieb:> Georg schrieb:>> Falk B. schrieb:>>> Und täglich grüßt das Murmeltier. Unser Exemplar hier hat ordentlich was>>> an der Murmel!>>>> Warum so unfreundlich zu einem unerfahrenen Newbie?>> Der einzige unerfahrene Anfänger (aka Newbie) bist du.
Ok Boomer! ;-)
Moin,
bei mir lese ich die Key Pins in der Arduino TIMER0 ISR mit einem
Huckepack Compare A Interrupt.
Dazu habe ich diese ISR hinzugefügt die im Hintergrund (Schmarotzerisch)
mit der Arduino TIMER0 ISR mitläuft:
ISR(TIMER0_COMPA_vect)
{
_keyreg = ....
}
// Der TIMER0 ist schon fuer millis() gebraucht. Man triggert den
Interrupt // einfach in der Mitte des T0 Timers und ruft die COMPARE A
Funktion auf/
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
Der Rest ist der normale Einsatz des Standard Beispiels von Peter.
_keyregs ist natuerlich Global deklariert und übermittelt den
Portzustand der KEYS in Peters Code .
Das ganze hat den Vorteil den AVR kaum zu belasten und die Keys werden
bequem von der schon existierenden ARDUINO TIMER0 ISR mitgezogen. die
rund 1ms T0 Rate lässt sich mit einem Zähler wie gewünscht anpassen. Bei
mir werden die Pins dann alle 10ms abgetastet.
Im konkreten Fall eigentlich über einen PCF8575 IO Expander. Aber das
tut nichts zur Sache.
Jedenfalls funktioniert es bei mir so ausgezeichnet. Läuft wie ein
Uhrwerk.
Gerhard
Gerhard O. schrieb:> Moin,>> bei mir lese ich die Key Pins in der Arduino TIMER0 ISR mit einem> Huckepack Compare A Interrupt.
Gerhard, du verschwendest dein Zeit und Energie und fütterst einen
lernresistenten Narzistzen! Meine Aussage war kein Witz!
Beitrag "Re: Peter Dannegger´s ( PeDa ) Entprellroutine in ein Arduino Sketch einbinden"
Der OP hat schon 10 Jahre (!) versucht, AVR Assembler zu kapieren, mit
SEHR begrenztem Ergebnis. Nun murkst er planlos mit 1/8 Wissen mit C
rum!
Don't feed the troll/fool!
Bernd S. schrieb:> Habe zum Schieben eine elegantere Schreibweise gefunden
Hast du vielleicht doch mal ausnahmsweise einen Blick in
ein C-Lehrbuch geworfen? Oder hat dir ein Arduino-Flüsterer
was untergeschoben?
Falk B. schrieb:> Don't feed the troll/fool!
Ja, war ein Fehler hier was zu schreiben, geb's ja zu ....
Ich habe einen Hand-Encoder der 20 Rastungen hat.
Pro Rastung werden 4 Signaländerungen erzeugt, also der typische
2-Bit-Graycode => 00; 01; 11; 10
Könnte jemand mal den Code im Anhang mit so wenig Codezeilen wie möglich
ändern, damit pro Klick bzw. Rastung nur eine Zahl ausgegeben wird und
nicht 4 ?
Aber bitte nicht gleich die Universallösung für 1, 2, 4 Rastungen.
Ist wieder mal ein Code von PeDa :
Beitrag "Re: Drehgeber auslesen"
Ich gebe es ja zu, so ganz bin ich da noch nicht durchgestiegen.
Bernd_Stein
Bernd S. schrieb:> Könnte jemand mal den Code im Anhang mit so wenig Codezeilen wie möglich> ändern, damit pro Klick bzw. Rastung nur eine Zahl ausgegeben wird und> nicht 4 ?
Die Anpassung ans Raster pro Änderung kann man über das Shiften des
Zählerwertes machen.
Veit D. schrieb:> Die Anpassung ans Raster pro Änderung kann man über das Shiften des> Zählerwertes machen.>
Ich vermute durch 2 maliges Rechtsschieben, was ja einer Teilung durch 4
entspricht.
Verstehe leider nur nicht, warum dies nicht klappt.
Packe ich *enc_delta >>= 2;* an die eine Stelle, passiert das Eine und
ein weiterdrehen bewirkt nichts mehr.
Genauso, wenn ich es an die andere Stelle kopiere ( siehe Screenshots ).
Bernd_Stein
Hallo,
du brauchst jetzt noch einen Absolutenzähler. Datentyp für deine
Anwendung passend. Auf diesen wird immer der Wert von enc_delta
aufaddiert. enc_delta gibt jetzt pro Rastung nur noch +1 oder -1 oder 0
raus.
Hallo,
bei uns in der Ausbildung hieß das MUP. Methode des unbekümmerten
Probierens. Kann man durchaus einmal machen. :-) Ich kann Bernd nicht
einschätzen. Es fällt ihm scheinbar sehr schwer und er quält sich durch.
Ich habe PeDa`s solide Lösung für einen ATmega 2560-Board angepasst,
wobei der CTC-Modus des Timer1 genutzt wird.
Könnte mir jemand einen Code zeigen oder schreiben, wo pro Klick, also
pro Rastung nur einmal ein Wert über die RS232 geschickt wird?
An den LED`s kann ich sehen, dass es generell funktioniert.
Veit D. schrieb:> Es fällt ihm scheinbar sehr schwer und er quält sich durch.>
Dies stimmt leider. Ich bin kein Autodidakt und C ist noch sehr
kryptisch für mich.
Hallo,
val entfernt, dafür struct Counter erstellt, kannste auch umbenennen.
Immer wenn alt ungleich neu ist wird das verarbeitet.
Einfaches Prinzip um ständige Wiederholungen ohne Änderung zu
unterdrücken.
Harald K. schrieb:> Niemand hält Dich davon ab, es zu tun. Bring' Dich ein!
Es geht ja nur im den Variablennamen `new`, in C++ ist das ein
Schlüsselwort.
Wilhelm M. schrieb:> Es geht ja nur im den Variablennamen `new`, in C++ ist das ein> Schlüsselwort.
Du kannst den Text auch ändern, das ist ein Wiki.
Ich zitier' mich mal selbst:
> Niemand hält Dich davon ab, es zu tun. Bring' Dich ein!
Wilhelm M. schrieb:>> Niemand hält Dich davon ab, es zu tun. Bring' Dich ein!>> Es geht ja nur im den Variablennamen `new`, in C++ ist das ein> Schlüsselwort.
Naja, aber durch Änderung des Namens wird keine "echtes" C++ draus.
Falk B. schrieb:> Wilhelm M. schrieb:>>> Niemand hält Dich davon ab, es zu tun. Bring' Dich ein!>>>> Es geht ja nur im den Variablennamen `new`, in C++ ist das ein>> Schlüsselwort.>> Naja, aber durch Änderung des Namens wird keine "echtes" C++ draus.
Das stimmt, jedoch wird es als C++-Code compilierbar. Und das würde
sicher vielen Arduino-Leuten (wie hier) helfen.
Veit D. schrieb:> Hallo,>> val entfernt, dafür struct Counter erstellt, kannste auch umbenennen.>
Vielen dank für deinen Code, der auch funktioniert, den ich aber leider
nicht nachvollziehen konnte.
Vielleicht kann mir ja jemand erklären warum meine Lösung auch
funktioniert.
Selbst meine Lösung verstehe ich nicht. Habe sie durch Zufall gefunden,
als ich wenigstens nur einen Wert, nämlich die 1 ausgeben wollte. Beim
weiterdrehen kam dann 2 usw. Die Gegenrichtung funktionierte nicht, da
hab ich einfach mal ...
1
voidloop()
2
{
3
if(enc_delta==4|enc_delta==-4){
4
val+=encode_read(4);// 4 Signaländerungen pro Rastung
5
6
Serial.print("val = ");
7
Serial.println(val,DEC);
8
9
}
10
LEDS=val;
11
}// Ende void loop()
Ach, anbei noch eine gute Erklärung zu PeDa's Hand-Encoder-Lösung.
Ab Kapitel 5, Seite 11 bzw. 20.
Bernd_Stein
Kleiner Tipp: *.txt ist kein guter Name für einen Dateianhang mit Code.
Wenn ihr statt dessen *.cpp verwendet, kriegt ihr auch das
"Syntax-Highlighting). Ob das MC-net auch *.ino kann, weiß ich nicht.
Harald K. schrieb:> Wilhelm M. schrieb:>> Es geht ja nur im den Variablennamen `new`, in C++ ist das ein>> Schlüsselwort.>> Du kannst den Text auch ändern, das ist ein Wiki.
Echt? War mir noch gar nicht aufgefallen ;-)
> Ich zitier' mich mal selbst:>> Niemand hält Dich davon ab, es zu tun. Bring' Dich ein!
Die Frage ist, ob es überhaupt Sinn macht. Zwar bin ich davon überzeugt,
dass meine Lösung tatsächlich die flexibelste und effektivste ist,
jedoch scheitert es ja regelmäßig daran, dass die Leute hier sich
beschweren, dass bspw. für avr-g++ keine libstdc++ verfügbar ist, und
dass deswegen kein std::array<> oder std::make_index_sequence<>, ...
verfügbar sei. Aber auf die Idee, das selbst zu erstellen, kommt
irgendwie keiner. Und wenn man die Sachen hinzufügt, dann kommt die
Beschwerde, es sei zu umfangreich. Obwohl das natürlich Bestandteil
einer Bibliothek ist, damit gar keine Rolle spielt und der eigentliche
Code zur Lösung der Aufgabe recht kurz. Weil er so kurz ist, kommt die
Beschwerde, dass zu viel hinter Bibliotheken versteckt sei und man
deswegen nichts verstehe bzw. Meta-Programmierung, funktionale Ansätze
und Closures nicht geeignet seien. Für die meisten größeren Controller
(etwa STM) macht es dann auch wieder wenig Sinn, weil die ja oft einen
Quadratur-Encoder als interne Peripherie dabei haben. Daher verspüre ich
wenig Drang dazu, das in das Wiki zu schreiben.
Wilhelm M. schrieb:> Zwar bin ich davon überzeugt, dass meine Lösung tatsächlich> die flexibelste und effektivste ist,
Wenn Du Leute überzeugen willst, musst Du Leute überzeugen. Aufstampfen
und "meins ist aber besser" sagen bringt nicht viel.
Harald K. schrieb:> Wilhelm M. schrieb:>> Zwar bin ich davon überzeugt, dass meine Lösung tatsächlich>> die flexibelste und effektivste ist,>> Wenn Du Leute überzeugen willst, musst Du Leute überzeugen.
Ich will hier(!) keinen überzeugen ;-)
An anderer Stelle schon
> Aufstampfen
Kann mich nicht daran erinnern, das gemacht zu haben ;-)
Wilhelm M. schrieb:> Die Frage ist, ob es überhaupt Sinn macht. Zwar bin ich davon überzeugt,> dass meine Lösung tatsächlich die flexibelste und effektivste ist,
Kann sein, ist beim Thema Arduino und seiner großen Zielgruppe aber
nicht das wesentliche Kriterium. Es muss einfach anwendbar und robust
sein. Das reicht. Selbst Einschränkungen in der Funktionalität sind in
vielen Fällen akzeptabel und werden teileise sogar aktiv betrieben, um
die Einfachheit zu erreichen. Der Wurm muss dem Fisch schmecken und
nicht dem Angler!
Falk B. schrieb:> Der Wurm muss dem Fisch schmecken und> nicht dem Angler!
Ich mache mir weder Gedanken um den Wurm, noch um die kulinarischen
Vorlieben des Anglers oder das Nahrungsangebot für den Fisch ...
Bernd S. schrieb:> if( enc_delta == 4 | enc_delta == -4 )
Müsste es nicht
> if( enc_delta == 4 || enc_delta == -4 )
heißen?
Denn ansonsten verodert man den Wert 4 mit enc_delta und fragt keine
zwei Bedingungen ab.
Bernd S. schrieb:> Wieso meine Lösung auch funktioniert weiß wohl keiner hier oder ?>> if( enc_delta == 4 | enc_delta == -4 )
Doch, natürlich.
https://en.cppreference.com/w/cpp/language/operator_precedence
Wie du siehst, bindet == stärker sowohl als | (bitwise OR) als auch als
|| (logical OR). Du führst also eine bitweise Veroderung zweier
Vergleichsresultate aus. Vergleichsresultate sind immer entweder 0 oder
1. Und deren bitweise Veroderung ergibt dasselbe Resultat wie deren
logische Veroderung.
Dennoch solltest du dir natürlich angewöhnen, in logischen Ausdrücken
die logischen Operatoren zu verwenden, und nicht die Bitoperatoren.
LG, Sebastian
Sebastian W. schrieb:> Dennoch solltest du dir natürlich angewöhnen, in logischen Ausdrücken> die logischen Operatoren zu verwenden, und nicht die Bitoperatoren.>
Ich versuch es ja.
Ich versteh es trotzdem nicht.
Wenn ich beispielsweise 5 habe ist dies weder == 4 noch == -4.
Jetzt was anderes. Habe schon sämtliche Datentypen durch und weiß nicht
wie ich es schaffen soll, dass wenn der Wert von val < 0 wird, val = 0
gesetzt wird. Oder wenn val >= 65535 wird val auf 65535 begrenzt wird
(siehe Screenshot ).
Bernd_Stein
Bernd S. schrieb:> val >= 65535
Kann val denn überhaupt größer als 65535 werden? Wenn es ein uint16 ist,
dann wird dieser Wert nie erreicht. Der Zähler wenn er immer um 4
inkrementiert wird) erreicht erst den Wert 65.532 und läuft dann über
und steht auf dem Wert 1 anstatt 65.536 zu erreichen.
Konkret sieht es so aus:
val wird um 4 inkrementiert und hat den Wert 65.532. Dies erfüllt deine
Bedinungung noch nicht. Nächster Durchlauf, val wird wieder um 4
inkrementiert und anstatt 65536 zu erreichen, hat val den Wert 1. Und
vergleicht man, ob 1 >= 65535 ist, kommt man zu dem Schluss, dass dies
nicht der Fall ist.
Was aber außerhalb deines Schnipsels mit val passiert liegt wieder im
Dunkeln...
Wilhelm M. schrieb:> Die Frage ist, ob es überhaupt Sinn macht. Zwar bin ich davon überzeugt,> dass meine Lösung tatsächlich die flexibelste und effektivste ist,> jedoch scheitert es ja regelmäßig daran, dass die Leute hier sich> beschweren, dass bspw. für avr-g++ keine libstdc++ verfügbar ist, und> dass deswegen kein std::array<> oder std::make_index_sequence<>, ...> verfügbar sei. Aber auf die Idee, das selbst zu erstellen, kommt> irgendwie keiner. Und wenn man die Sachen hinzufügt, dann kommt die> Beschwerde, es sei zu umfangreich. Obwohl das natürlich Bestandteil> einer Bibliothek ist, damit gar keine Rolle spielt und der eigentliche> Code zur Lösung der Aufgabe recht kurz. Weil er so kurz ist, kommt die> Beschwerde, dass zu viel hinter Bibliotheken versteckt sei und man> deswegen nichts verstehe bzw. Meta-Programmierung, funktionale Ansätze> und Closures nicht geeignet seien. Für die meisten größeren Controller> (etwa STM) macht es dann auch wieder wenig Sinn, weil die ja oft einen> Quadratur-Encoder als interne Peripherie dabei haben. Daher verspüre ich> wenig Drang dazu, das in das Wiki zu schreiben.
Das liest sich alles nach Ausrede. Man muss ja nicht immer mit der
größten Keule jedes Problem erschlagen. Wenn man die libstdc++ nicht
hat, löst man das Problem eben ohne. Da finden sich immer Wege. Und wenn
du jemanden eine praktische Lösung vorschlagen möchtest ist es irgendwie
vermessen und gar komisch, von den gleichen Leuten denen man mit einer
Lösung ihres Problems helfen möchte gleichzeitig zu verlangen das die
gefälligst vorher sich ihre libstdc++ selbst schreiben. Das passt ja nun
nicht zusammen. Wer in der Lage ist seine libstdc++ zu schreiben, der
benötigt sicherlich keine fremde Hilfe mehr für irgendwas anderes. Für
diese Encoderauswertung hier benötigt man zudem keine libstdc++. Ich
wüßte nicht wofür. Der nächste Gedanke ist, wenn jeder seine libstdc++
schreibt ist das bestimmt nie zu 100% zur echten libstdc++ kompatibel.
Da gibt es zu viele Fallstricke der Umsetzung, nehme ich an. Du wirst
deine sicherlich auch immer mal wieder anpassen müssen, weil irgendwo
ein Problem auftauchte.
Wenn du wirklich helfen möchtest, dann kannst du den Leuten hier helfen
ihre libstdc++ aktuell zu halten.
https://github.com/modm-io/avr-libstdcpp
Das ist die Beste die ich kenne, läuft aber manchmal noch nicht "ganz
rund".
Ich formuliere es einmal anders. Du musst nicht jeden Tag den Leuten
unter die Nase reiben das du deine libstdc++ hast und sie alle
gefälligst nachprogrammieren sollen. Die meisten werden davon noch nie
etwas gehört haben und kamen auch ohne gut klar. Viele Dinge der
libstdc++ kann man auf dem AVR sowieso nicht nutzen wegen
Speicherallokationen. Da muss man sowieso wissen was man tut. Von daher
ist die komplette libstdc++ in meinen Augen witzlos.
Laut meines Wissens wird die libstdc++ für C++23 in größerem Umfang
"umgebaut". Um das Problem zu bekämpfen das man eigentlich gar nicht
weiß welche Bibliothek man einbinden muss um irgendwas passendes
anwenden zu können. Die ist also wie der gcc selbst nie fertig. Der
Pflegeaufwand muss sehr hoch sein. Das ist in meinen Augen noch ein
Grund warum ich mir bis jetzt nur paar Type Traits davon nachgebaut habe
aber nie wirklich angefangen habe mich mit der libstdc++ als solches zu
befassen. Ich will ja meine Aufgaben lösen und mir nicht künstlich neue
Probleme schaffen. Das Ding heißt ja nicht umsonst Standard STL und
nicht Wilhelm-STL oder Veit-STL. Die ist ja nur einfachen Nutzung da und
nichts anderes und ausgiebig getestet.
Wenn du für den Encoder eine praktische Lösung hast ohne libstdc++
kannste die zeigen. Vielleicht haste ja eine bessere Lösung als meine
für meinen Nano Every. Aber deine ständige Wiederholung nach dem Motto
"warum habt ihr Idioten keine eigene libstdc++" geht mir langsam aber
sicher auf den Zeiger. Weil das hilft niemanden weiter. Denn wenn ich
was habe was ich sowieso niemanden anderem zeige, dann erzähle ich davon
erst gar nicht.
Veit D. schrieb:> Für> diese Encoderauswertung hier benötigt man zudem keine libstdc++. Ich> wüßte nicht wofür.
Wenn man etwas mit TMP macht, so benötigt man eigentlich immer
std::index_sequence<>, std::integral_constant<>,
std::make_index_sequence<>. Und für integrierte Test oder LUTs dann auch
std::array<>.
Veit D. schrieb:> https://github.com/modm-io/avr-libstdcpp> Das ist die Beste die ich kenne, läuft aber manchmal noch nicht "ganz> rund".
Na, das ist ja großartig. Es ist schon wirklich Jahre her, dass ich mir
das Projekt mal angesehen hatte. Aber der Hinweis ist natürlich sehr
wichtig, als es nun gar keinen Grund mehr gibt, Dinge abzulehnen, die
für AVR auch die stdlibc++ benutzen.
Veit D. schrieb:> Viele Dinge der> libstdc++ kann man auf dem AVR sowieso nicht nutzen wegen> Speicherallokationen. Da muss man sowieso wissen was man tut. Von daher> ist die komplette libstdc++ in meinen Augen witzlos.
Wenn die o.g. Realisierung nun tatsächlich einen std::vector<> oder
std::string<> mit Heap-Alloc anbietet, dann ist das natürlich Murks.
Vielleicht doch nicht so gut, was Du da erwähnst. Entweder man hat so
etwas wie FixedVector<> oder man benutzt einen static-pool-allocator.
Veit D. schrieb:> Um das Problem zu bekämpfen das man eigentlich gar nicht> weiß welche Bibliothek man einbinden muss um irgendwas passendes> anwenden zu können.
Du meinst "modules". Man wird aber weiterhin header benutzen können. Der
Vorteil der "modules" liegt woanders.
Veit D. schrieb:> Aber deine ständige Wiederholung nach dem Motto> "warum habt ihr Idioten keine eigene libstdc++" geht mir langsam aber> sicher auf den Zeiger.
Es hat aber nun endlich Deinen Hinweis zu Tage gebracht, dass es
tatsächlich eine stdlibc++ für AVR gibt. Das finde ich schon mal sehr
wichtig.
Wilhelm M. schrieb:> Veit D. schrieb:>> Für>> diese Encoderauswertung hier benötigt man zudem keine libstdc++. Ich>> wüßte nicht wofür.>> Wenn man etwas mit TMP macht, so benötigt man eigentlich immer> std::index_sequence<>, std::integral_constant<>,> std::make_index_sequence<>. Und für integrierte Test oder LUTs dann auch> std::array<>.
Ein Bsp. von mir ohne stdlibc++.
Beitrag "Drehgeber und Tastenentprellung für Arduino"> Veit D. schrieb:>> Viele Dinge der>> libstdc++ kann man auf dem AVR sowieso nicht nutzen wegen>> Speicherallokationen. Da muss man sowieso wissen was man tut. Von daher>> ist die komplette libstdc++ in meinen Augen witzlos.>> Wenn die o.g. Realisierung nun tatsächlich einen std::vector<> oder> std::string<> mit Heap-Alloc anbietet, dann ist das natürlich Murks.> Vielleicht doch nicht so gut, was Du da erwähnst. Entweder man hat so> etwas wie FixedVector<> oder man benutzt einen static-pool-allocator.
Ist es nicht der Sinn eines Standards das Standardverhalten für alle zu
haben? Ich kann doch niemanden einen Vorwurf machen wenn er das
Standardverhalten für AVR nachbaut. Der es dann nutzt muss wissen was er
auf einem AVR sinnvoll einsetzen kann und was nicht. Soweit muss man da
gar nicht schauen. Das fängt schon mit der String Lib an, ohne zu wissen
was man tut kann die nach hinten losgehen. Das Problem mit dem Speicher
ist auch nicht zwingend auf AVR begrenzt. Alle die µC programmieren und
die libstdc++ verwenden müssen wissen was sie ihrem stark begrenzten
Speicher im Vergleich zur Desktop CPU/RAM zumuten können und was nicht.
> Veit D. schrieb:>> Um das Problem zu bekämpfen das man eigentlich gar nicht>> weiß welche Bibliothek man einbinden muss um irgendwas passendes>> anwenden zu können.>> Du meinst "modules". Man wird aber weiterhin header benutzen können. Der> Vorteil der "modules" liegt woanders.
Ja richtig, hing mit dem kommenden Modules zusammen.
Sorry Bernd für die Abschweifung in deinem Thread.
Veit D. schrieb:> Sorry Bernd für die Abschweifung in deinem Thread>
Danke, das zeigt dass du Anstand hast.
Ich finde hier seid ihr mit eurer Diskusion besser aufgehoben :
Beitrag "Drehgeber und Tastenentprellung für Arduino"Stefan S. schrieb:> Kann val denn überhaupt größer als 65535 werden? Wenn es ein uint16 ist,> dann wird dieser Wert nie erreicht.> ...>
Auch int32_t brachte kein Erfolg, aber jetzt mal ganz von Anfang.
val wurde in Einer Schritten gezählt. Zuerst vorwärts bis 2, dann
rückwärts um die Bedingung *val < 0* zu prüfen. Hierbei erwartete ich
-1, aber stattdessen wird die Bedingung *val >= 65535* erfüllt ( siehe
Screenshot im Link ).
Beitrag "16-Bit Wertbegrenzungen 0 und 65535 setzen"
Das Programm ist im Anhang ( ..._Original ) und die Folge für val ist "
*2 + 102 ", was eigentlich 164346 ergeben müsste. Jetzt dürfen wir
raten, warum 38810 herauskommt ( siehe Screenshot ).
Jaja, programmieren mit Unlogik . . .
Ich weiß zwar nicht warum ich das hier mache, ich mach's trotzdem. Siehe
Anhang.
1
volatileint8_tenc_delta;
2
staticuint8_tlast;
Diese beiden Variabelen sind TABU!!! Die faßt man an Anwender NIE an!
Die einzige Funktion, die man benutzt, ist
int8_t encode_read( uint8_t klicks );
Die liefert die Anzahl der Schritte seit dem letzten Aufruf mit
Vorzeichen! Nur DAMIT arbeitet man.
Dann ist es auch leicht, zu erkennen, wann am Rad gedreht wurde. Nämlich
dann, wenn der Rückgabewert ungleich 0 ist! WOW! Der Rest ist trivial^2.
Oder doch nicht? Naja, man sollte schon VOR der Benutzung einer
Variablen deren Grenzen prüfen und nicht DANACH! Du hast es genau anders
herum gemacht! (Sind wir überrascht? Nicht wirklich)
Und interen Pull-Ups schaltet man auch anders ein.
Bin mir gar nicht mehr sicher ob das mit cli und sei überhaupt nötig
ist.
Und wenn nein - warum ?
Falk B. schrieb:> Ich weiß zwar nicht warum ich das hier mache, ich mach's trotzdem.>
Wahrscheinlich, weil du es kannst ;-)
1
case4:enc_delta=val&3;val>>=2;break;
Diese Logik verstehe ich nicht. val ist zu Begin = enc_delta.
Man maskiert Bit 0 & 1 aus, dann schiebt diese so, dass enc_delta immer
Null ergibt.
Bernd S. schrieb:> cli( );> OCR3A = val; // An Rechteckgenerator Wert> übergeben> sei( );> Bin mir gar nicht mehr sicher ob das mit cli und sei überhaupt nötig> ist.> Und wenn nein - warum ?
Weil das Register durch den Compiler schon richtig beschrieben wird und
in deinem Programm kein Zugriff darauf in einem Interrupt passiert.
> Wahrscheinlich, weil du es kannst ;-)
case 4: enc_delta = val & 3; val >>>= 2; break;
> Diese Logik verstehe ich nicht. val ist zu Begin = enc_delta.> Man maskiert Bit 0 & 1 aus, dann schiebt diese so, dass enc_delta immer> Null ergibt.
Das muss du gar nicht verstehen, denn du willst den Drehgeber nur
benutzen. Fertig.
> ////////////////////////////////////////////////////////////////////////
////////
> void loop()> {> int8_t delta;> delta = encode_read(4); // 4 Signaländerungen pro Rastung> if( delta != 0 ) {> pwm_wert += delta;> if( pwm_wert > 65535 ) pwm_wert = 65535;> if( pwm_wert < 0 ) pwm_wert = 0;> OCR3A = pwm_wert; // An Rechteckgenerator Wert> übergeben> Warum erzeugt man zwei weitere Variablen ( delta, pwm_wert ) und> arbeitet nicht einfach mit val weiter ?
Weil es so besser ist. Klar kann man sich auch den alten Wert merken und
prüfen, ob eine Änderung vorliegt. Ist aber doppelt gemoppelt. Außerdem
ist delta eine kleine 8 Bit Zahl, pwm_wert ja nach Anwendung 16 oder 32
Bit. Mehr Speicher, mehr CPU-Last, mehr Aufwand für einen Vergleich.
Falk B. schrieb:> Das muss du gar nicht verstehen, denn du willst den Drehgeber nur> benutzen. Fertig.>
1
case4:h_encoder_delta=val&3;val>>=2;break;
Wär aber schön, denn ich verstehe auch nicht, wieso h_encoder_delta in
der ISR nur bis 4 bzw. -4 zählt. Der Ausdruck rechts vom
Gleichheitszeichen ergibt ja entweder 1 oder -1. Also wird doch
eigentlich h_encoder_delta bis zum Überlauf hoch,- bzw. runtergezählt
Was sorgt dafür, dass h_encoder_delta nur bis 4 hochzählt, wenn doch
immer 1 addiert wird ?
1
volatileint8_th_encoder_delta;
2
3
h_encoder_delta+=(diff&2)-1;// bit 1 = direction (+/-)
Bernd S. schrieb:> Falk B. schrieb:>> Das muss du gar nicht verstehen, denn du willst den Drehgeber nur>> benutzen. Fertig.>>case 4: h_encoder_delta = val & 3; val >>= 2; break;> Wär aber schön, denn ich verstehe auch nicht, wieso h_encoder_delta in> der ISR nur bis 4 bzw. -4 zählt.
Bei jedem Aufruf der Funktion passiert folgendes
h_encoder_delta = val & 3;
nur die unteren 2 Bit von h_encoder_delta bleiben übrig, die oberen Bits
werden gelöscht. 3 = 0b00000011, siehe Bitmanipulation.
val >>= 2; break;
Die Variable val, welche den Wert von h_encoder_delta enthält, wird um 2
Bits nach rechts geschoben. Damit werden die unteren 2 Bits
rausgeschoben und die Variable praktisch durch 4 dividiert. Denn genau
das will man bei einem Encoder, der 4 elektrische Pulse / mechanischer
Raststufe besitzt.
> Der Ausdruck rechts vom> Gleichheitszeichen ergibt ja entweder 1 oder -1. Also wird doch> eigentlich h_encoder_delta bis zum Überlauf hoch,- bzw. runtergezählt
Nö.
> Was sorgt dafür, dass h_encoder_delta nur bis 4 hochzählt, wenn doch> immer 1 addiert wird ?
Die Tatsache, daß dein Programm die Funktion encode_read(4) sehr oft
aufruft, mit mehreren Dutzend kHz. In der Zeit kann sich die Variable
gar nicht schneller ändern, denn die ISR, welche die Variable verändert,
läuft nur mit 1kHz. In einem richtigen Programm wird die Funktion
deutlich langsamer aufgerufen, vielleicht mit 1-10 Hz. In der Zeit kann
der Drehgeber aber mehrere Schritte machen. Die werden alle korrekt
gezählt.
Mach einfach mal einen Test. Füge ein
delay(1000);
ans Ende deiner Funktion loop() ein und staune.
Falk B. schrieb:> Bei jedem Aufruf der Funktion passiert folgendes> ...>
Danke, dass du es mir doch noch erklärt hast.
Die einfachsten Dinge bereiten mir Probleme, es ist schon fast
verflucht.
In der rechteckgenerator_init, weise ich OCR3A den Wert 10.000 zu.
Es hat aber seltsamerweise den Wert 16. Mache ich dies an einer anderen
Stelle, so stimmt alles.
Was läuft hier falsch?
Bernd_Stein
10.000 scheint nicht in ein 8 Bit Register zu passen. 10.000 modulo 256
ergibt 16.
Du musst mit den Grundlagen vom ersten Kapitel an anfangen.
Edit:
Ok, es ist ein 16 Bit Register. Das ist es nicht.
Der Wert steht vermutlich richtig im Register, aber im PrintLn wird der
Zugriff nicht richtig gemacht. Auslesen über 16 Bit Hilfsvariable könnte
gehen.
Bernd S. schrieb:> Was läuft hier falsch?
Ich stelle fest: Arduino Mega
Also werden alle Timer für 8 Bit PWM vorbereitet und Timer0 ist
zusätzlich für millis() und Freunde vorbereitet.
Das kann die lustigsten Fallen stellen!
Darum grundsätzlich die Timer Control Register erst zurücksetzen, bevor
man irgend etwas anderes damit anstellt.
(Ausnahme Timer0)
Es gab mal einen Thread hier, über das sonst entstehende undokumentierte
Durcheinander.
Denn, entweder hat der Timer einen Bug, oder das Datenblatt ist
unvollständig.
Beispiel:
Hallo,
man kann nicht einfach wahllos irgendein Register ändern und danach den
gesamten Timer neu konfigurieren. Bei Arduino sind die Timer mit PWM
Einstellungen für analogWrite vorkonfiguriert. Wenn man noch nicht ganz
genau weiß was macht macht, immer erstmal alle relevanten Timer Register
reseten. Zuerst TCCRnB, damit steht der Timer und kann keinen Unsinn
mehr machen. Dann den Rest reseten, dann neu einstellen und zum Schluss
den Prescaler setzen. Dann läuft der Timer sauber an. Wenn der vorher
schon läuft und die Konfig noch nicht fertig, kann und wird er Mist
machen, auch wenn es ggf. nur kurzeitig ist.