Themabewertung:
  • 1 Bewertung(en) - 5 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
per Drehencoder Tastenradio steuern
#1
der Titel klingt etwas seltsam. Ich versuche mal zu erklären worum es geht. Schon länger wollte ich mit minimalem Aufwand Radiobausteine wie den HEX3653, das Serial Port Baustein Modul oder den BK1068, welche per Mikro-Tasten gesteuert werden, mit einem Drehencoder bedienen können. Da der Encoder grundsätzlich Impulse abgibt, kann er eine einzelne Taste direkt ersetzen. Aber sobald die Drehrichtung des encoders ausgewertet werden muss kommt ein Mikroprozessor ins Spiel.
Mit einem Arduino ist das kein großer Akt. Aber es sollte ein kleiner attiny sein. An dessen Besonderheiten der Pin Change Interrupts bin ich aber gescheitert und bekam keine richtige Entprellung hin und auch keine treffsichere Richtungserkennung.

Diese Probleme konnte ich nun lösen. Ich benutze weitgehend den code von The Wandering Engineer. Der steuert per encoder die Helligkeit einer LED. Ich hab ihn mir so abgeändert daß eine Drehbewegung einen 200ms langen Impuls abgibt, und zwar in Abhängigkeit der Drehrichtung jeweils an einem anderen Ausgangsport.

So sieht mein fertiger code aus:

Code:
/*
https://thewanderingengineer.com/2014/08/11/rotary-encoder-on-the-attiny85-part-2/
*/

#include "avr/interrupt.h";

volatile int lastEncoded = 0;
volatile int search_mode = 0;

unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 2000;    // Impulslänge

void setup()
{
 pinMode(0, OUTPUT);
 pinMode(1, OUTPUT);
 
 // set pins 3 and 4 to input
 
 pinMode(3, INPUT); //Pullup ist im encoder eingebaut
 pinMode(4, INPUT); //Pullup ist im encoder eingebaut
 
 GIMSK = 0b00100000;       // Enable pin change interrupts
 PCMSK = 0b00011000;       // Enable pin change interrupt for PB3 and PB4
 sei();                    // Turn on interrupts
}

void loop()
{
   if (millis() - previousMillis > interval) {
   digitalWrite(0, HIGH);
   digitalWrite(1, HIGH);
     if (search_mode == 1) {
     digitalWrite(0, LOW);
     search_mode = 0;
     previousMillis = millis();   // aktuelle Zeit abspeichern  
     }
     if (search_mode == 2) {
     digitalWrite(1, LOW);
     search_mode = 0;
     previousMillis = millis();   // aktuelle Zeit abspeichern  
     }
     }      
}

// This is the ISR that is called on each interrupt
// Taken from http://bildr.org/2012/08/rotary-encoder-arduino/
ISR(PCINT0_vect)
{
 int MSB = digitalRead(3); //MSB = most significant bit
 int LSB = digitalRead(4); //LSB = least significant bit

 int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
 int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

 if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
   search_mode = 1;
 if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
   search_mode = 2;

 lastEncoded = encoded; //store this value for next time

}

ein paar Erklärungen dazu:

die Impulslänge wird durch die millis() Funktion festgelegt. Dies ist auch gleichzeitig die Entprellzeit. Die erste Einschwingflanke wird ausgewertet und danach wird der encoder 200ms lang in der loop ignoriert. Der Wert "unsigned long interval = 2000;" bedeutet eigentlich 2 Sekunden, vermutlich habe ich aber eine Diskrepanz zwischen dem Takt, den ich mit 1MHz gewählt habe, und den fuses des attiny. Da es sonst keine zeitkritische Funktion gibt macht das keine Probleme.

An den Eingängen werden keine pullups gesetzt, weil der verwendete encoder (KY-040) diese hardwaremässig eingebaut hat. Das gleiche gilt für die Ausgänge. Die Eingänge des Radiobausteins liegen bereits auf high-Potential, und der LOW-Impuls legt diese dann für 200ms auf Masse. Diese Zeit entspricht dem gemütlichen Drücken einer Taste von Hand.

Die Interruptfunktion wertet die Drehrichtung aus und speichert das Ergebnis in der Variablen "search_mode".

In der loop wird ausserhalb der Sperrzeit von 200ms auf diese Variable reagiert, also der entsprechende Ausgangsport gesetzt, und "search_mode" wieder auf 0 gesetzt (1 und 2 sind die beiden Drehrichtungen).

Die Variable "last_encode" könnte als Überrest des ursprünglichen codes ohne Bedeutung sein, das ist mir noch nicht so ganz klar.

So, genug Theorie.

Kommen wir zum Aufbau des Bedienteiles

die kleine Platine trägt den DIL-Sockel für den attiny, die Steckverbindung für das Encoder-Modul und die Steckverbindungen für Spannungsversorgung und Ausgänge.

   

An dem Encoder wird die Lötleiste rumgedreht, damit er besser an einer Frontplatte befestigt werden kann

   

   

   

hier ist der Grund zu erkennen:

   

Die Platine für die Lautstärkeregelung ist ein Stück länger als die für die Senderabstimmung, weil sie noch einen Spannungsregler für die 3,3V-Versorgung trägt. Die Speisung des Radio soll später über PowerPack oder USB erfolgen.

   

   

Die Verdrahtung der Unterseite:

   

Der Attiny wird mit Hilfe eines Arduino programmiert:

   

der komplette Laboraufbau:

   

   

hier die Unterschiede zwischen dem Modul für die Sender- und dem für die Lautstärkeeinstellung:

   

   

der HEX3653 Baustein (Mickey Mouse Radio):

   

bei einem anderen Baustein müssen dessen Eigenarten der Tasterbeschaltung bei der Programmierung der pullups und des Ausgangimpulses berücksichtigt werden. So hat der BK1068 zum Beispiel Tristate-Eingänge. Die Tasten für vol+ und scan+ schalten den Eingang auf HIGH und vol- und scan- auf LOW.

wer bis hierher durchgehalten hat wird nun noch mit einem Video belohnt. Eine praktische Anwendung für diese Radiosteuerung wird in Bälde folgen

Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#2
inzwischen hab ich den Verdrahtungsplan gezeichnet.

   
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#3
Schick Jupp, aber wo ist die Frequenzanzeige!? Big Grin
Viele Grüße aus Loccum, Wolfgang

Wer niemals fragt, bekommt nicht einmal ein Nein zur Antwort.

In Memorandum 2018
Zitieren
#4
die erwähnten Bausteine liefern alle keine Abgriffmöglichkeit die sich für eine Frequenzauswertung eignen würde. Der Serial Port Baustein hat zumindest ein internes Display. Meine Schaltung schließt lediglich eine Lücke die günstigen Empfängerbausteine anders bedienen zu können als über ein Tastenfeld.
Sie wäre aber auch einsetzbar um z.B. ein DAB+ Radio zu steuern. An einem Retro-Radio mit modernem Innenleben stören Tasten. Ich werde bald eine Anwendung vorstellen wo eine 20er Jahre Optik komplett erhalten und bedienbar bleibt.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#5
Hallo Jupp,

"lastEncoded = encoded; //store this value for next time"

Die Variable lastEncoded dient als Zwischenspeicher der Variablen encoded.
Mit lastEncoded wird beim nächsten Durchlauf der Wert von sum berechnet.

Sie wird benötigt und kann ohne Änderung des Programms nicht weggelassen werden.
Grüße aus Wassenberg,
Norbert.
Zitieren
#6
danke Norbert, das du dir die software angeschaut hast. Mein Zweifel waren ob man den Zwischenspeicher überhaupt noch benötigt, da ich ja keinen Helligkeitswert einer LED mehr vergleichen muss.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#7
Ich habe jetzt eine kompaktere Version gebaut, welche nicht mehr das KY-040 Encoder Modul verwendet, sondern den Encoder als Einzelbauteil. Dadurch bin ich flexibler was die Schaltlogik des Pushbutton Switch angeht. Mit einem Jumper kann ich jetzt je nach Anforderung den Switch wahlweise gegen Plus oder gegen Masse schalten lassen. Ich erspare mir also die Manipulation der smd-Pullups und der Verdrahtung im Modul, und auch sowieso den Umbau der Modul-Steckverbindung. Ein weiterer Vorteil ist der Gewinn an mechanischer Stabilität.

Da auch die Pullup-Widerstände für CLK und DT nun nicht mehr existieren muss ich im attiny die Software-Pullups einschalten.

Zitat:pinMode(3, INPUT_PULLUP); //Aktivieren der software-Pullups
pinMode(4, INPUT_PULLUP); //

Brauche ich für CLK und DT eine andere Logik muss ich das in der Software beim Setzen der Output's anpassen.


.png   encoder-taster_Leiterplatte.png (Größe: 45,46 KB / Downloads: 711)

Durch die Bauhöhe des gesockelten attiny und wegen der Zugänglichkeit zur Buchsenleiste empfiehlt es sich den Encoder auf die andere Seite der Leiterplatte zu setzen. Eine durchkontaktierte Standard 8x2cm Platine ist ideal, und bietet auch noch Platz falls ein Spannungsregler dazu gesetzt werden soll.

Das timing Problem des attiny ist nun auch behoben. Ich muss lediglich beim ersten Verwenden eines neuen attiny in der Arduino-Software einmalig die fuses setzen ("Bootloader brennen"). Ich benutze einen Takt von 1MHz.

Die Buchsenleiste ist 6-polig eine gängige Variante. Es hat sich angeboten den A1-PIN der attiny als Reserve auf den ansonsten freien PIN der Buchsenleiste zu legen.

   

   

   

   
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#8
Es gibt im AVR-BASCOM kleine fertige Codes dafür.
VG Micha
Zitieren
#9
(17.11.2018, 20:44)hardware.bas schrieb: Es gibt im AVR-BASCOM kleine fertige Codes dafür.
VG Micha

Hallo Micha,

kannst Du mal ein Codebeispiel dafür hier zeigen?
Ich habe jetzt oft gehört, daß Bascom übersichlichere
und kürzere Codes hat als C.

Gruß
Wilhelm
Niemandes Herr, Niemandes Knecht,
so ist es gut, so ist es recht

von Fallersleben
Zitieren
#10
was ich eher gerne realisieren würde wäre die Steuerung des iRadio auf dem Raspberry mit einem Encoder. Irgendie ist es Blödsinn auf einem frei programmierbaren Prozessormodul einen zweiten kleinen Prozessor zur Abfrage eines Encoders dazu zu setzen.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#11
(17.11.2018, 21:54)saarfranzose schrieb: was ich eher gerne realisieren würde wäre die Steuerung des iRadio auf dem Raspberry mit einem Encoder. Irgendie ist es Blödsinn auf einem frei programmierbaren Prozessormodul einen zweiten kleinen Prozessor zur Abfrage eines Encoders dazu zu setzen.

Was hindert Dich daran es zu tun? Ist doch nicht viel anders als die Sache mit einem AVR Mikrokontroller zu lösen.

https://radio-bastler.de/forum/showthrea...#pid134800
Chapter 8: Rotary Encoders

Google: rotary encoder raspberry pi c code

Erstes Ergebnis: https://www.sunfounder.com/learn/Super_K...rrypi.html

Fragen zur Umsetzung? Immer raus damit.
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#12
der code ist die eine Sache. Der encoder soll aber im iRadio die playlist schalten. Wie das ineinandergreift, dazu fehlen mir die Zusammenhänge. Und da nützt mir auch nicht die Lektüre eines englischen Buches. Das gleiche mit einem Display. Code-Beispiele sind schnell ergoogled. Bibliotheken, standalone Beispiele, alles kein Thema. Findet man auf deutsch und mit Bildchen und Filmchen. Aber wenn ich dann sehe welche Klimmzüge die Programmierer unter uns anstellen um Daten zwischen den Programmteilen auszutauschen bin ich als einfacher Anwender restlos überfordert.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#13
Hallo Jupp,

wie das "Ineinandergreifen" von Programmcode für den Rotary Encoder und VLC funktioniert, zeigen wir ja im Nachbarthread mit den GUIs. Der Rotary Encoder ist da ein grafischer Knopf oder ein Tastendruck (ncurses Beispiel von Martin).
Wir machen das nur in C/C++ (wegen der geringeren CPU Auslastung) wie Pimoroni es in Python vormacht, über das Remote Control Interface von VLC, sprich wir senden über TCP/IP ein bestimmtes Kommando an VLC.
Die ganze Netzwerkprogrammierung kann man in C "zu Fuß" erledigen oder wie gezeigt einfach mittels dem zusätzlichen Programm Netcat (nc) in einem Einzeiler.

Da wo im Beispielcode für den RoteryEncoder, aus dem verlinkten Artikel oben, der globalCounter inkrementiert wird (globalCounter++) steht dann einfach zusätzlich der Befehl zur Kontaktaufnahme zu VLC und das Absenden des Befehls für das Umschalten auf den nächsten Programmplatz.

system("echo \"next\" | nc 127.0.0.1 9294 -N");

Vereinfacht also so, aus:

Zitat:if(flag == 1){
       flag = 0;
       if((Last_RoB_Status == 0)&&(Current_RoB_Status == 1)){
           globalCounter ++;
           printf("globalCounter : %d\n",globalCounter);
       }

       if((Last_RoB_Status == 1)&&(Current_RoB_Status == 0)){
           globalCounter --;
           printf("globalCounter : %d\n",globalCounter);
       }
}


wird :

Zitat:if(flag == 1){
       flag = 0;
       if((Last_RoB_Status == 0)&&(Current_RoB_Status == 1)){
           system("echo \"next\" | nc 127.0.0.1 9294 -N");

           globalCounter ++;
           printf("globalCounter : %d\n",globalCounter);
       }

       if((Last_RoB_Status == 1)&&(Current_RoB_Status == 0)){
           system("echo \"prev\" | nc 127.0.0.1 9294 -N");
           globalCounter --;
           printf("globalCounter : %d\n",globalCounter);
       }
}

Der Befehl next, gesendet an 127.0.0.1:9294 schaltet ein Programm weiter hoch, prev ein Programm weiter runter.

Schaue Dir ruhig die Codebeispiele zu FLTK und auch zu ncurses im Nachbarthread an.

Bitte Jupp, wenn etwas unklar ist, gerade was das  Zusammenspiel mit VLC angeht, dann einfach raus damit und rein ins Forum. Hier ist der Platz um alle Fragen zu beantworten.

Viele Bastlergrüße
Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#14
Hallo, Wilhelm,
unter dem Link:
https://avrhelp.mcselec.com/index.html?encoder.htm
bekommt man die Lösung mit Drehencoder "direkt vom BASCOM-Hersteller"
Erwähnenswert als Radiobastler sind auch die BASCOM-Routinen, welche
diverse Codes von üblichen Fernbedienungen auswerten.
Zu BASCOM und C sind die Meinungen geteilt. Beides sind Compiler und
erzeugen wohl in etwa vergleichbaren Maschinencode.
Ich persönlich habe mich für BASCOM entschieden, da der Quelltext einfach
ist und ich lieber zum Lötkolben greife, als eine andere Programmiersprache
lernen zu wollen. Wie gesagt: Geschmackssache
Viele Grüsse
Micha
Zitieren
#15
Danke Micha, ich kann Deine Entscheidung für Bascom verstehen.
Ich werde mich auch mal damit befassen.

Gruß
Wilhelm
Niemandes Herr, Niemandes Knecht,
so ist es gut, so ist es recht

von Fallersleben
Zitieren
#16
Das geht natürlich mit allen Programmiersprächen bzw sicherlich
auch anderen Chips, welche sich von AVRs unterscheiden.
Man muss sich jedoch mit der Hardware auseinandersetzen,
welche sich lediglich auf die Phasenverschiebung von 2
Pineingängen bezieht. Ob es ausserhalb von BASCOM fertige
Befehle gibt, weiss ich nicht, jedoch sicherlich machbar.
VG Micha
Zitieren
#17
Hallo Jupp,

ich weiß, daß der Thread schon älter ist, wollte Dir aber trotzdem für die Drehencoder-Idee und die vorgestellte physische Umsetzung danken. Basierend auf diesen Anregungen habe ich meinen eigene Version gebaut (siehe Foto unten). Der Formfaktor ist 20x55mm, die Versorgungsspannung 3.3V. Angesteuert wird damit kein Radio sondern der Verstärker eines Multiroom-Systems (Arylic Up2Stream AMP2.1). Das Besondere hierbei ist, daß für Volume+ und Volume- keine dedizierten Eingänge existieren sondern beides (und weitere Funktionen) über einen Eingang läuft und nur über verschiedene Spannungslevel unterschieden wird. Deshalb enthält meine Version noch ein paar Transistoren und Widerstände, die ansonsten nicht notwendig wären.

Die Software basiert auf Deinem Vorschlag, die eigentliche Interruptroutine habe ich aber gegen eine ausgetauscht, die ich hier gefunden habe:
https://github.com/buxtronix/arduino/tre...ies/Rotary
Gefühlt schien diese Routine in meinem speziellen Szenario etwas zuverlässiger zu funktionieren als die von Dir verwendete (was das "Verschlucken" von Drehimpulen betrifft). Mit dem Debouncing-Intervall mußte ich noch etwas rumprobieren, da das Arylic-Board anscheinend noch eine eigene Debouncing-Logik enthält und zu kurze Impulse einfach ignoriert. In meinem Fall war 100msec ein guter Wert.

Viele Grüße und ein schönes Osterfest wünscht
Sven

[Bild: dreh_encoder.jpg]
Zitieren
#18
Hallo Sven,
freut mich dass ich dich inspirieren konnte.
Zu dem Zeipunkt hatten wir in iRadio noch keinen gpiod für einen encoder :-)
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#19
(21.08.2018, 14:44)saarfranzose schrieb: inzwischen hab ich den Verdrahtungsplan gezeichnet.

Hallo,
auch wenn dieser Bericht schon alt ist würde mich ein nachbau interessieren.Ich bin schon ein älterer Herr der des Programierens oder umwandelns nicht mehr mächtig ist.Wäre es irgendwie möglich das sie mir den code als Hex file zukommen lassen könnten. ich wäre ihnen sehr dankbar.
Gruss Horst Klug
Zitieren
#20
Hallo Horst,
auf meinem blog hattest du keine Möglichkeit hinterlassen wie ich dich erreichen könnte.

ich habe die Hex-Datei exportiert. Kann aber nicht garantieren dass da so funktioniert. Ich bin auch mal gespannt wie du die Datei auf den Attiny bringen willst.


.hex   rotary_attiny.ino.hex (Größe: 2,41 KB / Downloads: 3)
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren


Gehe zu: