Using SPI1 or SPI2 in Radiohead library

kets

Active member
Hi,

I would like to use SPI1 or SPI2 together with Radioheads RH_RF69 library to avoid my hanging problems.
How do I setup my code to do that?
Do I have to change something in the library code?

I'm using T3.5 or T4.0

Grateful for help.
 
It has been awhile since I did it, but there is some support for this at least in the Teensyduino installed version.

I played with this a few years ago. Note I am am using RF95, but assume would be the same... And I did it on SPI1, but did add it for SPI2 as well.

In my sketch I had:
Code:
#include <RHDatagram.h>
#include <RH_RF95.h>
#include <RHHardwareSPI1.h>
...
RH_RF95 rf95(RFM95_CS, RFM95_INT, hardware_spi1);

// Class to manage message delivery and receipt, using the driver declared above
RHDatagram manager(rf95, WM_MASTER_NODE);

Edit:
I also note I may not have used standard SPI1 pins so my code also had:
Code:
SPI1.setMISO(RFM95_MISO);
  SPI1.setMOSI(RFM95_MOSI);
  SPI1.setSCK(RFM95_SCK);

And I ran this on T3.5 or T3.6 but I believe I also tested it later on T4
 
Just taking a quick look at the examples and the lib for the RH_RF69 looks like you can specify SPI1 or SPI1 (default is SPI). For instance, from the rf69_tx_demo.ino in the Teensy example folder:
Code:
//For Teensy 3.x and T4.x the following format is required to operate correctly
//This is a limitation of the RadioHead radio drivers
#define RFM69_RST     3
#define RFM69_CS      10
#define RFM69_INT     digitalPinToInterrupt(2)

// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS,RFM69_INT);
. This is setting up the lib to use SPI but from the library RH_RF69.h the constructor has another element you can specify (the SPI port):
Code:
    /// \param[in] spi Pointer to the SPI interface object to use. 
    ///                Defaults to the standard Arduino hardware SPI interface
    RH_RF69(uint8_t slaveSelectPin = SS, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
so if you want to use SPI1 say with out example:

Code:
//For Teensy 3.x and T4.x the following format is required to operate correctly
//This is a limitation of the RadioHead radio drivers
#define RFM69_RST     3
#define RFM69_CS      10
#define RFM69_INT     digitalPinToInterrupt(2)

[B][COLOR="#FF0000"]#include <RHHardwareSPI1.h>[/COLOR][/B]

// Singleton instance of the radio driver
[COLOR="#FF0000"][B]RH_RF69 rf69(RFM69_CS,RFM69_INT, hardware_spi1);[/B][/COLOR]

The changes are highlighted in red. First you need to include the driver:
Code:
#include <RHHardwareSPI1.h
then update the constructor to tell it to use spi1:
Code:
RH_RF69 rf69(RFM69_CS,RFM69_INT, hardware_spi1);
 
I have tested with your suggestions on Teensy 3.5
The setup works OK with normal SPI on pins 10,11,12,13

I have skifted to pins: 0,1,31,32 according to T3.5 spec.


#include <RH_RF69.h> //Radiohead
#include <RHHardwareSPI1.h>

#define RFM69_RST 24
#define RFM69_CS 31
#define RFM69_INT digitalPinToInterrupt(25)

// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS,RFM69_INT,hardware_spi1);

....

void setup() {
Serial.begin(9600);

delay(500);


//For Teensy 3.x and T4.x the following format is required to operate correctly
pinMode(RFM69_RST, OUTPUT);

digitalWrite(RFM69_RST, LOW);
delay(100);

Serial.println("Midi interface med trådlös modul RFM69HCW!");

digitalWrite(RFM69_RST, HIGH);
delay(100);
digitalWrite(RFM69_RST, LOW);
delay(100);

//SPI1.setMISO(1);
//SPI1.setMOSI(0);
//SPI1.setSCK(32);

if (!rf69.init())
Serial.println("init failed");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
// No encryption
if (!rf69.setFrequency(868.0))
Serial.println("setFrequency failed");

// If you are using a high power RF69, you *must* set a Tx power in the
// range 14 to 20 like this:
rf69.setTxPower(14);
//rf69.setEncryptionKey((uint8_t*)ENCRYPTKEY);


Unfortunately I get "init failed"

Is there a way of testing?
 
Maybe try SPI1.begin();
Just before the call to the rf69.init?

Otherwise maybe need to add debug code to the init function and find out where it is failing.
 
Found my RF69HCW radio from Adafruit (https://www.adafruit.com/product/3070) and ran the sketch the modified rf69_tx_demo sketch that I mentioned but configured for SPI and I can't seem to duplicate your error about not initializing the radio:
Code:
RFM69 radio init OK!
RFM69 radio @434 MHz
Sending Hello World #0
No reply, is another RFM69 listening?
The radio is initializing. I didn't hook up the receiving one that is why the no reply message. Below is the exact sketch I am using. Would start by checking your wiring - maybe you have MISO/MOSI backwards - I have done that a number of times

Code:
// rf69 demo tx rx.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing client
// with the RH_RF69 class. RH_RF69 class does not provide for addressing or
// reliability, so you should only use RH_RF69  if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf69_server.
// Demonstrates the use of AES encryption, setting the frequency and modem 
// configuration

#include <SPI.h>
#include <RH_RF69.h>
#include <RHHardwareSPI1.h>

/************ Radio Setup ***************/

// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 434.0

//For Teensy 3.x and T4.x the following format is required to operate correctly
//This is a limitation of the RadioHead radio drivers
#define RFM69_RST 24
#define RFM69_CS 31
#define RFM69_INT digitalPinToInterrupt(25)

// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS,RFM69_INT, hardware_spi1);
//----- END TEENSY CONFIG

int16_t packetnum = 0;  // packet counter, we increment per xmission

void setup() 
{
  Serial.begin(115200);
  //while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer

  //For Teensy 3.x and T4.x the following format is required to operate correctly
  //pinMode(LED, OUTPUT);     
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, LOW);

  Serial.println("Feather RFM69 TX Test!");
  Serial.println();

  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);
  //----- END TEENSY CONFIG

  if (!rf69.init()) {
    Serial.println("RFM69 radio init failed");
    while (1);
  }
  Serial.println("RFM69 radio init OK!");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ)) {
    Serial.println("setFrequency failed");
  }

  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  rf69.setTxPower(20);  // range from 14-20 for power, 2nd arg must be true for 69HCW

  // The encryption key has to be the same as the one in the server
  uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);
  
  //pinMode(LED, OUTPUT);

  Serial.print("RFM69 radio @");  Serial.print((int)RF69_FREQ);  Serial.println(" MHz");
}



void loop() {
  delay(1000);  // Wait 1 second between transmits, could also 'sleep' here!

  char radiopacket[20] = "Hello World #";
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);
  
  // Send a message!
  rf69.send((uint8_t *)radiopacket, strlen(radiopacket));
  rf69.waitPacketSent();

  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf69.waitAvailableTimeout(500))  { 
    // Should be a reply message for us now   
    if (rf69.recv(buf, &len)) {
      Serial.print("Got a reply: ");
      Serial.println((char*)buf);
      //Blink(LED, 50, 3); //blink LED 3 times, 50ms between blinks
    } else {
      Serial.println("Receive failed");
    }
  } else {
    Serial.println("No reply, is another RFM69 listening?");
  }
}

void Blink(byte PIN, byte DELAY_MS, byte loops) {
  for (byte i=0; i<loops; i++)  {
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
    delay(DELAY_MS);
  }
}
 
No that did not help.
I have started to debug the library with a LED.

It fails in RHHardwareSPI1.cpp:

uint8_t RHHardwareSPI1::transfer(uint8_t data)
{
return SPI1.transfer(data);
}

It's called from RHSPIdriver.cpp:

uint8_t RHSPIDriver::spiRead(uint8_t reg)
{
uint8_t val;
ATOMIC_BLOCK_START;
_spi.beginTransaction();
digitalWrite(_slaveSelectPin, LOW);
_spi.transfer(reg & ~RH_SPI_WRITE_MASK); // Send the address with the write mask off
val = _spi.transfer(0); // The written value is ignored, reg value is read
digitalWrite(_slaveSelectPin, HIGH);
_spi.endTransaction();
ATOMIC_BLOCK_END;
return val;
}

which is called from RH_RF69.cpp:

_deviceType = spiRead(RH_RF69_REG_10_VERSION);
if (_deviceType == 00 ||
_deviceType == 0xff)
return false;


This returns 00

Am I using the correct pins for SPI1?

/Tomas
 
The pins look correct but as I mentioned are hooked up correctly to the Teensy 3.5

For SPI1:
Code:
sck -> pin 32 
cs -> pin 31
miso -> pin 1
mosi -> pin 0

then of course you have:
Code:
#define RFM69_RST 24
#define RFM69_CS 31
#define RFM69_INT digitalPinToInterrupt(25)
 
Thanks for all your help.
It was off cause my wireing that was the problem.
It was not MOSI/MISO that was switched. I had mirrored the whole Teensy
so 31 became 34 and so on. No wonder nothing worked.

Now it's up and running.
 
Thanks for all your help.
It was off cause my wireing that was the problem.
It was not MOSI/MISO that was switched. I had mirrored the whole Teensy
so 31 became 34 and so on. No wonder nothing worked.

Now it's up and running.

Cool glad thats all it was.
 
Hi, I hope someone can help me out here. I need NRF24 on SPI1, because I have an ethernet on SPI.
Below my code (simplified). From as soon as I add
RH_NRF24 nrf24(4,5,hardware_spi1);
I get tons of errors.
When I use
RH_NRF24 nrf24(4,5);
All works fine, but that is on SPI.
Other question, how do I add code in this forum in those nice boxes?
Thanks in advance,
Olivier

Code:
#include <SPI.h>
#include <RH_NRF24.h>
#include <RHHardwareSPI1.h>
RH_NRF24 nrf24(4,5,hardware_spi1);  //  CE pin, CSN pin


void setup() {
	Serial.begin(115200);
  Serial.println("start");
  if (!nrf24.init())
    Serial.println("init failed");
  if (!nrf24.setChannel(110))
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed"); 
}


void loop() {
}
 
Last edited by a moderator:
Select the text and use the # button on toolbar... On other forums the button might look like <>

Which teensy are you building for? Which Arduino version? Teensyduino version?

What are the errors? I did a cut and paste, and it built for me, for T4.1
 
Back
Top