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

Jak przyspieszyć wysyłanie danych przez RFM22B z M8?

Śledziu 03 Mar 2012 19:09 3265 16
REKLAMA
  • #1 10629075
    Śledziu
    Poziom 12  
    Witam

    Od dawna chodził mi po głowie projekt bezprzewodowego wysyłania danych.
    Po ładnych kilku latach zacząłem spełniać swoje marzenie :)

    Zaprzągłem do tego M8 i RFM22B całość ma chodzić na bateryjce, i wysyłać dane np co 2s.
    Skorzystałem z dobrodziejstwa internetu i znalazłem gotowe biblioteki do obsługi RFM.
    Procesor jaki i moduł jest usypiany i wybudzany tylko na czas wysłania informacji.
    Po po podłączeniu oscyloskopu zobaczyłem że cały procedura wysłania jednego bajtu
    danych trwa blisko 90ms za dużo jak dla mnie.
    Próbuję się przebić przez note aplikacyjna modułu ale nie ukrywam że bariera jest język (korzystam z translatora i jakoś to idzie no ale...) i mała znajomość transmisji radiowej.
    Umieszczę kod incjalizujący moduł bo podejrzewam że tutaj jest pies pogrzebany.
    Jeśli któryś z kolegów chciałby sie podzielić widzą jak powinno się to dziadostwo skonfigurować było by super.
    void rf22_init(void)
    {
         rf22_write(0x07, 0x80);		// software reset
        _delay_us(500);
    
        rf22_write(0x05, 0x02);		// valid packed received interrupt on
    
        rf22_write(0x06, 0x00);		// all interrupts off
        rf22_write(0x07, 0x01);		// operating mode: ready mode
        rf22_write(0x09, 0x7f);		// xtal load capacitance
        rf22_write(0x0A, 0x02);		// uC CLK: 10MHz
        
        rf22_write(0x0b, 0xf2);		// GPIO0: TX_ANT - f2 
        rf22_write(0x0c, 0xf5);		// GPIO1: RX ANT - f5
        rf22_write(0x0d, 0x00);		// GPIO2: uC Clock out
        rf22_write(0x0e, 0x00);		
        rf22_write(0x0f, 0x70);		// ADC Input: GND
        rf22_write(0x10, 0x00);		// ADC offset: 0
        rf22_write(0x12, 0x00);		// temp sensor calibration off
        rf22_write(0x13, 0x00);		// temp sensor offset: 0
        rf22_write(0x1d, 0x40);		// enable AFC
        rf22_write(0x1e, 0x0A);		// afc timing
    	rf22_write(0x1f, 0x03);		// afc timing
    
    	rf22_write(0x1C, 0x05);		// IF bandwidth
    	
    	rf22_write(0x20, 0x83);		// Clock Recovery Oversampling Rate
    	rf22_write(0x21, 0xC0);		// Clock Recovery Offset 2
    	rf22_write(0x22, 0x13);		// Clock Recovery Offset 1
    	rf22_write(0x23, 0xA9);		// Clock Recovery Offset 0
    	rf22_write(0x24, 0x00);		// Clock Recovery Timing Loop Gain 1
    	rf22_write(0x25, 0x04);		// Clock Recovery Timing Loop Gain 0
    	rf22_write(0x2A, 0x24);
    
    	rf22_write(0x27, 0x10);		// RSSI Threashold: -120dB
    
        rf22_write(0x30, 0x8c);		// data access: RX/TX packet handling, enable crc: CCIT
        rf22_write(0x32, 0xff);		// header check enable
        rf22_write(0x33, 0x42);		// 2 word synchronisation
        rf22_write(0x34, 0x10);		// preamble length: 16 nibbles, = 64bits
        rf22_write(0x35, 0x30);		// preamble detection control: 6 nibbles = 24bits
        rf22_write(0x36, 0x2d);		// sync word 3
        rf22_write(0x37, 0xd4);		// sync word 2
        rf22_write(0x38, 0xAA);		// sync word 1
        rf22_write(0x39, 0xAA);		// sync word 0
        rf22_write(0x3a, 'h');		// transmit header 3
        rf22_write(0x3b, 'o');		// transmit header 2
        rf22_write(0x3c, 'p');		// transmit header 1
        rf22_write(0x3d, 'e');		// transmit header 0
        rf22_write(0x3e, 17);		// packet length
        rf22_write(0x3f, 'h');		// check header 3
        rf22_write(0x40, 'o');		// check header 2
        rf22_write(0x41, 'p');		// check header 1
        rf22_write(0x42, 'e');		// check header 0
        rf22_write(0x43, 0xff);		// header enable mask 3
        rf22_write(0x44, 0xff);		// header enable mask 2
        rf22_write(0x45, 0xff);		// header enable mask 1
        rf22_write(0x46, 0xff);		// header enable mask 0
    
    	rf22_write(0x69, 0x60);		// AGC on
        rf22_write(0x6a, 0x0b);		// agc override 2
    	//rf22_write(0x6d, 0x0F);		// tx power: +17dBm
    	rf22_write(0x6d, 0x08);
    	
    	
    	rf22_write(0x6E,0x13);		// set baud high
    	rf22_write(0x6F,0xa9);		// set baud low
    
        rf22_write(0x70, 0x2C);		// modulation control
        rf22_write(0x71, 0x22);		// modulation control 2: FIFO mode, OOK  //0x21 / 0x00
    	
        rf22_write(0x72, 0x50);		// frequency deviation: 45kHz
    	rf22_write(0x73, 0x00);		// offset: 0
    	rf22_write(0x74, 0x00);		// offset: 0
    	
    	rf22_write(0x79, 0x0);		// frequency hopping off
        rf22_write(0x7a, 0x0);		// frequency hopping off
    	
    #ifdef BAND_868
    	rf22_write(0x75, 0x73);		// 860-880MHz range
    #else
    	rf22_write(0x75, 0x53);		// 430-440MHz range
    #endif
    
    }
  • REKLAMA
  • #2 10629262
    tmf
    VIP Zasłużony dla elektroda
    Transmisja czego trwa 80ms? Bajtu przez RFM? Skąd to wiesz? Czy bajtu z CPU do RFM? To drugie masz pod całkowitą kontrolą, bo to CPU steruje zegarem SPI. Co do transmisji przez RFM, to jest taka jaki baudrate ustawiłeś. Natomiast w takim przypadku nie wiem jak zmierzyłeś to 80ms. Weź też pod uwagę, że nawet wysyłając jeden bajt wysyłasz preambułę, synchronizację i w zależności od konfiguracji 1-4 bajty adresu, długość pakietu i CRC. Więc może wyjść nawet kilkadziesiąt bajtów overhead na jeden bajt danych. Niestety nie pocieszę cię, ale jeśli chcesz coś sensownego z tym modułem zrobić to musisz się zaprzyjaźnić z angielską notą.
  • REKLAMA
  • #3 10630325
    Śledziu
    Poziom 12  
    Może nie jasno się wyraziłem. Pomierzyłem czas procedury odpowiedzialnej za wysłanie danych. Czyli od wybudzenia modułu do jego uśpienia (pomiar napięcia na wstawionym w szereg oporniku). No oscylogramie dokładnie widać kiedy dane są transmitowane do RFM'a i kiedy następuje wysłanie, całość trwa około 90ms.
    Oczywiście mam świadomość tego że jest wysyłana preambuła, synchronizacja, dane itd.. ale żeby tylko to trwało?
  • REKLAMA
  • #4 10631014
    tmf
    VIP Zasłużony dla elektroda
    Czyli mierzysz czas potrzebny na przesłanie danych po SPI? Ten czas wprost wynika z prędkości SPI, co ustawia się w procesorze, a nie w module. Z kolei całkowity czas pracy modułu związany jest nie tylko z wysyłką danych, ale np. czasem potrzebnym na wybudzenie i dostrojenie modułów radiowych. W zależności od trybu uśpienia modułu czas ten może być naprawdę długi. Kolejna sprawa - z jakim baudrate moduł nadaje? Dla maksymalnego wysłanie kilkunastu bajtów to będzie czas rzędu 1-2 ms, ale dla niższych odpowiednio dłużej. Także z pewnością tak długi czas nadawania to wina programu i takiej a nie innej konfiguracji modułu radiowego.
  • #5 10631388
    Śledziu
    Poziom 12  
    tmf napisał:
    Czyli mierzysz czas potrzebny na przesłanie danych po SPI?

    mierzę czas procedury odpowiedzialnej za wysłanie danej, oto kod:

    w pętli głównej:
    	        data[0] = k;
    			rf22_sendpacket(data,1);
    


    obsługa wysyłania:
    
    void rf22_sendpacket(unsigned char *data, unsigned char size)
    {	
    	unsigned char i;
    	if (size>64)
    		size=64;
    
    	rf22_write(0x07, 0x01);		//	switch to ready mode
    
           rf22_read(0x03);			// clear interrupt status
           rf22_read(0x04);			// clear interrupt status
    
           rf22_write(0x08, 0x01);		// clear TX fifo
           rf22_write(0x08, 0x00);		// clear TX fifo
           rf22_write(0x34, 32);		// premable length: 32 nibbles -> 128 Bits
        
    	rf22_write(0x3e, size);		// packet length
    	
           for (i = 0; i<size; i++)
          {    
    		rf22_write(0x7f, *data++);
         }
    	
        rf22_write(0x05, 0x04);		// enable packet send
        rf22_write(0x07, 0x09);		// TX on
    
       while (nIRQ);			//czekaj aż wyśle
    
    	rf22_read(0x03);			// clear interrupt status
            rf22_read(0x04);			// clear interrupt status
    	rf22_write(0x07, 0x40);		// uśpij
    


    Cytat:

    Z kolei całkowity czas pracy modułu związany jest nie tylko z wysyłką danych, ale np. czasem potrzebnym na wybudzenie i dostrojenie modułów radiowych. W zależności od trybu uśpienia modułu czas ten może być naprawdę długi.

    Masz rację, zgodnie z dokumentacją str. 20 czas potrzebny do tego żeby wysłać cokolwiek to ponad 1ms.

    Cytat:
    Kolejna sprawa - z jakim baudrate moduł nadaje? Dla maksymalnego wysłanie kilkunastu bajtów to będzie czas rzędu 1-2 ms, ale dla niższych odpowiednio dłużej. Także z pewnością tak długi czas nadawania to wina programu i takiej a nie innej konfiguracji modułu radiowego.


    Baud rate ustawiony na 76,8kbps, przy takiej konfiguracji z antenkami z przewodu udało się uzyskać zasięg na poziomie 120-140m. Mi co prawda o zasięg nie chodzi :)
  • #6 10631554
    tmf
    VIP Zasłużony dla elektroda
    Czyli sądząc po powyższym kodzie czas wysłania danych powinien mieścić się w zakresie 2-3ms, czyli gdzieś gubisz ponad 70ms, sporo. Jaką masz częstotliwość SPI? Wywal linię while (nIRQ) - swoją drogą, jak masz ustawione generowanie zdarzeń? Może masz błąd w konfiguracji i nIRQ wcale nie sygnalizuje końca nadawania pakietu. Po wywaleniu tego czekania, ile trwa wykonanie funkcji?
  • #7 10631657
    Śledziu
    Poziom 12  
    Własnie przed chwila spróbowałem oszacować przybliżony czas wysyłania danych z preambułami itd... i wszedł mi podobny wynik <3ms.
    Procesor jest taktowany z wew. oscylatora o wartości 1MHz, więc ustawiłem SPI na = fosc/2
    
    void SPI_init(void)
    {
      DDRB |=(1<<PB2) | (1<<PB3) | (1<<PB5); 	//PINY SS,MOSI,SCK jako wyjscie
      SPCR |= (1<<SPE) | (1<<MSTR); 				//tryb master 
      SPSR |=(1<<SPI2X);   						//DWA RAZY SZYBCIEJ
    } 
    


    RFM22 generuje przerwania na
    rf22_write(0x05, 0x02);		// valid packed received interrupt on

    stąd
    while (nIRQ) 
    czeka.

    i tu jest chyba bład
    powinno być:
    rf22_write(0x05, 0x04);	// Packet Sense Interrupt will be enabled. 
    
  • #9 10635623
    Śledziu
    Poziom 12  
    Strasznie namieszałem, :cry: Nie zauważyłem że w procedurza wysłania jest wstawiona opcja:
    rf22_write(0x05, 0x04);   // Packet Sense Interrupt will be enabled. 


    Czyli od samego początku było OK.
    Układ dalej pozostaje w procedurze przez 90ms.
    o co chodzi :/?
  • #10 10635766
    tmf
    VIP Zasłużony dla elektroda
    Więc tak jak pisałem, usuń to czekanie i zmierz czas wykonania funkcji. Masz JTAG? co to jest to nIRQ? Pokaż pełne funkcje.
  • #11 10635792
    Śledziu
    Poziom 12  
    Niestety nie mam JTAG'a
    Po usunięciu pętli układ While układ wcale nie nadaje - prawdopodobnie przez to że w kolejnych krokach są wysyłane instrukcje usypiania.
    tak mam zdefiniowane nIRQ:
    
    //define NIRQ 2
    #define nIRQ	(PIND&(1<<2))


    W ramach testów
    zmieniłem linijkę odpowiedzialna za długość preambuły na 64bity
    	
          rf22_write(0x34, 0x10);		// preamble length: 16 nibbles, = 64bits
        //rf22_write(0x34, 32);		// premable length: 32 nibbles -> 128 Bits

    i z 90ms zrobiło sie 62ms :) coraz lepiej :D
  • #12 10636122
    tmf
    VIP Zasłużony dla elektroda
    Skoro tak, to by sugerowało, że twój baudrate wcale nie wynosi 75kbps, tylko 2,4 kbps. Sprawdź to. Producent udostępnia arkusz kalkulacyjny, w któym można poustawiać parametry i otrzymujesz wartości rejestrów. Sprawdź czy wszystko się zgadza.
  • #13 10753932
    speecu
    Poziom 11  
    Witam!
    Trochę z innej beczki.
    Czy komuś udało się poprawnie nawiązać transmisję GFSK z większym baudrate niż 4.8 kbps korzystając z arkuszy kalkulacyjnych producenta?
    Mnie interesuje ok. 38.4 kbps, wtedy czas wysyłania pakietu 20 bajtów trwa ok 1-2 ms. Niestety odbiornik wykrywa tylko nośną i żadnego poprawnego pakietu.

    Porównując ustawienia rejestrów z przykładów z noty, polecanych arkuszy kalkulacyjnych w wersji .v23 i .v5 w wielu przypadkach wartości wynikowe są różne, a odbiornik i tak nie odbiera.

    Do testów używam ustawień Jima Lindbloma, które jako jedyne działają, lecz z baudratem 4.8 kbps.

    Pozdrawiam.
  • #14 11145977
    Smashing
    Poziom 20  
    Witam
    Ja używam RFM23B
    Wysyłam dane(64 bajty) drugi odbiera w przerwaniu i od razu wysyła
    całość trwa to około 140ms, też chyba trochę długo.
    Chciałem ustawić jednego jako Master i np 10 Slave to transmisja z 10 Slave
    trwać będzie 1,4 sekundy (odpytuje każdego).
    Nie słyszeliście o jakimś "szybszym radiu"


    Witam
    używając arkuszy kalkulacyjnych w wersji .v5
    zmieniłem tylko na 50kbps FSK, PH+FIFO,
    Układ wysyła + odbiera w max 16ms. (15-16ms)
    Wow :)
  • REKLAMA
  • #15 12056706
    Zari44
    Poziom 11  
    Mam pytanie:
    czy używaliście pinów TX_ANT i RX_ANT jako pinów out uc? czy zwieraliście je do GPIO_0 i GPIO_1 ?

    Czy ktoś wie jak sterować tymi pinami?
    Tutaj: http://ukhas.org.uk/guides:rfm22b jest napisane, że wystarczy początkowa inicjalizacja:
    //This sets up the GPIOs to automatically switch the antenna depending on Tx or Rx state, only needs to be done at start up
    radio1.write(0x0b,0x12);
    radio1.write(0x0c,0x15);

    ale niestety nie działa to w moim przypadku.
    RFM22_init mam zaincjalizowane dokładnie tak samo jak opisuje to śledziu w pierwszym poście w tym temacie.
  • #16 12056907
    zbv
    Poziom 20  
    Ja w rfm22 zwierałem z gpio tak jak podałeś, a w rfm23 działa bez zwierania pinów.
  • #17 12057331
    Zari44
    Poziom 11  
    zbv - a jak ustawiałeś te piny podczas transmisji?
REKLAMA