Driver - Nordic nRF24L01+ wireless module driver

Thanks Gralin,
It would be useful if you could expose the Command through the API … something like this for example:


nordic.API.DataRate = nordic.DataRate.Low;// DataRate is a Property, so one could set and get the Speed...

//where nordic.DataRate.Low is part of an Enum: Lowest = 250Kbps, Low=1Mps, High=2Mps, and so on....

the above is just an idea…

thanks.

Sure, good idea. Please just check out if what i suggested works for you. Also please visit the codeplex site and try the gadgetee module installer. It will give you the nordic component in the designer toolbox.

Hi Gralin:
i had to change your Code a bit to make it compile, Because it complain about not being able to convert an int to byte[]. here is what it looks like on the Gadgeteer side…


           int regValue = nordic.Api.Execute(Commands.R_REGISTER, Registers.RF_SETUP, new byte[1])[1];
            regValue |=  1 << Bits.RF_DR_LOW;
            nordic.Api.Execute(Commands.W_REGISTER, Registers.RF_SETUP, new[] {(byte) regValue });

after running that code on both boards it worked, i can send and receive messages…the range improved now i can go about 20 m… or so… one long range module on one side and one standard module on the other side…

ok now that i have the basics…covered i would like to test the Mesh networking part of this…

would you like me to test that Gralin? if yes please point me to where to go to get started on building a mesh…

thanks.

First of all I’m very glad you are testing the driver and all info you can provide can be helpful for other. Good to know that you got it working within 20 m range. When you google about the range you will find that you should get something about 60m using the regular ones. Did you try indoor or outdoor?

http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo

Regarding mesh, here is the definition by Wikipedia:

This is what you can do when using XBee modules. When using Nordic you get start topology. If you want mesh you have to handle it on your own. There is a project for arduino that does that but it would have to be ported to C#

http://maniacbug.github.com/RF24Network/

Thanks to you for making this happen.
The range I have is indoors (cement concrete walls)
As for the mesh, I’m aware of Maniacbug project and I thought Ericson got it working with the cobra a while back, so I figured you were going to incorporate the changes to this driver since you helped when he got stuck…

Anyway I hope Ericson is reading this and will share his findings…

Cheers, and thanks…

Jay Jay, since you are testing nordics could you try doing one thing for me? Some time ago i was wondering can broadcast be done wit those modules. What i was thinking was to set two modules with the same addres, turn off auto ack. Send data from third node and see if the other two receive it. If this works then all devices can receive broadcast messages - one module can receive from many addresses (like ip addres and network interface)

i sure can…

If you could point me to where to turn off the ack…

a sample code would be nice… :slight_smile:

thanks.

You can try without turning it off first. Look in the source code of Configure method. There should be a comment where the auto ack bit is set. After that you can reset it the same way you did with rf speed. I can help you more when i will be next to a pc

i will report back in couple of hours…

Hi Gralin,
Sorry man i couldn’t find my USB power module… errrrrrrrrrrrrr
i will look for it again later I’m sure it just hiding somewhere…

@ Jay Jay, no hurry, I’m just exploting the fact that you are playing with nordics :wink:

Just an update on my module. The crystal doesn’t seem to be starting up. Don’t know why yet… :frowning:

@ GMod(Errol) keep us posted!

Hi Gralin,

Good news… It works :wink: right off the box… no changes to the code…

all i had to do is set Both my Spider and Panda to the same address by simply having this in the Panda:


    public class Program
    {
        private static NRF24L01Plus _module;
        public static OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);
        public static void Main()
        {

            const Cpu.Pin chipSelectPin = (Cpu.Pin)FEZ_Pin.Digital.Di3;
            const Cpu.Pin interruptPin = (Cpu.Pin)FEZ_Pin.Interrupt.UEXT10;
            const Cpu.Pin chipEnablePin = (Cpu.Pin)FEZ_Pin.Digital.Di2;
            const SPI.SPI_module spi = SPI.SPI_module.SPI1;
            var address = Encoding.UTF8.GetBytes("PANDA");

            _module = new NRF24L01Plus();
            _module.Initialize(spi, chipSelectPin, chipEnablePin, interruptPin);
            _module.Configure(address, 10);
            _module.OnDataReceived += OnReceive;
            _module.OnTransmitFailed += () => Debug.Print("Send failed");
            _module.OnTransmitSuccess += () => Debug.Print("Send ok");
            _module.Enable();

            int regValue = _module.Execute(Commands.R_REGISTER, Registers.RF_SETUP, new byte[1])[1];
            regValue |= 1 << Bits.RF_DR_LOW;
            _module.Execute(Commands.W_REGISTER, Registers.RF_SETUP, new[] { (byte)regValue });

            // example of reading your own address
            var myAddress = _module.GetAddress(AddressSlot.Zero, 5);
            Debug.Print("I am " + new string(Encoding.UTF8.GetChars(myAddress)));

            Debug.Print("Waiting for data...");
            _module.SendTo(Encoding.UTF8.GetBytes("HYDRA"), Encoding.UTF8.GetBytes("HELLO Hydra"));
            
            PowerState.Sleep(SleepLevel.DeepSleep, HardwareEvent.GeneralPurpose);//put the device to sleep...

            Thread.Sleep(Timeout.Infinite);
        }

        private static void OnReceive(byte[] data)
        {
            try
            {
                Debug.Print("<- " + new string(Encoding.UTF8.GetChars(data)));
            }
            catch (Exception)
            {

            }

            led.Write(!led.Read());
        }
    }

and the Spider Code:



       public partial class Program
    {
      
        void ProgramStarted()
        {
            nordic.Configure(Encoding.UTF8.GetBytes("PANDA"), 10);
            nordic.DataReceived += new NRF24L01Plus.OnDataRecievedHandler(NordicDataReceived);
            nordic.TransmitFailed += () =>
                                         {
                                             Mainboard.SetDebugLED(false);
                                             Debug.Print("Send failed");
                                         };
        

        nordic.TransmitSuccess += () =>
                                      {
                                          Mainboard.SetDebugLED(true);
                                          Debug.Print("Send ok");
                                          Thread.Sleep(1000);
                                          Mainboard.SetDebugLED(false);
                                      };
            nordic.Enable();
            button.ButtonPressed += ButtonButtonPressed;

            int regValue = nordic.Api.Execute(Commands.R_REGISTER, Registers.RF_SETUP, new byte[1])[1];
            regValue |=  1 << Bits.RF_DR_LOW;
            nordic.Api.Execute(Commands.W_REGISTER, Registers.RF_SETUP, new[] {(byte) regValue });

            // example of reading your own address
            var myAddress = nordic.Api.GetAddress(AddressSlot.Zero, 5);
            Debug.Print("I am " + new string(Encoding.UTF8.GetChars(myAddress)));

            Debug.Print("Program Started");
        }

        void NordicDataReceived(byte[] data)
        {
            try
            {

                Mainboard.SetDebugLED(true);
                Thread.Sleep(2000);
                Mainboard.SetDebugLED(false);
                ////Panda sends a string like this: "Hello Spider |true" where true/false represents the state of the LED on the Panda
                string result = new string(Encoding.UTF8.GetChars(data));
                Debug.Print("<- " + result);
            }
            catch (Exception)
            {
            }
        }

        void ButtonButtonPressed(Button sender, Button.ButtonState state)
        {
            try
            {
                nordic.SendTo(Encoding.UTF8.GetBytes("HYDRA"), Encoding.UTF8.GetBytes("Hi Hydra!"));
            }
            catch (Exception)
            {
            }

        }


    }

and finally the Hydra Code:


  public partial class Program
    {
      
        void ProgramStarted()
        {
            nordic.Configure(Encoding.UTF8.GetBytes("HYDRA"), 10);
            nordic.DataReceived += new NRF24L01Plus.OnDataRecievedHandler(NordicDataReceived);
            nordic.TransmitFailed += () =>
            {
                Mainboard.SetDebugLED(false);
                Debug.Print("Send failed");
            };


            nordic.TransmitSuccess += () =>
            {
                Mainboard.SetDebugLED(true);
                Debug.Print("Send ok");
                Thread.Sleep(1000);
                Mainboard.SetDebugLED(false);
            };
            nordic.Enable();
            button.ButtonPressed += new GTM.GHIElectronics.Button.ButtonEventHandler(button_ButtonPressed);

            int regValue = nordic.Api.Execute(Commands.R_REGISTER, Registers.RF_SETUP, new byte[1])[1];
            regValue |= 1 << Bits.RF_DR_LOW;
            nordic.Api.Execute(Commands.W_REGISTER, Registers.RF_SETUP, new[] { (byte)regValue });

            // example of reading your own address
            var myAddress = nordic.Api.GetAddress(AddressSlot.Zero, 5);
            Debug.Print("I am " + new string(Encoding.UTF8.GetChars(myAddress)));

            Debug.Print("Program Started");
        }

        void button_ButtonPressed(GTM.GHIElectronics.Button sender, GTM.GHIElectronics.Button.ButtonState state)
        {
            try
            {
                nordic.SendTo(Encoding.UTF8.GetBytes("PANDA"), Encoding.UTF8.GetBytes("Hi PANDA!"));
            }
            catch (Exception)
            {
            }
        }

        void NordicDataReceived(byte[] data)
        {
            try
            {
                Mainboard.SetDebugLED(true);
                Thread.Sleep(2000);
                Mainboard.SetDebugLED(false);
                string result = new string(Encoding.UTF8.GetChars(data));
                Debug.Print("<- " + result);
            }
            catch (Exception)
            {
            }
        }
    }

when i press the button the hydra both Panda and spider receive the string…
and when i press the button on the spider the hydra receives the string…

Coollllll :wink:

anything else to try please let me know… this is fun…

Jay…

That’s good news. Now you could test multiple address. Each module can have more that one address to receive data. I suggest you set up each one with unique address and a common broadcast address. This way you should be able to send data point-to-point and broadcast. You can add extra address using method SetAddress().

ok some good news and some bad news…

the bad news:
the only address i could set correctly was AddressSlot.One, the others two, three, four, five all returned TTTTT when i read the address back…

Hydra:

 
nordic.Configure(Encoding.UTF8.GetBytes("HYDRA"), 10);           
            nordic.Api.SetAddress(AddressSlot.One,Encoding.UTF8.GetBytes("BCAST"));

      // example of reading your own address
            var myAddress = nordic.Api.GetAddress(AddressSlot.Zero, 5);
            Debug.Print("I am " + new string(Encoding.UTF8.GetChars(myAddress)));

            var myBCastAddress = nordic.Api.GetAddress(AddressSlot.One, 5);
            Debug.Print("Broadcast Address is: " + new string(Encoding.UTF8.GetChars(myBCastAddress)));


Outputs:
I am Hydra
Broadcast Address is: BCAST

but this code below returns TTTTT: on all three boards, Hydra, Spider and Panda. the same happens for AddressSlot.Two, Three, Four, Five.


nordic.Configure(Encoding.UTF8.GetBytes("HYDRA"), 10);           
            nordic.Api.SetAddress(AddressSlot.Two,Encoding.UTF8.GetBytes("BCAST"));

      // example of reading your own address
            var myAddress = nordic.Api.GetAddress(AddressSlot.Zero, 5);
            Debug.Print("I am " + new string(Encoding.UTF8.GetChars(myAddress)));

            var myBCastAddress = nordic.Api.GetAddress(AddressSlot.Two, 5);
            Debug.Print("Broadcast Address is: " + new string(Encoding.UTF8.GetChars(myBCastAddress)));

Outputs:
I am Hydra
Broadcast Address is: TTTTT


Now the good news,
is that i do receive the Broadcast, but sometimes it doesn’t work correctly, most of the time the Spider always receives the Broadcast but not the hydra…

I switch the Names between the Hydra and the Spider , still the spider receives the Broadcast and not the Hydra, so i switched the MODULES Between the Spider and the Hydra, and the same behavior… hydra doesn’t receive the Broadcast… so something isn’t working properly on the HYDRA…

Cheers.
Jay

Hi Gralin.
more info… after removing this

var result = new string(Encoding.UTF8.GetChars(data));

from the receive event on the hydra… the Broadcast was working… and i notice that the data received by the hydra is always corrupted… and that’s what was blocking the broadcast… this happens only on the hydra…

another thing i noticed that when i hit restart on VS2010 debugger i get an exception about reading back the address…the only way to make it work again is by removing the Power…
Jay.

Please note that address 2 to 6 is crappy. They are only one byte big, the rest of the address comes from address 1.

So, if address 1 is "ABCDE"
And address 2 is set to “2” then the full address 2 is “ABCD2”

This limits the usability of address 2 through 6 to the point of unusability.

So you are saying that my config should have an address of ABCDE and the AddressSlot.One should be set to ABCD2? if yes what about my other board how should i configure that… i’m confused…

@ Gralin: how do i turn off Ack… all i see is this : Registers.EN_AA which enables the ack ? and one more thing HOW do i reset the module? because as of now when i reset the board by redeploying a changes the Module doesn’t replace it all register and keeps the old info running… for example if i change the address and hit F5 the address on the module doesn’t update and it keeps referencing the old one.

thanks.

@ GMod(Errol) is right, i forgot to mention that. Here is the description from datasheet to make it clear.