lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« on: April 01, 2013, 08:24:40 08:24 » |
|
Hello,
I'm fighting against 2 x RFM22B-S2 modules to get them working with a PIC. ( i use a 18F2620 ) I simply would like to get a working demo because i can't get communication working on these modules.
I've spend long time on the datasheet and on the Hoperf demo code without success. I will really appreciate if someone would share a working demo code, ie sending a demo sentence 'Hello World' to the distant module.
Many thanks for your help,
|
|
|
Logged
|
|
|
|
robotai
Junior Member
Offline
Posts: 60
Thank You
-Given: 27
-Receive: 23
|
|
« Reply #1 on: April 01, 2013, 12:13:10 12:13 » |
|
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #2 on: April 02, 2013, 09:39:22 09:39 » |
|
I think this can help you. This is for the pic16f610 but i used it in many pics. It also works whit the rfm23b and rfm23bp (1W good antenna distance 5Km.)
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #3 on: April 02, 2013, 02:50:41 14:50 » |
|
Thank you jamesbond,
May i ask you if i may have the entire MPLAB C18 project files please ?
Can you tell me : what #include <htc.h> is for ? i also do not see well what 'loop' unsigned char is for.
--
I've planned to use SPI libraries for my project. Later, i will try to replace the SPI software routine ( write_cmd) by SPI library once i get the code working.
Many thanks for your help,
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #4 on: April 02, 2013, 07:19:57 19:19 » |
|
I have not use it in c18 but i think you can easely export it to c18, or use the xc8 compiler(includes pic18). #include <htc.h> is used by the hi-tech c compiler. unsigned char "loop" is used for the const "datasize". I always use these functions when i start a new rfm22/23 project.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #5 on: April 03, 2013, 09:57:30 09:57 » |
|
Thanks,
As a simple test purpose and in order to validate that SPI communication from Pic to RFM22 modules works well,
I would to light and switch off a led connected to RFM22 GPIO 2 :
I've PIC SPI comms to work in SPI mode 0 at frequency 10 MHz.
According to the datasheet I need to set 0x0D register. But, I do not understand well what D3 to D0 are for ...
Datasheet page 55 does not light me on these bits. ( gpio2[4] to gpio2[0] )
Register 0x0E is not clear for me as well ... Can you help me on this please ?
|
|
« Last Edit: April 03, 2013, 11:04:38 11:04 by lcn »
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #6 on: April 03, 2013, 02:37:40 14:37 » |
|
I hope this help http://www.hoperf.com/upload/rf/AN440.pdf read page 16 to 19 for gpio in and outputs. You can use these ports if you have a shortage of ports on your PIC Its better to process the data in your PIC and do with it what you want. I use this rfm22 module in a mass product whit a cheap PIC so i do not use the SPI communication. Some comments added in the file to clarify.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #7 on: April 03, 2013, 09:51:04 21:51 » |
|
With the application note i see better now, many thanks
I've tried to send over SPI the software reset command to the RFM22 module :
rfm_write(0x07,0x80); // Software reset
MOSI line, µC sends as register address : 0x87 due to the mask : 0x07 | 0x80 it adds a '0' to the MSB of the address byte (WRITE MODE)
and sends 0x80 as value to the register afterwards.
My SPI clock is about 2.5Mhz, but i can see with my analyser that MISO line does not respond anything. I don't understand know why ( see attached screen capture ) Could my SPI configuration be wrong ?
Do you have any idea ?
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #8 on: April 04, 2013, 01:49:05 13:49 » |
|
the write_rfm seems good. to read a regisiter first write address and then read the data (see rfm_read() ).
WRITING to rfm22 start whit bit7=1 & bit 6 to 0 is address then followed by data. READING to rfm22 start whit bit7=0 & bit 6 to 0 is address / dataread. see datasheet SPI communication page 14.
in function write_cmd i first reset SDI, depending on bit7 in cmd set SDI cmd is not anded whit 0x80
SDI=0; // SDI LOW ( MOSI ) if(cmd&0x80)SDI=1; // if (bit7 in cmd is HIGH) SDI HIGH
I do not know if you have a pair of modules to test whit. The best way to start is one in send mode whit intervals of aprox. 50mS. And the second one in recieve mode attached to a lcd and try to get the data from the sender. Start first in "software SPI" and when its working good, go to the PIC SPI.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #9 on: April 08, 2013, 07:20:59 07:20 » |
|
Hello Still no better result with my SPI transmission. I do not understand why MOSI line starts BEFORE SCK clock edges. On the capture below when i try to send : rfm_write(0x0E,0b00000100); // 0x04Register address is 0x8E but we can edges start earlier than SCK. I can also see the MISO line does not respond anything when the register is written. ( it stays at 0x00 ) http://imageshack.us/f/442/spicapture.png/I've set the SPI transmission to be MODE 0 (0,0) CPHA = 0 / CKP-CPOL = 0 Is this correct for RFM22 modules ? Any help will be much appreciated.
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #10 on: April 08, 2013, 09:56:32 09:56 » |
|
mode 0 is OK for the rfm modules. the software SPI do exactly the same. when writing an register the the MISO will NOT respond.
you write (0x0E,0x04) in the rfm_write() bit 7 in register address is set to 1 result in (0x8E,04) this is write register. // this works When you read the register, bit 7 must be 0 !! .So only write (0x0E) to the register and then clock data in. i try to explain it whit this..
register data WRITE register- MOSI 1-0-0-0-1-1-1-0 0-0-0-0-0-1-0-0 // this is OK in your image
register data READ register- MOSI 0-0-0-0-1-1-1-0 // bit 7 = 0 !!!! you must send this byte via SPI (0x0E) MISO 0-0-0-0-0-1-0-0 // and then clock the data in via MISO
the difference in read and write is bit 7 in register address.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #11 on: April 08, 2013, 10:21:47 10:21 » |
|
Thanks, It is good to know i should not expect to have any response back on the MISO line when writing a data to a register. To read sequence of a register, i mask bit 7 with the following : address &= 0b01111111; // address &= 0x7F; -- In order to confirm SPI communication works fine, I'm trying to set GPIO2 to '1' and put it back to '0' in order to test my SPI communication. ( i've a led + resistor connected to GPIO2 ) The following code does NOT light the led connected to GPIO2 Do you confirm the code below it is correct ? rfm_write(0x07,0x01); // Goes to READY MODE (sends 0x87 as register address) rfm_write(0x0D,0b11001010); // Set GPIO2 as output ( sends 0xCA as register address)
rfm_write(0x0E,0b00000100); // GPIO2 is '1' : ON Delay100us_TMR2(); rfm_write(0x0E,0b00000000); // GPIO2 is '0' : OFF Delay100us_TMR2();
|
|
« Last Edit: April 08, 2013, 10:24:45 10:24 by lcn »
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #12 on: April 08, 2013, 01:08:32 13:08 » |
|
I've just tested the GPIO2 port connected to a led USING YOUR code, and here its working fine.
Please check.
Is your SDN pin from RFM22 LOW ?? it must be Before a read or write command NSEL must be LOW, on exit back to HIGH !! // see software SPI check if there is any respond on your analyzer when you do a read register command. Is MISO pin configured as input ? After read command you have generate 8 clock pulses to read out the MISO.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #13 on: April 08, 2013, 01:46:01 13:46 » |
|
Yes, i CS pin (NSEL) is always '1' and goes to '0' during the SPI read/write sequence. We can see it on the SPI capture. For the read sequence i indeed send the anded register address with mask 0x7F followed by 8 SCK clock edges. But the reading gets outstanding results. If i do the following and immediately read the register back, i get a different value ... rfm_write(0x0E,0b00000100); // GPIO2 is '1' : ON value = rfm_read(0x0E); In my case i get value = 0x03 instead of 0x04 I will post later today the SPI writing and reading capture i get for those 2 lines of codes. But would you please try them on your side and tell me what you get when you read 0x0E ? -- Can you also tell me what capacitor register (0x09) register is for ? I do not understand well the datasheet for that one. For register 0x0A : is it an output frequency that could be sent on GPIO2 for external purposes ? if so i do not need it at all.
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #14 on: April 08, 2013, 03:48:21 15:48 » |
|
When i write register 0x0E and read it back, i also get a false read. So i have to do more tests to find out how to get a correct read. That is good news for you.
I am sure that this works.. I use this to read my battery voltage. If you vary the power a little around 3.3V the value of "value" will change. rfm_write(0x07,0x41); //enable low batt. register do{ value=rfm_read(0x1B); //read batt. voltage //your delay }while(1);
you can also try this. this is the tx header register . can do no harm rfm_write(0x3A,0x40); //change the value for test value=rfm_read(0x3A);
register 0x09 is to adjust the frequency of the crystal. register 0x0A to divide the clock frequency for external use on GPIO2
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #15 on: April 08, 2013, 09:55:46 21:55 » |
|
when i write(0x0D,0b11000011) and subsequently read(0x0E) i actually read a change on the GPIO2 port. //just tested when write(0x0D,0b11001010) and read (0x0E) i get 0x00. If registor 0x0D is set to "direct digital output" , you can only write to bit 2 in register Ox0E. if you read bit 2 it returns invalid data or 0. And when configured as "direct digital input" you can only read bit 2. see page 19 in datasheet http://www.hoperf.com/upload/rf/AN440.pdfYou read 0x03. Your GPIO0 and GPIO1 are set to default value "microcontroller clock". Can you see anything on the GPIO0 and GPIO1 pins? I am curious about your new testresults.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #16 on: April 08, 2013, 10:57:43 22:57 » |
|
Actually most of the time MISO line responds 0x00 If i send the following : rfm_write(0x0D,0b00001010); // (0x0D,0x0A) GPIO2 is direct digital output rfm_write(0x0E,0b00000100); // (0x0E,0x04) rfm_write(0x0E,0b00000000); // (0x0E,0x00)
rfm_write(0x07,0x41); //enable low batt. register value = rfm_read(0x1B); //read batt. voltage
I get this : http://img195.imageshack.us/img195/638/capture1mk.png--- If i send these lines, rfm_write(0x3A,0x40); //change the value for test value = rfm_read(0x3A); value = rfm_read(0x03); i get this : http://img812.imageshack.us/img812/4909/capture2me.pngBut, look at MOSI line, especially when we write 0xBA : MOSI starts earlier than SCK clock edges, it is not normal i think. I'm suspecting an SPI issue. --- register 0x09 is to adjust the frequency of the crystal. This is only if we need to generate a clock for an external device, isn't it ? I guess this register does impact the wireless transmission, doesn't it ?
|
|
« Last Edit: April 08, 2013, 11:00:03 23:00 by lcn »
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #17 on: April 09, 2013, 10:10:30 10:10 » |
|
i think the MOSI line works fine. the data on MOSI must be "low or high" before the RISING edge of the clock. this is not the problem.
is your PIC powered to 5V and the rfm22 to 3.3V. is there any level shifter between the PIC and the RFM22. is your MISO dataline OK ? not pulled low by PIC or anything else? Disconnect MISO from PIC to rfm22 and use a oscilloscope to see if there is a squarewave on the rfm22 side. At last, go to software SPI to make sure that it works.
Yes, the GPIO2 microcontroller output can be use for clock or timer input . I guess this register(0x09) slightly correct the crystal frequency, but this has no impact to your SPI communication.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #18 on: April 09, 2013, 05:51:47 17:51 » |
|
Is your PIC powered to 5V and the rfm22 to 3.3V ? The whole board is 3.3V powered. Here is attached my schematic. SEE RFM22.PDFGood news : finally the SPI communication works fine. Look at the attached captures. I send the following : rfm_write(0x07,0x41); //enable low batt. register lecture = rfm_read(0x1B); //read batt. voltage Battery register returns 31, it means measured voltage is >3.2V , it is correct.See CAPTURE3.PNG--- rfm_write(0x3A,0xAA); //change the value for test lecture=rfm_read(0x3A); 0x3A is read back from the register.See CAPTURE3.PNGActually, i think the SPI transmission was working since the beginning. But for my tests, i'm using Microchip ICD3 debugger and i've made a STOP point just after a SPI sequence to capture it with my logic analyser. This always capture 0x00 on the MOSI line, i can't explain why. If i do not set a STOP point in the code and let it run continuisly, and take a piece of SPI frames with the logic analyser, i can see correct results.
|
|
« Last Edit: April 09, 2013, 09:42:09 21:42 by lcn »
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #19 on: April 09, 2013, 10:33:20 22:33 » |
|
Do you confirm the following has to be placed into the infinite loop of the program ? rx_mode(); //put in rx mode
while(IRQ==1); //wait for low (can also be done in interrupt) loop=datasize; //read the data out the rfm do{ datastr[--loop]=rfm_read(0x7F); }while(loop!=0);
// process the data in datastr[] for example: switch relay / send via rs232 / store data in eeprom / pwm
// collect data and put it in datastr[] tx_mode(); //send data in datastr[] When you wait for reception, you test the following : Did you previously set RFM22 IRQ pin in the init function to get that pin low when a string is being received ? i did not find where ... -------------- I've made 2 identical boards with RFM22 module. I would like to program the first one as 'sender' and the second one as 'receiver' ie : the 'sender' board sends the string 'HELLO WORD' if the receiver board gets this string, i would like it lights the LED connected to its GPIO2 Can you tell how to do that please ?
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #20 on: April 10, 2013, 08:00:08 08:00 » |
|
Nice to read that it works.
Have you succeeded in turning the LED on and off ?
see page 51 in the datasheet for output by low battery detector register. my board power is 3.3 V. and the battery register(0x1B) returns 0x1E.
while(IRQ==1); this is a active waitloop. it's better to use the pin interrupt and use interrupt function. IRQ is the NIRQ output pin on the rfm22. in this case a not well-chosen name by me.
/* // example for the reciever board . set " #define datasize" to the number of characters to recieve, in your case 10 rfm_init(); do{ rx_mode(); //put rfm22 in rx mode while(IRQ==1); //wait for low (can also be done in interrupt) loop=datasize; //read the data out the rfm do{ datastr[--loop]=rfm_read(0x7F); }while(loop!=0);
// process the data in datastr[] for example: switch relay / send via rs232 / store data in eeprom / pwm if ( datastr[] == 'HELLO WORD' ) { // for example // your code rfm_write(0x0D,0b11001010); // Set GPIO2 as output ( sends 0xCA as register address) rfm_write(0x0E,0b00000100); // GPIO2 is '1' : ON } }while(1); */
/* // example for the transmitter board. also set " #define datasize" to 10 rfm_init(); do{ if(pushbutton is low){ // if there is any put 'HELLO WORD' in datatstr[]; tx_mode(); //send data in datastr[] } wait(time); //your waitloop }while(1); */
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #21 on: April 10, 2013, 08:46:17 20:46 » |
|
I'm now testing the 2 modules together. The sender is properly sending the string HELLO WORLD by starting from the end : DLROW OLLEH I can see the FIFO filling on the SPI frames. At the moment, i continusly send every 3 seconds the same string. -- However, the receiver looks not working properly : The program never sees IRQ pins going low. so the program stays here : ( in red ) rx_mode(); //put rfm22 in rx mode while(IRQ==1); //wait for low (can also be done in interrupt) loop=datasize; //read the data out the rfm do{ datastr[--loop]=rfm_read(0x7F); }while(loop!=0); I've check with the logic analyser : rx_mode(); is correctly run : TX-ANT is indeed set to '0' and RX-ANT is set to '1' all looks good from that side. The issue is only that IRQ pin never goes to '0' ... How could we be sure that IRQ register is properly set to generate a low level on IRQ pin when a correct string reception happens ?
|
|
|
Logged
|
|
|
|
jamesbond
Newbie
Offline
Posts: 23
Thank You
-Given: 50
-Receive: 9
|
|
« Reply #22 on: April 11, 2013, 12:23:38 12:23 » |
|
Have you set datasize to 11 = 'HELLO WORLD' on both boards ? I said 10 because the text was 'HELLO WORD' .
Use for this test identical rfm_init() in transmitter and reciever boards , you can customize it later. When there is a lot of noise on the frequency you use, create at least on one board an antenna. A piece of wire will do. If the FIFO in the receiver is full this pin goes low and read datastr[].
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #23 on: April 11, 2013, 12:39:06 12:39 » |
|
Ok I will redo some tests, because I have set datastr size to 20 So it might be too long and FIFO never gets full with 'HELLO WORLD' string
Maybe this explain why nIRQ pin does not go get low.
|
|
|
Logged
|
|
|
|
lcn
Junior Member
Offline
Posts: 42
Thank You
-Given: 15
-Receive: 1
|
|
« Reply #24 on: April 11, 2013, 05:20:01 17:20 » |
|
I still have no chance, i have set the sizze to 12 in order to handle the contents of the string : HELLO WORLD\0 Even i have modified the size of the nIRQ pin won't go low. i have no idea how i could debug it. Not really easy to find out if the issue comes from sender or receiver . How can i be sure that sender module sends something and receiver receives a string ? -- Are your RFM modules 433Mhz or 868 Mhz ? Mine are normally 433 Mhz. ( can't be sure since nothing is written on it )
|
|
|
Logged
|
|
|
|
|