- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 18

Thema: RC5 Empfang mit TSOP1736

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270

    RC5 Empfang mit TSOP1736

    Anzeige

    Powerstation Test
    Hallo,
    ich habe versucht ein Programm zu schreiben, mit dem ich RC5 Code empfangen und an die serielle Schnittstelle weitergeben kann. Mit einem Basic-Programm funktioniert dass, mit meinem C-Programm leider nicht.
    Es wird zwar "Hallo Martin" ausgegeben, aber sonst nix.

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    
    struct rc5_parts
     {
        volatile char s_bit;
    	uint8_t addresse;
    	uint8_t code;
    	volatile char rdy;
     } rc5;
    
    volatile char start_rx = 0;
    char mid;
    
    void init_rc5()
    {
     MCUCR |= (1<<ISC11) | (1<<ISC10);
     GICR |= (1<<INT1);
     TCCR0 |= (1<<CS02);
     TCNT0 = 145;
    }
    
    //****************************************************USART******************************
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s) 
    { 
     while (!(UCSRA & (1<<UDRE))); 
     UDR = s; 
    } 
    
    void send_string(char *s) 
    { 
     while(*s != '\0') 
      { 
       send_char(*s); 
       s++; 
      } 
    } 
    
    //**********************************************************USART-ENDE********************
    
    SIGNAL(SIG_OVERFLOW0)
    {
     uint8_t i,j;
     i++;
     TCNT0 = 145;      //Timer soll nach 1.778ms Overflow haben
     if(i == 12)      
      {
       TIMSK &= ~(1<<TOIE0);
       rc5.rdy = 1;
       i = 0;
      }
     
     if(i<6)             //Wenn i<6, werden die ausgelesenen Bits zu Addresse hinzugefügr
    	{
    	  if(PORTD & (1<<4))
    	   {
    	    rc5.addresse |= (1<<(i-1));
    	   }
    	  else
    	   {
    	    rc5.addresse &= ~(1<<(i-1));
    	   }
        }
    	
     if((i>=6)&(i<12))    //6 - 11 werden zu rc5.code hinzugefügt
    	{
    	  if(PORTD & (1<<4))
    	   {
    	    rc5.code |= (1<<(i-6));
    	   }
    	  else
    	   {
    	    rc5.code &= ~(1<<(i-6));
    	   }
    	}
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
    
     
     if(rc5.s_bit<4)
      {
       rc5.s_bit++;
      }
     else
      {
       start_rx = 1;
       TIMSK |= (1<<TOIE0);
       TCNT0 |= 228;
       rc5.s_bit = 0;
      }
    }
       
    int main(void)
    {
     init_usart();
     init_rc5();
     char i = 1;
     sei();
     char result[10];
     char hello[15] = "Hallo Martin";
     send_string(hello);
     for(;;)
      {
       if(rc5.rdy == 1)
        {
         itoa(0110,result,10);
         send_string(result);
    	 rc5.rdy = 0;
    	}
      }
    }
    Seht ihr irgendwelche Fehler, die ich übersehen habe? Vom Prinzip her zählt das Programm mit jedem Interrupt an PD4 eine Variable hoch und sobald die größer 3 ist, springt der Timer an. Bei diesen 3 Interrupts sollen die 2 Startbits und das Togglebit erkannt werden.

    Gruß
    Martin

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Zitat Zitat von Spurius
    Code:
    TCNT0 |= 228;
    IMHO funktioniert das so nicht, weil du nicht an jedem Bit-Anfang einen IRQ bekommst

    Bei [01][01] bekommst du IRQs (als *) bei 0*1*0*1
    Bei [01][10] bekommst du IRQs (als *) bei 0*1.1*0, bei . gibt's keine IRQ

    Wenn es dir nicht darauf ankommt, das alles selber zu machen, gibt's nen C-Code im Wiki.
    Disclaimer: none. Sue me.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo,
    der Interupt wird halt dann ausgelöst, wenn das Togglebit 1 ist. Und sich das ja immer toggelt, müsste ich zumindest bei mehrmaligem Drücken ein Ergebnis sehen.

    Deinen Artikel im Wiki habe ich mir schon angeschaut, er ist auch eine große Hilfe, aber ich möchte selbst eine Lösung finden.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Was ist mit i und j in SIG_OVERFLOW0? Die sind nicht initialisiert! Eigentlich sollte der Compiler das warnen...

    So wie du die verwendest sollten die static sein:
    Code:
    SIGNAL(...)
    {
       static uint8_t i=0, j=0;
       i++;
       ...
    Das nimmt die aber die möglichkeit, sie von "aussen" zu verändern, etwa resetten wenn die IR-Daten korrupt sind. Was du willst ist IMHO nicht lokal static, sondern static.
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo SprintSB,

    ich habe jetzt einige Sachen verändert, ausgebessert, etc., aber rc5.code ist immer 0. Hat noch jemand eine Idee, was ich da falsch mache?

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <math.h>
    
    
    
    struct rc5_parts
     {
        volatile char s_bit;
    	volatile uint8_t addresse;
    	volatile uint8_t code;
    	volatile char rdy;
     } rc5;
    
    char mid;
    volatile uint8_t bitnummer = 0;
    
    void init_rc5()
    {
     MCUCR |= (1<<ISC11) | (1<<ISC10);
     GICR |= (1<<INT1);
     TCCR0 |= (1<<CS02);
    }
    
    //****************************************************USART******************************
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s) 
    { 
     while (!(UCSRA & (1<<UDRE))); 
     UDR = s; 
    } 
    
    void send_string(char *s) 
    { 
     while(*s != '\0') 
      { 
       send_char(*s); 
       s++; 
      } 
    } 
    
    //**********************************************************USART-ENDE********************
    
    SIGNAL(SIG_OVERFLOW0)
    {
     bitnummer++;
     TCNT0 = 145;      //Timer soll nach 1.778ms Overflow haben
    	
     if(bitnummer == 12)      
      {
       TIMSK &= ~(1<<TOIE0);
       rc5.rdy = 1;
       rc5.s_bit = 0;
       bitnummer = 13;
      }
     
     if(bitnummer<6)             //Wenn i<6, werden die ausgelesenen Bits zu Addresse hinzugefügr
    	{
    	  if((PORTD & (1<<3)) == 1)
    	   {
    	    rc5.addresse |= (1<<(bitnummer-1));
    	   }
    	  else
    	   {
    	    rc5.addresse &= ~(1<<(bitnummer-1));
    	   }
        }
    	
     if((bitnummer>=6)&(bitnummer<=11))    //6 - 11 werden zu rc5.code hinzugefügt
    	{
    	  
    	  if((PORTD & (1<<3)) == 1)
    	   {
    	    rc5.code = 0xff; //(1<<(bitnummer-6));
    	   }
    	  else
    	   {
    	    rc5.code = 0x00; //~(1<<(bitnummer-6));
    		char hello[15] = "111";
            send_string(hello);
    	   }
    	}
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
    
     
     if(rc5.s_bit<4)
      {
       rc5.s_bit++;
      }
     if(rc5.s_bit == 4)
      {    
       TIMSK |= (1<<TOIE0);  // Timer0 Interrupts enablen
       TCNT0 |= 228;         //Timer so vorladen, dass er zur Mitte des 2. Halbbits den ersten Timeroverflow hat      
     
       GICR &= ~(1<<INT1);  //Int1 disablen
      }
    }
       
    int main(void)
    {
     init_usart();
     init_rc5();
     char i = 1;
     sei();
     char result[10];
     char hello[15] = "Hallo Martin";
     send_string(hello);
     for(;;)
      {
       if(rc5.rdy == 1)
        {
         itoa(rc5.code,result,10);
    	 char hello2[15] = "RC5";
         send_string(hello2);
         send_string(result);
    	 rc5.rdy = 0;
    	 GICR |= (1<<INT1);
    	}
      }
    }

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    -- Es sollte heissen: TCNT0 = 228;
    -- Es sollte heissen: if (bitnummer>=6 && bitnummer<=11) ...
    -- Es sollte heissen: if ((PORTD & (1<<3)) != 0)
    -- bitnummer=11 wird 2x erhöht erhöht?
    -- Was ist, wenn bitnummer=0 (AGC #2)?
    -- Was ist, wenn bitnummer=1 (FLIP)?
    -- Wo wird Timer0-IRQ deaktiviert und INT-IRQ aktiviert?
    -- Wie kommst du auf diese init-Werte für TCNT0???
    -- Hast du bedacht, daß der Ausgang eines TSOP1736 open collector ist?
    -- Wie erkennst du ungültige Daten?
    Disclaimer: none. Sue me.

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo,
    habe deine Einwände zum Teil beseitig und Kommentare im Code ergänzt.
    Die Werte für TCNT0 errechnen sich folgendermaßen:

    1/(16000000/256) = 1.6exp-5
    Das erste Intervall soll bis zur Mitte des low-Pegels vom Togglebit dauern, also 1.778ms/2->55.5 Timersteps
    Danach sollen die Intervalle jeweils 1.778ms dauern, so dass immer die das 2. Halbbit erfasst wird.

    Selbst wenn meine Timings nicht ganz stimmen würden, dürfte rc5.code doch nicht immer 0 sein??

    Ich meine doch, ich habe hier den OpenCollector berücksichtigt, und wenn nicht, wäre das Signal halt invertiert.

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <math.h>
    
    
    
    struct rc5_parts
     {
        volatile char s_bit;
    	volatile int8_t addresse;
    	volatile int8_t code;
    	volatile char rdy;
     } rc5;
    
    char mid;
    volatile uint8_t bitnummer = 0;
    
    void init_rc5()
    {
     MCUCR |= (1<<ISC11) | (1<<ISC10);
     GICR |= (1<<INT1);
     TCCR0 |= (1<<CS02);
    }
    
    //****************************************************USART******************************
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s) 
    { 
     while (!(UCSRA & (1<<UDRE))); 
     UDR = s; 
    } 
    
    void send_string(char *s) 
    { 
     while(*s != '\0') 
      { 
       send_char(*s); 
       s++; 
      } 
    } 
    
    //**********************************************************USART-ENDE********************
    
    SIGNAL(SIG_OVERFLOW0)
    {
     bitnummer++;
     TCNT0 = 145;      //Timer soll nach 1.778ms Overflow haben
    	
     if(bitnummer == 12)      
      {
       TIMSK &= ~(1<<TOIE0);    //Wenn die 11 Bits davor erfasst wurden, TimerIRQ deaktivieren
       rc5.rdy = 1;
       rc5.s_bit = 0;
       bitnummer = 13;
      }
     
     if(bitnummer<6)             //Wenn i<6, werden die ausgelesenen Bits zu Addresse hinzugefügr
    	{
    	  if((PORTD & (1<<3)) != 0)
    	   {
    	    rc5.addresse |= (1<<(-1)*(bitnummer-6));
    	   }
    	  else
    	   {
    	    rc5.addresse &= ~(1<<(-1)*(bitnummer-6));
    	   }
        }
    	
     if((bitnummer>=6 && bitnummer<=11))    //6 - 11 werden zu rc5.code hinzugefügt
    	{
    	  
    	  if((PORTD & (1<<3)) != 0)
    	   {
    	    rc5.code |= (1<<(-1)*(bitnummer-7));
    	   }
    	  else
    	   {
    	    rc5.code &= ~(1<<(-1)*(bitnummer-7));
    	   }
    	}
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
    
     
     if(rc5.s_bit<4)
      {
       rc5.s_bit++;
      }
     if(rc5.s_bit == 4)
      {    
       TIMSK |= (1<<TOIE0);  // Timer0 Interrupts enablen
       TCNT0 = 200;         //Timer so vorladen, dass er zur Mitte des 2. Halbbits den ersten Timeroverflow hat      
     
       GICR &= ~(1<<INT1);  //Int1 disablen
      }
    }
       
    int main(void)
    {
     init_usart();
     init_rc5();
     char i = 1;
     sei();
     char result[10];
     char hello[15] = "Hallo Martin";
     send_string(hello);
     for(;;)
      {
       if(rc5.rdy == 1)
        {
         itoa(rc5.code,result,10);
    	 char hello2[15] = "RC5-Code: ";
         send_string(hello2);
         send_string(result);
    	 rc5.rdy = 0;
    	 GICR |= (1<<INT1);          //    ext. Interrupt wieder aktivieren
    	}
      }
    }

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Von der ersten Flanke, die du siehst (1/2 AGC #1) bis zur Mitte der zweiten Hälfte von Flip (3/4 Flip) vergehen 2.25 * 1.778ms.

    Die Bitzählerei stimmt IMHO immer noch nicht.

    Was soll das (-1)* bei bitnummer???

    Was zählt s_bit??? Wenn das AGC zählen soll, dann geht's nach Flanke No. 3 los (1/2 AGC #2). Von da bis 3/4 Flip sind's 1.25 * 1.778ms. --> TCNO0 = -138.88 ~ -139 = 117.
    Disclaimer: none. Sue me.

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    s_bit wird bis 3 hochgezählt, d.h. die ersten 3 Bits waren 1, dann wird die
    TimerISR ausgelöst.
    Der erste Wert muss meiner Meinung anch 1.778ms/4 sein und nicht /2, wie ich vorhin schrieb. Somit ergibt sich ein erstes TCNT0 von 228.
    Das (-1) soll bewirken, dass die Werte mit steigendem i vom MSB zum LSB in rc5.code geschrieben werden, stimmt aber nicht, dass muss ich mir noch anders überlegen...
    Außerdem reagiere ich jetzt auf fallende Flanken am Anfang, ich hatte da die Invertierung des TSOP wohl doch nicht so ganz berücksichtigt.
    Es scheint IMMER eine 1 anzuliegen, wenn rc5.code abgefragt wird, da ich jedesmal CODE-EINS per USART auf den Rechner kriege.

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <math.h>
    
    
    
    struct rc5_parts
     {
        volatile char s_bit;
    	volatile int8_t addresse;
    	volatile int8_t code;
    	volatile char rdy;
     } volatile rc5;
    
    char mid;
    volatile uint8_t bitnummer = 0;
    
    void init_rc5()
    {
     MCUCR |= (1<<ISC11);
     GICR |= (1<<INT1);
     TCCR0 |= (1<<CS02);
    }
    
    //****************************************************USART******************************
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s) 
    { 
     while (!(UCSRA & (1<<UDRE))); 
     UDR = s; 
    } 
    
    void send_string(char *s) 
    { 
     while(*s != '\0') 
      { 
       send_char(*s); 
       s++; 
      } 
    } 
    
    //**********************************************************USART-ENDE********************
    
    SIGNAL(SIG_OVERFLOW0)
    {
     bitnummer++;
     TCNT0 = 145;      //Timer soll nach 1.778ms Overflow haben
    	
     if(bitnummer == 12)      
      {
       TIMSK &= ~(1<<TOIE0);    //Wenn die 11 Bits davor erfasst wurden, TimerIRQ deaktivieren
       rc5.rdy = 1;
       rc5.s_bit = 0;
       bitnummer = 13;
      }
     
     if(bitnummer<6)             //Wenn i<6, werden die ausgelesenen Bits zu Addresse hinzugefügr
    	{
    	  if((PORTD & (1<<3)) != 0)
    	   {
    	    rc5.addresse |= (1<<(-1)*(bitnummer-6));
    	   }
    	  else
    	   {
    	    rc5.addresse &= ~(1<<(-1)*(bitnummer-6));
    	   }
        }
    	
     if((bitnummer>=6 && bitnummer<=11))    //6 - 11 werden zu rc5.code hinzugefügt
    	{
    	  
    	  if((PORTD & (1<<3)) != 1)
    	   {
    	    rc5.code |= (1<<5);
    		char hello[15] = "CODE-EINS";
     send_string(hello);
    	   }
    	  else
    	   {
    	    rc5.code &= ~(1<<3);
    		char hello[15] = "CODE-NULL";
     send_string(hello);
    	   }
    	}
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
    
     
     if(rc5.s_bit<3)
      {
       rc5.s_bit++;
      }
     if(rc5.s_bit == 3)
      {    
       TIMSK |= (1<<TOIE0);  // Timer0 Interrupts enablen
       TCNT0 = 228;         //Timer so vorladen, dass er zur Mitte des 2. Halbbits den ersten Timeroverflow hat      
     
       GICR &= ~(1<<INT1);  //Int1 disablen
      }
    }
       
    int main(void)
    {
     init_usart();
     init_rc5();
     char i = 1;
     sei();
     char result[10];
     char hello[15] = "Hallo Martin";
     send_string(hello);
     for(;;)
      {
       if(rc5.rdy == 1)
        {
         itoa(rc5.code,result,10);
    	 char hello2[15] = "RC5-Code: ";
         send_string(hello2);
         send_string(result);
    	 rc5.rdy = 0;
    	 GICR |= (1<<INT1);          //    ext. Interrupt wieder aktivieren
    	 bitnummer = 0;              // bitnummer zurücksetzten
    	}
      }
    }

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    So, mittlerweile bekomme ich zumindest sowohl 1 als auch 0 in rc5.code geschrieben, allerdings stimmen die Codes meistens nicht, oft kommt bei mehreren Tasten der selbe Code etc.
    Vom Timing her müsste es stimmen, das hab ich mittlerweile oft nachgerechnet. Kann es sein, dass die Zeit, die bei der Abarbeitung des Codes verloren geht, meine Rechnung stört?
    Code:
    //**********************************************************USART-ENDE********************
    
    SIGNAL(SIG_OVERFLOW0)
    {
     bitnummer++;
     TCNT0 = 145;      //Timer soll nach 1.778ms Overflow haben
    	
     if(bitnummer == 12)      
      {
       TIMSK &= ~(1<<TOIE0);    //Wenn die 11 Bits davor erfasst wurden, TimerIRQ deaktivieren
       rc5.rdy = 1;
       bitnummer = 13;
      }
     
     if(bitnummer<6)             //Wenn i<6, werden die ausgelesenen Bits zu Addresse hinzugefügr
    	{
    	  if((PIND & (1<<3)) != 0)
    	   {
    	    rc5.addresse |= (1<<(5-bitnummer));
    	   }
    	  else
    	   {
    	    rc5.addresse &= ~(1<<(5-bitnummer));
    	   }
        }
    	
     if((bitnummer>=6 && bitnummer<=11))    //6 - 11 werden zu rc5.code hinzugefügt
    	{
    	  
    	  if((PIND & (1<<3)) != 0)
    	   {
    	    rc5.code &= ~(1<<(11-bitnummer));
    
    	   }
    	  else
    	   {
    	    rc5.code |= (1<<(11-bitnummer));
    	
    	   }
    	}
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
    
     
     if(rc5.s_bit<3)
      {
       rc5.s_bit++;
      }
     if(rc5.s_bit == 3)
      {    
       TIMSK |= (1<<TOIE0);  // Timer0 Interrupts enablen
       TCNT0 = 228;         //Timer so vorladen, dass er zur Mitte des 2. Halbbits den ersten Timeroverflow hat      
     
       GICR &= ~(1<<INT1);  //Int1 disablen
      }
    }
       
    int main(void)
    {
     init_usart();
     init_rc5();
     char i = 1;
     sei();
     char result[10];
     char hello[15] = "Hallo Martin";
     send_string(hello);
     for(;;)
      {
       if(rc5.rdy == 1)
        {
         itoa(rc5.code,result,10);
    	 char hello2[15] = "RC5-Code: ";
         send_string(hello2);
         send_string(result);
    	 rc5.rdy = 0;
    	 rc5.s_bit = 0;
    	 GICR |= (1<<INT1);          //    ext. Interrupt wieder aktivieren
    	 bitnummer = 0;              // bitnummer zurücksetzten
    	 rc5.addresse = 0;
    	 rc5.code = 0;
    	}
      }
    }

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen