logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Atmega32, RFM12, przesyłanie danych pomiędzy dwoma modułami

mutleyy 29 Mar 2012 20:48 2846 5
  • #1 10734187
    mutleyy
    Poziom 9  
    Witam. Skonstruowałem sobie samochód zdalnie sterowany. Zarówno pilot jak i auto posiadają uP Atmega32 oraz moduły RFM12. Na razie próbuję wysłać ramkę z danymi, które będą wyświetlane na LCD podłączonym do auta. Wysyłanie oraz odbiór sygnalizują diody LED. Ramka zostaje odebrana, jednak jej długość oraz zawartość zostają zmienione (długość ramki odebranej jest jednak "proporcjonalna" do wysłanej.
    Wyświetlone zostają: pełna kratka, jakiś znak, pełna kratka ....
    Zamieszczam kody odbiornika i nadajnika oraz schemat podłączenia modułu. Byłbym wdzięczny za pomoc.

    Nadajnik:
    
    #include <avr\io.h>
    #include <util/delay.h>
    #define F_CPU 16000000
    #define SCK 7   // SPI clock
    #define SDO 6   // SPI Data output (RFM12B side)
    #define SDI 5   // SPI Data input (RFM12B side)
    #define CS  4   // SPI SS (chip select)
    #define NIRQ 2  // (PORTD)
    
    #define HI(x) PORTB |= (1<<(x))
    #define LO(x) PORTB &= ~(1<<(x))
    #define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ))
    
    #define LED 5
    #define LED_OFF() PORTD |= (1<<LED)
    #define LED_ON() PORTD &= ~(1<<LED)
    
    void portInit() {
      HI(CS);
      HI(SDI);
      LO(SCK);
      DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
      DDRD = (1<<LED);
    
    }
    
    unsigned int writeCmd(unsigned int cmd) {
      unsigned char i;
      unsigned int recv;
      recv = 0;
      LO(SCK);
      LO(CS);
      for(i=0; i<16; i++) {
        if(cmd&0x8000) HI(SDI); else LO(SDI);
        HI(SCK);
        recv<<=1;
        if( PINB&(1<<SDO) ) {
          recv|=0x0001;
        }
        LO(SCK);
        cmd<<=1;
      }
      HI(CS);
      return recv;
    }
    
    void rfInit() {
    	 writeCmd(0x80D7); //EL,EF,433band,12.0pF
    	  writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
    	    writeCmd(0xA640); //frequency select
    	    writeCmd(0xC647); //4.8kbps
    	    writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
    	    writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
    	    writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
    	    writeCmd(0xCED4); //sync
    	    writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
    	    writeCmd(0x9850); //!mp,90kHz,MAX OUT
    	   writeCmd(0xCC17); //lpx, iddy
    	   writeCmd(0xE000); //NOT USE
    	    writeCmd(0xC800); //NOT USE
    	    writeCmd(0xC040); //1.66MHz,2.2V
    }
    
    void rfSend(unsigned char data){
     //while(WAIT_NIRQ_LOW());
      WAIT_NIRQ_LOW();
      writeCmd(0xB800 + data);
    }
    
    void rfSendString(char *str)
    {
    	while(*str)
    		rfSend(*str++);
    
    }
    int main() {
      volatile unsigned int i,j;
      char a[1];
      asm("cli");
      for(i=0;i<1000;i++)for(j=0;j<123;j++);
      portInit();
      /* rsInit(BAUDRATE); */
      rfInit();
    
      LED_OFF();
      while(1)
      {
    
    LED_ON();
    _delay_ms(1000);
    for(int i=0;i<11;i++)
    {
    		  writeCmd(0x0000);
    		     rfSend(0xAA); // PREAMBLE
    		     rfSend(0xAA);
    		     rfSend(0xAA);
    		     rfSend(0x2D); // SYNC
    		     rfSend(0xD4);
    
    		       rfSendString("mateusz");
    			     rfSend(0xAA); // PREAMBLE
    			     rfSend(0xAA);
    			     rfSend(0xAA);
    }
    LED_OFF();
    
    _delay_ms(3000);
    
    
      }
    }
    



    Odbiornik:
    
    // Rx odbior 9600 bodow 2 bity stopu
    #include <avr\io.h>
    #include <util/delay.h>
    #include "lcd.h"
    #define F_CPU 16000000
    #define SCK 7   // SPI clock
    #define SDO 6   // SPI Data output (RFM12B side)
    #define SDI 5   // SPI Data input (RFM12B side)
    #define CS  4   // SPI SS (chip select)
    #define NIRQ 2  // (PORTD)
    
    #define HI(x) PORTB |= (1<<(x))
    #define LO(x) PORTB &= ~(1<<(x))
    #define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ))
    
    #define LED 5
    #define LED_ON() PORTD &= ~(1<<LED)
    #define LED_OFF() PORTD |= (1<<LED)
    #define BAUDRATE 25 //
    // Ustawienie portu 9600 b  2 bity stopu
    void rsInit(unsigned char baud) {
       UBRRH = 0;
       UBRRL = 51;
       UCSRB = (1<<RXEN)|(1<<TXEN);
       UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
    }
    // Wysylanie na port UART odebranych danych z RFM12
    void rsSend(unsigned char data) {
        while ( !( UCSRA & (1<<UDRE)) );
       UDR = data;
    }
    
    unsigned char rsRecv() {
      while( !(UCSRA & (1<<RXC)));
      return UDR;
    }
    
    void portInit() {
      HI(CS);
      HI(SDI);
      LO(SCK);
      DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
      DDRD = (1<<LED);
    }
    
    unsigned int writeCmd(unsigned int cmd) {
      unsigned char i;
      unsigned int recv;
      recv = 0;
      LO(SCK);
      LO(CS);
      for(i=0; i<16; i++) {
        if(cmd&0x8000) {
          HI(SDI);
        }
        else {
          LO(SDI);
        }
        HI(SCK);
        recv<<=1;
        if( PINB&(1<<SDO) ) {
          recv|=0x0001;
        }
        LO(SCK);
        cmd<<=1;
      }
      HI(CS);
      return recv;
    }
    
    void FIFOReset() {
      writeCmd(0xCA81);
      writeCmd(0xCA83);
    }
    /*
    void waitForData() {
      unsigned int status;
      while(1) {
        status = writeCmd(0x0000);
        if ( (status&0x8000) ) {
          return;
        }
      }
    }
    */
    void rfInit() {
    	writeCmd(0x80D7); //EL,EF,433band,12.0pF
    	  writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC
    	  writeCmd(0xA640); //freq select
    	  writeCmd(0xC647); //4.8kbps
    	  writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
    	  writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
    	  writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
    	  writeCmd(0xCED4); //SYNC=2DD4;
    	  writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
    	  writeCmd(0x9850); //!mp,90kHz,MAX OUT
    	  writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0
    	  writeCmd(0xE000); //NOT USE
    	  writeCmd(0xC800); //NOT USE
    	  writeCmd(0xC040); //1.66MHz,2.2V
    }
    
    /*
    unsigned char rfRecv() {
      unsigned int data;
      writeCmd(0x0000);
      data = writeCmd(0xB000);
      return (data&0x00FF);
    }
    */
    
    unsigned char rfRecv() {
      unsigned int data;
      while(1) {
        data = writeCmd(0x0000);
        if ( (data&0x8000) ) {
          data = writeCmd(0xB000);
          return (data&0x00FF);
        }
      }
    }
    
    int main(void) {
      unsigned char i;
      char data[15];
      portInit();
      char odbior;
      rfInit();
      //LED_ON();
      //PORTC=0xFF;
      //rsInit(BAUDRATE);          // >> debag
      FIFOReset();
      WlaczLCD();
      CzyscLCD();
      Wyswietlnapis("czekam");
      while(1) {
          //waitForData();
    	  LED_ON();
    	  _delay_ms(1000);
    for(int i=0;i<100;i++)
    {
           odbior = rfRecv();
           data[i]=odbior;
           i++;
    
    }
    
          FIFOReset();
          UstawKursor(1,1);
          Wyswietlnapis(data);
    LED_OFF();
    _delay_ms(2000);
    }
    }
    
    
    
  • Pomocny post
    #2 10734240
    snnaap
    Poziom 25  
    Co to znaczy proporcjonalna?
    Znaczy krótsza? Gubisz dane?
    Na schemacie nie widać kondensatora ok 10..100uF na wyjściu stabilizatora, a muszę powiedzieć że z doświadczenia wiem, że RFM go bardzo lubi i nieraz nie potrafi sobie bez niego poradzić - przynajmniej mój taki problem miał - przydałby się również taki na wejściu.
    Dla RFM filtrowanie napięcia to podstawa.

    Dodano po 2 [minuty]:

    PS. Data zadeklarowana ma 15 znaków natomiast ty wrzucasz w nią 100
  • #3 10734304
    mutleyy
    Poziom 9  
    Odebrana ramka jest dłuższa niż wysłana. Co do kondensatorów to sugerowałem się datasheete'm. Zapisywanie do ramki tak wygląda, ponieważ troszkę kombinowałem..
    Czyli problem może być spowodowany zasilaniem. Kondensatory rozumiem, że elektrolityczne? Czy w kwestii programowej (poza zapisywanymi znakami) wszystko ok?
  • #5 10736016
    adammruk
    Poziom 16  
    snnaap napisał:

    Na schemacie nie widać kondensatora ok 10..100uF na wyjściu stabilizatora, a muszę powiedzieć że z doświadczenia wiem, że RFM go bardzo lubi i nieraz nie potrafi sobie bez niego poradzić - przynajmniej mój taki problem miał - przydałby się również taki na wejściu.
    Dla RFM filtrowanie napięcia to podstawa.


    Święte słowa, potwierdzone przeze mnie i nie tylko przeze mnie.. Filtracja napięcia to podstawa tutaj. Do uruchomienia te moduły są dość dziadowskie, ale potem działają aż miło.
    Mam nadzieję że poczytałeś ten temat:
    https://www.elektroda.pl/rtvforum/topic890223-510.html
    Jak nie, to zacznij od niego, sporo problemów jest tam opisanych i rozwiązanych, umieściłem też tam w 100% działający kod+schemat dla attiny2313, ale dla innego AVR to żaden problem przerobić.
  • #6 10737094
    mutleyy
    Poziom 9  
    Oczywiście, że przerobiłem powyższy temat:).
    Problem został rozwiązany. Spróbowałem wysłać zmienną 8 bitową. Obieranie raz zakończyło się powodzeniem, raz nie. Metodą prób i błędów za każdym razem (już po raz n-ty) sprawdzałem przejścia na płytce. Przy podłączaniu programatora pin od SCK przesuwał się wraz z lutem;/
    Jak na razie wszystko działa poprawnie. Dziękuję za pomoc. Temat uważam za zamknięty.
REKLAMA