Teensy 4.1 - Connecting multiple SPI devices

Status
Not open for further replies.

Neel

Member
Hi everyone! I'm new to the forum and teensy/arduino. I have a general question on how I can connect multiple SPI devices, would this work?

Teensy 4.1
SCK - Pin 13
MOSI - Pin 11
MISO - Pin 12
CS1 - Pin 10 (External SD card)
CS2 - Pin 36 (HSCDRRV001PDSA3 - Honeywell differential pressure sensor)
CS3 - Pin 37 (HSCDRRV001PDSA3 - Honeywell differential pressure sensor)

Also, on this link:
https://www.pjrc.com/better-spi-bus-design-in-3-steps/

It states that I should use pull up resistors. What value would be suitable?

Thanks in advance!
Regards,

Neel
 
A lot of SPI devices already have something like 10K Pull ups on their boards... I believe some suggest something in the range of 2.2K
Alternative simply set all of the CS pins high before you initialize any of the devices.

And as for multiple ones, as mentioned in the link you gave, it sometimes depends on how well the devices behave, especially with the MISO pin.
 
Usually resistors between 10K to 100K are best. Really, just about any resistor is fine. But don't go below about 470 ohms since it needs so much more current.

If you don't have resistors, you can also just put all 3 pins into output mode at the beginning of your program and drive them all high. They are still "floating" before Teensy runs your program, and while you're loading new code, but at least that will keep the other 2 devices disabled while you initialize the first, and the last one disabled while you initialize the 2nd device.
 
Thank you so much KurtE. I thought it depended on the Teensy but I understood now. I took a look at the data sheet of the pressure sensors. They don't have a pull-up but recommended min 1k. Therefore, I will try the "work around" (without pull-ups) once the sensors have arrived.

Regarding the SPI pins of the Teensy 4.1, can you explain me why the pin-out picture states that pins 10, 36 and 37 are regarded as "CS" but pins 0 and 38 are "CS1"? Can I connect the 3 sensors on the "CS" pins?

teensy41_card.png

Regards

Neel
 
Hello PaulStoffregen, Thank you! I have resistors, but I want to try and use as little parts as possible. I will try both methods and then decide later.
 
You can use any 3 pins for CS.

The pins marked "CS" on the card have the ability to be used in a special hardware optimized way. But that optimization gives only very small benefit for most uses and costs a lot of complexity inside the library code, so most libraries don't use it. Unless documentation for the library specifically says you must use those pins, you can connect the CS signals to any digital I/O pin (some Teensy models have analog-only pins, but Teensy 4.1 does not).

So the take-away is you can choose whatever 3 pins are convenient for the 3 CS signals. You don't need to use the pins marked "CS" (unless you find a library which specifically says to do so). But there's no harm in choosing those pins marked "CS" even when the library will access them as if they were just ordinary digital pins.
 
Hello everyone, I got the sensors and connected to the teensy with 2 HSC (pressure sensors) and 1 SD. Both of the HSC sensors worked well together, however, with the addition of the SD card, it started causing alot of problems. I re soldered my circuit board so that both of the HSC sensors are on SPI1 and the SD still on SPI0. Now the problem is that if no SD card is present the values of the sensor data from the HSC gets multiplied by factor 100. But once the SD card is inserted, then I get perfect values. Can you explain the issue here?

Code:
#include <SPI.h>

#include <SPI.h>
#include <SD.h>

#include <Arduino.h>
#define OUTPUT_MIN 1638.4        // 1638 counts (10% of 2^14 counts or 0x0666)
#define OUTPUT_MAX 14745.6       // 14745 counts (90% of 2^14 counts or 0x3999)
#define PRESSURE_MIN -1         // psi
#define PRESSURE_MAX 1          // psi

#define INTERVAL_HSC 200 // HSC
unsigned long time_4 = 0; // HSC

#define INTERVAL_SD 200 // SD
unsigned long time_3 = 0; // SD

File sdcard_file;

uint8_t SDpin = 10;

uint8_t TASpin = 33;
uint8_t AoApin = 40;

unsigned long HSCmillis = 0;
unsigned long SDmillis = 0;

float TAS;
float val1;
float val2;

void setup() {
  Serial.begin(115200);
  SPI.begin();
  
  SPI1.setMOSI(26);
  SPI1.setMISO(39);
  SPI1.setSCK(27);
  SPI1.begin();

  pinMode(SDpin, OUTPUT);
  
    if (SD.begin())
  {
    Serial.println("SD card is ready to use.");
  } else
  {
    Serial.println("SD card initialization failed");
    return;
  }
  
  digitalWrite(SDpin, HIGH);

  
  pinMode(TASpin, OUTPUT);
  digitalWrite(TASpin, HIGH);

  pinMode(AoApin, OUTPUT);
  digitalWrite(AoApin, HIGH);


}
void loop()
{

  HSCmillis = millis(); // Millis only for AT commands
  SDmillis = millis(); // Millis only for IMU commands

    if(HSCmillis >= time_4 + INTERVAL_HSC){
      time_4 +=INTERVAL_HSC;  
  
  val1 = 1.0 * ((float)readSensor(TASpin) - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  TAS = sqrt(1.94384*2*(val1*6894.76)/1.225);
  Serial.print("TAS = "); Serial.print(val1*68.9476); Serial.print(" hPa,  "); Serial.print(TAS); Serial.println(" knots");

  val2 = 1.0 * ((float)readSensor(AoApin) - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  Serial.print("AoA = "); Serial.print(val2*68.9476); Serial.println(" hPa");

    }

    if(SDmillis >= time_3 + INTERVAL_SD){
      time_3 +=INTERVAL_SD;  

      
  sdcard_file = SD.open("data.txt", FILE_WRITE);
  if (sdcard_file) {    
    sdcard_file.print(val1*6895);
    sdcard_file.print(" Pa,     ");   
    sdcard_file.print(val2*6895);
    sdcard_file.println(" Pa");
    sdcard_file.close(); // close the file
  }

}
}

int16_t readSensor (uint8_t selectPin) {

  SPI1.beginTransaction(SPISettings(800000, MSBFIRST, SPI_MODE1)); // Set to 700kHz, MSB and MODE1
  digitalWrite(selectPin, LOW);       //pull Chipselect Pin to Low

  int inByte_1 = SPI1.transfer(0x00);  // Read first Byte of Pressure
  int inByte_2 = SPI1.transfer(0x00);  // Read second Byte of Pressure
  int inByte_3 = SPI1.transfer(0x00);  // Read first Byte of Temperature
  int inByte_4 = SPI1.transfer(0x00);  // Read second Byte of Temperature


  digitalWrite(selectPin, HIGH);      //pull Chipselect Pin to High
  SPI1.endTransaction();               //end SPI Transaction

  int16_t pressure_dig = inByte_1 << 8 | inByte_2;

  return pressure_dig; //return digital Pressure Value
}
 
Paul posted this link some time ago about typical problems encountered with multiple SPI devices on the same bus:

With my uncanny eyes setup that runs two SPI displays on the same SPI bus on Teensy 3.x, I found that adding 2.2K pull-up resistors on each of the two CS pins made the displays able to run much faster without screen corruption.
 
Hi Michael, thanks for the reply. I read this already and from my understanding this only applies if its from the same SPI bus. However, I have separated the SD with my pressure sensors therefore using 2 separate SPI busses (SPI0 and SPI1). The 2 pressure sensors run perfectly together on 1 SPI bus. The problem is the SD card.
 
Basically, what I don’t understand is, how can and why do the 2 SPI busses interfere with each other? I thought they were independent of each other.
 
Does the SD alone work when the pressure sensors are removed?

They should be independent - as long as they are wired right and the software only uses the proper pins and settings. Which is on SPI0 and which moved to SPI1?
 
Yeah, the SD works perfectly fine alone. Wiring is as follows:

SPI0:
SCK - Pin 13
MOSI - Pin 11
MISO - Pin 12
CS_SD - Pin 10 (External SD card)

SPI1:
SCK1 - Pin 27
MISO1 - Pin 39
CS_HSC1 - Pin 33 (HSCDRRV001PDSA3 - Honeywell differential pressure sensor)
CS_HSC2 - Pin 40 (HSCDRRV001PDSA3 - Honeywell differential pressure sensor)

I have tripple checked the wiring with the multimeter and by eye aswell. Its all good. Plus if I upload a code with this wiring but without including the code for the SD card, it works perfectly fine aswell.
 
So the issue then is the p#8 :
Code:
with the addition of the SD card, it started causing alot of problems. I re soldered my circuit board so that both of the HSC sensors are on SPI1 and the SD still on SPI0. Now the problem is that if no SD card is present the values of the sensor data from the HSC gets multiplied by factor 100. But once the SD card is inserted, then I get perfect values.

Is there a scaling command issued that would account for the 100 factor?
 
That's a good question. I will check the bytes and if they look fine then it has to be a scaling issue.
 
After some testing, I decided to print out the binary values and found that once the SD card is removed the sensors goes into "command mode". That is for example: 0100111111111110. The 2 first values are the status bits which determine the "Diagnostic Conditions" and should be set to 00, and the rest are the pressure bits.
If the SD is inserted, then the binary values display "normal operation, valid data", that is 00.
The data sheet says: "Command Mode is used for programming the sensor. This mode should not be seen during normal operation."

Does anyone have an idea why this is happening? I have not connected the MOSI.

@defragster: Do you still reckon its the scaling command? If so, what can I change?

Code:
SD card initialization failed

Byte_1 =   10000000 Byte_2 =   0 Bytes: Byte_1 =   1000000 Byte_2 =   0 16384.00, TAS = -430.92 hPa,  nan knots

Byte_1 =   1001111 Byte_2 =   11111110 Bytes: Byte_1 =   11001111 Byte_2 =   11111110 -12290.00, AoA = 129.26 hPa

Byte_1 =   11100000 Byte_2 =   0 Bytes: Byte_1 =   1000000 Byte_2 =   0 16384.00, TAS = -172.37 hPa,  nan knots

Byte_1 =   1001111 Byte_2 =   11111110 Bytes: Byte_1 =   11001111 Byte_2 =   11111110 -12290.00, AoA = 129.26 hPa

Byte_1 =   11100000 Byte_2 =   0 Bytes: Byte_1 =   1000000 Byte_2 =   0 16384.00, TAS = -172.37 hPa,  nan knots

Byte_1 =   1001111 Byte_2 =   11111110 Bytes: Byte_1 =   10001111 Byte_2 =   11111111 -28673.00, AoA = 129.26 hPa

Byte_1 =   11100000 Byte_2 =   0 Bytes: Byte_1 =   1000000 Byte_2 =   0 16384.00, TAS = -172.37 hPa,  nan knots

Byte_1 =   1001111 Byte_2 =   11111111 Bytes: Byte_1 =   11001111 Byte_2 =   11111111 -12289.00, AoA = 129.27 hPa

Byte_1 =   11100000 Byte_2 =   0 Bytes: Byte_1 =   1000000 Byte_2 =   0 16384.00, TAS = -172.37 hPa,  nan knots

Byte_1 =   1001111 Byte_2 =   11111111 Bytes: Byte_1 =   11001111 Byte_2 =   11111111 -12289.00, AoA = 129.27 hPa

Code:
SD card is ready to use.

Byte_1 =   10000000 Byte_2 =   0 Bytes: Byte_1 =   10000000 Byte_2 =   0 -32768.00, TAS = -430.92 hPa,  nan knots

Byte_1 =   11111 Byte_2 =   11111111 Bytes: Byte_1 =   10011111 Byte_2 =   11111111 -24577.00, AoA = -0.01 hPa

Byte_1 =   100000 Byte_2 =   110 Bytes: Byte_1 =   10100000 Byte_2 =   110 -24570.00, TAS = 0.06 hPa,  4.48 knots

Byte_1 =   11111 Byte_2 =   11111111 Bytes: Byte_1 =   10011111 Byte_2 =   11111111 -24577.00, AoA = -0.01 hPa

Byte_1 =   100000 Byte_2 =   11 Bytes: Byte_1 =   10100000 Byte_2 =   11 -24573.00, TAS = 0.03 hPa,  3.16 knots

Byte_1 =   100000 Byte_2 =   1 Bytes: Byte_1 =   10100000 Byte_2 =   1 -24575.00, AoA = 0.01 hPa

Byte_1 =   100000 Byte_2 =   110 Bytes: Byte_1 =   10100000 Byte_2 =   110 -24570.00, TAS = 0.06 hPa,  4.48 knots
 
Update: I have added pull-ups on every CS to 3.3V. 3k for the pres sensors and 10k for the SD card. The same problem is still present. However, now when the SD card is not inserted no data is transferred from the pres sensors and everything is just 0. But when the SD card is inserted, then the proper values occur. Therefore, SPI0 and SPI1 must interfere with each other. There is no other way... What do you guys think?
 
I feel like a total idiot! :D I found out my mistake:

Code:
    if (SD.begin())
  {
    Serial.println("SD card is ready to use.");
  } else
  {
    Serial.println("SD card initialization failed");
    return;
  }

The return; is my mistake. I guess its the long nights and early mornings that put me off. Now it works perfectly fine. Thanks everyone for your help!

Regards,

Neel
 
Status
Not open for further replies.
Back
Top