nRF24L01-TinyCLR V2 RC2 on Github

The source code of RC2 of my port GHI Electronics TinyCLR-0SV2RC1 nRF24L01 library is live on GitHub. The sample application now supports Fezduino (with embeddedcoolness.com or other Arduino shield), Fezportal and the SC2010 Dev board (with mikroe nrf24C Click, mikroe nRF24S Click or mikroenRF24T Click) .

Fezduino with Embedded Coolness shield
Fezportal with Mikroe nRF24 C Click
SC20100 Dev board

The application has gained four compile time configuration options

  • TINYCLR_V2_SC20100DEV_MIKROBUS_1
  • TINYCLR_V2_SC20100DEV_MIKROBUS_2
  • TINYCLR_V2_FEZDUINO
  • TINYCLR_V2_FEZPORTAL

These options configure the chip enable, chip selected and interrupt pins.

//---------------------------------------------------------------------------------
// Copyright (c) May 2020, devMobile Software
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Need one of TINYCLR_V2_SC20100DEV_MIKROBUS_1/TINYCLR_V2_SC20100DEV_MIKROBUS_2/TINYCLR_V2_FEZDUINO/TINYCLR_V2_FEZPORTAL defined
//---------------------------------------------------------------------------------
namespace devMobile.IoT.FieldGateway.TinyCLRV2nRF24Client
{
   using System;
   using System.Diagnostics;
   using System.Text;
   using System.Threading;

   using GHIElectronics.TinyCLR.Pins;

   using Radios.RF24;

   class Program
   {
      private const string BaseStationAddress = "Base1";
      private const string DeviceAddress = "Dev01";

      static void Main()
      {
         RF24 radio = new RF24();
         byte messageCount = System.Byte.MaxValue;

         try
         {
            radio.OnDataReceived += Radio_OnDataReceived;
            radio.OnTransmitFailed += Radio_OnTransmitFailed;
            radio.OnTransmitSuccess += Radio_OnTransmitSuccess;

#if TINYCLR_V2_SC20100DEV_MIKROBUS_1
            radio.Initialize(SC20100.SpiBus.Spi3, SC20100.GpioPin.PD4, SC20100.GpioPin.PD3, SC20100.GpioPin.PC5);
#endif
#if TINYCLR_V2_SC20100DEV_MIKROBUS_2
            radio.Initialize(SC20100.SpiBus.Spi3, SC20100.GpioPin.PD15, SC20100.GpioPin.PD14, SC20100.GpioPin.PA8);
#endif
#if TINYCLR_V2_FEZDUINO
            radio.Initialize(SC20100.SpiBus.Spi6, SC20100.GpioPin.PE11, SC20100.GpioPin.PC4, SC20100.GpioPin.PA1);
#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.PowerLevel = PowerLevel.Minimum;
            radio.DataRate = DataRate.DR250Kbps;
            radio.IsEnabled = true;

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

            Debug.WriteLine($"Address: {Encoding.UTF8.GetString(radio.Address)}");
            Debug.WriteLine($"PowerLevel: {radio.PowerLevel}");
            Debug.WriteLine($"IsAutoAcknowledge: {radio.IsAutoAcknowledge}");
            Debug.WriteLine($"Channel: {radio.Channel}");
            Debug.WriteLine($"DataRate: {radio.DataRate}");
            Debug.WriteLine($"IsDynamicAcknowledge: {radio.IsDyanmicAcknowledge}");
            Debug.WriteLine($"IsDynamicPayload: {radio.IsDynamicPayload}");
            Debug.WriteLine($"IsEnabled: {radio.IsEnabled}");
            Debug.WriteLine($"Frequency: {radio.Frequency}");
            Debug.WriteLine($"IsInitialized: {radio.IsInitialized}");
            Debug.WriteLine($"IsPowered: {radio.IsPowered}");

            while (true)
            {
               string payload = $"hello {messageCount}";
               messageCount -= 1;

               Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-TX {payload.Length} byte message {payload}");
               radio.SendTo(Encoding.UTF8.GetBytes(BaseStationAddress), Encoding.UTF8.GetBytes(payload));

               Thread.Sleep(30000);
            }
         }
         catch (Exception ex)
         {
            Debug.WriteLine(ex.Message);
         }
      }

      private static void Radio_OnDataReceived(byte[] data)
      {
         // display as hex
         Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-RX Hex Length {data.Length} Payload {BitConverter.ToString(data)}");

         // Display as Unicode
         string unicodeText = Encoding.UTF8.GetString(data);
         Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-RX Unicode Length {unicodeText.Length} Unicode text {unicodeText}");
      }

      private static void Radio_OnTransmitSuccess()
      {
         Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-TX Succeeded!");
      }

      private static void Radio_OnTransmitFailed()
      {
         Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-TX failed!");
      }
   }
}

TinyCLR OS V2 RC1 LoRa library Part4

Interrupts Revisited

In my last post I had two approaches for fixing the issue with transmit interrupts. As I was sorting out the configuration for my Fezportal device and SS20100 Dev board(both sockets) with a Cascologix MikroBus LoRa click I had similar issues with both receive and transmit.

SC20100 Dev Rev A with Cascologix Click in socket1
Fezportal with Cascologix click

I noticed the extra RegIrqFlags 0X58, Receive-Message in the debugging output.

The thread '<No Name>' (0x2) has exited with code 0 (0x0).
Sending 13 bytes message Hello LoRa 1!
RegIrqFlags 0X08
Transmit-Done
Sending 13 bytes message Hello LoRa 2!
RegIrqFlags 0X08
Transmit-Done
RegIrqFlags 0X58
Receive-Message
Received 23 byte message  �LoRaIoT1N3WT 20.5,H 86
Transmit-Done
Sending 13 bytes message Hello LoRa 3!
RegIrqFlags 0X08
Transmit-Done

This was with the modified device write methods so I tried changing the Serial Peripheral Interface(SPI) configuration.

public RegisterManager(string spiPortName,  int chipSelectPin, int clockFrequency = 500000)
{
	GpioPin chipSelectGpio = GpioController.GetDefault().OpenPin(chipSelectPin);

	var settings = new SpiConnectionSettings()
	{
		ChipSelectType = SpiChipSelectType.Gpio,
		ChipSelectLine = chipSelectGpio,
		Mode = SpiMode.Mode0,
		ClockFrequency = clockFrequency,
		ChipSelectActiveState = false,
		ChipSelectHoldTime = new TimeSpan(1),
	};

	SpiController spiController = SpiController.FromName(spiPortName);

	rfm9XLoraModem = spiController.GetDevice(settings);
}

When I added the ChipSelectHoldTime (even the smallest possible one) the code worked as expected.

The thread '' (0x2) has exited with code 0 (0x0).
Sending 13 bytes message Hello LoRa 1!
RegIrqFlags 0X08
Transmit-Done
Sending 13 bytes message Hello LoRa 2!
RegIrqFlags 0X08
Transmit-Done
RegIrqFlags 0X50
Receive-Message
Received 23 byte message �LoRaIoT1N3WT 20.5,H 87
Sending 13 bytes message Hello LoRa 3!
RegIrqFlags 0X08
Transmit-Done
Sending 13 bytes message Hello LoRa 4!
RegIrqFlags 0X08
Transmit-Done

At this point I have run out of ideas so I will release the code this fix.