Forum: Mikrocontroller und Digitale Elektronik IR NEC Signal mit einlesen


von Michael (Gast)


Lesenswert?

Hallo zusammen,

auf die Gefahr hin gleich geseinigt zu werden wollte ich hier mal was 
fragen.

Möchte eine IR- Fernbedienung, die NEC Signale sendet mit einem Atmel 
einlesen.
Dieser soll dann bei bestimmten Tastendruck Funktionen ausführen. (Nur 
Ausgang ansteuern z.B. LED einschalten)
Es ist nur eine Spielerei was ich ausprobieren möchte.

Bin was programmieren angeht eine totale Pfeife.
Möchte da aber bissl was ausprobieren und Versuche machen.
Was ich aber mittlerweile "geschafft" habe, etwas in C zu programmieren,
(besser gesagt zu kopeiren) dass meine Ausgänge angeseuert werden sobald 
ein Taster gedruckt wird :-)
Allerdings möchte ich keinen Taster, sondern das Signal der IR 
Fernbedienung verwenden.
IR Empfänger hab ich, kann ich auch an den Atmel anschließen.


Die Signale der Fernbedieung (nach dem ersten Break Signal) hab ich mit 
dem Oszi ausgelesen und in binär aufgeschreiben.
Der Wert war plausiebel, da die Blöcke invertiert zum vorherigen waren.
Also richtig aufgeschrieben :-)
Hab da ein Bild gefunden, in dem das schön aufgezeichnet war.

Nun weiß ich allerdings nicht wie ich dem Controller "beibringe", dass 
er auf die 11000100 00111011 usw. hören soll.
(wollte jetzt nicht alle 4 Blöcke aufschreiben).

z.B. Wenn PinD5 ist 11000100 ...
(oder diesen Wert in einem anderen Zahlensystem)
Wenn PinD5 ist Taster gedrückt hab ich geschafft, aber nicht, dass er 
auf das IR Signal reagiert :-(

Gibt es dazu ein "Grundprojekt", damit die "Hör auf NEC Protokoll" beim 
Atmel aktiviert wird, bei dem ich dann "einfach" meine ausgelesenen 
Werte eintragen und dem Pin an dem der IR Empfänger angeschlossen ist 
zuweißen kann?
Suche kein kompliziertes alles könnendes (ich nicht versehendes), 
sondern nur auf bestimmte NEC Signale hören.

p.s.
Englischkenntnisse sind so gut wie nicht vorhanden.

Hoffe ich hab mich einigermaßen verständlich ausgedrückt?

Grüße
Michael

von Thomas G. (blasebalg)


Lesenswert?


: Bearbeitet durch User
von my2ct (Gast)


Lesenswert?

Michael schrieb:
> Suche kein kompliziertes alles könnendes (ich nicht versehendes),
> sondern nur auf bestimmte NEC Signale hören.

Dann ist IRMP wohl nichts für dich

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

1. Bau dir einen Empfänger mit der o.a. IRMP Library und compiliere mit 
NEC und NEC42 Unterstützung.
2. Nutze eine serielle Schnittstelle (oder ein LCD) um die Codes deiner 
NEC Fernbedienung (Adresse und Tastencode) herauszufinden.
3. Baue eine Software, die die FB-Adresse durchlässt und dann per 
'switch-case' oder 'if else', um die Tastencodes auszuwerten und damit 
Pins zu schalten.

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

Hallo,

danke für die Antworten.
Das IRMP hab ich bereits im Vorfeld angeschaut und nix verstanden.
(werd ich auch niemals).
Ich such NUR ein paar Zeilen, dass die Startsequenz beginnt, endet und 
der Tastencode anfängt.
Den TastenCode hab ich bereits per Oszi ausgelesen.

von Wolfgang (Gast)


Lesenswert?

Michael schrieb:
> Das IRMP hab ich bereits im Vorfeld angeschaut und nix verstanden.
> (werd ich auch niemals).

Mit deinem Smartphone, falls du Besitzer eines solchen bist, wird es dir 
nicht viel anders ergehen. Benutzen kann man es trotzdem.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Michael schrieb:
> Ich such NUR ein paar Zeilen, dass die Startsequenz beginnt, endet und
> der Tastencode anfängt.

Ich habe den Eindruck, das du keine Ahnung hast, wie schwierig es ist, 
z.B. Codes anderer Fernbedienungen, Störungen des IR Empfängers und 
Situationen wie nur teilweise empfangene Codes auszublenden. Genau das 
macht IRMP in nahezu perfekter Manier und deswegen ist es wirklich 
sinnvoll, sich lieber ein paar Stunden mit IRMP zu beschäftigen, anstatt 
zu probieren, das Rad neu zu erfinden.
Immerhin hast du damit auch eine Basis für andere Projekte und lernst 
nebenbei noch eine Menge.

von Nec Decoder (Gast)


Lesenswert?

Fertige Zeilen in C habe ich nicht, aber in PIC Assembler wie folgt 
gelöst:

Eine mögliche Vorgehensweise zum Erkennen der Startsequenz:
Bei fallender Flanke des IR Empfängers einen Timer starten, der länger 
als 9ms Laufzeit hat. z.B einen 8Bit Timer mit 64µs Taktrate ergibt 
16,384ms Messzeit.
Tritt nun eine folgende steigende Flanke auf, so kann man den Timerwert 
prüfen. Liegt er z.B. unterhalb von 8,5ms oder oberhalb von 9,5ms oder 
ist er sogar übergelaufen, so verlässt man die Routine und beginnt sie 
von Neuem. Also wieder auf eine fallende Flanke warten. Liegt die 
Messung im gewünschten Toleranzfenster so wurde die 9ms Lowphase 
erkannt. Die Routine wird nicht verlassen sondern der Timer erneut 
genullt und auf dieselbe Weise wird überprüft, ob der 9ms Lowphase eine 
4,5ms Highphase folgt. Wird etwas anderes als die 4,5ms plus minus 
Toleranz erkannt, so wird die Routine hier verlassen und wieder ganz von 
Vorne begonnen. Wurde aber auch die 4,5ms Highpase korrekt erkannt, so 
ist die Startsequenz detektiert und es kann  nun ans Einlesen der 
Datenbits gehen.

Zuerst wird die 8Bit Geräteadresse eingelesen und zwischengespeichert, 
dann wird die invertierte Geräteadresse eingelesen und auf 
Übereinstimmung mit der zuvor eingelesenen überprüft. Bei Abweichung... 
Routine verlassen und wieder von Vorne.

Bei Übereinstimmung geht es mit dem Einlesen des 8Bit Kommandos weiter. 
Dieses wird dann im zweiten Lesevorgang mit dem invertierten Kommando 
verglichen.
Abweichung = Routine verlassen. Übereinstimmung = weitermachen.

Zur Sicherheit den kompletten Vorgang mehrfach wiederholen, also nicht 
nur ein einziges Protokoll einlesen sondern zwei oder drei 
aufeinanderfolgende und diese dann auf Übereinstimmung prüfen. Wenn 
mehrere aufeinanderfolgende übereinstimmen kann man davon ausgehen 
richtig empfangen zu haben.
Nun kann das gelesene Kommando mit den bekannten Kommandos verglichen 
und die dem Kommando entsprechende Aktion ausgeführt werden.

Die Leseroutine arbeitet ebenfalls mit dem Timer, aber diesmal auf 
2,048ms Overflow eingestellt. Läuft er über wurde nichts Sinvolles 
erkannt.
Zum Lesen der 8Bit wird erneut auf eine fallende Flanke gewartet und 
dann der Timer gestartet wenn sie auftritt. Danach folgt entweder 560µs 
Lowpegel weil eine 0 gesendet wurde oder 1,69ms Lowpegel weil eine 1 
gesendet wurde. Unterscheiden läasst sich das indem man z.B. nach ca. 
830µs den Pegel einliest. Ist er hier noch Low so liegt das an der 
langen Lowpegel Phase weil eine "1" gesendet wurde. Ist er hier bereits 
wieder High, so liegt das an der kurzen Lowphase weil eine "0" gesendet 
wurde.
Auf diese Art un Weise werden in einer Loop jeweils 8Bit eingelesen. 
Läuft der Timer über ist etwas schief gelaufen, also Routine verlassen 
und alle Daten verwerfen. Läuft er nicht über so hat man etwas mit einer 
gewissen Sicherheit/Unsicherheit empfangen, nämlich nur einmal. Deshalb 
macht es Sinn, mehrfach zu lesen und auf Übereinstimung zu prüfen.

von Nec Decoder (Gast)


Angehängte Dateien:

Lesenswert?

Nec Decoder schrieb:
> Danach folgt entweder 560µs
> Lowpegel weil eine 0 gesendet wurde oder 1,69ms Lowpegel weil eine 1
> gesendet wurde. Unterscheiden läasst sich das indem man z.B. nach ca.
> 830µs den Pegel einliest. Ist er hier noch Low so liegt das an der
> langen Lowpegel Phase weil eine "1" gesendet wurde. Ist er hier bereits
> wieder High, so liegt das an der kurzen Lowphase weil eine "0" gesendet
> wurde.

Dieser Text bezieht sich auf das IR Signal. Der Emfpänger liefert aber 
die Pegel genau umgekehrt. Also sind die Einsen und Nullen hier genau 
umgekehrt wie oben beschrieben.
Anbei noch ein Bild wie der Code am Empfängerausgang aussieht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> Das IRMP hab ich bereits im Vorfeld angeschaut und nix verstanden.

1. IRMP-Source herunterladen

Klicke auf IRMP: Download

2. IRMP-Quellen ins Projekt einfügen

Klicke auf IRMP: Source-Code

3. irmp-main-avr.c als main-Modul hinzufügen oder Inhalt
   ins vorgefertigte main.c kopieren

Klicke auf IRMP: Source-Code unter "Beispiele ..."

4. F_CPU im Projekt setzen

Klicke auf IRMP: Source-Code und rolle vor bis zum roten Kasten: 
"Wichtig"

5. irmpconfig.h: Setze alle IRMP_SUPPORT_xxx_PROTOCOL auf 0
   IRMP_SUPPORT_NEC_PROTOCOL auf 1

Klicke auf IRMP: IRMP SUPPORT xxx PROTOCOL

Du kannst die Stelle aber auch so lassen wie es ist. Dann "versteht" 
Dein µC sogar noch ein paar weitere Fernbedienungen, die außerdem noch 
in Deinem Haushalt rumschwirren.

6. irmpconfig.h: IRMP_PORT_LETTER + IRMP_BIT_NUMBER definieren

Klicke erst auf IRMP: IRMP SUPPORT xxx PROTOCOL und
rolle bis zum nächsten Unterkapitel vor.

7. Projekt kompilieren und Programm flashen

Klicke dazu auf die Dokumentation Deiner eingesetzten IDE.

8. USB-UART-Adapter an µC-UART anschließen und sich über
   Ausgabe bei jedem Fernbedienungs-Tastendruck freuen

Klicke jetzt nicht, sondern schnapp Dir Bleistift und Zettel und notiere 
Dir nun jeden empfangenen Code samt Tastennamen auf dem Zettel.

Geschätzter Aufwand: 15 Minuten für den fortgeschrittenen Anwender, 
halbe bis ganze Stunde für den Anfänger. Bis dahin hast Du gerade eine 
Handvoll von Zeilen Deines NEC-Decoders überhaupt geschrieben bzw. aus 
anderen Quellen zusammengeklaubt.

Wenn alle Schritte 1-8 erfolgreich waren:

9. Anpassungen von main(), um IR-Signale auszuwerten und in
    Aktionen umzusetzen. Dazu obigen Zettel einsetzen.

Klicke dazu auf IRMP: Anwendung von IRMP

War das jetzt sooo schwierig? Oder ist es Dir zu anstrengend einen 
Artikel wie IRMP überhaupt sinnentnehmend zu lesen?

Merke: IRMP bekommst Du geschenkt. Aber deshalb ist freie Software nicht 
immer kostenlos. Man muss schon etwas reinstecken: Es nennt sich 
"Aufwand". Aber dieser ist dank der IRMP-Dokumentation äußerst 
niedrig. Rausreden kannst Du Dich mit Deinen nicht vorhandenen 
Englischkenntnissen jedenfalls nicht: Der Artikel ist in deutsch 
verfasst.

: Bearbeitet durch Moderator
von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

hab jetzt fast 2 Tage damit verbracht das Standard IRMP Projekt inkl. 
UART Ausgabe in Studio 6 zum Laufen zu bringen.
Das funktioniert und ich kann die Tastensignale anschauen. :-)

Jetzt versuch ich seit 1 Tag eine LED zum Blinken im Takt zu bringen 
solange eine Taste gedrückt ist.
Aber da scheiterst gewaltig... (Es passiert einfach mal nix, egal was 
ich schreib)

Ja, ich hab den Artikel gelesen, hilft MIR aber nicht weiter.
Kann nicht mal einschätzen wo der Fehler liegt. (oder die Fehler)
Evtl. schon ganz am Anfang bei der Zuordnung der Ein/ Ausgänge beim 
Mega8 oder dann doch an den paar Zeilen die ich geschrieben und aus 
einem anderen funktionierenden Projekt rauskopiert habe.

Mein "Werk" beginnt ab main (void)
sowie oben die 16MHz, die ich reingeschrieben habe.

Hat evtl. jemand einen Tip?

Grüße
Michael

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

1
     (irmp_data.protocol == IRMP_NEC_PROTOCOL &&        // NEC-Protokoll
2
       irmp_data.address == 0xDC23            // Adresse 0xDC23
3
       && irmp_data.command == 0x0014 |          // Taste Vol+
4
       irmp_data.protocol == IRMP_NEC_PROTOCOL && 
5
       irmp_data.address == 0xDC23        
6
       && irmp_data.command == 0x0017 )          // Taste Pfeil oben  
7
       {
Das sieht zu kompliziert aus. Teste einmal in der Hauptschleife auf NEC 
Protokoll und die Adresse, dann mache aus irmp_data.command ein 
switch-case Konstrukt.
Dann musst du nicht jedesmal alles abfragen.
Das mit dem Repetition Flag klappt nicht bei allen Fernbedienungen. Lass 
es besser weg und löse die Tastenwiederholung durch das Durchlaufen der 
Hauptschleife.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> hab jetzt fast 2 Tage damit verbracht das Standard IRMP Projekt inkl.
> UART Ausgabe in Studio 6 zum Laufen zu bringen.
> Das funktioniert und ich kann die Tastensignale anschauen. :-)

Gratuliere erst einmal zu Deinem Durchhaltevermögen :-)
Ich nehme an, dass Du dabei auch einiges gelernt hast.

Matthias S. schrieb:
> Das sieht zu kompliziert aus.

Das ist nicht nur viel zu kompliziert, sondern auch mit einigen Fehlern 
gespickt.

Zum Beispiel sollte man statt dem bitweisen Operator '|' besser den 
Logik-Operator '||' verwenden, wenn man Bedingungen miteinander 
verknüpfen möchte.

Außerdem ist das hier falsch:
1
while (IRMP_FLAG_REPETITION == 0x01)

IRMP_FLAG_REPETITION ist eine Konstante, nämlich exakt 0x01. Diese 
ändert sich nie. Damit wird das zu einer Endlosschleife. Das Programm 
hängt sich hier sprichwörtlich auf.

@Michael: Du hast offenbar gewaltige Lücken bei Deinen C-Kenntnissen. So 
wird das schwierig.

Was möchtest Du? Eine LED leuchten lassen, solange eine Taste gedrückt 
ist?

Hier mal eine mögliche Lösung, dabei musst Du die ISR und main() durch 
den unteren Code ersetzen. Dabei vermeide ich grundsätzlich 
Delay-Funktionen, die nur das Programm ausbremsen. Dann verhält sich das 
Programm träge und reagiert nicht so schnell, wie man möchte. Wenn ich 
sowieso eine Timer-Routine habe, dann sollte ich sie auch nutzen!

Zunächst definieren wir eine globale Variable als Countdown, die jede 
Millisekunde heruntergezählt wird:
1
static volatile unsigned char msec_counter;     // Countdown, wird jede Millisekunde heruntergezaehlt

Jetzt bauen wir in die ISR den Countdown ein:
1
ISR(COMPA_VECT)                                 // Timer1 ISR, called every 1/15000 sec
2
{
3
    static uint8_t cnt;                         // Zaehlvariable, wird bei jedem Aufruf um 1 inkrementiert
4
5
    (void) irmp_ISR();                          // call irmp ISR
6
7
    cnt++;
8
9
    if (cnt == F_INTERRUPTS / 1000)             // Wenn cnt == 15, ist eine Millisekunde vergangen
10
    {
11
        cnt = 0;                                // cnt zuruecksetzen
12
13
        if (msec_counter > 0)                   // Countdown herunterzaehlen
14
        {
15
            msec_counter--;
16
        }
17
    }
18
}

Jetzt die main-Funktion. Sie prüft das IR-Protokoll und die Adresse nur 
einmal.
1
int
2
main (void)
3
{
4
    IRMP_DATA   irmp_data;
5
6
    DDRB = 0b11111111;                          // Alle auf B sind als Ausgaenge definiert
7
    DDRC = 0b11001111;                          // PC4, PC5 Eingaenge
8
    DDRD = 0b11110011;                          // PD2, PD3 Eingaenge (D2= IR IN; IR auch in IRMPConfig.h eingestellt!
9
10
    irmp_init();                                // initialize IRMP
11
    timer1_init();                              // initialize timer1
12
13
    sei ();                                     // enable interrupts
14
15
    for (;;)
16
    {
17
        if (irmp_get_data (&irmp_data))
18
        {
19
            if  (irmp_data.protocol == IRMP_NEC_PROTOCOL &&         // NEC-Protokoll
20
                 irmp_data.address == 0xDC23)                       // Adresse 0xDC23
21
            {
22
                if (irmp_data.command == 0x0014 ||                  // Taste Vol+ oder
23
                    irmp_data.command == 0x0017)                    // Taste Pfeil oben
24
                {
25
                    PORTD |= (1<<PD0);                              // Ausgang PD0 ansteuern
26
                    msec_counter = 200;                             // countdown auf 200 (maximal 255 moeglich!)
27
                }
28
                else if (irmp_data.command == 0x0015 ||             // Taste Vol- oder
29
                         irmp_data.command == 0x0018)               // Taste Pfeil unten
30
                {
31
                    PORTD |= (1<<PD1);                              // Ausgang PD1 ansteuern
32
                    msec_counter = 200;                             // countdown auf 200 (maximal 255 moeglich!)
33
                }
34
            }
35
        }
36
        else if (msec_counter == 0)                                 // 200 msec vergangen...
37
        {
38
            PORTD &= ~((1<<PD0) | (1<<PD1));                        // PD0 und PD1 zuruecksetzen
39
        }
40
    }
41
}

Immer, wenn eine Taste erkannt wurde, wird die entsprechende LED 
eingeschaltet. Wurde 200msec kein IR-Signal erkannt, werden beide LEDs 
wieder abgeschaltet.

Wie funktioniert das? Wenn eine LED eingeschaltet wird, wird der 
Countdown-Zähler auf 200 gesetzt. In der ISR wird dieser Countdown dann 
jede Millisekunde heruntergezählt. Sobald der Wert 0 ist, werden die 
LEDs gelöscht.

Wenn Du LED1 und LED2 vom Timing her getrennt behandeln willst, musst Du 
für jede LED einen eigenen Countdown-Zähler einbauen. Aber normalerweise 
willst Du offenbar immer nur eine LED leuchten lassen, wenn eine 
Taste gedrückt wurde. Probiere es also aus und berichte, ob das für Dich 
so passt oder nicht.

Das Programm ist ungetestet. Wenn etwas nicht so läuft wie beschrieben, 
melde Dich bitte.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Alternativ könnte man auch je eine EIN-Taste und eine AUS-Taste für jede 
LED definieren. Dann braucht man den Millisekunden Countdown gar nicht 
und die ISR- und main-Funktion kann man dann folgendermaßen schreiben:
1
ISR(COMPA_VECT)                                 // Timer1 ISR, called every 1/15000 sec
2
{
3
    (void) irmp_ISR();                          // call irmp ISR
4
}
5
6
int
7
main (void)
8
{
9
    IRMP_DATA   irmp_data;
10
11
    DDRB = 0b11111111;                          // Alle auf B sind als Ausgaenge definiert
12
    DDRC = 0b11001111;                          // PC4, PC5 Eingaenge
13
    DDRD = 0b11110011;                          // PD2, PD3 Eingaenge (D2= IR IN; IR auch in IRMPConfig.h eingestellt!
14
15
    irmp_init();                                // initialize IRMP
16
    timer1_init();                              // initialize timer1
17
18
    sei ();                                     // enable interrupts
19
20
    for (;;)
21
    {
22
        if (irmp_get_data (&irmp_data))
23
        {
24
            if  (irmp_data.protocol == IRMP_NEC_PROTOCOL &&         // NEC-Protokoll
25
                 irmp_data.address == 0xDC23)                       // Adresse 0xDC23
26
            {
27
                switch (irmp_data.command)
28
                {
29
                    case 0x0014: PORTD |= 1<<PD0; break;            // Taste Vol+: PD0 ein
30
                    case 0x0015: PORTD &= ~(1<<PD0); break;         // Taste Vol-: PD0 aus
31
                    case 0x0017: PORTD |= 1<<PD1; break;            // Taste Pfeil oben: PD1 ein
32
                    case 0x0018: PORTD &= ~(1<<PD1); break;         // Taste Pfeil unten: PD1 aus
33
                }
34
            }
35
        }
36
    }
37
}

Die ISR kannst Du in diesem Fall wieder auf den Aufruf von irmp_ISR() 
reduzieren, den Kram mit dem msec_counter kannst du komplett aus dem 
Source wieder löschen. Jetzt ist die main()-Funktion noch einfacher 
geworden.

Aber wie gesagt: Jetzt brauchst Du für jede Ein-/Aus-Funktion immer 
jeweils 2 Tasten.

: Bearbeitet durch Moderator
von Michael (Gast)


Lesenswert?

Super,
Dankeschön. :-)
Meine C Kenntnisse sind gleich Null.
Hab das nie gelernt bzw. beigebracht bekommen.
Versuche selber etwas damit rum zu probieren.

Spiele momentan mit beiden Varianten (die erste und die zweite mit den 
switch)

Wollte nun einen Schritt weiter gehen und noch dazu Eingänge abfragen.
den ersten Fall mit einer Taste,
den zweiten mit dem switch und zwei tasten
zusätzlich das mit dem Eingang abfragen

Auf bestimmtes Fernbedienungssignal UND einen high Pegel am Atmel.
Erst dann soll der Ausgang geschaltet werden.

Was möchte ich nun probieren?
Eine Tast soll unterschiedliche Ausgänge ansteuern.
Je nach dem welcher Eingang high ist soll der andere Ausgang angesteuert 
werden.
Versucht hab ich das:
Mit && wird ein Ausgang angesteuert egal was an dem PIN anliegt.
Mit & wird garnix mehr angesteuert.

else if ((irmp_data.command == 0x0050) &&  // Taste MENU
  (PINC & (1<<PINC5)))      // PC5 = high  ->einlesen Funktioniert NICHT
  {
  PORTC |= (1<<PC1);                       // Ausgang PC1 ansteuern, da 
PC5 hight ist
  msec_counter = 200;                      // countdown auf 200 (maximal 
255 moeglich!)
  }

else if ((irmp_data.command == 0x0050) &&  // Taste MENU
  (PINC & (1<<PINC4)))      // PC4 = high  ->einlesen Funktioniert NICHT
  {
  PORTC |= (1<<PC2);                      // Ausgang PC2 ansteuern, da 
PC4 high ist
  msec_counter = 200;                     // countdown auf 200 (maximal 
255 moeglich!)
  }

von Michael (Gast)


Lesenswert?

Meinen vorherigen Beitrag bitte erstmal ignorieren.
Hab den Fehler gefunden...
Lag an meiner Versuchs HW (Steckbrett; teils fliegender Aufbau)

Werd mich nun an einen weiteren Versuch wagen.

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

da ich momentan mit einer Funktion nicht weiterkomme wollte ich hier 
nochmal um Rat fragen.

Meine Programmiererei funktioniert soweit recht gut.
Hat mich selber überrascht ;-)

Nur eines schaff ich leider nicht.

Ich möchte:

Wenn Taster an Fernbedienung gedrückt ist:
PD5 ansteuern

Fall 1:
- solange PD3 low ist
- solange PD3 dann high ist

Aufhören wenn PD3 dann wieder low ist
(PD5 nicht mehr ansteuern)
Also low, high, low -> Aus

Fall 2:
- solange PD3 high ist

Aufhören wenn PD3 dann low ist
(PD5 nicht mehr ansteuern)
Also high, low -> Aus


Des weiteren soll diese Funktion JEDERZEIT mit der OK Taste der 
Fernbedienung abgebrochen werden können
(PD5 wird dann nicht mehr angesteuert und Funktion verlassen)

[schön wäre, wenn der Spaß nach 12 Sekunden automatisch stoppen würde, 
aber das war mir zu viel]


Anbei den Ausschnitt des Programms die die nicht so funktionierende 
Funktion beinhaltet.

Probleme:
OK Taste wird gar nicht beachtet :-(

Fall 1 ist erst zu Ende wenn PD3:
low, high, low, high, low -> Aus

Fall 2 ist erst zu Ende wenn PD3:
high, low, high, low -> Aus


Nur warum muss "hinten" immer ein weiteres high, low dazu?


Vor dem else if frag ich nur normale Tasten ab und steuer die Ausgänge 
so lange wie die Taste gedrückt ist.
Also ncihts verschachteltes oder kompliziertes, sondern ganz einfaches 
wie mir paar Beiträge vorher von Frank gezeigt wurde.
Den Case hab ich momentan nicht in Verwendung.


Grüße
Michael

von Forist (Gast)


Lesenswert?

Michael schrieb:
> Funktioneirt_nicht_wie_es_soll.txt

Was soll das sein. Kein Syntax Highlightning, nichts funktioniert :-(

Was spricht dagegen, die für die Programmiersprache üblicherweise 
verwendete File Extension zu verwenden?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Das hier
1
&& (!(irmp_data.command == 0x0055))

tritt immer ein, denn die ganze Entscheidung hängt ja zuerst hiervon ab:
1
else if (irmp_data.command == 0x0054)
Um eine etwaige OK Taste abzufragen, musst du ja erstmal ein neues 
Kommando von der FB empfangen.
Ich würde sowas vermutlich mit Flags machen. Also ein Flag setzen für 
den 'schwebenden Zustand' mit PD3, das später den Pin setzt.

Und wenn irmp.data_command() die OK Taste empfängt, löschst du das Flag 
wieder. Ansonsten wird es nach der Sequenz Low,high,low an PD3 gelöscht 
(oder was auch immer du definierst).
Ganz am Ende der Hauptschleife setzt du dann zentral den gewünschten 
Port, abhängig vom Flag.
Übrigens finde ich es sehr gut, das du dich soweit damit schon 
beschäftigt hast - Respekt :-)
Wenn du nächstes Mal deine Datei einfach als main.c oder so hochlädst, 
überrascht dich dieses Forum mit syntaxhighlighting.

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

puhhh... Flags
War schon froh die "einfachen" Abfragen hinzubekommen.
Das mit den Flags schau ich grad bissl an... schwierige Sache (zumindest 
für mich)
Hört sich aber für meine Zwecke gut an :-)

Aber dass mein low, high, low Teile nicht funktionieren ist mir ein 
Rätsel.
Auch wenn ich Funktion einzeln in lauter verschiednee kleine if mach, 
kommt immer das Gleiche dabei raus :-(

Grüße
Michael

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Michael schrieb:
> puhhh... Flags

Flags sind easy. Das ist einfach eine Veriable, die du mit TRUE oder 
FALSE füllen kannst. Wenn du z.B. PD5 high machen willst, setzt du eine 
Variable auf TRUE und am Ende der Hauptschleife checkst du, wie die 
Variable steht.
Ist sie TRUE, setzt du PD5, ist sie FALSE, löschst du PD5.
Um vVerwirrungen damit zu vermeiden, steht bei meinem Projekten die 
Definition von TRUE und FALSE (nicht verwechseln mit true und false), in 
den Settings:
1
#define TRUE 1
2
#define FALSE !TRUE
3
// und hier mal ein Bitfeld mit Flags
4
typedef struct theFlags {
5
 uint8_t Send  : 1 ; 
6
 uint8_t Mute  : 1 ; 
7
 uint8_t TimerActive : 1 ;
8
 } theFlags_t;

Dann kann man damit rummachen, z.B.
1
 theFlags_t MyFlags ;
2
    if (irmp_get_data (&irmp_data))
3
    {
4
    if ((irmp_data.protocol == 0x1C) && (irmp_data.address == 0x0113)) 
5
    {
6
    switch (irmp_data.command) {   
7
     case    FB_VIDEOUP  :  if (DAC[0] < 63) DAC[0]++; 
8
           MyFlags.Send = TRUE; 
9
          break;
10
     case    FB_VIDEODN  :  if (DAC[0] > 0) DAC[0]--; 
11
           MyFlags.Send = TRUE; 
12
          break;
13
     case    FB_CHANUP   :  if (DAC[1] < 63) DAC[1]++; 
14
           MyFlags.Send = TRUE; 
15
          break;
16
     case    FB_CHANDN   :  if (DAC[1] > 0) DAC[1]--; 
17
           MyFlags.Send = TRUE; 
18
          break;
19
    case    FB_STORE  : store_EEPROM(); break;
20
21
// if power is pressed mute both
22
    case  FB_POWER  : if (MyFlags.Mute) {
23
          DAC[0] = vol0;
24
          DAC[1] = vol1;
25
          MyFlags.Send = TRUE;
26
          MyFlags.Mute = FALSE;
27
          PORTB |= (1 << MUTE_PIN);  // Audio PA on
28
        } else {
29
          vol0 = DAC[0]; DAC[0] = 0;
30
          vol1 = DAC[1]; DAC[1] = 0;
31
          MyFlags.Send = TRUE;
32
          MyFlags.Mute = TRUE;
33
          PORTB &= ~(1 << MUTE_PIN); // mute Audio PA
34
        }; break;
35
       }; // end switch
36
      } // end irmp_data_prot
37
     } // end irmp_get_data

Kleiner Ausschnitt. Das Flag myFlags.Mute sagt mir, ob die Anlage schon 
gemutet ist, also ob ein Tastendruck wieder laut machen soll. Das Flag 
myFlags.Send sagt, ob nach der ganzen Abfragerei was an den I²C Bus 
gesendet werden soll.
Entschuldige die merkwürdige Formatierung, aber das Forum ist mit TABs 
etwas eigenwillig.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.