RFM01, RFM02, ontvangen/verzenden doet het niet

Ik heb de 868MHz RF01, RF02 versie aangeschaft en dit heb ik aangesloten op de ATmega32. Echter ontvang ik volgens mij wel wat, maar niet wat ik verwacht. Ik heb de code gebruikt en aangepast aan de ATmega. Om te testen stuur ik elke seconde een waarde waarmee led0 t/m 7 aangaat, een voor een. Ook heb ik twee leds als status. Groen als de ChkSum overeenkomt met alle verzonden bij elkaar opgetelde waarden van 1 Send methode. Rood als het niet zo is.

Ze zijn allebei aan, dus ik ga er van uit dat hij soms wel, soms niet ontvangt. Echter zijn alle leds altijd aan, terwijl hij eigenlijk hoort te beginnen bij led0, 1 seconde, led2, seconde.. etc.

Als ik de verzender uitzet, dan is de status soms ook gewoon groen en staan alle leds ook aan. Terwijl er niet eens wat verzonden word.

Ik heb op het moment geen idee en ik hoop dat er wat mensen zijn die me in de goede richting kunnen helpen. Hier is de infopagina van de 2 modules, inclusief datasheet.
Ontvanger: http://ideetron.biedmeer.nl/Webwinkel-Product-182196/FSK-ontvangermodu…
Verzender: http://ideetron.biedmeer.nl/Webwinkel-Product-182077/FSK-zendermodule-…

En mijn code voor verzender:

#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL
#include <util/delay.h>


#define DDR_IN	  	0
#define DDR_OUT		1

#define PORT_SEL	PORTB
#define PIN_SEL		PINB
#define DDR_SEL		DDRB

#define	PORT_SDI	PORTB
#define PIN_SDI		PINB
#define DDR_SDI		DDRB

#define PORT_SCK	PORTB
#define PIN_SCK		PINB
#define DDR_SCK		DDRB

#define PORT_SDO	PORTB
#define PIN_SDO		PINB
#define DDR_SDO		DDRB

#define RFXX_SCK  	7	// SCK	6
#define RFXX_SDO  	6	// SDO = SPI data input	-
#define RFXX_SDI  	5	// MOSI	3
#define RFXX_SEL  	4	// nSEL	5
#define RFXX_DATA 	3	// FSK	1
#define PB2			2 	// -
#define PB1			1   // -
#define PB0       	0	// -

#define SEL_OUTPUT() 	DDR_SEL  |= (1<<RFXX_SEL)
#define HI_SEL()		PORT_SEL |= (1<<RFXX_SEL)
#define LOW_SEL()		PORT_SEL &=~(1<<RFXX_SEL)

#define SDI_OUTPUT()	DDR_SDI  |= (1<<RFXX_SDI)
#define HI_SDI()		PORT_SDI |= (1<<RFXX_SDI)
#define LOW_SDI()		PORT_SDI &=~(1<<RFXX_SDI)

#define SDO_INPUT()		DDR_SDO  &=~(1<<RFXX_SDO)
#define SDO_HI()		PIN_SDO&(1<<RFXX_SDO)

#define SCK_OUTPUT()	DDR_SCK  |=(1<<RFXX_SCK)
#define HI_SCK()		PORT_SCK |=(1<<RFXX_SCK)
#define LOW_SCK()		PORT_SCK &=~(1<<RFXX_SCK)


void RFXX_PORT_INIT(void) { // initialise all neccesary ports
  HI_SEL();		// set bit SEL
  HI_SDI();		// set bit SDI
  LOW_SCK();	// reset bit SCK
  SEL_OUTPUT();	// set port SEL as output
  SDI_OUTPUT(); // set port SDI as output
  SDO_INPUT();  // set port SDO as input
  SCK_OUTPUT(); // set port SCK as output
}

unsigned int RFXX_WRT_CMD( unsigned int aCmd) {	// to send commands 

  unsigned char i;
  unsigned int temp;

  LOW_SCK();	// reset bit SCK
  LOW_SEL();    // reset bit SEL
  for(i=0;i<16;i++)
    {
    temp<<=1;	// temp=temp<<1;
    if(SDO_HI()) {  // if SPI (PIN5 SDO) data input is high
	  temp|=0x0001; // temp is a 16-bit integer
    }
	LOW_SCK();	// reset bit SCK
    if(aCmd&0x8000) {	// if((aCmd&0x8000)==0x8000)
	  HI_SDI();	// set bit SDI
	  }
	  else {
      LOW_SDI();// reset bit SDI
	  }
      HI_SCK();	// set bit SCK
      aCmd<<=1; // aCmd=aCmd<<1
  }
  LOW_SCK();	// reset bit SCK
  HI_SEL();		// set bit SEL
  return(temp);
}


void RF02B_SEND(unsigned char aByte) {	// send a byte

  unsigned char i;

  for(i=0;i<8;i++)
    {
	while(PINB&(1<<RFXX_SDO));	// polling nIRQ
	while(!(PINB&(1<<RFXX_SDO)));
	if(aByte&0x80)
	  {
      PORTB|=(1<<RFXX_DATA);	// set bit(FSK): request data input
	  }
	  else {
	  PORTB&=~(1<<RFXX_DATA);	// reset bit(FSK): request data input
      }
    aByte<<=1;	// aByte=aByte<<1
  }
}


void Send (unsigned int byte) {

  unsigned int i, j, ChkSum;

  RFXX_WRT_CMD(0xC039);	// start TX
  ChkSum=0;
  RF02B_SEND(0xAA); // PREAMBLE
  RF02B_SEND(0xAA); // PREAMBLE
  RF02B_SEND(0xAA); // PREAMBLE
  RF02B_SEND(0x2D); // HEAD HI BYTE
  RF02B_SEND(0xD4); // HEAD LOW BYTE
  RF02B_SEND(byte);	// Data0
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data1
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data2
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data3
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data4
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data5
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data6
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data7
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data8
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data9
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data10
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data11
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data12
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data13
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data14
  ChkSum+=byte;
  RF02B_SEND(byte);	// Data15
  ChkSum+=byte;
  RF02B_SEND(ChkSum);// Data16
  RF02B_SEND(0xAA);	// dummy byte

  RFXX_WRT_CMD(0xC001); // close TX

  for(i=0;i<5000;i++)
  for(j=0;j<123;j++);
}

void wait() {
  for(int i=0;i<=10;i++)
  _delay_ms(100);
}

void main(void) {

  RFXX_PORT_INIT();	// initialise all neccesary ports

  RFXX_WRT_CMD(0xCC00); // read internal status register content
  RFXX_WRT_CMD(0x9361); // 868band, 2MHz CLK pin, 11.5pF, 60kHz
  RFXX_WRT_CMD(0xA640); // 868MHz (86 + 6 )
  RFXX_WRT_CMD(0xD040); // RATE/2 <<------------------?
  RFXX_WRT_CMD(0xC823); // 4.8kbps
  RFXX_WRT_CMD(0xC220); // ENABLE BIT SYNC	
  RFXX_WRT_CMD(0xC001); // CLOSE ALL

  PORTB|=(1<<RFXX_DATA);// set bit FSK
  DDRB|=(1<RFXX_DATA);	// set port FSK as output

while(1) {

  Send(0xFF); // led0 on - 00000001
  wait();
  Send(0xFE); // led1 on - 00000010
  wait();
  Send(0xFD); // led3 on - 00000100
  wait();
  Send(0xFB); // led 4....
  wait();
  Send(0xF7);
  wait();
  Send(0xEF);
  wait();
  Send(0xDF);
  wait();
  Send(0xBF);
  wait();
  Send(0x7F);
  wait();
  }
}

En nu de ontvanger:

#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#define DDR_IN	  	0
#define DDR_OUT		1

#define PORT_SEL	PORTB
#define PIN_SEL		PINB
#define DDR_SEL		DDRB

#define	PORT_SDI	PORTB
#define PIN_SDI		PINB
#define DDR_SDI		DDRB

#define PORT_SCK	PORTB
#define PIN_SCK		PINB
#define DDR_SCK		DDRB

#define PORT_SDO	PORTB
#define PIN_SDO		PINB
#define DDR_SDO		DDRB

#define PORT_LED 	PORTC
#define DDR_LED		DDRC

#define RFXX_SCK  	7	// SCK 11
#define RFXX_SDO  	6	// SDO = SPI data input	// MISO 10
#define RFXX_SDI  	5	// MOSI --> SDI 2
#define RFXX_SEL  	4	// SS --> SEL 3
#define RFXX_DATA 	3	// -
#define PB2			2  	// -
#define PB1			1   // -
#define PB0       	0 	// -

#define SEL_OUTPUT() 	DDR_SEL  |= (1<<RFXX_SEL)
#define HI_SEL()		PORT_SEL |= (1<<RFXX_SEL)
#define LOW_SEL()		PORT_SEL &=~(1<<RFXX_SEL)

#define SDI_OUTPUT()	DDR_SDI  |= (1<<RFXX_SDI)
#define HI_SDI()		PORT_SDI |= (1<<RFXX_SDI)
#define LOW_SDI()		PORT_SDI &=~(1<<RFXX_SDI)

#define SDO_INPUT()		DDR_SDO  &=~(1<<RFXX_SDO)
#define SDO_HI()		PIN_SDO&(1<<RFXX_SDO)

#define SCK_OUTPUT()	DDR_SCK  |=(1<<RFXX_SCK)
#define HI_SCK()		PORT_SCK |=(1<<RFXX_SCK)
#define LOW_SCK()		PORT_SCK &=~(1<<RFXX_SCK)

#define LED_OUTPUT()	DDR_LED|=0x0F	// DDR_LED = output		

#define LED0_ON()		PORT_LED&=~(1<<0)
#define LED0_OFF()		PORT_LED|=(1<<0)
#define LED0_TRG()		PORT_LED^=(1<<0)

#define LED1_ON()		PORT_LED&=~(1<<1)
#define LED1_OFF()		PORT_LED|=(1<<1)
#define LED1_TRG()		PORT_LED^=(1<<1)

#define LED2_ON()		PORT_LED&=~(1<<2)
#define LED2_OFF()		PORT_LED|=(1<<2)
#define LED2_TRG()		PORT_LED^=(1<<2)

#define LED3_ON()		PORT_LED&=~(1<<3)
#define LED3_OFF()		PORT_LED|=(1<<3)
#define LED3_TRG()		PORT_LED^=(1<<3)



unsigned char RF_RXBUF[22];


void RFXX_PORT_INIT(void) {
  HI_SEL();		// set bit SEL
  HI_SDI();		// set bit SDI
  LOW_SCK();	// reset bit SCK
  SEL_OUTPUT();	// set port SEL as output
  SDI_OUTPUT(); // set port SDI as output
  SDO_INPUT();  // set port SDO as input
  SCK_OUTPUT(); // set port SCK as output
}


unsigned int RFXX_WRT_CMD( unsigned int aCmd) {	// // to send commands 

  unsigned char i;
  unsigned int temp;

  LOW_SCK();	// reset bit SCK
  LOW_SEL();    // reset bit SEL
  for(i=0;i<16;i++)
    {
    temp<<=1;	// temp=temp<<1;
    if(SDO_HI()) {  // if SPI (PIN5 SDO) data input is high
	  temp|=0x0001; // temp is a 16-bit integer
    }
	LOW_SCK();	// reset bit SCK
    if(aCmd&0x8000) {	// if((aCmd&0x8000)==0x8000)
	  HI_SDI();	// set bit SDI
	  }
	  else {
      LOW_SDI();// reset bit SDI
	  }
      HI_SCK();	// set bit SCK
      aCmd<<=1; // aCmd=aCmd<<1
  }
  LOW_SCK();	// reset bit SCK
  HI_SEL();		// set bit SEL
  return(temp);
}


unsigned char RF01_RDFIFO(void) {

  unsigned char i, Result;
  LOW_SCK();
  LOW_SDI();
  LOW_SEL();
  for(i=0;i<16;i++)	{	// skip status bits
    HI_SCK();
	HI_SCK();
	LOW_SCK();
	LOW_SCK();
  }
  Result=0;
  for(i=0;i<8;i++) {	// read fifo data byte
    Result<<=1;	// Result=Result<<1;
	if(SDO_HI()) {
	  Result|=1;
	}
    HI_SCK();
	HI_SCK();
	LOW_SCK();
	LOW_SCK();
    }	
  HI_SEL();
    return(Result);
}	

void main(void) {

  unsigned int intI, intJ;
  unsigned char i, j, ChkSum;

  for(intI=0;intI<10000;intI++)for(intJ=0;intJ<123;intJ++);
  RFXX_PORT_INIT();		// initialize

  RFXX_WRT_CMD(0x0000);	// read internal status register
  RFXX_WRT_CMD(0X918A); // 868MHz, crystal oscillator, 12,5pF, 134KHz 
  RFXX_WRT_CMD(0xA640); // 868MHz (860 + 6 )
  RFXX_WRT_CMD(0XC847); // 4.8kbps
  RFXX_WRT_CMD(0xC6AB); // AFC setting
  RFXX_WRT_CMD(0XC42A); // clock recovery manual control, digital filter, DQD=4
  RFXX_WRT_CMD(0xC240); // output 1.66Mhz
  RFXX_WRT_CMD(0xC080);
  RFXX_WRT_CMD(0xCE88); // use FIFO
  RFXX_WRT_CMD(0xCE8B);
  RFXX_WRT_CMD(0xC081); // open RX
  DDRB|=(1<<RFXX_DATA); 

  DDRD&=~(1<<2);	// everything 0 except int0



  LED_OUTPUT();	// DDR_LED = output	
  PORTC=0xFF;	// TEMP
  DDRA=0xFF;	// TEMP
  i=0;
  

while(1) {
  while((PIND&(1<<2))) {	// polling the nIRQ data

    RF_RXBUF[i++]=RF01_RDFIFO();	// read FIFO data
	if(i==18) {
	  i=0;
	  RFXX_WRT_CMD(0xCE88);	// reset FIFO for next frame recognition    
	  RFXX_WRT_CMD(0xCE8B);
	  ChkSum=0;
	  for(j=0;j<16;j++) {
	    ChkSum+=RF_RXBUF[j];	// calculate checksum
      }
	  if(ChkSum==RF_RXBUF[16]) {	// frame check
	    LED3_TRG();		// receive indication
		}
      else( LED2_TRG());
	  PORTA=RF_RXBUF[1];
      }
	}
  }
}

hallo UneXisted hebt jij toevallig ook nog een schema van die led cube heb er zelf ook een gemaakt maar het programeren lukte niet

als u het schema heeft zou u dan ook zo vriendelijk willen wezen om hem naar mij te sturen?

Emailadres in profiel openbaar

[Bericht gewijzigd door Henry S. op (11%)]

Heb je ze bij mij gekocht of ergens anders?

Op 12 maart 2009 20:40:04 schreef Bart Hiddink:
Heb je ze bij mij gekocht of ergens anders?

Bij jou.
Ik heb ze bij jou gekocht. :) Ik was aardig op weg. Als ik weer tijd heb ga ik er nog eens naar kijken. Ik vind het wel heel naar dat het voorbeeld totaal niet klopt en werkt.

Je bedoelt dan wrsch het voorbeel van Hope RF.
Ik heb daar al meer klachten over.
Ik heb het zelf alleen gebruikt als opstapje.

Ik kijk vandaag even naar je code.

Dit is al van lang geleden!

Ik ga er komende weken nog even aan sleutelen. Als het dan niet lukt mail ik je.

Klopt dat het voorbeeld uit de datasheet niet werkt. Zitten een aantal fouten in...

Dat klopt helaas.

Het is een beetje lastig voor mij om alle 'bugs' te verzamelen.

Het grootste probleem met het voorbeeld is dat je op het verkeerde been wordt gezet door het MISO en MOSI verhaal.
Dat wekt de suggestie dat de SPI interface van de micro wordt gebruikt maar dat is niet zo.
Ik heb het vermoeden dat de programmeur de code portable heeft willen maken en daarbij de aansluitingen naar de RFM is vergeten.

Ook worden in de RFM02 eigenlijk 2 verschillende poorten gebruikt; De SPI poort (hier wel!) voor initialisatie en de FSK pin (poort) voor het versturen van data.
En data versturen kan ook nog op een andere manier, maar vergeet dat gelijk maar weer..

De fouten bij de zender (waarvan ik weet) zijn:
(ATmega source)

De MOSI (Master Out Slave In) uitgang wordt niet gebruikt.
Dat is PB4 geworden en dat is gewoon een uitgang.

Het gaat dus mis bij het rijtje #Define voor PB.
Daarbij moet je even goed naar het schema staren.

Het zenden van een frame gaat als volgt:

1. de RFM wordt geïnitialiseerd:

Dat doe je via de SPI interface van de RFM.
Kijk in RF02_code.pdf op blz. 1; 1. Timing diagram voor een voorbeeld van de timing.

nSEL is laag, SDI bevat de data en met SCK klok je het naar binnen.

Achtereenvolgens de volgende groepen van 16bits:

0xCC00 : status tegister read
0x8B61 : Band select: 434 MHz, CLK out select
(alt: 0x9361 : 868 MHz)
0xA640 : 434.000 MHz (868.000 MHz)
0xD040 : PLL setting, Data Rate/2
0xC823 : Data Rate = 4800 bps (9600 instellen!)
0xC220 : Enable bit sync
0xC001 : Enable clk out but close all other processes

Nu is de RFM klaar voor gebruik.

Als je een frame wilt verzenden dan moet je eerst de zender aanzetten.
Met dezelfde functie als de groepen hierboven, schijf dan naar de SPI poort:

0xC039 : Open TX

Daarna moet met een andere functie de data naar de RFM worden geschreven.
De nSEL uitgang zet je hoog en dat is het teken voor de RFM om data op de FSK ingang uit te zenden.
De RFM bepaalt door de status van nIRQ of het volgende bit op de FSK lijn overgenomen gaat worden.

Omdat de timing dus wordt bepaald door de RFM kun je begrijpen dat het dus op dit punt critisch kan worden. Hier zitten ook de meeste fouten in de programmering.
Doordat de timing voor de zender niet goed is, zal de ontvanger de syncronisatie verliezen en komt er helemaal of maar soms een deel van de data aan.

Dit is ook de reden dat de RFM02 beter een eigen microcontroller kunt geven en die via SPI of UART kunt koppelen aan de micro van je doelontwerp.
(zie de setup van Easy-RF).

Het frame bestaat altijd uit een preamble:

0xAA
0xAA
0xAA
(mogen er meer zijn)

En daarna de code:

0x2D
0xD4

Hierdoor kan de RFM01 (ontvanger) syncroniseren.

Daarna komt je data.

Let erop dat je niet teveel allemaal '0' of '1' achter elkaar verstuurd, dit kan de syncronisatie verstoren.
Afhankelijk van wat parameters (waar ik nu niet op in zal gaan), zijn 8 '0'-en of '1'-en achter elkaar het maximum.

Als je klaar bent met de data dan kun je afsluiten en met een CRC of weer een paar maal 0xAA.

Tot zover werkt het voorbeeld heel aardig.

De fouten bij de ontvanger (waarvan ik weet) zijn:
(ATmega source)

De nIRQ uitgang van de RFM zit niet aangesloten in het schema. Dat moet wel, want daarmee geeft de RFM aan dat de ontvanger gesynchroniseerd is en dat een byte klaar staat in de FIFO. Erg belangrijk dus..

Vergeet vooral de 10k weerstand tussen VCC en DATA niet!
Dat staat wel goed in het schema.

Initialiseren gaat op dezelfde manier als de zender maar dan met wat meer parameters.
De manier van werken is hetzelfde en je kunt dezelfde functie gebruiken.

De ontvanger staat in het voorbeeld altijd aan en is klaar voor ontvangst.

De ontvanger haalt de data uit de detector en zal blijven proberen te syncroniseren.
Als de ontvanger juist is ingesteld en een signaal valt binnen de 'lock' van de PLL, dan geeft ze intern een bitsyncronisatie signaal af.
Dan gaat ze wachten op de combinatie 0x2D en 0xD4.
Als dat is geweest, dan zal de ontvanger de nIRQ laag maken.

Op dat moment moet je code de data uit de FIFO lezen.

De manier om dat te doen is om in totaal 24 bits te gaan 'halen'.

Je maakt de uitgang SEL laag en dan kun je de data naar buiten clocken via CLK.

De eerste 16 bits bevat alle informatie van de ontvanger.
Mijn code bestuurt hier de firmware MAC mee.

Voor een uitleg van de individuele bits, zie :RF01.pdf, blz. 17.

De 8 bits daarna (uitgaande van een 8bits systeem) zijn de bits in de FIFO.

Als je alle 24 bits hebt gelezen, dan is de FIFO leeg en kun je wachten op de volgende nIRQ.

Als je een fout ontvangt, dan is het mogelijk om dat uit de eerste 16 bits te herkennen. Dan is het zaak om zo snel mogelijk de FIFO weer leeg te maken (te resetten) voor de volgende byte.

Dat die je door de volgende combinatie te sturen naar de SPI poort van de RFM:

0xCE88
0xCE8B

Dat wordt de FIFO gereset.

~~

Op de Fysieke laag kunnen de volgende fouten optreden:

- verkeerde frequentie
- verkeerde data rate
- bandbreedte van de zender/ontvanger (~1:1.5)
- storingen

Op MAC niveau kunnen de volgende fouten optreden:

- geen bitsyncronisatie
- geen byte synchonisatie
- timing van de zender (muy, muy importante!!!!)

Op systeemniveau (data verbindingslaag) kunnen de volgende fouten voorkomen:

- een afgebroken verbinding door bitfouten; teveel '0'-en en '1'-en achter elkaar.
- CRC fout

Enfin, buiten de fouten in de beide datasheets dus nog een heleboel ellende in de code en de timing van de code.

Er is nog Hope :) Ik ben nu een nieuw boek aan het schrijven met daarin een zeer uitgebreide uiteenzetting van de chips met nog veel meer tips en truuks voor het programmeren van een firmware stack.

Ik hoop dat je hiermee wat verder kan komen.
Je kunt mij overigens altijd privé mailen met vragen.

Voor de rest nodig ik iedereen uit eventuele andere fouten in de source van Hope RF (datasheets: RF01_code.pdf en RF02_code.pdf) hier te posten.
Ik zal ze dan verzamelen en de datasheet in het Nederlands herschrijven.

Misschien hebben we binnenkort wel nieuwe datasheets met wel werkende voorbeelden! :)

Hi Bart e.a.

Ik weet hij is oud, maar ik bump hem toch maar even...

Ik zit ook te worstelen met deze modules. En ik hoopte met jouw aanwijzingen weer iets verder te komen. Het zou perfect zijn als we gezamenlijk tot een werkende 'datasheet' zouden kunnen komen.

In de beschrijving van het ontvang gedeelte heb je het over het binnenklokken via de CLK pin. Dat staat inderdaad ook zo in het originele datasheet, maar moet dat niet ook gewoon via de SCK pin zijn?

Voor de rest gebruik ik de volgende init code voor de ontvanger:


	rf_write_cmd( 0x898A ); // 433 MHz, Low battery detect off, Wake up timer disabled, Xtal enabled, Bandwidth 134 kHz, Clk enabled 
	rf_write_cmd( 0xA640 ); // 434 MHz
	rf_write_cmd( 0xC847 ); // 4800 baud
	rf_write_cmd( 0xC69B ); // VDI + offset, range -16 - +15, offset in output reg, no AFC high accuracy, AFC output enabled, AFC enabled 
	rf_write_cmd( 0xC42A ); // no clock recover auto-lock, No clock recover fast mode, data filter = Digital, DQD treshold = 2
	rf_write_cmd( 0xC260 ); // Clk freq 2 MHz, low voltage treshold = 0v
	rf_write_cmd( 0xC080 ); // VDI = clock recover lock output, LNA gain = 0dbm, DRSSI treshold = -103dbm, receiver not enabled
	rf_write_cmd( 0xCE88 ); // FIFO interrupt level = 8, FIFO fill start = Sync-word, FIFO fill off, FIFO off

Bij het ontvangen krijg ik van de SDO pin alleen status bits terug. Op volgorde: 0x0F02, 0x0DC0, ...
Ik vermoed echter dat als er problemen zijn met bit-synchronisatie deze waarden niet te vertrouwen zijn. De VDI uitgang is wel hoog gemaakt door de RFM in deze periode. Dus dat spreekt daar weer tegen. Gebruik jij de VDI?
Het gekke is wel dat ik van de FFIT poort een soort van clock terug krijg. Maar als ik die gebruik om mijn FFS binnen te klokken dan zie ik daar consequent maar 12 klokpulsen dus dat is ook vreemd. Gebruik jij die FFIT poort ueberhaupt?

Ik weet dat er andere modules zijn, zoals de RFM12 en nu de RFM22 en RFM23, maar voor een simplex applicaties zouden dit in theorie perfecte en betaalbare modules zijn dus ik wil nog niet opgeven!

edit: RMF34 veranderd in RMF23

Inmiddels is er voor de RFM12 werkende source geschreven:

http://www.ideetron.nl/Hope/Verzenden%20en%20ontvangen%20met%20de%20RF…

Ik kan niet goed beoordelen waar het vout gaat.
Kun je mij jou source sturen?

Binnen deze reeks zijn het de RFM01 (ontvanger) RFM02 (zender) en RFM12 (zend- ontvanger).
Dus nu ook leverbaar als ALPHA module via Farnell.

De RFM22 en 23 zijn echt hele andere dingen.
Die hebben ook een veel complexere interface.

Ja, precies die Alpha dingen gebruik ik. Ik werk overigens met PICs. In dit geval hangt-ie aan een LF14k50.

Dit is de zendcode


main start:
	reply = rf_write_cmd( 0xCC00 );	// read status register
	reply = rf_write_cmd( 0x8B61 ); // 433MHz, 2MHz clock, polarity fo+df, 60kHz deviation
	reply = rf_write_cmd( 0xA640 ); // 434MHz
	reply = rf_write_cmd( 0xD040 ); // PLL, datarate / 2
	reply = rf_write_cmd( 0xC823 ); // 9600 / 2 = 4800 baud
	reply = rf_write_cmd( 0xC220 ); // No wake up timer, TX bit synch, Low battery treshold = 0v
	reply = rf_write_cmd( 0xC001 ); // Osc and synth manual, Power amp manual, Xtal disabled, Syntesizer disabled, Power amp disabled
					// Low voltage detect disabled, CLK output enabled

	while(1)
        {
		reply = rf_write_cmd( 0xC039 ); // Start transmitter

		rf_write_data( 0xAA ); // Warm up sequence; preamble	
		rf_write_data( 0xAA ); // 		||
		rf_write_data( 0xAA ); // 		||
		rf_write_data( 0x2D ); // 		||
		rf_write_data( 0xD4 ); // 	       \__/

		// write data bytes here
		// finish with writing checksum or crc
		rf_write_data( 0x55 ); // Just send 'U' characters	
		rf_write_data( 0x55 ); // Just send 'U' characters	

		rf_write_data( 0xAA ); 

		reply = rf_write_cmd( 0xC001 );

		// delay long time ( 1 sec)
		WAIT1s;
	}
main end:

void rf_write_0( void )
{
	nSCK = 0;
	Delay1TCY();
	nSDI = 0;

	// delay 15 cycles @ 10 MHz = 6 usec
	WAIT6u;

	nSCK = 1;
	Delay1TCY();
}

void rf_write_1( void )
{
	nSCK = 0;
	Delay1TCY();
	nSDI = 1;

	// delay 15 cycles @ 10 MHz = 6 usec
	WAIT6u;

	nSCK = 1;
	Delay1TCY();
}

void rf_write_data( BYTE data )
{
	BYTE n = 8;

	nSEL = 1;

	while( n-- )
	{
		if( data&0x80 )
			nFSK = 1;
		else
			nFSK = 0;

		// delay 15 cycles @ 10 MHz = 6 usec
		WAIT6u;
	
		data <<= 1;
	}

	nSEL = 0;
}

WORD rf_write_cmd( WORD cmd )
{
	BYTE n = 16;
	WORD result = 0;

	nSEL = 0;

 	while( n-- )
	{
		if( cmd&0x8000 )
			rf_write_1();
		else
			rf_write_0();

		cmd <<= 1;
	}

	nSEL = 1;

	return result;
}

En de receive code:


main lus start:
	rf_write_cmd( 0x0000 ); // read status register
	rf_write_cmd( 0x898A ); // 433 MHz, Low battery detect off, Wake up timer disabled, Xtal enabled, Bandwidth 134 kHz, Clk enabled 
	rf_write_cmd( 0xA640 ); // 434 MHz
	rf_write_cmd( 0xC847 ); // 4800 baud
	rf_write_cmd( 0xC69B ); // VDI + offset, range -16 - +15, offset in output reg, no AFC high accuracy, AFC output enabled, AFC enabled 
	rf_write_cmd( 0xC42A ); // no clock recover auto-lock, No clock recover fast mode, data filter = Digital, DQD treshold = 2
	rf_write_cmd( 0xC260 ); // Clk freq 2 MHz, low voltage treshold = 0v
	rf_write_cmd( 0xC080 ); // VDI = clock recover lock output, LNA gain = 0dbm, DRSSI treshold = -103dbm, receiver not enabled
	rf_write_cmd( 0xCE88 ); // FIFO interrupt level = 8, FIFO fill start = Sync-word, FIFO fill off, FIFO off
	WAIT1s;

	rf_write_cmd( 0xCE8B ); // FIFO interrupt level = 8, FIFO fill start = Sync-word, FIFO fill on, FIFO on
	rf_write_cmd( 0xC081 ); // VDI = clock recover lock output, LNA gain = 0dbm, DRSSI treshold = -103dbm, Receiver enabled
	while(1)
        {	
		while( !nIRQ )
		{
			receiveBuffer[i++] = rf_read_fifo();

			if( i == 8 )
			{
				rf_write_cmd( 0xCE88 ); // FIFO interrupt level = 8, FIFO fill start = Sync-word, FIFO fill on, FIFO on
				rf_write_cmd( 0xCE8B ); // FIFO interrupt level = 8, FIFO fill start = Sync-word, FIFO fill on, FIFO on

				i = 0;
			}
		}	
	}
main lus end:

void rf_write_data( BYTE data )
{
	BYTE n = 8;

	nSEL = 1;

	while( n-- )
	{
		if( data&0x80 )
			nFSK = 1;
		else
			nFSK = 0;

		// delay 15 cycles @ 10 MHz = 6 usec
		WAIT6u;
	
		data <<= 1;
	}

	nSEL = 0;
}

rf_wite_cmd identiek aan zender

Dit is de code die ik nu heb. Ik had n.a.v. jouw opmerkingen een paar dingen veranderd: PLL in zender, FIFO commando's van CE84/CE87 naar wat jij had. In principe ging ik nog steeds uit van de Hope datasheets.

Hier een stukje van de output uit de analyzer:
http://img21.imageshack.us/img21/1808/analyzer.png

Npg even over die output van de analyzer. Vanaf ong. de helft zie je 0xCE88 en 0xCE8B commando`s weggeschreven worden. Het gekke is dat aan het einde van het eerste commando (0xCE88) de RFM al FFIT interupts/clocks begint te geven en bits uitspuugt op SDO. In dit geval 12 bits: 0xCFE

[Bericht gewijzigd door Henry S. op (3%)]

@Bart,

Heb jij nog iets kunnen ontdekken aan mijn code?

Willem

Het echo-ed een beetje hier... :)

Ondertussen heb ik het aan de praat gekregen. Dankzij hulp van Hope RF (Mark ofwel ?? als ik het goed heb) was bijzonder behulpzaam. En hoewel hij me niet echt heeft kunnen helpen, behalve door duidelijk te maken dat de bandbreedte van de ontvanger minimaal 2x de frequentie 'deviation' van de zender moet zijn, was het wel daardoor dat ik bleef zoeken.
Uiteindelijk bleek er niet zoveel fout te zijn, maar wel dat de timing van het zenden uiterst cruciaal is wanneer je de gegevens via FSK binnen klokt.
Onmiddellijk als je het zendcommando gegeven hebt, begint de transmitter irq's te genereren 'op de maat van' de ingestelde baudrate. Die pulsen zijn dan laag voor de duur van 1 baud en daarna heel even hoog (1.6usec) om daarna weer laag te gaan. In het voorbeeld staat er dat je daarom

while( !nIRQ) ; while( nIRQ );

moet doen om dat af te vangen. En dat gaat vaak niet goed. Niet alleen moet je je MCU op een voldoende hoge clock laten draaien om sowieso de eerste puls al te vangen, maar veel MCU's hebben meerdere clockcycli nodig om die tweede while uit te voeren en omdat deze maar 1.6 usec duurt (bij alle in te stellen snelheden voor de transmitter trouwens, zo leek wel) mis je dus het afvangen daarvan. In dat geval moet je inclock routine dus exact gelijk lopen met de irq pulsen en dat is niet te doen.
Ik heb dat opgelost door toch een gewone IRQ routine te gebruiken die een bool zet als er een irq binnenkomt. In mijn routine hoef ik dus alleen maar daarop te wachten. En bij 4800 baud bijv. heb je dan meer dan genoeg tijd om de lus uit te voeren voor de volgende puls.
Welke clockfrequentie en welke baudrate je gebruikt zijn niet bijzonder van invloed op de werking trouwens. Ik heb verschillende geprobeerd en dat werkte allemaal vlekkeloos.

Willem

Op 3 december 2009 18:36:00 schreef WJR:
Het echo-ed een beetje hier... :)

Ondertussen heb ik het aan de praat gekregen. Dankzij hulp van Hope RF (Mark ofwel ?? als ik het goed heb) was bijzonder behulpzaam. En hoewel hij me niet echt heeft kunnen helpen, behalve door duidelijk te maken dat de bandbreedte van de ontvanger minimaal 2x de frequentie 'deviation' van de zender moet zijn, was het wel daardoor dat ik bleef zoeken.
Uiteindelijk bleek er niet zoveel fout te zijn, maar wel dat de timing van het zenden uiterst cruciaal is wanneer je de gegevens via FSK binnen klokt.
Onmiddellijk als je het zendcommando gegeven hebt, begint de transmitter irq's te genereren 'op de maat van' de ingestelde baudrate. Die pulsen zijn dan laag voor de duur van 1 baud en daarna heel even hoog (1.6usec) om daarna weer laag te gaan. In het voorbeeld staat er dat je daarom

while( !nIRQ) ; while( nIRQ );

moet doen om dat af te vangen. En dat gaat vaak niet goed. Niet alleen moet je je MCU op een voldoende hoge clock laten draaien om sowieso de eerste puls al te vangen, maar veel MCU's hebben meerdere clockcycli nodig om die tweede while uit te voeren en omdat deze maar 1.6 usec duurt (bij alle in te stellen snelheden voor de transmitter trouwens, zo leek wel) mis je dus het afvangen daarvan. In dat geval moet je inclock routine dus exact gelijk lopen met de irq pulsen en dat is niet te doen.
Ik heb dat opgelost door toch een gewone IRQ routine te gebruiken die een bool zet als er een irq binnenkomt. In mijn routine hoef ik dus alleen maar daarop te wachten. En bij 4800 baud bijv. heb je dan meer dan genoeg tijd om de lus uit te voeren voor de volgende puls.
Welke clockfrequentie en welke baudrate je gebruikt zijn niet bijzonder van invloed op de werking trouwens. Ik heb verschillende geprobeerd en dat werkte allemaal vlekkeloos.

Willem

Heeft iemand toevallig een volledig werkende code inmiddels? (+schema etc) Ik heb de -02 module hier, en wil graag voor de hobby wat dingen testen.