- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 7 von 7

Thema: Probleme bei Initialisierung des RFM 01 Funkmod. Gelöst !!!

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214

    Probleme bei Initialisierung des RFM 01 Funkmod. Gelöst !!!

    Anzeige

    Praxistest und DIY Projekte
    Hallo Leute,

    ich hab ein Problem bei der Initialisierung eines RFM 02 Empfänger Funkmodules (Pollin) mit einem ATMEGA 8.
    Die erste Initialisierung im Hauptprogramm funktioniert die meiste Zeit nicht, ab und zu schon.
    Als Sicherheit wurde im Programmcode eine Zyklische Initialisierung eingebaut, die das Funkmodul nach 3 Sekunden Untätigkeit neu Initialisiert.
    Die funktioniert so gut wie immer.
    Das Fehlerbild:
    Nach dem Einschalten der Betriebsspannung wird nichts Empfangen. Nach 3 Sekunden bekomm ich dann die ersten Werte.
    Möchte mal einer von Euch mal über den Quellcode drüberschauen, wo ich da einen Fehler gemacht hab. Mir fällt einfach nichts mehr dazu ein.
    Am Sender kann es meiner Meinung nach nicht liegen, der sendet alle Sekunde ein neues Paket ab und wurde zum Testen nicht abgeschaltet.
    Code:
    #include <mega8.h>
    // Standard Input/Output functions
    #include <stdio.h>
    #include <string.h>
    #include <delay.h>
    #asm
    .equ portb=0x18
    .equ portd=0x12
    .equ sdi=0     ;PortB,0
    .equ sck=1     ;PortB,1
    .equ nsel=2    ;PortB,2
    .equ sdo=3     ;PortB,3
    .equ nirq=2    ;PortD,2
    #endasm
    
    // Declare your global variables here
    bit newstring=0; /* Ein neuer gültiger Datenstring wurde empfangen */
    flash unsigned int ui_frequ[32]={1240,1270,1300,1330,1360,1390,1420,1450,1480,1510,1540,1570,1600,1630,1660,1690,1720,1750,1780,1810,1840,1870,1900,1900,1900,1900,1900,1900,1900,1900,1900,1900};
    volatile unsigned char uc_receivebuffer[127];/* Empfangspuffer */
    volatile unsigned char uc_receivebyte=0;/* Zeiger aktuelles Sendebyte */
    volatile unsigned char uc_timeout=0;
    volatile unsigned char uc_kanal; /* gewählter Kanal */
    
    // Sende ein Byte zum RFM 01
    void sendbyte(volatile unsigned char uc_byte)
    {   
        #asm
        push r26        ;Register retten
        in r26,sreg
        push r26
        push r27
        ldi r26,8       ;Schleifenzähler mit 8 laden
        ld r27,y        ;uc_Byte vom Ram holen
        
        sendloop:
            tst r26     ;Schleifenzähler eins runterzählen
            breq endsend
            dec r26
            clc
            rol r27     ;High Byte ins Carry schieben
            brcs send1  ;Bei 1 -> High ausgeben
            cbi portb,sdi     ;Bei 0 -> Low ausgeben
            rcall clockpulse
            rjmp sendloop
        
        send1:
            sbi portb,sdi
            rcall clockpulse
            rjmp sendloop
        
        clockpulse:
            nop
            nop
            nop
            sbi portb,sck     ;Clock Port auf 1 setzen
            nop
            nop
            nop
            nop
            nop
            nop
            cbi portb,sck     ;Clock Port auf 0 setzen
            nop
            nop
            nop
            ret         ;Zurück zur aufrufenden Routine
        
        endsend:
            cbi portb,sdi ;SDI Port auf 0 setzen zwecks kosmetik
            pop r27
            pop r26
            out sreg,r26
            pop r26
       #endasm
    }
    
     // XOR Verknüpfung Code Vision kann kein EXOR
    #pragma warn- // this will prevent warnings
    unsigned char funk_xor (unsigned char uc_wert1,unsigned char uc_wert2)
     {
        #asm
        push r26
        in r26,sreg
        push r26
        ld r26,y        ;uc_wert2 holen
        ldd r30,y+1     ;uc_wert1 holen
        eor r30,r26     ;Rückgabewert im Register r30
        pop r26
        out sreg,r26
        pop r26
        #endasm
     
     }
    #pragma warn+ // enable warnings
    
    // Checksumme berechnen
    unsigned char checksum (void)
    {
        volatile unsigned char uc_check[2]={0,0}; /* (Checksummenpuffer)*/
        volatile unsigned char uc_i=0;
        uc_check[0]=uc_receivebuffer[uc_receivebyte-4]; /* High nibble einlesen */
        uc_check[1]=uc_receivebuffer[uc_receivebyte-3]; /* Low nibble einlesen */
        if (uc_check[0]>0x39)
        {
            uc_check[0]=uc_check[0]-0x37; /*ASCII Code A...F */
        }
        else
        {
            uc_check[0]=uc_check[0]-0x30; /*ASCII Code 0...9 */
        }    
        if (uc_check[1]>0x39)
        {
            uc_check[1]=uc_check[1]-0x37;
        }
        else
        {
            uc_check[1]=uc_check[1]-0x30;
        }    
        uc_check[0]=uc_check[0]<<4;         /* Checksummen zusammenführen */
        uc_check[0]=uc_check[0]|uc_check[1];
        
        for (uc_i=0;uc_i<(uc_receivebyte-4);uc_i++)
        {
            uc_check[0]=funk_xor(uc_check[0],uc_receivebuffer[uc_i]); /* XOR Verknüpfung */
        }
        return uc_check[0]; /* Rückgabe der Checksumme, sollte wenn richtig 0 sein */
    }
    
    //FIFO Puffer initialisieren bei Fehlern und Datensatzende
    void reset_fifo (void)    
    {
        /* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, stop FIFO  */
        #asm ("cbi portb,nsel");
        sendbyte(0b11001110);
        sendbyte(0b10001001);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, start FIFO  */
        #asm ("cbi portb,nsel");
        sendbyte(0b11001110);
        sendbyte(0b10001011);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        uc_receivebyte=0;
    }
    
    // Einen Taktimpuls erzeugen 
    void clockpulse(void)
    {
        #asm
            nop
            nop
            nop
            sbi portb,sck     ;Clock Port auf 1 setzen
            nop
            nop
            nop
            nop
            nop
            nop
            cbi portb,sck     ;Clock Port auf 0 setzen
            nop
            nop
            nop
            
        
        #endasm
    }
    
    // Empfange Daten vom RFM 01
    interrupt [EXT_INT0] void ext_int0_isr(void)
    {
        unsigned char uc_i=0;
        unsigned char uc_buffer=0;
        unsigned char uc_check=0;
        
        uc_timeout=0; /* Timeout Zähler zurücksetzen */
        
        /* Die ersten 16 Bit des Statuswortes übergehen */
        #asm ("cbi portb,nsel");
        sendbyte(0b00000000);
        sendbyte(0b00000000); 
        
        for(uc_i=0;uc_i<8;uc_i++)/* 8 Bits auslesen */
        {
            
            
            if ((PINB&(1<<3))!=0) /* SDO abfragen = PortB,3 */
            {
                uc_buffer=(uc_buffer<<1)| 0x01;
            }
            else
            {
                uc_buffer=(uc_buffer<<1);     
            }
            clockpulse();
        }
        #asm ("sbi portb,nsel"); /* nSel Leitung abschalten */
        #asm ("nop");
        
            
        uc_receivebuffer[uc_receivebyte]=uc_buffer;
        uc_receivebyte++;
             
        if (uc_buffer==10) /* Line Feed wurde empfangen*/ 
        {
            uc_receivebuffer[uc_receivebyte]=0;
            reset_fifo();
            uc_check=checksum();
            uc_receivebyte=0;
                            
            if (uc_check==0);
            {
                newstring=1;
            }
        }
    }   
    
    
    
    
    #define RXB8 1
    #define TXB8 0
    #define UPE 2
    #define OVR 3
    #define FE 4
    #define UDRE 5
    #define RXC 7
    
    #define FRAMING_ERROR (1<<FE)
    #define PARITY_ERROR (1<<UPE)
    #define DATA_OVERRUN (1<<OVR)
    #define DATA_REGISTER_EMPTY (1<<UDRE)
    #define RX_COMPLETE (1<<RXC)
    
    // USART Transmitter buffer
    #define TX_BUFFER_SIZE 127
    char tx_buffer[TX_BUFFER_SIZE];
    
    #if TX_BUFFER_SIZE<256
    unsigned char tx_wr_index,tx_rd_index,tx_counter;
    #else
    unsigned int tx_wr_index,tx_rd_index,tx_counter;
    #endif
    
    // USART Transmitter interrupt service routine
    interrupt [USART_TXC] void usart_tx_isr(void)
    {
    if (tx_counter)
       {
       --tx_counter;
       UDR=tx_buffer[tx_rd_index];
       if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
       };
    }
    
    #ifndef _DEBUG_TERMINAL_IO_
    // Write a character to the USART Transmitter buffer
    #define _ALTERNATE_PUTCHAR_
    #pragma used+
    void putchar(char c)
    {
    while (tx_counter == TX_BUFFER_SIZE);
    #asm("cli")
    if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
       {
       tx_buffer[tx_wr_index]=c;
       if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
       ++tx_counter;
       }
    else
       UDR=c;
    #asm("sei")
    }
    #pragma used-
    #endif
    
    
    //RFM01 initialisieren
    void init_rfm01(void)
    {
        volatile unsigned char uc_frequ[2]; /* Frequenz tuningword */
        /* Frequenzwortermittlung aus der Kanalangabe */
        uc_frequ[1]=ui_frequ[uc_kanal]/256;
        uc_frequ[1]|=0b10100000;
        uc_frequ[0]=ui_frequ[uc_kanal]%256;
        
        /* Configuration Setting: 433MHz, CLK on, 11,5pf Kapaz., 67kHz */
        #asm ("cbi portb,nsel");
        sendbyte(0b10001001);
        sendbyte(0b01101100); 
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* Low Batt Clock Divider Command: clock 5MHz */
        #asm ("cbi portb,nsel");
        sendbyte(0b11000010);
        sendbyte(0b11000000); 
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* Frequency Setting: 434MHz (je nach Kanal) */
        #asm ("cbi portb,nsel");
        sendbyte(uc_frequ[1]);
        sendbyte(uc_frequ[0]); 
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* Receiver Setting Command: VDI= Digital RSSI Out, -103dB, receiver disabled */
        #asm ("cbi portb,nsel");
        sendbyte(0b11000000);
        sendbyte(0b10000000);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* Receiver Setting Command: VDI= Digital RSSI Out, -103dB receiver enabled */
        #asm ("cbi portb,nsel");
        sendbyte(0b11000000);
        sendbyte(0b10000001);
        #asm ("sbi portb,nsel");
        #asm ("nop");
           
        /* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, stop FIFO  */
        #asm ("cbi portb,nsel");
        sendbyte(0b11001110);
        sendbyte(0b10001001);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        /* FIFO Command: Enable FIFO, IT level=8, Sync. Patt + VDI, start FIFO  */
        #asm ("cbi portb,nsel");
        sendbyte(0b11001110);
        sendbyte(0b10001011);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        
        /* Data Filter Command:  */
        #asm ("cbi portb,nsel");
        sendbyte(0b11000100);
        sendbyte(0b10101100); 
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        
        /* Data Rate Command: 2400 bit/s */
        #asm ("cbi portb,nsel");
        sendbyte(0b11001000);
        sendbyte(0b10010001);
        #asm ("sbi portb,nsel");
        #asm ("nop");
        
        
        /* AFC Command: Enable AFC, +3/-4, offset at VDI high */
        #asm ("cbi portb,nsel");
        sendbyte(0b11000110);
        sendbyte(0b10111111); 
        #asm ("sbi portb,nsel");
        #asm ("nop");
           
    }
    
    // Timer 1 output compare A interrupt service routine
    interrupt [TIM1_COMPA] void timer1_compa_isr(void)
    {
    /* 1 Sekunde */
    uc_timeout++;
    
    if (uc_timeout>3)/* Wenn 3 Sekunden kein Bit mehr Empfangen wurde wird der FiFo resetet */
    {
        init_rfm01();
        reset_fifo();
        uc_timeout=0;
    }
    }
    
    // Declare your global variables here
    
    void main(void)
    {
    // Declare your local variables here
    unsigned char uc_i=0;
    // Input/Output Ports initialization
    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out 
    // State7=T State6=T State5=T State4=T State3=T State2=0 State1=0 State0=0 
    PORTB=0x00;
    DDRB=0x07;
    
    // Port C initialization
    // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State6=T State5=P State4=P State3=P State2=P State1=P State0=P 
    PORTC=0x3F;
    DDRC=0x00;
    
    // Port D initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTD=0x00;
    DDRD=0x00;
    
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    TCCR0=0x00;
    TCNT0=0x00;
    
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 31,250 kHz
    // Mode: Normal top=FFFFh
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer 1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: On
    // Compare B Match Interrupt: Off
    // CTC Mode : On
    TCCR1A=0x00;
    TCCR1B=0x0C;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x7A; /* Comparematch Register mit 31250 laden = 1 Sekunde */
    OCR1AL=0x11;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    // Timer/Counter 2 initialization
    // Clock source: System Clock
    // Clock value: Timer 2 Stopped
    // Mode: Normal top=FFh
    // OC2 output: Disconnected
    ASSR=0x00;
    TCCR2=0x00;
    TCNT2=0x00;
    OCR2=0x00;
    
    // External Interrupt(s) initialization
    // INT0: On
    // INT0 Mode: Falling Edge
    // INT1: Off
    GICR|=0x40;
    MCUCR=0x02;
    GIFR=0x40;
    
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x10;
    
    // USART initialization
    // Communication Parameters: 8 Data, 1 Stop, No Parity
    // USART Receiver: Off
    // USART Transmitter: On
    // USART Mode: Asynchronous
    // USART Baud Rate: 38400
    UCSRA=0x00;
    UCSRB=0x48;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x0C;
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    
    // Kanalauswahl
    uc_kanal=(PINC&0b00111111);
    
    // RFM 01 initialisieren
    delay_ms(200);
    init_rfm01();
    reset_fifo();
    
    // Testroutinen
    /*strcpyf (uc_receivebuffer,"$123456789ABCDEF#31");
    uc_receivebyte=strlen(uc_receivebuffer);
    uc_receivebuffer[uc_receivebyte]=13;
    uc_receivebuffer[uc_receivebyte+1]=10;
    uc_receivebuffer[uc_receivebyte+2]=0;
    
    uc_receivebyte=strlen(uc_receivebuffer);
    checksum();*/
    // Ende der Testroutinen
    
    // Global enable interrupts
    #asm("sei")
    
    while (1)
          {
          /*newstring=1;*/ /* zu Testzwecken */
          
          if (newstring==1)
          {
            for (uc_i=0;uc_i<strlen(uc_receivebuffer);uc_i++)
            {
            putchar (uc_receivebuffer[uc_i]);
            }
            newstring=0;
          }  
          };
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    11.01.2004
    Beiträge
    44
    hi,
    ich habe mir auch die beiden rfm01/rfm02 zugelegt und krieg sie nicht zum Laufen, habe auch schon in Foren nachgefragt, aber meistens gibts nur die Anwort:" Benutzte die Suchfunktion". Falls du es geschafft hast wäre es nett wenn du mir ein paar Tipps geben könntest.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    No meine Funkstrecke läuft soweit.

    Der im ersten Post angegebene Code laäuft auch, allerding s hab ich immer noch das Problem mit der ersten Initialisierung.
    Wenn Du mir mal schreibst, wo du Probleme hast, kann ich Dir schon helfen.
    Fertigen Code in C und Schaltpläne mit nem ATMEGA 8 hab ich auch.
    Wo genau liegt dein Problem ?

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    11.01.2004
    Beiträge
    44
    Ja ich hab' verschiedene Sachen noch gar nicht verstanden. Ich weiß durch den Tipp eines anderen, daß der RFM02 keinen FIFO hat. Das war schonmal ein Fehler. Ich möchte die RFM01 /02 mit Bascom proggen,und verstehe den C-Code noch nicht richtig. Aber jetzt möchte erstmal paar allgemeine Funktionen usw. wissen. Ich kann ja die Teile mittels SPI configurieren, das klappt wohl, also die CLK-Mhz konnte ich ändern und hab's per Ozzi kontrolliert. Wenn ich z.B was Senden möchte muss ich ja das Commando &Hc6 per SPI senden, und das CS auf low setzen. Nun wird doch alles bis ich CS wieder auf High setze als Daten genommen. Und diese Daten muss ich Bit für Bit senden. Muss ich den SCK manuell wechseln und wenn ja in welcher Freq. und wie ist das mit dem IRQ nSEL?

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    Mir ist da ein Lapsus unterlaufen, ich meine natürlich ein RFM 01 Empägermodul und das hat sehr wohl einen FiFo Puffer.
    Es geht ja im Prinzip auch alles, nur leider initialisiert sich der Empfänger erst mit der "Sicherheits" Initiaisierung nach 3 Sekunden.

    @stevensen
    Wenn ich z.B was Senden möchte muss ich ja das Commando &Hc6 per SPI senden
    Das klappt so nicht, weil das Senden von Datenströmen uber SDI nicht zum SPI Mode kompatibel ist (Steht auch so im Datenblatt).
    Es darf während der Versendung von einzelnen Bits kein ! Takt (SCK) mit ausgegeben werden.
    Die SPI gibt aber immer! ein Taktsignal raus und muss also während des Versendens von Bits nach dem Hc6 Kommando abgeschaltet werden.

    Ich hab die Hardware SPI des Controllers überhaupt nicht genutzt und die SPI über Software realisiert, dann ist das natürlich kein Problem.

    Ich lass den Baudrategenerator des RFM 02 laufen, der setzt nach dem Senden eines Bits den NIRQ und ich schieb dann das nächste Bit auf den SDI Pin.
    Du kannst aber auch ohne diesen NIRQ arbeiten, dann muss allerdings dein Controller für das Bittiming sorgen.

    Sind alle Bits gesendet sperre ich den Interrupt meines ATMEGA 8 , da der NIRQ auch durch andere ereignisse getriggert werden könnte.

    Vor dem Senden der nächsten Sequenz lösche ich das Interrupt Flag meines ATMEGA 8 und starte eine neue Übertragung.

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    11.01.2004
    Beiträge
    44
    Hallo Wkrug,
    danke für die Antworten. Ich habe nochmal ein paar Fragen wenn ich darf.
    Den Umstand mit dem Hc6 habe ich noch nicht verstanden. Das ist doch das Commando,welches sagt, daß das was anschliessend gesendet wird als Daten zu nehmen ist bis nSEL wieder High wird? Kann ich Hc6 noch über SPI schicken oder muss ich es auch schon bitweise schicken ? Könntest Du mir eine Hex-Datei für den Sender schicken der die Preamble und ein paar Daten sendet? Für nen Mega 8 mit 8 Mhz. Dann könnte ich testen ob mein Empfänger die syncs erkennt,danach könnte ich dann wieder am Sender weitermachen.

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    Probleme bei Initialisierung des RFM 01 Funkmod.
    Der Fehler lag vermutlich bei meinem "wilden" Versuchsaufbau.
    Entweder die Speisespannung lief zu langsam hoch, oder im Augenblick des Einschaltens waren dermassen viele Fehler auf dem SPI, das keine richtige Komunikation möglich war.
    Nachdem der Empfänger auf einer Platine aufgebaut war, konnte der Fehler nicht mehr festgestellt werden.

Berechtigungen

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

Solar Speicher und Akkus Tests