Getting started with MiRF v2 (RP-SMA version) and nRF24L01

Hello,

I’ve been into electronics for a few years now, but its mostly been analog electronics and a few things with PIC microcontrollers. Long story short, I am into radio-controlled cars and as a project to help me learn about RF electronics, I’ve decided to try to switch my 27 mhz electronics to 2.4 ghz electronics in my RC. I don’t know if I will be successful, but even if I’m not I will learn a lot along the way.

My goal for now is to get a simple RF connection working (mostly on a breadboard, but obviously surface mount components will have to be on a PCB). I would like to be able to send a value from 0 to 255, and on the receiver end I will have an LED that is lit using the value sent. I don’t know for sure the method I will use to get the value, it might just be a random number, or maybe I will use a pot on the transmitter end to create a value. However I do it, I want to be able to send a value from 0 to 255 to another microcontroller via RF, and that microcontroller will power an LED at a certain voltage.

After some searching around, I came across the MiRF v2 Module from SFE, and decided it would be a cheap, easy way to start. My only problem is they are currently out of stock, so I will have to wait to order them. When I finally get the modules, I will be able to do experimenting to learn how to use them, but for now I am just collecting ideas.

I read through some of the datasheet for the nRF24L01, but as I am not very experienced in digital electronics, I did not understand a lot of what they were talking about. I copied the list of pins and there functions, and deleted all of the ones I understand. Here is the list I am left with. I have put my guesses next to some as to what I think the pins are for. However, if someone could explain the function of these pins, I would greatly appreciate it. Here’s the list:

2 CSN - used to select mode for configuration or use?

3 SCK -

4 MOSI - data to be sent via RF (and for config.)?

5 MISO - data received via RF (and for config.)?

6 IRQ - goes to HIGH when an interrupt occurs? why would you need this pin?

11 VDD_PA -

12 ANT1 - used for antenna, but why are there two antenna pins?

13 ANT2 - used for antenna, but why are there two antenna pins?

16 IREF - reference current. but what is the reference current used for? why do you connect it to ground via a resistor? how does the value of that resistor affect anything?

19 DVDD -

If someone could explain those pins, I would appreciate it. :smiley:

Also, if someone could explain the basic idea of these “packets” I keep reading about, I would appreciate it. I understand that they are sets of information, but how do you create a “packet” with another microcontroller to send out? Is it just serial communication?

Thanks much for helping me. :smiley:

CSN is used as the “chip select not”, as in it is active low. This is the chip select function for the SPI interface.

SCK is the clock for the SPI interface.

MOSI is “master out, slave in”. You would connect this pin to your micro’s SPI data out pin (also MOSI if you are using a chip that uses common SPI terminology)

MISO is “master in, slave out”. This is the data into the micro and out of the MiRF.

IRQ is “interrupt request”. This is asserted when the MiRF has received data.

VDD_PA is the power amplifier supply for the 24L01.

ANT1 and ANT2 are the antenna outputs, and there are two of them because the 24L01 is meant to be used directly with a dipole antenna. A matching network must be installed to use it with a normal antenna.

IREF is a reference current for something in the chip (it isn’t elaborated on in the datasheet).

DVDD is the digital power output, which is used for coupling purposes. This is basically there to strap a decoupling capacitor to ground.

Remember that on the MiRF-v2 board, all of the hard stuff is taken care of. You only have the SPI interface (SCK, MOSI, MISO, CSN), power and ground connections (VDD and GND, respectively), and the interrupt request line (IRQ). I have posted a link to example code in C to get the chip up and working, but it requires that you write a few functions of your own. At some point I’m going to simplify it so that it’s easier to use, but for now it’s good to take a gander at.

A packet is a unit of data that you send. The nRF24L01 can send from 1 to 32 data bytes in one packet (you also send one byte of preamble, up to two bytes of CRC, and up to 5 bytes of address data per packet). To send a packet, you first send the nRF24L01 the write data instruction, then you clock in your data bits. This is done over the SPI interface. You then pulse CE (if I remember correctly), and the 24L01 sends the packet off into space. When the receiver receives the packet, it will assert its IRQ (assuming you have that feature turned on). Then you send it the instruction to read data and you clock out your data bits on the SPI interface. At this point, you have the data in your receiving micro and you can process it at will.

Thank you very much for the explanation. It helped me a lot. :smiley:

I still don’t understand a few things though. (ok, maybe I don’t understand a lot, but I understand more now)

For CSN, what is it used to select between? Is it used to switch between regular data transmission mode and configuration mode?

You said SCK is the clock for the SPI interface. Could you explain this a little more? I don’t really understand “clocking data bits”. Could you please explain this? Thanks.

You said VDD_PA is the power amplifier. If I remember correctly, the datasheet showed this hooked up to 1.8v. How can it amplify power when it has a lower voltage than VCC? What does this pin do then? If you adjust the amount voltage to this pin, will it change the power of the transmitting?

For the antenna outputs, you said you need a matching network for a regular antenna. What kind of “matching network” do you need?

So DVDD’s only purpose is connect a decoupling capacitor to ground? The purpose of a decoupling capacitor is to prevent sudden voltage changes, right?

Let’s say you want to send a number from 0 to 255. Let’s pick 255. How many bytes would this be? Anyway, let’s say we are going to send this number to the receiver. The first thing you do would be to send the write data instruction. How do you do this? Is this the preamble? What pin do you send it to, and what kind of instruction is it? Next you clock the data bits. How is this done? What about the address data in the packet? Where does that come in?

On this receiving end. When the data is received, IRQ will go HIGH (LOW?). The microcontroller on that end will read IRQ, and send the instruction to read data. Again, how do you send this instruction? Next you clock out the data bits. I’m sure this is similar to clocking in data bits, but how is this done? After that the microcontroller can do whatever it needs. When data is received and “clocked out” by the micro, what part of the packet will the micro get? Will it get the preamble and the address data, or just the data (in this case the number 255) I want it to get?

Again, thank you so much for helping me. I really appreciate it. :smiley:

Before you delve too far into this, some background reading will be helpful. Essentially SPI is two shift registers (one in and one out). Here is some general info on shift registers: http://en.wikipedia.org/wiki/Shift_register. There is also an article on SPI, but it’s not as useful: http://en.wikipedia.org/wiki/Serial_Per … _Interface. Take a look at the nRF24L01 datasheet on page 20 to see the intricacies of the SPI interface for the 24L01. It will help illustrate some of the questions I’m answering.

For CSN, what is it used to select between? Is it used to switch between regular data transmission mode and configuration mode?

If a device's chip select is high, its SPI interface assumes that it is not being used. This is to allow multiple devices to be used on a bus (each device must have its own CSN that is independent of every other device's CSN). When the CSN goes low, the device will expect an SPI receive. Once the CSN goes back high, the device will process whatever it received on the SPI interface.

You said SCK is the clock for the SPI interface. Could you explain this a little more? I don’t really understand “clocking data bits”. Could you please explain this? Thanks.

When the SPI interface on a device is active (i.e., CSN is low for the nRF24L01), it samples its data pin (the nRF24L01 will sample the MOSI pin) on a specified clock edge, either rising or falling (the nRF24L01 uses a falling clock edge to sample data). To illustrate the point, assume CSN is low, which indicates to the 24L01 it is receiving SPI data. Then, every time SCK goes from high to low, the 24L01 will shift in whatever it reads on the MOSI pin. It will continue to do this until CSN goes back high. This is illustrated on page 20 of the datasheet.

You said VDD_PA is the power amplifier. If I remember correctly, the datasheet showed this hooked up to 1.8v. How can it amplify power when it has a lower voltage than VCC? What does this pin do then? If you adjust the amount voltage to this pin, will it change the power of the transmitting?

More than likely there is some level transition within the chip itself. You don't change the voltage on this pin to change the power. There is a configuration register that allows you to change it (RF_SETUP register, RF_PWR field...see the datasheet on page 23).

For the antenna outputs, you said you need a matching network for a regular antenna. What kind of “matching network” do you need?

It is illustrated on page 33 of the datasheet, but on the MiRF boards, it is already done for you. You only have to worry about the pins I described in my last post. On page 33, it is basically all the stuff hooked up to the pins ANT1, ANT2, and VDD_PA.

So DVDD’s only purpose is connect a decoupling capacitor to ground? The purpose of a decoupling capacitor is to prevent sudden voltage changes, right?

It has several purposes. Its main purpose is to shunt AC frequencies to ground so that the internal DVDD is as purely DC as possible (capacitor impedance is infinity at DC and decreases as frequency increases). It does help to stabilize the power supply against sudden inrush currents that could cause the supply voltage to temporarily drop if the capacitor wasn't there.

Let’s say you want to send a number from 0 to 255. Let’s pick 255. How many bytes would this be? Anyway, let’s say we are going to send this number to the receiver. The first thing you do would be to send the write data instruction. How do you do this? Is this the preamble? What pin do you send it to, and what kind of instruction is it? Next you clock the data bits. How is this done? What about the address data in the packet? Where does that come in?

This would require one byte. Since there are 8 bits in a byte, one byte can go from 0 to 2^8-1, or 255. If you want to know what the capacity of any data word is (8 bits, 16 bits, 32 bits, etc.), just raise 2 to the power of the number of bits in the word. The maximum number that this word can hold is one less than that (since it also has to hold 0). Learn about binary here: [http://en.wikipedia.org/wiki/Binary_numeral_system](http://en.wikipedia.org/wiki/Binary_numeral_system).

First off, turn to page 19 of the datasheet. You will want to use the W_TX_PAYLOAD instruction. Therefore, you will first bring CSN low, and then send the binary number ‘10100000’ or 0xA0 in hex (http://en.wikipedia.org/wiki/Hexadecimal) over the SPI interface. This tells the 24L01 that it will be receiving a data payload. Once the instruction is sent, you immediately (without bringing CSN high) send all of your payload bytes. Then you bring CSN back high again. The only issue here is that the 24L01 will be expecting a certain number of bytes in the payload. This is specified in RX_PW registers and can be different for each data pipe.

The 24L01 will handle the preamble, address bits, and CRC for you. You simply have set up the configuration for each of them in the configuration registers. This is what Shockburst mode is - it simplifies all the details so that you just have to send a command (here the write payload instruction) and data to go with that command (here your data payload, or the 0 to 255 number).

On this receiving end. When the data is received, IRQ will go HIGH (LOW?). The microcontroller on that end will read IRQ, and send the instruction to read data. Again, how do you send this instruction? Next you clock out the data bits. I’m sure this is similar to clocking in data bits, but how is this done? After that the microcontroller can do whatever it needs. When data is received and “clocked out” by the micro, what part of the packet will the micro get? Will it get the preamble and the address data, or just the data (in this case the number 255) I want it to get?

On page 10 of the datasheet, it shows that IRQ is active low (which means it will be ground when active). The receiving process is pretty much identical to the writing process, and the main difference is that you send the R_RX_PAYLOAD instruction instead of the W_TX_PAYLOAD instruction. What comes out is the data payload, meaning that the 24L01 has stripped away the preamble, address, and CRC from the message it received. That way, you only get data that is useful to you and don't have to process other stuff.

You generally want to tie IRQ to a pin on your microcontroller that can act as an interrupt. This will free you from constantly having to poll the IRQ pin in the microcontroller to see if it has received data. This setup will also generally allow for better data throughput if your micro is doing a lot of other stuff besides simply reading from the data pin.

Wow, that was probably the longest post I’ve ever made :lol: . I hope I answered your questions as well as I can, and if you have any more feel free to ask. I would highly suggest you look at some of the background reading that I have linked to before you continue with your project. Also, most of the information that you asked about is in the datasheet, so once you get the background stuff you should be able to better understand the datasheet information. You will find that google, wikipedia, and datasheets are your best friend when it comes to this stuff (though datasheets in particular can also be your biggest foe when they’re incorrect :evil: ).

Thank you SOOOOOOO much for that explanation. I read both of those pages you suggested, and they helped a LOT. I now understand (pretty much completely) what data clocking is and how it works. Now the data sheet makes more sense to me.

You explained everything VERY well, so I only have a few questions now.

What datasheet were you looking at? I downloaded the one from Nordic Semiconductors website a few days ago, but your page references don’t match my datasheet. Could you give me a link to the datasheet you have? Thanks.

CE is the “chip enable” pin. I read about it in the data sheet, but I am a little confused about it. I understand that you set it to high when you want to use the device, and setting it to low puts in standby. However, could you explain the function of this pin and how to use the different modes?

I think I understand the whole procedure for sending and receiving data, but let me summarize what you said to make sure I got it right. For sending data: First, you set CSN to low. Next, you send the W_TX_PAYLOAD instruction (do you do this by clocking in the bits also?). Then you immediately begin clocking in the data to send, or the “payload”. I have no idea what number this is, but lets say our byte consisted of these bits 11110000. The process would go like this: Micro sets SCK to High and MOSI to high (1). Micro sets SCK to low (which shifts the bit in). Micro sets SCK to High again and MOSI to High again (it would probably still be High) and then sets SCK to low. This continues for the rest of the bits. After SCK is set to low for the last time, the Micro sets CSN to high again, and the data will be sent. Is that right? In the data sheet, they say you fill up FIFO with the payload. What is FIFO and what is it for?

My last question is about configuration. Could you please explain the process for configuring things in the 24L01? For example, if you wanted to change the value of the RF_PWR setting, what would the process be to do it? I found it in the datasheet, but I don’t understand the whole address thing. How would I access this setting, and how would I change its value?

Again, thank you SO much for you help. By the time I get the modules, I will definetely have an idea as to what I am doing. By the way, the reason I want to learn all about the 24L01 is because eventually I want to build my own modules to simply my original project, which is converting my RC car’s electronics. Again, thanks so much for helping me learn. I know way more than I did a few days ago.

What datasheet were you looking at? I downloaded the one from Nordic Semiconductors website a few days ago, but your page references don’t match my datasheet. Could you give me a link to the datasheet you have? Thanks.

It should be linked to on the product page for the MiRF boards: [http://www.sparkfun.com/datasheets/Comp ... ec_1_2.pdf](http://www.sparkfun.com/datasheets/Components/nRF24L01_prelim_prod_spec_1_2.pdf).

CE is the “chip enable” pin. I read about it in the data sheet, but I am a little confused about it. I understand that you set it to high when you want to use the device, and setting it to low puts in standby. However, could you explain the function of this pin and how to use the different modes?

CE is has different purposes based on whether you're in RX or TX mode (you're only in one at a time...the device is half-duplex). In RX mode, you have to have CE high in order for the device to listen to on-air transmissions (which means you generally want to leave it high). In TX mode, you generally leave CE low until you clock in a data payload. Once you clock in the payload, you pulse CE high and then back low to tell the 24L01 to send the packet. This information is on page 10 of the datasheet in tables 6 and 7.

I think I understand the whole procedure for sending and receiving data, but let me summarize what you said to make sure I got it right. For sending data: First, you set CSN to low. Next, you send the W_TX_PAYLOAD instruction (do you do this by clocking in the bits also?). Then you immediately begin clocking in the data to send, or the “payload”. I have no idea what number this is, but lets say our byte consisted of these bits 11110000. The process would go like this: Micro sets SCK to High and MOSI to high (1). Micro sets SCK to low (which shifts the bit in). Micro sets SCK to High again and MOSI to High again (it would probably still be High) and then sets SCK to low. This continues for the rest of the bits. After SCK is set to low for the last time, the Micro sets CSN to high again, and the data will be sent. Is that right? In the data sheet, they say you fill up FIFO with the payload. What is FIFO and what is it for?

First and foremost, unless you're bitbanging your SPI interface, your microcontroller will take care of the clock and data lines for you (most decent PICs have a built-in SPI interface). The only line you have to take care of yourself is the CSN line. You simply have to load the data bytes into the micro's SPI data holding register in the correct order (and operate the CSN line properly).

A FIFO is a first-in, first-out data scheme (see http://en.wikipedia.org/wiki/FIFO). It is analogous to standing in a line, in that the first person that gets into the line is the first person to get out of the line. In the 24L01, the FIFO simply allows you to enter more than one packet at a time such that you don’t have to wait for a packet to get all the way out of the antenna to send another one. I forget how deep the FIFO is, though, and how many packets you can send to the 24L01 before it stops accepting them.

My last question is about configuration. Could you please explain the process for configuring things in the 24L01? For example, if you wanted to change the value of the RF_PWR setting, what would the process be to do it? I found it in the datasheet, but I don’t understand the whole address thing. How would I access this setting, and how would I change its value?

Ahh, here is the fun part. This is where you start staring at pages 22 to 25 of the datasheet for hours on end :shock: . To write to a configuration register, you use the W_REGISTER instruction, and to read a configuation register, you use the R_REGISTER instruction. With both of these registers, the 5 least significant bits make up the address of the register (hence the binary instruction being 001AAAAA).

Since you ask about the RF_PWR setting, I’ll use it as an example. The RF_PWR setting is found in the RF_SETUP register, which is location 06 (remember that these addresses are in HEX…I read them as decimal a few times and it messed me up). Now we know that 6 in hex translates to 101 in binary. Since we need a 5-bit register address to use with the instruction, simply pad the left side with zeroes out to 00101. Then, if you want to write to the RF_SETUP register, your instruction is 00100101, where we have put 00101 into the AAAAA portion of the instruction).

Since this is a one-byte long register (they all are except for the addresses), once you clock in this instruction byte, you will immediately clock in your configuration byte (with the addresses, you will clock in more than one data byte, generally). Remember that you have to be careful when you clock in the data byte because whatever you clock in will overwrite all the other settings. By looking at the datasheet on page 23, we can see that the default value for the RF_SETUP register is going to be 00001111 (or 0x0F in hex). The default value of the RF_PWR field is 11, so lets say we want to change this to 00. That would mean that we want to send the configuration byte of 00001001 to reflect this change. In order to do this, clear CSN, send the instruction byte I described above, and then send the data byte I just explained. Finally, set CSN.

One thing to remember about these devices is that they are by default powered down. In order to get them to work, you HAVE to send them a configuration word for the CONFIG register that sets the PWR_UP bit.

One last thing that will help you is to pick a microcontroller out and study its datasheet, particularly the SPI module. You will have to become very familiar with it to get everything working.

Thank you again. That was very helpful also.

So what you were saying about always setting PWR_UP, you mean every time you cut off the power to the 24L01 and then give it power again, you will have do the PWR_UP thing? Could you just briefly explain the CONFIG register and setting PWR_UP? The CONFIG register is all of the configuration settings you might want to change, right? So the RF_PWR setting is in CONFIG?

I am going to use a PIC microcontroller, probably a 12F675 if it will work ok. The reason for this is because I can only program 8 or 14 pin PIC micros, until I get another programmer when I will be able to program a larger variety. I have a bunch of 12F675’s laying around, so it would be convenient to use one. I know they are not as powerful as some, so I’ll have to look and see if they have SPI stuff.

Thanks for your great explanations. I’m at the point where I’m not an expert at it, but I understand the concept of most of it. Hopefully the modules are restocked soon so I can buy some and begin experimenting.

So what you were saying about always setting PWR_UP, you mean every time you cut off the power to the 24L01 and then give it power again, you will have do the PWR_UP thing?

Exactamundo. Every time this puppy is powered up, it reverts to the default settings (there is no non-volatile memory to hold your configuration when power is off). Therefore, you have to re-send all of the configuration data at any time the unit is powered off and back on. Chances are, however, that the wireless unit and your microcontroller will always lose power at the same time, so the micro will just run its initialization code when it starts back up. Don't think that if you go into power-down mode you lose your settings, however, because you don't. Settings are only lost when you lose the power that comes into the device (i.e., battery dies, unit gets unplugged, etc.).

Could you just briefly explain the CONFIG register and setting PWR_UP? The CONFIG register is all of the configuration settings you might want to change, right? So the RF_PWR setting is in CONFIG?

The CONFIG register is simply the first register in the set of registers. It is address 0 (look on page 22 of the datasheet), and has 8 bits, most all of which are very important. There are many other registers, however, so changing this register will not affect any others besides it.

CPW:
I am going to use a PIC microcontroller, probably a 12F675 if it will work ok. The reason for this is because I can only program 8 or 14 pin PIC micros, until I get another programmer when I will be able to program a larger variety. I have a bunch of 12F675’s laying around, so it would be convenient to use one. I know they are not as powerful as some, so I’ll have to look and see if they have SPI stuff.

The PIC12F675 does not have a built in SPI module. But, this is not to say that you cannot use it with an SPI device.

The PIC12F675 has 8 pins, 2 have to be use as power, so that leaves you with 6 pins. I assume you will want/need to use an external clock source with this PIC(and if not, pretend you do), so that leaves 4 pins. Using SPI, no matter how it is implemented, hardware or software, will require a minimum of 4 pins (some devices may only need to send data one way, so one pin may sometimes be eliminated, which is very rare, and I’m just saying this to cover my butt!). If you decide to use this PIC in the end, you will most likely not be able to use it for anything other than controlling the wireless module. If you do not need to use the OSC1 and OSC2 pins for an external clock source, then you have 2 extra pins at your disposal.

Finally, you will need to implement SPI in software, which, is not too difficult, but is definitely more trivial than using a built in SPI module. If you are using Microchip’s C18, there is a built in Software-SPI library, and documentation for it is available on the C18 download page at www.microchip.com.

If you have to use this PIC, but need more I/O pins, you could sample/purchase/obtain a GPIO expander from microchip. This chip is connected via SPI to the PIC, and you would then have to connect the wireless module to this chip. All in all, I do not suggest this route for beginning with PICs

Good luck with your project!

There’s lots of people here willing to help, so just ask (I’m sure you already know this though).

PS, I’ll let brennen answer your other questions, as he seems to be familiar with the datasheet.

— Ah snap, he beat me to it! —

you can sample 14 pin PICs from microchip (9 at a time), they usually ship pretty fast. I get them from Thailand to california in about a week !!!

there are some 20 pin PIC’s (16F series) that have SPI and will work with PICKIT1 (assuming thats why you have 12F675s) but require some hacking. Of course, SPI is pretty simple with PICs and the 14 pins should be addequate to your needs.

I suggest though that you start off with something simpler, go at it step by step, you should start programming and getting acquainted with microcontrollers and how basic digital stuff works before going on larger steps

Assuming you have a desktop with a serial port, why not buy SparkFun’s PIC programmer (http://www.sparkfun.com/commerce/produc … ducts_id=8)? It costs a whopping $13 bucks and can program up to 40 pin PICs using ICPROG (a free program) on your computer to download your program to the PIC. The only problem with it is that it won’t work with lower voltage serial ports like those found on most laptops and some newer desktops. Check out http://www.sparkfun.com/commerce/catego … ?cPath=1_6 for a complete list of SparkFun’s programmers.

The CONFIG register is simply the first register in the set of registers. It is address 0 (look on page 22 of the datasheet), and has 8 bits, most all of which are very important. There are many other registers, however, so changing this register will not affect any others besides it.

After reading through the datasheet, I understand the CONFIG register better. My only question about changing registers is how you know what bits to send. I understand that the first 3 bits are for the address, but how do you figure out the other five if there are multiple settings for that address? For example, lets say that on the RF_SETUP register, you want to change RF_DR and RF_PWR. I don’t know if you could change both at once, but lets say you were going to change RF_DR first and RF_PWR second. If I want to change RF_DR to 0, you would first send the command for RF_SETUP: 00100101. But how would I determine the byte to send it to change the value? I guess what I’m asking is, what do the ‘bit’ values mean in the table? For RF_DR, the bit is 3. So would the command to change the value be this: 00000111? Because (assuming the right-most bit is index 0), the fourth number from the right would be bit 3 and contains a 1 that gets changed to 0. Is that right? So to change RF_DR from 1 to 0 and RF_PWR from 11 to 01, the new byte would be this: 00000011 (leaving the other bits at their reset values)? I think I get this now!

The PIC12F675 does not have a built in SPI module. But, this is not to say that you cannot use it with an SPI device.

The PIC12F675 has 8 pins, 2 have to be use as power, so that leaves you with 6 pins. I assume you will want/need to use an external clock source with this PIC(and if not, pretend you do), so that leaves 4 pins. Using SPI, no matter how it is implemented, hardware or software, will require a minimum of 4 pins (some devices may only need to send data one way, so one pin may sometimes be eliminated, which is very rare, and I’m just saying this to cover my butt!). If you decide to use this PIC in the end, you will most likely not be able to use it for anything other than controlling the wireless module. If you do not need to use the OSC1 and OSC2 pins for an external clock source, then you have 2 extra pins at your disposal.

Finally, you will need to implement SPI in software, which, is not too difficult, but is definitely more trivial than using a built in SPI module. If you are using Microchip’s C18, there is a built in Software-SPI library, and documentation for it is available on the C18 download page at www.microchip.com.

I would probably not be using an external clock, so I would have those two free pins, and that’s exactly how many I need. However, if the 12F675 doesn’t have an SPI interface, I guess its not worth using. So you’re suggesting the C18? Is that 16C18? I’ll have to look into what micros have SPI.

there are some 20 pin PIC’s (16F series) that have SPI and will work with PICKIT1 (assuming thats why you have 12F675s) but require some hacking. Of course, SPI is pretty simple with PICs and the 14 pins should be addequate to your needs.

I do have the PICKIT 1, but I’mgoing to buy another programmer. I’ll look into the sampling too.

Assuming you have a desktop with a serial port, why not buy SparkFun’s PIC programmer (http://www.sparkfun.com/commerce/produc … ducts_id=8)? It costs a whopping $13 bucks and can program up to 40 pin PICs using ICPROG (a free program) on your computer to download your program to the PIC. The only problem with it is that it won’t work with lower voltage serial ports like those found on most laptops and some newer desktops. Check out http://www.sparkfun.com/commerce/catego … ?cPath=1_6 for a complete list of SparkFun’s programmers.

Actually, that’s the programmer I am going to buy. I’ve been planning on getting it for a while, I’m just to lazy to actually go and do it. I will probably wait until those modules restocked, and then I will buy all the stuff together.

Thanks for the help everyone. I’ve got some more questions, but I have to go for now.

After reading through the datasheet, I understand the CONFIG register better. My only question about changing registers is how you know what bits to send. I understand that the first 3 bits are for the address, but how do you figure out the other five if there are multiple settings for that address? For example, lets say that on the RF_SETUP register, you want to change RF_DR and RF_PWR. I don’t know if you could change both at once, but lets say you were going to change RF_DR first and RF_PWR second. If I want to change RF_DR to 0, you would first send the command for RF_SETUP: 00100101. But how would I determine the byte to send it to change the value? I guess what I’m asking is, what do the ‘bit’ values mean in the table? For RF_DR, the bit is 3. So would the command to change the value be this: 00000111? Because (assuming the right-most bit is index 0), the fourth number from the right would be bit 3 and contains a 1 that gets changed to 0. Is that right? So to change RF_DR from 1 to 0 and RF_PWR from 11 to 01, the new byte would be this: 00000011 (leaving the other bits at their reset values)? I think I get this now!

By looking in the datasheet, the RF_SETUP register is made up of 8 bits, which will form a byte. The default value looks like this:

bit: 76543210

val: 00001111

So now, any time you write this register, you will be changing every bit at the same time. Therefore, you only need to issue one write to that register to change any or all of the values simultaneously. If you wanted to change RF_DR and RF_PWR to 0 and 00 respectively, you would send the data byte of 00000001 (you still have to send the W_REGISTER command for this register first). If you only wanted to change RF_DR to 0, you would send 00000111. Just remember that you will change every bit in a register every time you write to that register, so you have to be careful to leave every bit you don’t want to be changed in its default state.

I would probably not be using an external clock, so I would have those two free pins, and that’s exactly how many I need. However, if the 12F675 doesn’t have an SPI interface, I guess its not worth using. So you’re suggesting the C18? Is that 16C18? I’ll have to look into what micros have SPI.

I would definitely advise you to choose a PIC with a hardware SPI port. This will simplify your life considerably. C18 is Microchip's C compiler for the 18 series PICs (18F4520, for example). You can download the student version for free and basically the only thing that is disabled is optimization. If you know C, then this is a much better way to program than assembly.

bit: 76543210

val: 00001111

So now, any time you write this register, you will be changing every bit at the same time. Therefore, you only need to issue one write to that register to change any or all of the values simultaneously. If you wanted to change RF_DR and RF_PWR to 0 and 00 respectively, you would send the data byte of 00000001 (you still have to send the W_REGISTER command for this register first). If you only wanted to change RF_DR to 0, you would send 00000111. Just remember that you will change every bit in a register every time you write to that register, so you have to be careful to leave every bit you don’t want to be changed in its default state.

That makes a lot more sense now. I only have one question about changing registers now. Let’s say you have a setting in a register (let’s assume it’s a 1 byte register) that you would like changed from 11 to 01, according to the datasheet. For an example, let’s assume that the byte from that register, by default, is 00001111. If the setting we want to change uses bits 1 & 2, and I wanted to change the 11 to 01, would the new byte be 00001011, or would it be 00001101 because you start at the right and go to left? (I’m pretty sure it would be 00001011) That’s my only question about that, otherwise I understand changing registers now, thanks to you guys. :smiley:

I would definitely advise you to choose a PIC with a hardware SPI port. This will simplify your life considerably. C18 is Microchip’s C compiler for the 18 series PICs (18F4520, for example). You can download the student version for free and basically the only thing that is disabled is optimization. If you know C, then this is a much better way to program than assembly.

I will definetely have to find a micro with an SPI interface. By the way, thanks for the suggestion about the student version and everything, but I use the free version of Proton Development Suite for my PIC micros so I can program them in BASIC. Visual Basic was the first language I learned, so I favor BASIC over C. I’m almost positive the development suite has commands for SPI, so as long as I have a good microcontroller and programmer, I already have the programming software I need.

Now here are my questions that I didn’t have time to ask earlier. Once I learn how to use the modules and the 24L01 and everything and I begin working on creating electronics for my radio-controlled car, I will need to send two sets of information. This brings up two questions I have.

The first question is, what is the best way to send throttle and steering values together every time data is sent, in a way that the receiver will know which is which? The best way I can think of would be to use FIFO so I can send two bytes at once (one for each of throttle and steering), and then the receiver will have no problem determining between them because every time it receives data, the first byte will be throttle and the second byte will be steering. Is there a better way to do it? I would like to avoid sending a packet (I forget the term for it) that tells the receiver the order of data is starting over, so sending the two values at once seems to be the best way. What do you suggest?

The other question is this. What is the best way to send a negative number? For each channel, the value will range from -255 to 255. I could do this in all positive numbers (for example 0 to 500) with the middle value representing 0 and the extreme numbers (0 and 500) representing -255 and 255 respectively, but I would prefer to use negative numbers if possible. Which would be the better way? I’m assuming that what I want to do will require two bytes per channel, but that shouldn’t be a problem.

That’s all the questions I have for now, and again, thanks for helping.

As far as how to send the data, I can’t give any suggestions, I would do the 2 bytes, but I’m not nearly as experienced as the other people here are.

As far as representing negative numbers, you could just add a sign bit, so you would then have 18 bits, 9 for throttle and 9 for steering.

If you wanted to simplify things a bit (no pun intended!), you could use 7 bits for the values (you would then have -128 through 127) and the 8th bit would be the sign bit.

Also, the latter way is probably already implemented, you just need to set your datatype in the program you write to be signed 8 bit. It uses 2s compliment to store the negative numbers…

That makes a lot more sense now. I only have one question about changing registers now. Let’s say you have a setting in a register (let’s assume it’s a 1 byte register) that you would like changed from 11 to 01, according to the datasheet. For an example, let’s assume that the byte from that register, by default, is 00001111. If the setting we want to change uses bits 1 & 2, and I wanted to change the 11 to 01, would the new byte be 00001011, or would it be 00001101 because you start at the right and go to left? (I’m pretty sure it would be 00001011) That’s my only question about that, otherwise I understand changing registers now, thanks to you guys.

In normal binary representation, the higher bit number is always to the left. This gives rise to the terms most significant bit and least significant bit, meaning that the most significant bit is the bit that has the highest weight and the least significant bit has the least weight. Therefore, you are correct in the assumption that changing bits 2 and 1 to 01 will make your value go from 00001111 to 00001011. Basically just look at the little diagram I made and it shows you what the bit positions are and how you would change the bits.

The first question is, what is the best way to send throttle and steering values together every time data is sent, in a way that the receiver will know which is which? The best way I can think of would be to use FIFO so I can send two bytes at once (one for each of throttle and steering), and then the receiver will have no problem determining between them because every time it receives data, the first byte will be throttle and the second byte will be steering. Is there a better way to do it? I would like to avoid sending a packet (I forget the term for it) that tells the receiver the order of data is starting over, so sending the two values at once seems to be the best way. What do you suggest?

When you mention the FIFO, I think you're a bit confused. The operation of the FIFO is to hold packets of data, not just bytes. You can send more than one byte at a time in a single packet, and there will only be one packet in the FIFO as long as you have only sent one packet. In fact, you can send up to 32 bytes in one packet.

Why not just use a two byte packet. Let the first byte be a status byte that tells the receiver what type of data it is receiving (throttle, steering, etc). Let the second byte be the value of this setting, i.e., your 0-255 number. This will allow you to send 256 different types of messages so that your software and hardware will be extremely flexible.

The other question is this. What is the best way to send a negative number? For each channel, the value will range from -255 to 255. I could do this in all positive numbers (for example 0 to 500) with the middle value representing 0 and the extreme numbers (0 and 500) representing -255 and 255 respectively, but I would prefer to use negative numbers if possible. Which would be the better way? I’m assuming that what I want to do will require two bytes per channel, but that shouldn’t be a problem.

Here, you could just make one of the bits in the status byte be a sign bit. Remember, when you are talking about a number that can go from -255 to 255, you are basically talking about a 9-bit number, which can technically go from -256 to 255. I would second reklipz's suggestion on trying to use signed 8 bit numbers unless you have to use -256 to 255 stuff because it makes software easier.

As far as how to send the data, I can’t give any suggestions, I would do the 2 bytes, but I’m not nearly as experienced as the other people here are.

When you mention the FIFO, I think you’re a bit confused. The operation of the FIFO is to hold packets of data, not just bytes. You can send more than one byte at a time in a single packet, and there will only be one packet in the FIFO as long as you have only sent one packet. In fact, you can send up to 32 bytes in one packet.

Why not just use a two byte packet. Let the first byte be a status byte that tells the receiver what type of data it is receiving (throttle, steering, etc). Let the second byte be the value of this setting, i.e., your 0-255 number. This will allow you to send 256 different types of messages so that your software and hardware will be extremely flexible.

Thank you both. I think I was confused about FIFO. I like the suggestion of a status byte and a data byte, so I will probably use that method.

As far as representing negative numbers, you could just add a sign bit, so you would then have 18 bits, 9 for throttle and 9 for steering.

If you wanted to simplify things a bit (no pun intended!), you could use 7 bits for the values (you would then have -128 through 127) and the 8th bit would be the sign bit.

Also, the latter way is probably already implemented, you just need to set your datatype in the program you write to be signed 8 bit. It uses 2s compliment to store the negative numbers…

Here, you could just make one of the bits in the status byte be a sign bit. Remember, when you are talking about a number that can go from -255 to 255, you are basically talking about a 9-bit number, which can technically go from -256 to 255. I would second reklipz’s suggestion on trying to use signed 8 bit numbers unless you have to use -256 to 255 stuff because it makes software easier.

Again, thank you both. I will consider both suggestions. However, if I use a status byte, then I will probably do what brennen said and have one bit in the status byte be a positive or negative indicator. That way I can have a large range of values to work with, although -128 to 127 would probably work just fine anyway, since in the end the signals will be converted to pulses for standard servos and electronic speed controls, and that will only give me a range of 100 - 200, so about 50 different possible values in each direction, as opposed to 127 or 255. So either way I do it, I don’t think it will affect performance at all.

I need some help figuring out what PIC micro I will want to use. For right now, I can only program 8 or 14 pin micros with my PICKIT 1 (I have heard there is a hack for larger micros, but I don’t know how to do it). Are there any 8 or 14 pin micros with SPI? I will be getting that $13 programmer when I get the modules, so I will probably not be limited to 8 or 14 pin micros any more. But just because it would simplify things, do any 8/14 pin PIC micros exist with SPI? If not, what would be a cheap but effective micro to use that has SPI and where could I get it? I generally order electronics from Mouser Electronics (www.mouser.com), but they don’t stock any PIC micros I would be interested in, and plus they charge $6 for shipping. Does SFE stock any micros with SPI? If so, what are they? Basically, what would be a good SPI PIC micro, and where could I get it for pretty cheap?

Thanks. :smiley:

I recommend you just look at www.microchip.com and use the parametric search to find some with SPI (I believe there are a few that do have SPI modules). If you find one at microchips site, and you have a corporate email address (basically an email where the domain is not gmail.com, hotmail.com, yahoo.com, or any of the other free providers), then you can just order a free sample, shipping is paid for you.

Also, if you know that you will have absolutely no need for 256 different status bytes, then you could use 4 bits for status, and 12 bits for data, if you need that. But, as brennen said, the data part of the packet can be as long as you want, so maybe just ignore this suggestion.

I did some searches on Microchip’s website, but the lowest pin count I could find on a micro with SPI was 18, and that was a 16F something or a 16C something. I think I will just go with a 18F2550 or something similar. I am going to order some samples of a few different kinds, and then I’ll see what kind I like best. Would I want I2C/SPI or MI2C/SPI? Those were the two kinds I saw with SPI, but I didn’t know what the difference was. Does anyone know?

My last question about the 24L01 is about interference. Since this will be for an RC car eventually, I might end up with two or more RC cars using my custom made RF link with the 24L01. This brings up interference. I will want the right transmitter to always be controlling the right receiver, so how will I accomplish this? I would like to avoid having each transmitter have its own unique code, but I guess if that’s the only way to do it, that’s the only way. I could probably make a simple one button channel switching feature on the transmitter and receiver, so that way the user could change to a channel that is different than the other cars. That would work, but then I will need some sort of channel indication, and even if I use a combination of LEDs, that will start to get complicated. It would be nice if it was automatic so the user would have to do nothing but drive, but really the only way to do that would be for each transmitter to have a unique id and for each receiver to only respond to that id, so if the transmitter decided there was too much interference and the channel had to be switched, it could hopefully get a signal to the receiver to switch the channel. What would be the best way to accompish interference free communication since all of the modules would be identical?

Thanks for the help everyone.

I did some searches on Microchip’s website, but the lowest pin count I could find on a micro with SPI was 18, and that was a 16F something or a 16C something. I think I will just go with a 18F2550 or something similar. I am going to order some samples of a few different kinds, and then I’ll see what kind I like best. Would I want I2C/SPI or MI2C/SPI? Those were the two kinds I saw with SPI, but I didn’t know what the difference was. Does anyone know?

I2C is a different serial communication protocol. You don't need to worry about the type of I2C on the PIC, just that it has SPI. I've only ever seen one type of SPI, and the only differences being the names of the pins (I think it depends on whether or not the manufacturer of the chip pays Motorola to use the copyrighted names or not...Microchip does not).

My last question about the 24L01 is about interference. Since this will be for an RC car eventually, I might end up with two or more RC cars using my custom made RF link with the 24L01. This brings up interference. I will want the right transmitter to always be controlling the right receiver, so how will I accomplish this? I would like to avoid having each transmitter have its own unique code, but I guess if that’s the only way to do it, that’s the only way. I could probably make a simple one button channel switching feature on the transmitter and receiver, so that way the user could change to a channel that is different than the other cars. That would work, but then I will need some sort of channel indication, and even if I use a combination of LEDs, that will start to get complicated. It would be nice if it was automatic so the user would have to do nothing but drive, but really the only way to do that would be for each transmitter to have a unique id and for each receiver to only respond to that id, so if the transmitter decided there was too much interference and the channel had to be switched, it could hopefully get a signal to the receiver to switch the channel. What would be the best way to accompish interference free communication since all of the modules would be identical?

You pretty much named all of the schemes that I could come up with quickly. It is easy to change the RF channel on the 24L01 (RF_CH register), but, like you said, you will have to either let the software handle it automatically or let the user choose it. The former adds considerably to your code, and the latter adds to necessary hardware, increasing cost.

Having a unique ID for each system becomes a pain because you have to keep track of all the IDs you have used and then you are limited in the number of IDs you can give out (256 if the ID is one byte, 65,536 if two byte, etc.). You also have to recompile the software each time or put jumpers in certain positions for each receiver and transmitter you use.

Either scheme has its advantages and disadvantages. The only other way I can think of is for a transmitter to do some type of automatic discovery of a receiver, kind of like with wireless routers and laptops. That would become very cumbersome to handle in code, and I don’t think would really be worth it. Honestly, I would probably opt for using IDs that are held in software and just recompile each time you load the code for a receiver or a transmitter. This will have to be sent with each packet, and you will have to decide how many bits you want to use (it could be part of the status byte we have discussed). It depends a lot on how many of these units you plan on making, though.