Tiny CLR V2 nRF24L01P connectivity

Hi all,

Beta version of my nRF24L01 library is now available.

There is a demo with an embedded coolness shield for Fezduino.


There are demos for Fezportal and SC20100(both sockets) boards with mikroe nRF24C or nRF24S or nRF24T clicks.

The library is a port of techfoonninja’s Windows 10 IoT core library, which was a port of Gralin’s netMF library and over the last 8 years the library has collected some “baggage” so I’m thinking about doing a V2 version.

Yes, I know it’s a stupid idea to start again but with covid-19 things have been a bit quiet.

@KiwiBryn

4 Likes

A few months back, I think it was around June I spotted your work on getting the tinyCLR dev boards working with the nrf24L001 so figured I had a couple that I’ve used with MSP430’s and Arduinos just fine, but for the life of me I couldn’t get them communicating with the SC20100 connected to a nrf trx device. Mind you I don’t have a MikroBus device, so I had to wire it through the pins on the nrf device that I have. Would love to know if there are any pointers in terms of debugging on this. I believe I have it all connected correctly as the moduleSPI program seemed to work(output wise).

Hi voodoopanda

What device are you working with?

I would start with the ModuleSPI code in the github repo (have just added config for the port on the Fezportal and both on the SC20100 dev) with that you should be able to check your SPI port configuration.

Your SPI port setup (MISO, MOSI, CS & SCLK pins) is most probably good if the output looks like below…

The length setting is most obvious one it should be 5.

The thread ‘’ (0x2) has exited with code 0 (0x0).
nrf24L01Device Device…
ConfigureSpiPort Done…

Read address width
nrf24L01Device.TransferFullDuplex…SETUP_AW
txBuffer:03-00
rxBuffer:0E-03
Address width 0x03 - Value 0X03 Value adjusted 5

Write Pipe0 Receive Address ZYXWV
nrf24L01Device.Write…RX_ADDR_P0
txBuffer:2A-5A-59-58-57-56

Read Pipe0 Receive address
nrf24L01Device.TransferFullDuplex…RX_ADDR_P0
txBuffer:0A-00-00-00-00-00
rxBuffer:0E-5A-59-58-57-56
Address 0x0a Address ZYXWV

RF Channel read 1
nrf24L01Device.TransferFullDuplex…RF_CH
txBuffer:05-00
rxBuffer:0E-02
RF Channel 1 0x05 - Value 0X02 - Value adjusted 2402

RF Channel write
nrf24L01Device.Write…RF_CH
txBuffer:25-03

RF Channel read 2
nrf24L01Device.TransferFullDuplex…RF_CH
txBuffer:05-00
rxBuffer:0E-03
RF Channel 2 0x05 - Value 0X03 - Value adjusted 2403

If that is ok, I would then fire up the TinyCLRV2nRF24Client and put a breakpoint on the while(true) around line 85 and check that the configuration read back matches what is set (try changing the power level).

        Debug.WriteLine($"Address: {Encoding.UTF8.GetString(radio.Address)}");
        Debug.WriteLine($"PowerLevel: {radio.PowerLevel}");
        //....
        Debug.WriteLine($"IsInitialized: {radio.IsInitialized}");
        Debug.WriteLine($"IsPowered: {radio.IsPowered}");

If that works then your chip enable(CE) config is most probably good.

If you’re not getting any Radio_OnDataReceived, Radio_OnTransmitSuccess or Radio_OnTransmitFailed notifications then it’s most probably the interrupt pin config.

That’s how I would debug setup…

Other users might find this useful so i’ll add it to the Github readme

@KiwiBryn

@Bryn_Lewis

So the output values on the Modulespi program were pretty much spot on. I had changed the values for RF_CH and P0_Address to match the ones that I used for the client program.

On the client, I included the result of the status method as well.and values.
This is the setup.

    private const string BaseStationAddress = "NODE1";
    private const string DeviceAddress = "NODE2";

//
radio.Address = Encoding.UTF8.GetBytes(DeviceAddress);
Debug.WriteLine($“Status: {radio.GetStatus()}”);

            radio.Channel = 0x78;
        //radio.PowerLevel = PowerLevel.Max;
        //radio.PowerLevel = PowerLevel.High;
        radio.PowerLevel = PowerLevel.Low;
            //radio.PowerLevel = PowerLevel.Minimum;
            radio.DataRate = DataRate.DR250Kbps;
        //radio.DataRate = DataRate.DR1Mbps;
        //radio.DataRate = DataRate.DR2Mbps;
        radio.IsEnabled = true;
        radio.SetAddress(AddressSlot.One, Encoding.UTF8.GetBytes(BaseStationAddress)); //I tried to set this as the DataPipe shows 7 which doesn't seem correct.
        radio.IsAutoAcknowledge = true;
        radio.IsDyanmicAcknowledge = true;
        radio.IsDynamicPayload = true;

And the output.

Status: DataReady: False, DateSent: False, ResendLimitReached: False, TxFull: False, RxEmpty: True, DataPipe: 7, DataPipeNotUsed: False
Address: NODE2
PowerLevel: 1
IsAutoAcknowledge: True
Channel: 120
Frequency: 2520
DataRate: 2
IsDynamicAcknowledge: False
IsDynamicPayload: True
IsEnabled: False
IsInitialized: True
IsPowered: True
Status: DataReady: False, DateSent: False, ResendLimitReached: False, TxFull: False, RxEmpty: True, DataPipe: 7, DataPipeNotUsed: False

Note that DataPipe shows as 7…this isn’t quite making sense to me as to why it would be this value. I tried setting it to 1.

I’ll hook up the int pin to my LA and see if I see it blip.

Thanks for the assistance on this!

Forgot to add the device that I’m using but they look like these.
https://www.amazon.com/Aideepen-NRF24L01-Wireless-Transceiver-Compatible/dp/B07SGJ8CM5/ref=sr_1_9?dchild=1&keywords=nrf24l01&qid=1597860311&sr=8-9

Now, to be clear, I have some that I suspect are the Si24R1 but I also have a pair of legit nordic Trx devices that I also have tested and were unsuccessful with.

Hi

This is my testrig with GHI devices and Arduino compatible

With my setup like this

#if TINYCLR_V2_FEZPORTAL
      private const string BaseStationAddress = "NODE1";
      private const string DeviceAddress = "NODE2";
#endif
#if TINYCLR_V2_SC20100DEV_MIKROBUS_1
      private const string BaseStationAddress = "NODE2";
      private const string DeviceAddress = "NODE1";
#endif

#if TINYCLR_V2_FEZPORTAL
            radio.Initialize(SC20100.SpiBus.Spi3, SC20100.GpioPin.PD4, SC20100.GpioPin.PC13, SC20100.GpioPin.PC2);
#endif
            radio.Address = Encoding.UTF8.GetBytes(DeviceAddress);

            //radio.Channel = 15;
            radio.Channel = 0x78;
            //radio.PowerLevel = PowerLevel.Max;
            //radio.PowerLevel = PowerLevel.High;
            radio.PowerLevel = PowerLevel.Low;
            //radio.PowerLevel = PowerLevel.Minimum;
            radio.DataRate = DataRate.DR250Kbps;
            //radio.DataRate = DataRate.DR1Mbps;
            //radio.DataRate = DataRate.DR2Mbps;
            radio.IsEnabled = true;

            radio.IsAutoAcknowledge = true;
            radio.IsDyanmicAcknowledge = false;
            radio.IsDynamicPayload = true;

I could receive messages from my devDuino configured like this

// nRF24L01 ISM wireless module setup
RF24 radio(7,6);
char payload[] = "devDuino";
const byte FieldGatewayAddress[5] = "NODE1";
const byte FieldGatewayChannel = 0x78 ;
const rf24_pa_dbm_e RadioPALevel = RF24_PA_MAX;
const rf24_datarate_e RadioDataRate = RF24_250KBPS; 

const int LoopSleepDelay = 5000 ;
 
void setup()
{
  Serial.begin(9600);
  Serial.println("Setup called");

  // Configure the nRF24 module
  Serial.println("nRF24 setup");
  radio.begin();
  radio.setPALevel(RadioPALevel);
  radio.setDataRate(RadioDataRate) ;
  radio.setChannel(FieldGatewayChannel);
  radio.enableDynamicPayloads();
  radio.openWritingPipe(FieldGatewayAddress);
 
  delay(5000);
 
  Serial.println("Setup done");
}
 
void loop()
{
  Serial.println("Loop called");

  // Powerup the nRF24 chipset then send the payload to base station
  radio.powerUp();
  delay(500);
 
  Serial.println( "nRF24 write" ) ;
  boolean result = radio.write(payload, sizeof(payload));
  if (result)
    Serial.println("Write Ok...");
  else
    Serial.println("Write failed.");
 
 Serial.println( "nRF24 power down" ) ;
 radio.powerDown();
 
 delay(LoopSleepDelay);
}

Most probably something todo with the pipe setup, don’t have time to drill deeper this AM will have a look this PM. Vague memory it’s something todo with multicasting…

@KiwiBryn

1 Like

Awesome! that got me receiving data from the Devduino code. This should give me a starting point to hopefully get the MSP430’s working.

So far I’ve noted two issue with my original code that had an affect on this working. One was how I was defining the address. The other was a crc setting which I know I had set when testing this a while back.

hopefully now I can get some 2 way communication going!

Thanks for the help!

Some interesting data while letting things run for a bit as a test…
At a certain point, the datapipe switched to 0…

00:32:16-RX Hex Length 4 Payload 31-34-36-39
00:32:16-RX Unicode Length 4 Unicode text 1469
00:32:19-RX Hex Length 4 Payload 31-34-36-39
00:32:19-RX Unicode Length 4 Unicode text 1469
00:32:20-TX 9 byte message hello 128
Status: DataReady: False, DateSent: False, ResendLimitReached: False, TxFull: False, RxEmpty: True, DataPipe: 7, DataPipeNotUsed: False
00:32:20-TX failed!
00:32:22-RX Hex Length 4 Payload 31-34-36-39
00:32:22-RX Unicode Length 4 Unicode text 1469
00:32:25-TX 9 byte message hello 127
Status: DataReady: False, DateSent: False, ResendLimitReached: False, TxFull: False, RxEmpty: True, DataPipe: 7, DataPipeNotUsed: False
00:32:25-TX failed!
00:32:30-TX 9 byte message hello 126
Status: DataReady: True, DateSent: False, ResendLimitReached: False, TxFull: False, RxEmpty: False, DataPipe: 0, DataPipeNotUsed: False
00:32:35-TX 9 byte message hello 125
Status: DataReady: True, DateSent: False, ResendLimitReached: True, TxFull: False, RxEmpty: False, DataPipe: 0, DataPipeNotUsed: False
00:32:40-TX 9 byte message hello 124
Status: DataReady: True, DateSent: False, ResendLimitReached: True, TxFull: True, RxEmpty: False, DataPipe: 0, DataPipeNotUsed: False
00:32:45-TX 9 byte message hello 123
Status: DataReady: True, DateSent: False, ResendLimitReached: True, TxFull: True, RxEmpty: False, DataPipe: 0, DataPipeNotUsed: False

Just for completeness, you can have a look at the driver we provide for this chip : nRF Click driver.
Sample code also available here.

Credits for this driver go to Jakub Bartkowiak (Gralin).

Hi all,

The design of the Gralin library was “inspired” by one of the popular Arduino libraries. Techfooninja then ported (though I sometimes wonder if he started with mfNordic library) it to Windows 10 IoT Core. Then I have ported it to Meadow, nanoFramework & TinyCLR.

The core of the implementation is quite “arduinoy”(can’t think of a better term) and over the last 9 years cruft has accumulated.

As per my initial post I was thinking about starting again and doing a version that could be built for the embedded .Net platforms TinyCLR, Meadow, nanoFramework, Windows 10 IoT Core (not like anyone cares) and .Net Core on *nix.

I know starting again from scratch is a usually a dumb idea, but after a number of ports and debugging issues I have a plan…

Would anyone be interested in helping with testing etc.

@KiwiBryn

2 Likes

I understand and I agree. But not completely :wink:

The only thing I would disagree with is to make some kind of “universal driver”. Each OS has its own particularities and dealing with those in a single driver may either complicate it or make it bigger than needed.
Although size does not matter here (for once :slight_smile: ) , since we have plenty of memory. But still.

Other than that, I am ready to help. No problem.