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

ATtiny 2313 + RFM12B problem z uruchomieniem

lukasz_elektronika 23 Sty 2011 17:12 3382 8
  • #1 9046514
    lukasz_elektronika
    Poziom 13  
    Witam, od kilku dni próbuje uruchomić nadajnik oparty na module RFM12B ale jakoś bez skutku. Nie wysyłam narazie żadnych danych tylko sprawdzam miernikiem czy układ generuje nośną 868MHz pod konfiguracji. Czasem po n-tym resecie układ zaczyna generować nośną ale po odłączeniu zasilania i ponownym włączeniu nie ma żadnej reakcji. Przeglądałem róźne artykuły i tematy na forach. Zmniejszyłem długość połączeń miedzy modułem a uC ale to nie rozwiązało problemu. Poniżej wklejam kod którego używam:
    
    #include <stdio.h>
    #include <avr/io.h>
    #include <avr/delay.h>
    #define  CS_SET PORTD|=_BV(6);
    #define  CS_CLR PORTD&=~_BV(6);
    #define  MOSI_SET PORTB|=_BV(1);
    #define  MOSI_CLR PORTB&=~_BV(1);
    #define  MISO_SET PORTB& 0x08;
    #define  SCK_CLR PORTB&=~_BV(2);
    #define  SCK_SET PORTB|=_BV(2);
    #define  LED_SET PORTD|=_BV(5);
    #define  LED_CLR PORTD&=~_BV(5) ;
    #define WAIT_NIRQ_LOW() while(PINB&0x01);
    
    void main (void)
    {
    SPI_SOFTWARE_INIT();
    _delay_ms(3000);
    RFM12B_Init(); 
    while (1){LED_CLR;
    }
    }
    
    
      void SPI_SOFTWARE_INIT(void)
    {
    DDRB=255;
    PORTB=0 ; //MOSI i SCK
    //DDRB&=_BV(2);
    DDRD=255;
    CS_CLR;
    
    
    }
    
    
    void SEND_SOFTWARE_SPI (int dana)
    
    {
    
    
    for (int i=0;i<16;i++)
    {
    if (dana &0x8000) 
    	{
    	MOSI_SET;
    	}
    else {MOSI_CLR; }
    
    dana=dana<<1;
    
    
    SCK_SET;
    delay();
    
    SCK_CLR;
    //delay();
    
    }
    
    }
    
    
    
    
    
    void RFM12B_Init (void)
    {
    
    //SEND_SOFTWARE_SPI(0xFE00);
    
    
    SEND_SOFTWARE_SPI(0x0000);
    SEND_SOFTWARE_SPI(0x80E7);
    SEND_SOFTWARE_SPI(0x8238);
    SEND_SOFTWARE_SPI(0xA640);
    SEND_SOFTWARE_SPI(0xC687);
    SEND_SOFTWARE_SPI(0x94A0);
    SEND_SOFTWARE_SPI(0xC2AC);
    SEND_SOFTWARE_SPI(0xCA81);
    SEND_SOFTWARE_SPI(0xCED4);
    SEND_SOFTWARE_SPI(0xC483);
    SEND_SOFTWARE_SPI(0x9850);
    SEND_SOFTWARE_SPI(0xCC77);
    SEND_SOFTWARE_SPI(0xE000);
    SEND_SOFTWARE_SPI(0xC800);
    SEND_SOFTWARE_SPI(0xC070);
    //SEND_SOFTWARE_SPI(0xCA81);
    }
    
    
    
    void delay (void)
    {
    for (int i=0; i<4;i++)
    {
    asm("nop");
    }
    }
    
    



    Proszę o jakieś porady co może byc nie tak.
    PS. ATtiny i RFM zasilane napięciem 3,3V, uC taktowany wewnętrznym oscylatorem 8MHz
  • #2 9052026
    lukasz_elektronika
    Poziom 13  
    Naprawdę nikt nie ma jakiś podejrzeń co może byc nie tak?
  • Pomocny post
    #3 9054812
    kajojj
    Poziom 13  
    Tu masz działający kod, tylko musisz poustawiać pod swój hardware sekcje configuration. Na końcu masz funkcję main tam masz 3 tryby pracy. Musisz jedną z nich odhaszować. Możesz zrobić kilka konfiguracji.
    Powinieneś zacząć od (1), tylko wysyłanie pakietów w "eter". Powinna Ci migać dioda od nadawania. Potem jeśli masz dwa zestawy uC i RFM12, to możesz na jeden wgrać (2) a na drugi (3). Zresetuj ten na który wgrałeś (2) i powinny wymieniać się pakietami nawzajem.

    #include <avr/io.h>
    #include <util/delay.h>
    
    /* ------------------ Start configuration ----------------------------------------- */
    
    // ustawienia SPI dla ATmega644PA dla innego uC mogą być inne!
    #define SPI_PORT		PORTB
    #define SPI_DDR			DDRB
    #define SPI_CS			3		// (uC)PB.3 - (RF12)nSEL
    #define SPI_SS			4		// to zostaw niepodłączone!
    #define SPI_MOSI		5		// (uC)MOIO - (RF12)SDI
    #define SPI_MISO		6		// (uC)MISO - (RF12)SDO
    #define SPI_SCK			7		// (uC)SCK - (RF12)SCK
    
    #define RF_IRQ_PORT		PORTB
    #define RF_IRQ_DDR		DDRB
    #define RF_IRQ_PIN		PINB
    #define RF_IRQ_BIT		2		// (uC)PB.2 - (RF12)nIRQ
    
    #define RF_LED_TX_PORT	PORTA	// podłącz diodę czerwoną przez rezystor pomiędzy
    #define RF_LED_TX_DDR	DDRA	// PA.0 i (+) zasilania
    #define RF_LED_TX_BIT	0
    
    #define RF_LED_RX_PORT	PORTA	// podłącz diodę zieloną przez rezystor pomiędzy
    #define RF_LED_RX_DDR	DDRA	// PA.1 i (+) zasilania
    #define RF_LED_RX_BIT	1
    
    #define PACK_SIZE		100		// długość pakietów testowych
    
    /* ------------------ End configuration ------------------------------------------- */
    
    #define LED_TX_OUT()	RF_LED_TX_DDR |= (1 << RF_LED_TX_BIT)
    #define LED_TX_OFF()	RF_LED_TX_PORT |= (1 << RF_LED_TX_BIT)
    #define LED_TX_ON()		RF_LED_TX_PORT &= ~(1 << RF_LED_TX_BIT)
    
    #define LED_RX_OUT()	RF_LED_RX_DDR |= (1 << RF_LED_RX_BIT)
    #define LED_RX_OFF()	RF_LED_RX_PORT |= (1 << RF_LED_RX_BIT)
    #define LED_RX_ON()		RF_LED_RX_PORT &= ~(1 << RF_LED_RX_BIT)
    
    /* -------------------------------------------------------------------------------- */
    
    typedef enum { TRUE = 1, FALSE = 0 } bool;
    
    /* -------------------------------------------------------------------------------- */
    
    uint16_t RF12Cmd(uint16_t Cmd)
    {
    	uint16_t Data;
    	
    	SPI_PORT &= ~(1 << SPI_CS);
    	
    	SPDR = Cmd >> 8;
    	while (!(SPSR & (1 << SPIF)));
    	Data = SPDR << 8;
    	
    	SPDR = Cmd & 0xff;
    	while (!(SPSR & (1 << SPIF)));
    	Data |= SPDR;
    	
    	SPI_PORT |= (1 << SPI_CS);
    	
    	return Data;
    }
    
    /* -------------------------------------------------------------------------------- */
    
    void RF12Send(uint8_t Data)
    {
    	while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
    	
    	RF12Cmd(0x0000);
    	
    	RF12Cmd(0xb800 | Data);
    }
    
    /* -------------------------------------------------------------------------------- */
    
    uint8_t RF12Recv(void)
    {
    	while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
    	
    	RF12Cmd(0x0000);
    	
    	return RF12Cmd(0xb000);
    }
    
    /* -------------------------------------------------------------------------------- */
    
    void RF12PacketSend(uint8_t Data[], uint8_t Len)
    {
    	uint16_t crc = 0;
    	uint8_t i, byte;
    	
    	RF12Cmd(0x0000);	// read status
    	RF12Cmd(0x8221);	// ET, DC				\\ TX
    	
    	while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
    	
    	LED_TX_ON();		// TX start
    	
    	RF12Send(0xaa);
    	RF12Send(0xaa);
    	RF12Send(0xaa);
    	RF12Send(0x2d);
    	RF12Send(0xd4);
    	
    	for (i = 0; i < Len; i++)
    	{
    		byte = Data[i];
    		RF12Send(byte);
    		crc += (i % 16) * byte;
    	}
    	
    	RF12Send(crc >> 8);
    	RF12Send(crc & 0xff);
    	
    	RF12Send(0xaa);
    	RF12Send(0xaa);
    	RF12Send(0xaa);
    	
    	LED_TX_OFF();		// TX stop
    	
    	RF12Cmd(0x8281);	// ER, DC				\\ RX
    	RF12Cmd(0xca81);	//
    	RF12Cmd(0xca83);	// FIFO8, DR
    }
    
    /* -------------------------------------------------------------------------------- */
    
    bool RF12PacketRecv(uint8_t Data[])
    {
    	uint16_t crc = 0, pcrc;
    	uint8_t i = 0, byte;
    	
    	RF12Cmd(0x8281);	// ER, DC				\\ RX
    	RF12Cmd(0xca81);	//
    	RF12Cmd(0xca83);	// FIFO8, DR
    	
    	byte = RF12Recv();
    	Data[i] = byte;
    	crc += (i % 16) * byte;
    	
    	LED_RX_ON();
    	
    	for (i++; i < PACK_SIZE; i++)
    	{
    		byte = RF12Recv();
    		Data[i] = byte;
    		crc += (i % 16) * byte;
    	}
    	
    	LED_RX_OFF();
    	
    	pcrc = RF12Recv() << 8;
    	pcrc |= RF12Recv();
    	
    	if (pcrc == crc)
    	{
    		return TRUE;
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    /* -------------------------------------------------------------------------------- */
    
    void RF12Init(void)
    {
    	// inicjalizacja SPI
    	SPI_PORT &= ~(1 << SPI_MOSI | 1 << SPI_SCK);
    	SPI_DDR |= (1 << SPI_MOSI) | (1 << SPI_SCK) | (1 << SPI_SS);
    	
    	SPI_PORT |= (1 << SPI_CS);
    	SPI_DDR |= (1 << SPI_CS);
    	
    	SPSR = 0;							// F_SPI = F_CPU/16
    	SPCR = (1 << SPR0);				//
    	
    	SPCR |= (1 << SPE) | (1 << MSTR);	// włączenie SPI
    	
    	// inicjalizacja portów do obsługi RF
    	
    	RF_IRQ_DDR &= ~(1 << RF_IRQ_BIT);
    	RF_IRQ_PORT |= (1 << RF_IRQ_BIT);
    	
    	// inicjalizacja modułu RF
    	
    	RF12Cmd(0x80d8);	// EL, EF, 433band, 12.5pF
    	RF12Cmd(0x8209);	// EX, DC			\\ NONE
    	RF12Cmd(0xa640);	// 434MHz
    	RF12Cmd(0xc611);	// 19.2kbps
    	RF12Cmd(0x94a0);	// VDI, FAST, 137kHz, 0dBm, -103dBm
    	RF12Cmd(0xc2ac);	// AL, S, DQD4
    	RF12Cmd(0xc487);	// A1, FI, OE, EN
    	RF12Cmd(0x9850);	// 90kHz, MAX OUT
    	
    	// odczekanie na uruchomienie oscylatora
    	
    	_delay_ms(5);
    	
    	// zerowanie do odbierania
    	RF12Cmd(0xca81);	//
    	RF12Cmd(0xca83);	// FIFO8, DR
    	RF12Recv();
    }
    
    /* -------------------------------------------------------------------------------- */
    
    int main(void)
    {
    	uint8_t BufWr[PACK_SIZE], BufRd[PACK_SIZE], i;
    	
    	for (i = 0; i < PACK_SIZE; i++)
    	{
    		BufWr[i] = i + 1;
    	}
    	
    	LED_TX_OFF();
    	LED_TX_OUT();
    	LED_RX_OFF();
    	LED_RX_OUT();
    	
    	for (i = 0; i < 4; i++)
    	{
    		_delay_ms(200);
    		LED_TX_ON();
    		LED_RX_ON();
    		_delay_ms(200);
    		LED_TX_OFF();
    		LED_RX_OFF();
    	}
    	
    	RF12Init();
    	
    	//////////////////////////////////////////////////////////////////
    	
    	// (1) nadaje cały czas
    	/*
    	for ( ; ; )
    	{
                    _delay_ms(500);
    		RF12PacketSend(BufWr, PACK_SIZE);
    	}
    	*/
    	
    	//////////////////////////////////////////////////////////////////
    	
    	// (2) nadaje pierwszy pakiet a potem odpowiada jeśli coś odbierze
    	/*
    	_delay_ms(500);
    	RF12PacketSend(BufWr, PACK_SIZE);
    	
    	for ( ; ; )
    	{
    		RF12PacketRecv(BufRd);
    		RF12PacketSend(BufWr, PACK_SIZE);
    	}
    	*/
    	
    	//////////////////////////////////////////////////////////////////
    	
    	// (3) jeśli odbierze coś to odpowiada
    	/*
    	for ( ; ; )
    	{
    		RF12PacketRecv(BufRd);
    		RF12PacketSend(BufWr, PACK_SIZE);
    	}
    	*/
    }
    


    Jeśli coś nie będzie działać, napisz co dokładnie nie działa. ;-) Pozdrawiam
  • #4 9056011
    lukasz_elektronika
    Poziom 13  
    Dziękuje za zainteresowanie moim problemem. Kod sprawdzę jeszcze dziś bądź jutro. Powiedz mi czy pomiędzy RFM a uC stosowałeś jakieś bufory czy poprostu bezpośrednio pod uC?
  • #5 9056146
    kajojj
    Poziom 13  
    Możesz to podłączyć bezpośrednio, zwłaszcza jak masz zasilanie 3,3V. Możesz jednak dla testów RFM12B podłączyć do 5V, gwarantuje że Ci się nie spali.
    Nie wiem jak RFM12B, ale RFM12 wymaga rezystora podciągającego pullup do linii FSK/DATA/nFFS. Co do resetu to mam go podłączonego razem z tym od uC, nie wiem czy to będzie działać jak reset od RFM będzie wisiał - tego nie testowałem.
  • #6 9056546
    lukasz_elektronika
    Poziom 13  
    Przyjrzałem się Twojemu kodowi i widze, że używasz sprzętowego SPI, jakiej długości masz przewody między uC a RFM, czy może masz to na płytce?Czytałem, że te moduły są wrażliwe na zakłocenia i należy używać jak najkrótszych połaczeń.
  • #7 9056986
    kajojj
    Poziom 13  
    Jak są rozwiązania sprzętowe to warto z nich skorzystać, bo po co robić coś na piechotę skoro może to za nas zrobić hardware. U mnie działa na płytce, ale działało też na kabelkach ~10cm i to z częstotliwością SPI ponad 2MHz. Jeśli Ty masz taktowanie 8MHz preskaler SPI dzieli jeszcze przez 16 (bo tak jest ustawiony). Zatem 500kHz, nie sądzę żeby to nie działało. Chyba że masz jakieś długie kable.
  • #8 9059615
    lukasz_elektronika
    Poziom 13  
    Zrobiłem nowy układ na ATtiny48 i mój kod działa, Twój zresztą też.Nie wiem co mogło być powodem, że pod Tiny2313 nie działa. Jeszcze tylko odbiornik i bede wysyłał jakies informacje. Jaki zasięg uzyskałeś z tymi modułami w pomieszczeniach?
  • #9 9059772
    kajojj
    Poziom 13  
    To wszystko zależy od parametrów jakie ustawisz w tych modułach m.in od:
    - anten
    - częstotliwości (433/868 MHz)
    - szybkości transmisji
    - dewiacji
    - pasma

    Mi udało się uzyskać zasięg 250 m w otwartym terenie 868 MHz i 9600bps. Co do w budynku to zależy jakie grube ściany itp. Ale w mieszkaniu zasięg jest wszędzie, nawet w lodówce - co się okazało przy testach działania AFC -> zmiana temperatury -> zmiana częstotliwości kwarcu.
REKLAMA