.Net Meadow RFM95/96/97/98 LoRa library Part1

After writing Windows 10 IoT Core & .NetMF RFM9X libraries I figured a port to a Wilderness Labs Meadow device shouldn’t be “rocket science”.

To get started I used a Dragino LoRa shield for Arduino which looked compatible with my Meadow device.

Dragino shield schematic

The shield ships with the SPI lines configured for ICSP so the three jumpers diagonally across the shield from the antenna connector need to be swapped to the side closest to the edge of the shield.

Dragino Arduino shield based test harness
//---------------------------------------------------------------------------------
// Copyright (c) Dec 2019, 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.
//
//---------------------------------------------------------------------------------
namespace devMobile.IoT.Rfm9x
{
   using System;
   using System.Threading.Tasks;
   using Meadow;
   using Meadow.Devices;
   using Meadow.Hardware;

   public class MeadowApp : App<F7Micro, MeadowApp>
   {
      const byte RegVersion = 0x42;
      ISpiBus spiBus;
      SpiPeripheral sx127xDevice;
      IDigitalOutputPort spiPeriphChipSelect;

      public MeadowApp()
      {
         ConfigureSpiPort();
         //ReadDeviceID();
         ReadDeviceIDDiy();
      }

      public void ConfigureSpiPort()
      {
         try
         {
            spiBus = Device.CreateSpiBus(500);
            if (spiBus == null)
            {
               Console.WriteLine("spiBus == null");
            }

            Console.WriteLine("Creating SPI NSS Port...");
            spiPeriphChipSelect = Device.CreateDigitalOutputPort(Device.Pins.D09);
            if (spiPeriphChipSelect == null)
            {
               Console.WriteLine("spiPeriphChipSelect == null");
            }
   
            Console.WriteLine("sx127xDevice Device...");
            sx127xDevice = new SpiPeripheral(spiBus, spiPeriphChipSelect);
            if (sx127xDevice == null)
            {
               Console.WriteLine("sx127xDevice == null");
            }

            Console.WriteLine("ConfigureSpiPort Done...");
         }
         catch (Exception ex)
         {
            Console.WriteLine("ConfigureSpiPort " + ex.Message);
         }
      }

      
      public void ReadDeviceID()
      {
         Task.Delay(500).Wait();

         while (true)
         {
            try
            {
               Console.WriteLine("sx127xDevice.ReadRegister...1");

               byte registerValue = sx127xDevice.ReadRegister(RegVersion);

               Console.WriteLine("sx127xDevice.ReadRegister...2");

               Console.WriteLine("Register 0x{0:x2} - Value 0X{1:x2} - Bits {2}", RegVersion, registerValue, Convert.ToString(registerValue, 2).PadLeft(8, '0'));
            }
            catch (Exception ex)
            {
               Console.WriteLine("ReadDeviceID " + ex.Message);
            }

            Task.Delay(10000).Wait();
         }
      }

      public void ReadDeviceIDDiy()
      {
         var txBuffer = new byte[2];
         var rxBuffer = new byte[2];

         Task.Delay(500).Wait();

         while (true)
         {
            try
            {
               Console.WriteLine("spiBus.ExchangeData...1");

               txBuffer[0] = RegVersion;

               spiBus.ExchangeData(spiPeriphChipSelect, ChipSelectMode.ActiveLow, txBuffer, rxBuffer, 2);

               Console.WriteLine("spiBus.ExchangeData...2");

               byte registerValue = rxBuffer[1];

               Console.WriteLine("Register 0x{0:x2} - Value 0X{1:x2} - Bits {2}", RegVersion, registerValue, Convert.ToString(registerValue, 2).PadLeft(8, '0'));
            }
            catch (Exception ex)
            {
               Console.WriteLine("ReadDeviceIDDiy " + ex.Message);
            }

            Task.Delay(10000).Wait();
         }
      }
   }
}

After some trial and error (using beta 3.6) I found that the ReadRegister method didn’t work as expected (possibly related to this issue) and I had to manually assemble the request to read the SX127X RegVersion register.

'App.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. 
'App.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\Users\BrynLewis\source\repos\RFX9X.Meadow\FeatherWingSPI\bin\Debug\net472\App.exe'. Symbols loaded.
'App.exe' (CLR v4.0.30319: App.exe): Loaded 'C:\Users\BrynLewis\source\repos\RFX9X.Meadow\FeatherWingSPI\bin\Debug\net472\Meadow.dll'. 
The program '[22324] App.exe: Program Trace' has exited with code 0 (0x0).
The program '[22324] App.exe' has exited with code 0 (0x0).
.
.
DirectRegisterAccess = True
==========================================================
Ignore the exceptions generated by the DateTime call here.
==========================================================
.
Creating SPI NSS Port...
sx127xDevice Device...
ConfigureSpiPort Done...
spiBus.ExchangeData...1
spiBus.ExchangeData...2
Register 0x42 - Value 0X12 - Bits 00010010
spiBus.ExchangeData...1
spiBus.ExchangeData...2
Register 0x42 - Value 0X12 - Bits 00010010
spiBus.ExchangeData...1
spiBus.ExchangeData...2
Register 0x42 - Value 0X12 - Bits 00010010
spiBus.ExchangeData...1
spiBus.ExchangeData...2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.