RFM69 hat library Part4C

Transmit Basic: Rasmatic/RFM69-Arduino-Library

While I was searching for a suitable library on GitHub I downloaded the RFM-Arduino-Library by Rasmatic which had a link to sample library on the HopeRF website which I also downloaded.

/*
@author Tadeusz Studnik https://rasmatic.pl

MIT License
...

This library is a port of HopeRF's library:

https://www.hoperf.com/data/upload/back/20181122/HoepRF_HSP_V1.3.rar
*/

I made the minimum possible modifications to the C/C++ code to get it to compile, then to run on my Arduino Nano Radio Shield RFM69/95 device. I had to change the RFM69 DIO pin mode, the SPI config, and I added a method to dump all the registers.

/**********************************************************
**Name:     vInitialize
**Function: initialize rfm69 or rfm69c
**Input:    none
**Output:   none
**********************************************************/
void RMRFM69::vInitialize(void)
{
	pinMode (_csPin, OUTPUT);
	pinMode (_rstPin, OUTPUT);
	pinMode (_dio0Pin, INPUT_PULLDOWN); // Changed from INPUT_PULLDOWN

	digitalWrite(_csPin, HIGH);
	digitalWrite(_rstPin, LOW);
	
	vSpiInit();
	
	//�˿ڳ�ʼ�� for 32MHz
	FrequencyValue.Freq = (Frequency << 11) / 125; //Calc. Freq
	BitRateValue = (SymbolTime << 5) / 1000;	   //Calc. BitRate
	DevationValue = (Devation << 11) / 125;		   //Calc. Fdev
	BandWidthValue = bSelectBandwidth(BandWidth);

	vConfig();
	vGoStandby();
}
/**********************************************************
**Name:     vSpiInit
**Function: init SPI
**Input:    none
**Output:   none
**********************************************************/
void RMRFM69::vSpiInit()
{
	digitalWrite(_csPin, HIGH);
//	_spiPort-&gt;setFrequency(1000000); 
	_spiPort-&gt;setBitOrder(MSBFIRST);
	_spiPort-&gt;setDataMode(SPI_MODE0);
	_spiPort-&gt;begin();

}

void RMRFM69::dumpRegisters(Stream&amp; out)
{
  for (int i = 0; i <= 0x3d; i++) {
    out.print("0x");
    out.print(i, HEX);
    out.print(": 0x");
    out.println(this-&gt;bSpiRead(i), HEX);
  }
}

I created an application based on the RFM69-ESP32-arduino-example which received messages.

#include <SPI.h&gt;
#include <RMRFM69.h&gt;

RMRFM69 radio(SPI, 10, 2, 9);

void setup() 
{
  Serial.begin(9600);
  
  radio.Modulation     = FSK;
  radio.COB            = RFM69;
  radio.Frequency      = 915000;
  radio.OutputPower    = 10+18;          //10dBm OutputPower
  radio.PreambleLength = 16;             //16Byte preamble
  radio.FixedPktLength = false;          //packet in message which need to be send
  radio.CrcDisable     = false;          //CRC On
  radio.AesOn          = false;
  radio.SymbolTime     = 416000;         //2.4Kbps
  radio.Devation       = 35;             //35KHz for devation
  radio.BandWidth      = 100;            //100KHz for bandwidth
  radio.SyncLength     = 3;              //
  radio.SyncWord[0]    = 0xAA;
  radio.SyncWord[1]    = 0x2D;
  radio.SyncWord[2]    = 0xD4;

  radio.vInitialize();

  radio.dumpRegisters(Serial);
  radio.vGoRx();

  Serial.println("Start RX...");
}

void loop() 
{
  char messageIn[128] = {""};
  byte messageOut[] = {"Hello world"};

  if(radio.bGetMessage(messageIn)!=0)
  { 
    Serial.print("MessageIn:");
    Serial.print(messageIn);
    Serial.println();
  }    
}

The application started up after I sorted out the RFM69 chip select, interrupt and reset pin numbers.

20:03:56.574 -> 0x0: 0x0
20:03:56.608 -> 0x1: 0x4
20:03:56.608 -> 0x2: 0x0
20:03:56.608 -> 0x3: 0x34
20:03:56.643 -> 0x4: 0x0
20:03:56.643 -> 0x5: 0x2
20:03:56.643 -> 0x6: 0x3D
20:03:56.643 -> 0x7: 0xE4
20:03:56.677 -> 0x8: 0xC0
20:03:56.677 -> 0x9: 0x0
20:03:56.677 -> 0xA: 0x41
20:03:56.710 -> 0xB: 0x40
20:03:56.710 -> 0xC: 0x2
20:03:56.710 -> 0xD: 0x92
20:03:56.745 -> 0xE: 0xF5
20:03:56.745 -> 0xF: 0x20
20:03:56.745 -> 0x10: 0x24
20:03:56.779 -> 0x11: 0x9C
20:03:56.779 -> 0x12: 0x5
20:03:56.813 -> 0x13: 0xF
20:03:56.813 -> 0x14: 0x40
20:03:56.813 -> 0x15: 0xB0
20:03:56.846 -> 0x16: 0x7B
20:03:56.846 -> 0x17: 0x9B
20:03:56.846 -> 0x18: 0x88
20:03:56.880 -> 0x19: 0x2A
20:03:56.880 -> 0x1A: 0x2A
20:03:56.880 -> 0x1B: 0x78
20:03:56.880 -> 0x1C: 0x80
20:03:56.914 -> 0x1D: 0x6
20:03:56.914 -> 0x1E: 0x10
20:03:56.947 -> 0x1F: 0x0
20:03:56.947 -> 0x20: 0x0
20:03:56.947 -> 0x21: 0x0
20:03:56.981 -> 0x22: 0x0
20:03:56.981 -> 0x23: 0x2
20:03:56.981 -> 0x24: 0xFF
20:03:57.015 -> 0x25: 0x0
20:03:57.015 -> 0x26: 0xF7
20:03:57.049 -> 0x27: 0x80
20:03:57.049 -> 0x28: 0x0
20:03:57.049 -> 0x29: 0xFF
20:03:57.083 -> 0x2A: 0x0
20:03:57.083 -> 0x2B: 0x0
20:03:57.083 -> 0x2C: 0x0
20:03:57.118 -> 0x2D: 0x10
20:03:57.118 -> 0x2E: 0x90
20:03:57.152 -> 0x2F: 0xAA
20:03:57.152 -> 0x30: 0x2D
20:03:57.152 -> 0x31: 0xD4
20:03:57.152 -> 0x32: 0x0
20:03:57.186 -> 0x33: 0x0
20:03:57.186 -> 0x34: 0x0
20:03:57.186 -> 0x35: 0x0
20:03:57.219 -> 0x36: 0x0
20:03:57.219 -> 0x37: 0x90
20:03:57.219 -> 0x38: 0x40
20:03:57.253 -> 0x39: 0x0
20:03:57.253 -> 0x3A: 0x0
20:03:57.253 -> 0x3B: 0x0
20:03:57.288 -> 0x3C: 0x1
20:03:57.288 -> 0x3D: 0x0
20:03:57.322 -> Start RX...

I then manually set the RFM69HCW Radio Bonnet registers to match the Arduino device.

public sealed class StartupTask : IBackgroundTask
{
	private const int ChipSelectLine = 1;
	private const int ResetLine = 25;
	private Rfm69HcwDevice rfm69Device = new Rfm69HcwDevice(ChipSelectLine, ResetLine);

	const double RH_RF6M9HCW_FXOSC = 32000000.0;
	const double RH_RFM69HCW_FSTEP = RH_RF6M9HCW_FXOSC / 524288.0;

	const byte NetworkID = 100;
	const byte NodeAddressFrom = 0x03;
	const byte NodeAddressTo = 0x02;

	public void Run(IBackgroundTaskInstance taskInstance)
	{
		//rfm69Device.RegisterDump();

		// regOpMode standby
		rfm69Device.RegisterWriteByte(0x01, 0b00000100);

		// BitRate MSB/LSB
		rfm69Device.RegisterWriteByte(0x03, 0x34);
		rfm69Device.RegisterWriteByte(0x04, 0x00);

		// Frequency deviation
		rfm69Device.RegisterWriteByte(0x05, 0x02);
		rfm69Device.RegisterWriteByte(0x06, 0x3d);
			
		// Calculate the frequency accoring to the datasheett
		byte[] bytes = BitConverter.GetBytes((uint)(915000000.0 / RH_RFM69HCW_FSTEP));
		Debug.WriteLine("Byte Hex 0x{0:x2} 0x{1:x2} 0x{2:x2} 0x{3:x2}", bytes[0], bytes[1], bytes[2], bytes[3]);
		rfm69Device.RegisterWriteByte(0x07, bytes[2]);
		rfm69Device.RegisterWriteByte(0x08, bytes[1]);
		rfm69Device.RegisterWriteByte(0x09, bytes[0]);

		// RegRxBW
		rfm69Device.RegisterWriteByte(0x19, 0x55);
		// RegAfcBw
		rfm69Device.RegisterWriteByte(0x1A, 0x8b);
		// RegOokPeak
		rfm69Device.RegisterWriteByte(0x1B, 0x40);

		// Setup preamble length to 16 (default is 3)
		rfm69Device.RegisterWriteByte(0x2C, 0x0);
		rfm69Device.RegisterWriteByte(0x2D, 0x10);
	
		// Set the Sync length and byte values SyncOn + 3 custom sync bytes
		rfm69Device.RegisterWriteByte(0x2e, 0x90);

		rfm69Device.RegisterWriteByte(0x2f, 0xAA);
		rfm69Device.RegisterWriteByte(0x30, 0x2D);
		rfm69Device.RegisterWriteByte(0x31, 0xD4);

		// RegPacketConfig1 changed for Variable length after 9:00PM vs 10:00PM fail
		rfm69Device.RegisterWriteByte(0x37, 0x90);
		//rfm69Device.RegisterWriteByte(0x38, 0x14);

		rfm69Device.RegisterDump();
	
		while (true)
		{
			// Standby mode while loading message into FIFO
			rfm69Device.RegisterWriteByte(0x01, 0b00000100);
			byte[] messageBuffer = UTF8Encoding.UTF8.GetBytes(" hello world " + DateTime.Now.ToLongTimeString());
			messageBuffer[0] = (byte)messageBuffer.Length;
			rfm69Device.RegisterWrite(0x0, messageBuffer);

			// Transmit mode once FIFO loaded
			rfm69Device.RegisterWriteByte(0x01, 0b00001100);

			// Wait until send done, no timeouts in PoC
			Debug.WriteLine("Send-wait");
			byte IrqFlags = rfm69Device.RegisterReadByte(0x28); // RegIrqFlags2
			while ((IrqFlags & 0b00001000) == 0)  // wait until TxDone cleared
			{
				Task.Delay(10).Wait();
				IrqFlags = rfm69Device.RegisterReadByte(0x28); // RegIrqFlags
				Debug.Write(".");
			}
			Debug.WriteLine("");

			// Standby mode while sleeping
			rfm69Device.RegisterWriteByte(0x01, 0b00000100);
			Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}Send-Done");
			Task.Delay(5000).Wait();
		}
	}
}

My Arduino device then started receiving messages from my Raspberry PI 3 running Windows 10 IoT Core.

20:03:57.288 -> 0x3C: 0x1
20:03:57.288 -> 0x3D: 0x0
20:03:57.322 -> Start RX...
20:03:58.648 -> MessageIn:hello world 8:03:58 PM
20:04:03.920 -> MessageIn:hello world 8:04:03 PM
20:04:09.161 -> MessageIn:hello world 8:04:09 PM
20:04:14.421 -> MessageIn:hello world 8:04:14 PM
20:04:19.662 -> MessageIn:hello world 8:04:19 PM
20:04:24.895 -> MessageIn:hello world 8:04:24 PM
20:04:30.139 -> MessageIn:hello world 8:04:30 PM
20:04:35.392 -> MessageIn:hello world 8:04:35 PM
20:04:40.637 -> MessageIn:hello world 8:04:40 PM
20:04:45.890 -> MessageIn:hello world 8:04:45 PM
20:04:51.158 -> MessageIn:hello world 8:04:51 PM

Transmit is working! Though it’s starting to look like I might have to create my own lightweight Arduino RFM69HCW library “inspired” by the Arduino-LoRa library.

One thought on “RFM69 hat library Part4C

  1. Pingback: RFM69 hat library Part7 | devMobile's blog

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.