SPI For Two Shields

I am trying to a CAN SHIELD and a BME280 sensor. I need to read temp, humidity, pressure and then transmit those values trough CAN. Both the BME280 sensor and the CAN Shield use the SPI and Pin CS (Pin 10). How can I read from the sensor then send it through CAN. I have seen a lot of comments on utilizing CHIP SELECT but I am not sure how to do it.

BME SKETCH

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BME_SCK 13 //SCK
#define BME_MISO 12 //SDO
#define BME_MOSI 11 //SDI
#define BME_CS 10 //CS

#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

unsigned long delayTime;

void setup() {
Serial.begin(9600);
Serial.println(F(“BME280 test”));

bool status;

// default settings
status = bme.begin();
if (!status) {
Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
while (1);
}

Serial.println("-- Default Test --");
delayTime = 1000;

Serial.println();
}

void loop() {
printValues();
delay(delayTime);
}

void printValues() {
Serial.print(“Temperature = “);
Serial.print(bme.readTemperature());
Serial.println(” *C”);

Serial.print("Pressure = ");

Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");

Serial.print(“Approx. Altitude = “);
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(” m”);

Serial.print(“Humidity = “);
Serial.print(bme.readHumidity());
Serial.println(” %”);

Serial.println();
}

CAN SKETCH

// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN); // Set CS pin

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

while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println(“CAN BUS Shield init fail”);
Serial.println(" Init CAN BUS Shield again");
delay(100);
}
Serial.println(“CAN BUS Shield init ok!”);
}

void loop()
{

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
//send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x01, 0, 8, stmp);
delay(10); // send data per 10ms
}

But the chip select pins are different in your code:

#define BME_CS 10 //CS
  • from the BME sketch

and

const int SPI_CS_PIN = 9;
  • from the CAN sketch.

If these statements are correct - then you should have no issues.

Read more here: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Independent_slave_configuration

Thank you very much for the help. Is the CS a DIN to the CAN Shield and Temp Sensor? When it is High it enables/disables them? If i sen the Temp sensor to CS = 10 and CAN Shield to CS = 9; Can them work at the same time without enabling or disabling?

Can them work at the same time without enabling or disabling?

No. You need to disable all devices, and then enable the one you want to talk to.

I am sorry, first time working on something like this.

How do i go about doing that?

Can I assume I need to go under Voi setup and Void Loop and set the CS as outputs and set them high when I am trying to communicate with hem and turn them off when I am not? Can I have two ISP CS HIGH (enabled) at the same time?

void setup(){ pinMode(SPI_CS_PIN, OUTPUT); }

void loop() {

digitalWrite(SPI_CS_PIN,HIGH);

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7}; //send data: id = 0x00, standrad frame, data len = 8, stmp: data buf CAN.sendMsgBuf(0x01, 0, 8, stmp);

delay(10); // send data per 10ms

digitalWrite(SPI_CS_PIN,LOW);

}

Can I assume I need to go under Voi setup and Void Loop

Into, not under. And they are the setup() and loop() functions.

and set the CS as outputs and set them high when I am trying to communicate with hem and turn them off when I am not?

You need to check which mode enables the device (HIGH or LOW) and use the correct value to enable (and the other to disable).

Can I have two ISP CS HIGH (enabled) at the same time?

What was that? Someone else was talking to me.

No, you can not talk to multiple SPI devices at the same time. Doing so would be meaningless. The CAN shield and the BME sensor would have no idea what a message intended for the other one was supposed to mean.

Because the BME_CS it is in a format #define, I don't think I am able to change its value. I have tried doing what we have discussed above

digitalWrite(BME_CS, HIGH)

and the chip still works just fine.

I change it to Low and the same result.

Is there way around it? I tried to look at the Library it uses .h and .cpp but I only got more confused.

Thanks.

Because the BME_CS it is in a format #define, I don't think I am able to change its value.

Somewhere, there is a statement

#define BME_CS somePinNumber

Fire up your favorite text editor, and change the number.

It isn't rocket science.

are you referring somewhere within the .cpp or .h from the #include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>? or from my .ino?

at the very top of the example sketch there is a #define BME_CS 10. I tried instead of passing a constant make it a variable so that when HIGH it selects that chip and when LOW it does not. But when I do that, doesn’t matter what the value of BME_CS 10 is (HGH or LOW) the chip doesn’t communicate.

at the very top of the example sketch there is a #define BME_CS 10.

That defines the chip select pin to be pin 10. Which device are you trying to control with pin 10?

I tried instead of passing a constant make it a variable

Made WHAT a variable? Where, in what code, did you do that?

But when I do that, doesn’t matter what the value of BME_CS 10 is (HGH or LOW) the chip doesn’t communicate.

“BME_CS 10” is meaningless nonsense. It can’t possibly have a value of HIGH or LOW.

PaulS,

I am sorry for this, and I do appreciate you taking time to help me out.

The code that I am trying to make work it is a compile of the CAN example code and the BME280 Example code at the same time. Nothing else nothing more. The CAN Shield has its CS on Pin 9 and the BME280 has it on pin 10. I was told that not both Chip Selects can be on at the same time since the Arduino will not know who is it talking to, that I needed to turn the BME280 Chip Select off while talking to the CAN shield and vice versa. Thus my natural attempt was to change the set up as follows:

#include <mcp_can.h>
#include <SPI.h>
int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);

Void setup()
{

pinMode(SPI_CS_PIN, OUTPUT);
}

Void loop()
{

digitalWrite(SPI_CS_PIN, LOW);
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
CAN.sendMsgBuf(0x01, 0, 8, stmp);
delay(10);

digitalWrite(SPI_CS_PIN, LOW);

}

I DID THE SAME FOR THE BME280

my thinking here was when I would enable the BME20 and read all the sensor’s data, store them in some random variables then turning off the BME280 and then enabling the CAN Shield and transmitting the values, then disabling the CAN Shield and repeat the process all over.

Once again thanks for your patience and help.

Erick

Void loop()
{
   
digitalWrite(SPI_CS_PIN, LOW);
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
CAN.sendMsgBuf(0x01, 0, 8, stmp);
delay(10); 

digitalWrite(SPI_CS_PIN, LOW);                     

}

Does setting the CS pin HIGH enable communication? Or does it disable it? For either answer, why are you setting the pin to the same state before and after you want to communicate with the device?

I will NOT answer again until you post all of your code THAT ACTUALLY COMPILES.

Thanks PaulS,

Here it is!

/***************************************************************************
This is a library for the BME280 humidity, temperature & pressure sensor

Designed specifically to work with the Adafruit BME280 Breakout
----> http://www.adafruit.com/products/2650

These sensors use I2C or SPI to communicate, 2 or 4 pins are required
to interface. The device’s I2C address is either 0x76 or 0x77.

Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!

Written by Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution


*/

// TEMP SENSOR DEFINITIONS

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BME_SCK 13 //SCK
#define BME_MISO 12 //SDO
#define BME_MOSI 11 //SDI
#define BME_CS 10 //CS
#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

unsigned long delayTime;

// CAN COMMUNICATION DEFINITIONS

// CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10

int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN); // Set CS pin

// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>

void setup() {

pinMode(BME_CS, OUTPUT);

pinMode(SPI_CS_PIN, OUTPUT);

Serial.begin(9600);

///////////////BME SENSOR////////////////////////////////
Serial.println(“SENSOR SPI CHECK STARTS”);
Serial.println(F(“BME280 test”));

bool status;

// default settings
status = bme.begin();
if (!status) {
Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
while (1);
}

Serial.println("-- Default Test --");
delayTime = 1000;

Serial.println();
Serial.println(“SENSOR SPI CHECK ENDS”);

///////////CAN SHIELD ////////////////////////////

Serial.println(“CAN SHIELD SPI CHECK STARTS”);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println(“CAN BUS Shield init fail”);
Serial.println(" Init CAN BUS Shield again");
delay(100);
}
Serial.println(“CAN BUS Shield init ok!”);

Serial.println(“CAN SHIELD SPI CHECK ENDS”);

}

void loop() {

//////////SENSOR MAIN LOOP/////////
digitalWrite(BME_CS, LOW);
printValues();
digitalWrite(BME_CS, HIGH);
delay(1000);

//////////CAN MAIN LOOP/////////

digitalWrite(SPI_CS_PIN , LOW);
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
//send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x01, 0, 8, stmp);
digitalWrite(SPI_CS_PIN, HIGH);
delay(1000); // send data per 10ms

}

void printValues() {
Serial.print(“Temperature = “);
Serial.print(bme.readTemperature());
Serial.println(” *C”);

Serial.print("Pressure = ");

Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");

Serial.print(“Approx. Altitude = “);
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(” m”);

Serial.print(“Humidity = “);
Serial.print(bme.readHumidity());
Serial.println(” %”);

Serial.println();

}

#include <mcp_can.h>
#include <SPI.h>

// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>

Maybe you need to include those files a few more times…

#define BME_SCK 13  //SCK
#define BME_MISO 12 //SDO
#define BME_MOSI 11 //SDI
#define BME_CS 10 //CS
#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

You can NOT do software SPI on the hardware SPI pins while doing hardware SPI on those same pins!

The BME shield that you have can use SPI or I2C. Since you are having problems using the two SPI shields at the same time (mostly caused by shooting yourself in the foot), switch the BME shield to I2C, by not specifying a CS pin or any SPI pins.

In any case, the BME library takes care of the chip select pin for that shield (setting it LOW to talk to the BME shield and HIGH to not talk to it anymore).

The CAN library also takes care of its chip select pin, so you don’t need to be diddling with either one.