Teensy use multiple SPIs

Status
Not open for further replies.

Nazım

Member
I will use 2 Lora modules for communication in my project, but I don't know how to connect both of them to SPI0 and SPI1 pins at the same time, can you help?
 
Info is here.

Since in this implementation the maximum throughput is only 9.6kbps why not use one of these. Similar throughput but communicates vis UART with many drivers available.
 
Sorry, there is not enough information here to give many suggestions, other than the obvious.

With questions like this, it would be great if you would mention additional information, like: Which Teensy, Which LoRa module, yes you mentioned DRF... in second post, but is it the simple castellated board or some breakout board from someone like Sparkfun, Adafruit... What library are you wanting to use? Does it support you specifying which SPI port to use. What do you mean by at the same time?

Like how to hook them up? Again only thing I can say is hook up each LoRa pins to the right pins on the Teensy. Which I know is not very helpful. With all of the normal caveats, like again what voltage do the IO pins run on the module? If 5v and your teensy is not 5v tolerant than need level shifters. Power, you need to make sure you supply enough power to both modules...

Library I mentioned... Some libraries like RadioHead, have ways to pass in which SPI thing to use... Some are hard coded...

Same time? If you are saying you want both modules to be able to transmit and/or receive suff at the same time, never tried... Actually never tried hooking up two.... So don't know really much about things like will the signals of both of them interfere with the signals of the other one... Code Wise, I am sort of assuming that in a lot of cases most of these libraries, when you send or receive a packet, that the software will do the SPI transfers synchronously. Hopefully someone who actually uses these will give you more details.

Things like: do the radio chips/board have some form of Interrupt pin, that says, I have new data or the like and can you setup your code to when one of the two do this, to handle that one (respond or read or ...) and likewise for the other one. But again a lot of this may depend on the library and the like.

Good luck
 
The DRF1278F uses the SX1278 which works in master/slave (or many slaves) mode. Master transmits, slave(s) reply.
 
Let me put it this way, I am using the Radiolib library for the LoRa module (Dorji DRF1278F ). I am using teensy 3.6 in my project. I use MISO, MOSI, SCK pins used as hardware. I was planning how to use MISO1, MOSI1, SCK1 pins for other lora. I have no clue how to use this. I saw that a few sensors can be used over MISO, MOSI, SCK pins, but I don't know if communication modules can be used.
 
Nazım;286508 said:
Let me put it this way, I am using the Radiolib library for the LoRa module (Dorji DRF1278F ). I am using teensy 3.6 in my project. I use MISO, MOSI, SCK pins used as hardware. I was planning how to use MISO1, MOSI1, SCK1 pins for other lora. I have no clue how to use this. I saw that a few sensors can be used over MISO, MOSI, SCK pins, but I don't know if communication modules can be used.

Sorry I don't really know this library at all... First time I have heard of it.

Did download it.

First things I noticed, is that no where on github or the wiki or sources mention anything about supporting Teensy boards. However I did compile one of the examples for a T4 and it does build... So that is promising.

My quick look through the library, it does appear to have constructors for the Module class that allow you to pass through which SPI object to use.
Code:
    Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass& spi, SPISettings spiSettings);

So for example sketch that has:
Code:
// RF69 has the following connections:
// CS pin:    10
// DIO0 pin:  2
// RESET pin: 3
RF69 radio = new Module(10, 2, 3);
You could probably get the same results with:
Code:
// RF69 has the following connections:
// CS pin:    10
// DIO0 pin:  2
// RESET pin: 3
RF69 radio = new Module(10, 2, 3, SPI, SPISettings(2000000, MSBFIRST, SPI_MODE0));
So you could be able to create a radio1 and radio2 object using different pins, and different SPI object

Edit:
Meant to mention you might also be able to run both on the same SPI buss with using different IO pins for CS and IRQ and probably RST ...

however again I don't know how well this SPI object works with sharing especially the MISO pin
 
Nazım;286473 said:
I will use 2 Lora modules for communication in my project, but I don't know how to connect both of them to SPI0 and SPI1 pins at the same time, can you help?

Are you expecting both modules to operate simultaneously without interfering with each other? Perhaps you only
need to connect them to the same SPI bus?
 
Why do you want both of them on the same Teensy?

There is a situation like this, I am participating in a competition, I use LoRa as communication, I need to receive commands from the ground station while sending data every 1 second. We cannot do this with a single LoRa. It causes packet loss when passing from TX to RX. Adding another processor poses other problems. such as weight.
 
Are you expecting both modules to operate simultaneously without interfering with each other? Perhaps you only
need to connect them to the same SPI bus?

Yes, I need to connect at the same time without data mixing. Having the same SPI is not a problem, it is enough that the data is not mixed, but I do not know how to do this.
 
Each device on an SPI bus needs its own chip select (aka slave select) any pin can be used as a chip select, check out the
SPI examples perhaps.
 
Each device on an SPI bus needs its own chip select (aka slave select) any pin can be used as a chip select, check out the
SPI examples perhaps.

Yes but surely this means that he can only use ONE SPI device at a time. He wants FULL DUPLEX not HALF.
 
I'd use bit banging. He can access both boards in parallel, then.
Spi is always fullduplex?!

Spi bitbang is very easy (as master)
 
Oh, on the same channel. Missed that. But this has nothing todo with spi.
Spi is still fullduplex... :)

And yes, he just needs two CS pins for two SPI ports.
Or one with bitbang parallel.
 
Apparently he wants simultaneous send/receive over LORA, so looking at implementing two radios.
 
Nazım;286540 said:
There is a situation like this, I am participating in a competition, I use LoRa as communication, I need to receive commands from the ground station while sending data every 1 second. We cannot do this with a single LoRa. It causes packet loss when passing from TX to RX. Adding another processor poses other problems. such as weight.

Now that is useful information. Problem is when you transmit on one Lora module it will temporarily deafen the other one, so you
won't be able to avoid packet loss unless you can separate the two antennas by a large distance and/or highly direction antennas.
Typical receive powers are > 100dB down on the transmit power, no radio front-end can handle that large a dynamic range on channel.

This is why mobile phone uplinks and downlinks are separated by tens of megahertz - to enable filtering out the TX signal from the RX front-end.

Or are you already using different bands?
 
On the same channel? Rx and tx?
This does not work. I think something else is wanted.. but not this..

Let me explain it this way, I send it with TX every 1 second, except for one second, it needs to receive the commands sent from the Ground station, when it receives the command, there should be no deficiency in the sent packet. I understood from my research that the Lora module I used could not do this because it was not full duplex. I want to make one TX and the other RX using two loras, and I'll attach them to Teensy 3.6. I've seen that this can happen if I swapped my CS pins using the same MISO pins while plugging in the teens. But I don't know how to do it.
 
Again I am for sure no expert in these devices. I have tried to fix a few bugs in some of these libraries and do have a board I did for myself to maybe monitor my well systems from a different building using some RFM95s...

Sorry in advance for my probably to verbose ramblings below.

However regardless if you are using one or two SPI buses, unless your code and the library code is setup to do SPI in an asynchronous way, than you are only going to be talking to at most one radio at a time.

And for example if you look at the radiolib library examples like the SX127X_Transmit.ino or even their transmit with interrupt example when you see code in the loop
When you see calls like:

Code:
void loop() {
  Serial.print(F("[SX1278] Transmitting packet ... "));

  // you can transmit C-string or Arduino string up to
  // 256 characters long
  // NOTE: transmit() is a blocking method!
  //       See example SX127x_Transmit_Interrupt for details
  //       on non-blocking transmission method.
  int state = radio.transmit("Hello World!");

or even better more asynchronous calls like:
Code:
    transmissionState = radio.startTransmit("Hello World!");

The library code will do all of the SPI transfers to the radio for the whole packet before it returns. Note: as far as I can tell it also uses the most common and as such the slowest way to transfer:
That is wait for each byte to transfer before starting the transfer of the next byte... Most of the code I believe revolves on calling:
Code:
void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {

So what is the difference between the radio.transmit("Hello World!"); and radio.startTransmit("Hello World!"); ?

The first one waits for the Radio to complete the actual transfer of the packet, which I am guessing may include waiting for an ACK from the other side. The second one does not, instead it tells the raido to change the interrupt IO pin when the transfer completes. Which depending on how code is setup, you can either poll that IO pin or have it interrupt you...

And again the read operation is similar... That is you can setup to have the Radio set the interrupt IO pin when it receives a packet or you can sit there waiting for a new packet. But then in either case the library code will then use SPI to retrieve the packet from the module and it will do this with the calls like: int state = radio.readData(str);

Which again I am pretty sure again will boil down to multiple calls to Module::SPItransfer

So are there good reasons to use multiple SPI buses with this library code? Maybe. For example some SPI hardware does not play well with others. For example they don't properly handle the MISO pin and always drive it High or Low even when they are not active. This can cause other devices to not be able to respond. You can fix these cases either by using different SPI buses and/or in some cases add in hardware like a tri state buffer between the offending device and the buss... Have done that with some TFT displays.

Likewise if you had the two radios on two different SPI buses, could you have code that has SPI transfers going on both buses at the same time... Yes. With a lot of work one could write the library code to allow you to setup the transfers to be done either using DMA or interrupts. For example we do have display driver code that transfers whole frames of data to a display without waiting. And I have setup where you can have multiple of these display on different SPI buses and have them updating at the same time.

Probably more important is maybe experiment some, to see if the simple more direct ways work for you. For example if it were me, a few tests I would run include things like:

a) start with one radio and the transmit_interrupt example and get an idea of how long does it take to setup to send a packet versus how long does it take to complete sending the packet.
What I mean is something like: (Note I edited out most their comments to keep things shorter here.
Code:
[COLOR="#FF0000"]elapsedMillis em_transfer;[/COLOR]
void loop() {
  if(transmittedFlag) {
    enableInterrupt = false;
    transmittedFlag = false;

    if (transmissionState == ERR_NONE) {
      // packet was successfully sent
      [COLOR="#FF0000"]Serial.printf(F("transmission finished! %u\n"), (uint32_t)em_transfer);[/COLOR]


    } else {
      Serial.print(F("failed, code "));
      Serial.println(transmissionState);

    }

    // wait a second before transmitting again
    delay(1000);

    // send another one
    Serial.print(F("[SX1278] Sending another packet ... "));
    [COLOR="#FF0000"]em_transfer = 0;[/COLOR]
    transmissionState = radio.startTransmit("Hello World!");
    [COLOR="#FF0000"]Serial.printf("Startup time: %u\n", (uint32_t) em_transfer);[/COLOR]

    enableInterrupt = true;
  }
}
This should give you an idea of how much time is being spent in SPI versus time for sending the whole packet...

b) Could do similar for reads if need be.

c) I would try something like a) again but with two radio object, Probably start off with both on same SPI bus. Would probably get rid of delay... And instead keep a time to send next packet for each radio and send then.
Hope that makes sense.

Again sorry for the rambling.
 
Nazım;286623 said:
Let me explain it this way, I send it with TX every 1 second, except for one second, it needs to receive the commands sent from the Ground station, when it receives the command, there should be no deficiency in the sent packet. I understood from my research that the Lora module I used could not do this because it was not full duplex. I want to make one TX and the other RX using two loras, and I'll attach them to Teensy 3.6. I've seen that this can happen if I swapped my CS pins using the same MISO pins while plugging in the teens. But I don't know how to do it.

Again not sure if previous post helped... But if you are simply asking how to hook up two radios on the same Buss.

Then you should be able to do something like:

Hook up both radios such that both of them use the same pins for: SCK(13), MISO(12) and MOSI(11)
And then each of the two ones use different pins for the other pins.
Like in example they have:
Code:
// SX1278 has the following connections:
// NSS pin:   10
// DIO0 pin:  2
// RESET pin: 9
// DIO1 pin:  3
SX1278 radio = new Module(10, 2, 9, 3);
Now you can choose 4 different pins for the 2nd module... Again not know your radio and if needs all of these pins defined or not.

For example you can maybe share RESET pins, but then don't pass that into constructor but for now assume pass in unique...

Now the interesting thing with CS pins is that each radio will try to process data on the SPI buss if their CS pin is not at a high state. This can hit you at startup.
A few different ways to handle a good writeup about this is: https://www.pjrc.com/better-spi-bus-design-in-3-steps/

The best way is with Pull up resistors
A quick and dirty is at the start of your program if for example radio 1 CS is on 10 and radio 2 CS is on 9 you could add:
Code:
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);

Before your first call to first radio begin method
 
Status
Not open for further replies.
Back
Top