Also bei mir funktioniert es:
Und die atomic.h ist dort zu finden:
Ich benutze nicht die Version aus dem App-Store! sondern die mit dem Windowsinstaller
Also bei mir funktioniert es:
Und die atomic.h ist dort zu finden:
Ich benutze nicht die Version aus dem App-Store! sondern die mit dem Windowsinstaller
Nein, es drängt mich nicht. Wichtig ist, dass ich auf meinem PC eine funktionsfähige Arduino IDE installiert habe. Es ist auch kein Problem, Arduino neu zu installieren. Ich bin auf das Ergebnis gespannt, wenn du den Sketch heute Abend mit deiner Arduino Umgebung getestet hast.
Wie gesagt, ich werde es heute Abend mal mit meiner Arduino IDE (ebenfalls 1.819) ausprobieren. Üblicherweise benutze ich PlatformIO. Da funktioniert das anstandslos. Sonst hätte ich die Messungen ja auch nicht vornehmen können.
Wenn es dich so drängt, dann kommentiere die zwei ATOMIC_BLOCK Zeilen aus und schreibe das, was bei den Anweisungen zwischen den geschweiften Klammern steht, in eine eigene Zeile. Dann kommst Du ohne die Header Datei aus.
Also ICR1 = icr1; und OCR1A = ocr1a;
Sollte auch funktionieren…. ich habe ATOMIC_BLOCK nur als zusätzliche Sicherheit eingefügt, weil ich mir nicht sicher bin ob sich die 16Bit Werte immer schreiben lassen, ohne Interrupts kurz abzuschalten.
Hallo Kai,
ich habe Arduino1.8 .19 über Windows Store installiert, als ich mir den PC im Frühjahr gekauft habe.
Ich hatte schon das ganze AVR Verzeichnis durchsucht und auch die Arduino Corefiles. (hardware/ AVR /1.8.5 /cores / Arduino) Es gibt kein Verzeichnis /util mit der atomic.h Datei. Ich muss gestehen, mit dem Windows PC bin ich noch nicht so sehr vertraut, weil ich vorher immer mit einem Macbook PC gearbeitet habe.
Achte darauf, den Sketch vollständig zu kopieren. Die atomic.h gehört zu den Arduino Corefiles und sollte vorhanden sein. Es muss nichts nachinstalliert werden.
Ich verwende die Arduino IDE nicht, aber wenn Software im WokWi-Simulator läuft und sich dort compilieren lässt, sollte sie auch in der Arduino IDE funktionieren. Ich werde das heute Abend mal mit der IDE prüfen.
Hallo Kai,
herzlichen Dank für deine große Mühe und Hilfsbereitschaft!
Nach dem Hochladen deines Sketch in den Arduino wird die Fehlermeldung "util/atomic.h: No such file or directory" angezeigt.
Die atomic.h sollte, wenn ich richtig gelesen und verstanden habe, in der AVR LIBc enthalten sein. Wenn ich diese im Arduino-Verzeichnis Libraries installieren will, erscheint der Hinweis, dass keine gültigen Dateien in der AVR LIB sind.
Grüße, Franz
Ich habe mal eine kleine Klasse geschrieben mit der, neben der Frequenz, auch das Tastverhältnis von 0 bis 100% eingestellt werden.
Das zuvor in diesem Thread besprochene Programm habe ich entsprechend angepasst, dass beide Parameter über den Encoder eingegeben werden können.
Die Tone Bibliothek wird nicht mehr benötigt.
Hier mal zwei Beispiele zur Ausgabe:
Links werden 10Hz mit 50% Tastverhältnis ausgegeben, rechts sind es 12Hz mit 15% Tastverhältnis.
Die Frequenzgenauigkeit hängt von Temperatur und Quarz des µControllers (evtl. auch vom Programm) ab. In meinem Beispiel ist die Frequenz etwas über 0,02 Hertz zu niedrig. Dafür ist der "Fehler" aber recht konstant. Der verwendete Modus ist "phasenkorrektes PWM" (Modus 10 nach ATmega Datenblatt Seite 109). Die Frequenzeingabe ist auf einen 16 Bit unsigned int Wert beschränkt. Somit wäre die maximal einstellbare Frequenz 65,535 KHz.
Ich habe mich in diesem Beispiel jedoch nur auf den, im vorherigen Programm behandelten, Frequenzbereich beschränkt.
Es wird der Timer1 des ATmega328P verwendet. Der Ausgabe-Pin ist auf D9 festgelegt. Das hängt mit dem verwendeten Timer-Mode zusammen und kann meines Wissens auch nicht so ohne weiteres geändert werden. Die Klasse funktioniert mit ATmega48A-PA ATmega 88A-PA ATmega 168A-PA und ATmega 328-P µControllern. In der "Arduinowelt" sind das der Nano, Uno und Pro-Mini.
Sollten Bibliotheken in einem Programm verwendet werden, die ebenfalls den Timer 1 verwenden dann "kracht" es. Funktionen wie millis() oder delay() sind davon aber nicht betroffen. Die werden durch Timer 0 gesteuert.
Wenn der Encoder nur kurz gedrückt wird (min. 150ms) wechselt die Eingabe zwischen den beiden Parametern Hertz und Tastverhältnis. Das drehen des Encoders ändert den ausgewählten Parameterwert. Gestartet wird die Frequenzausgabe, wenn der Encoder min. 1 Sekunde gedrückt wird.
Im vorliegenden Beispiel ist die Klassendefinition und das Hauptprogramm in einer Datei. Schöner ist es natürlich, dass in eine Header- und eine Programmdatei aufzuteilen.
Zum Ausprobieren:
Ich habe zwar keine Ahnung vom Arduino, aber ein Rechteck Signal mit einer definierten On/Off Zeit lässt sich, sieht man von einem leichten Jitter mal ab, leicht realisieren.
Ein Timer, der sagen wir mal mit einer Clock-Rate von 0.5mS zählt, löst immer dann einen Interrupt aus, wenn der Zähler den Wert (oder wenn man runter zählt 0) erreicht. In der Interrupt Routine wird dann die neue Zeit gesetzt und man wartet erneut, bis der Zähler das Ende erreicht hat.
Bei jedem erreichen der Ziel - Zeit wird gleichzeitig das Ausgangspin aktiviert oder deaktiviert.
Gruss
Pius
ZitatKönnte man das auch mit dem Tone Generator programmieren?
Meines Wissens nicht. Da ist das Tastverhältnis auf 50/50 festgelegt. Zumindest ist es so bei der Beschreibung der Tone Bibliothek beschrieben:
This is an Arduino Library to produce square-wave of the specified frequency (and 50% duty cycle) on any Arduino pin.
ZitatIst so eine Verschiebung überhaupt programmierbar?
Ja ist es.
Wie das geht, steht im Datenblatt des ATMega328 beschrieben. Da muss Du dich mit der Programmierung von Timern beschäftigen
Mit "normalen" Arduino Mitteln gibt es analogWrite(). Hier kann das Tastverhältnis einer Frequenz, die jedoch fest vorgegeben ist, verändert werden. Darum hilft das im vorliegenden Fall nicht. Andere Mittel sind mir nicht bekannt. Außer halt, einen Timer direkt über die Register des µControllers zu programmieren.
Hallo Kai ich wollte dir noch zeigen, wie schön das Signal von dem Generator ist. Auch mit einem Fluke gemessen stimmt die Frequenz genau.
Ich denke noch an eine Erweiterung.
Interessant wäre auch z.B. 12Hz = 83 ms Periode.
Dann ist das Signal 41,5 ms heigth und 41,5ms low.
Wenn das Signal aber Pro Periode einstellbar z.B 10ms hight und 73ms low sein soll. Könnte man das auch mit dem Tone Generator programmieren?
Ist so eine Verschiebung überhaupt programmierbar?
Grüße, Franz
Freut mich das es klappt. Allerdings verstehe ich jetzt, beim letzten Schritt nicht wirklich, wo die Schwierigkeiten lagen, das mit der Tone Library und dem Programm zusammen zu bringen. Wenn Du Dir anschaust wo Generator.xxx eingefügt wurde, war das doch eigentlich ganz einfach .
ZitatDeshalb habe ich in der Codezeile (ich meine Zeile 91)
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2, 1, 0 };
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 1, 2, 0 };
OK. Das funktioniert in dem WokWi Simulator nicht, weil man dort nicht an die tone.cpp heran kommt.
Dann kannst Du aus dem Code die timeStamp Geschichte und doBlink ja auch herauswerfen. Das wird dann nicht mehr benötigt.
Kai, du bist der Größte!!
Es funktioniert super und auch genau.
Der Tonegenerator ist ToneLibrary-1.7.1
Dieser kann aber nur Frequenzen >32Hz.
Deshalb habe ich in der Codezeile (ich meine Zeile 91)
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2, 1, 0 };
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 1, 2, 0 };
geändert.
Herzlichen Dank
Franz
Dann musst du den Code schon korrekt kopieren. Ich habe den alten, auskommentierten Kram mal wieder raus geschmissen.
Beim kompilieren werden folgende Fehlermeldungen gelistet:
169:17: error: variable or field 'askEncoder' declared void
void askEncoder(EncoderData& data) {
^~~~~~~~~~~
neu:169:17: error: 'EncoderData' was not declared in this scope
neu:169:30: error: 'data' was not declared in this scope
void askEncoder(EncoderData& data) {
^~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:169:30: note: suggested alternative: 'atan'
void askEncoder(EncoderData& data) {
^~~~
atan
neu:74:2: error: expected unqualified-id before '/' token
*/
^
neu:74:2: error: expected constructor, destructor, or type conversion before '/' token
neu:89:16: error: redefinition of 'constexpr const byte I2C_ADDR'
constexpr byte I2C_ADDR {0x27};
^~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:18:16: note: 'constexpr const byte I2C_ADDR' previously defined here
constexpr byte I2C_ADDR {0x27};
^~~~~~~~
neu:90:16: error: redefinition of 'constexpr const byte LCD_COLUMNS'
constexpr byte LCD_COLUMNS {16};
^~~~~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:19:16: note: 'constexpr const byte LCD_COLUMNS' previously defined here
constexpr byte LCD_COLUMNS {16};
^~~~~~~~~~~
neu:91:16: error: redefinition of 'constexpr const byte LCD_LINES'
constexpr byte LCD_LINES {2};
^~~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:20:16: note: 'constexpr const byte LCD_LINES' previously defined here
constexpr byte LCD_LINES {2};
^~~~~~~~~
neu:101:23: error: redefinition of 'LiquidCrystal_I2C lcd'
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
^~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:21:19: note: 'LiquidCrystal_I2C lcd' previously declared here
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
^~~
neu:102:1: error: 'RotaryEncoder' does not name a type; did you mean 'RotaryEncoder_h'?
RotaryEncoder encoder(pin_in1, pin_in2, RotaryEncoder::LatchMode::FOUR0);
^~~~~~~~~~~~~
RotaryEncoder_h
neu:106:6: error: redefinition of 'Tone Generator'
Tone Generator;
^~~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:22:6: note: 'Tone Generator' previously declared here
Tone Generator;
^~~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino: In function 'void setup()':
neu:110:6: error: redefinition of 'void setup()'
void setup()
^~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:23:6: note: 'void setup()' previously defined here
void setup(){
^~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino: In function 'void loop()':
neu:123:6: error: redefinition of 'void loop()'
void loop()
^~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:32:6: note: 'void loop()' previously defined here
void loop(){
^~~~
neu:129:3: error: 'askEncoder' was not declared in this scope
askEncoder(encData);
^~~~~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino: In function 'void askEncoder(EncoderData&)':
neu:170:3: error: 'encoder' was not declared in this scope
encoder.tick();
^~~~~~~
C:\Users\fenge\OneDrive\Dokumente\Arduino\neu\neu.ino:170:3: note: suggested alternative: 'askEncoder'
encoder.tick();
^~~~~~~
askEncoder
exit status 1
variable or field 'askEncoder' declared void
Also ich habe das in WokWi jetzt zusammengefügt. Habe auch Deinen unten geposteten Sketch da laufen lassen. Da blinkt jedoch nichts. Nur Dauerleuchten.
Kann aber auch an der Simulation liegen. Oder an der verwendeten Tone Lib.
Jedenfalls kannst Du Dir den Code da abholen. Wenn es nicht funktioniert musst du halt weiter probieren..
Hallo Kai,
ich habe die Frequenz gemessen. Eingestellte z.B.12 Hz sind gemessen etwas schwankend 12,12 bis12,20 Hz.
Mit dem Tone Sketch ist die Frequenz nicht schwankend und genau. Ich habe das noch einmal getestet. Hier wird die Frequenz aus dem seriellen Monitor gelesen. (Siehe Sketch in #1 unten)
Danke für deine Hilfe.
Ich habe versucht beide Sketche zu verbinden, kriege das aber nicht hin.
Grüße, Franz
Folgender Code lässt es Blinken:
Ist aber nicht besonders genau. Ein Frequenzgenerator ist das nicht . Aber so ungefähr geht es ...
Sorry, du hast recht.
ZitatMir ist aufgefallen, dass in der Simulation der Taster an Pin 5 verdrahtet ist.
Nee, ist er nicht. Der Kontrast zwischen „Kabel“ und Controller ist etwas schwach. Die Verbindung macht an Pin 5 einen Knick und ist an Pin 4 angeschlossen.