19.08.2018, 19:14
(Dieser Beitrag wurde zuletzt bearbeitet: 19.08.2018, 19:55 von saarfranzose.)
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:
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
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)
Jupp
-----------------------------
was du baust ist immer mit dir verbunden
(Lego)
Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)