0

Whenever I use multiple devices on SPI, TFT Screen, and the BME280 breakout board from Adafruit, the Arduino fails to detect the devices.

Code of the screen separately (works)

// include the necessary libraries
#include <SPI.h>
#include <SD.h>
#include <TFT.h>  // Arduino LCD library

// pin definitions
#define sd_cs  7
#define lcd_cs 10
#define dc     9
#define rst    8

// Define screen pins
TFT TFTscreen = TFT(lcd_cs, dc, rst);

//Define variables
char sensorPrintout[4];
char sensorPrintout2[4];

// this variable represents the image to be drawn on screen
PImage logo;

void setup() {
  Serial.begin(9600);
  while (!Serial) {  }

  Serial.print("Initializing SD card...");
  if (!SD.begin(sd_cs)) {
    Serial.println("failed!");
    return;
  } else {
    Serial.println("OK!");
  }

  // Start and clear TFT screen
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);

  // Lookup image on TFT screen
  logo = TFTscreen.loadImage("Logo.bmp");
  if (!logo.isValid()) {
    Serial.println("error while loading Logo.bmp");
  }
  if (logo.isValid() == false) {
    return;
  }

  //Draw logo on the screen 
  Serial.println("drawing image");
  TFTscreen.image(logo, 0, 0);

  // Change textcolor to white
  TFTscreen.stroke(255,255,255);

  //Write some text
  TFTscreen.setCursor(0,25);
  TFTscreen.print("Schuif 1: ");
  TFTscreen.setCursor(75,25);
  TFTscreen.print((char)247);
  TFTscreen.print("C");

  //Write some text
  TFTscreen.setCursor(0,50);
  TFTscreen.print("Schuif 2: ");
  TFTscreen.setCursor(75,50);
  TFTscreen.print((char)247);
  TFTscreen.print("C");
}

void loop() {
  // Read value of A0
  int value = analogRead(A0);
  Serial.println(value);
  float voltage = value * (5.0/1023.0);
  Serial.println(voltage);
  String sensorVal = String(analogRead(A0));
  String sensorVal2 = String(voltage);

  // Change sensor value to a character array
  sensorVal.toCharArray(sensorPrintout, 4);
  sensorVal2.toCharArray(sensorPrintout2, 4);

  // Change text color to white
  TFTscreen.stroke(255,255,255);

  // Write value of sensor 1
  TFTscreen.setCursor(55,25);
  TFTscreen.print(sensorPrintout);

  // Write value of sensor 2
  TFTscreen.setCursor(55,50);
  TFTscreen.print(sensorPrintout2);

  // wait  500ms
  delay(1000);

  // Change text color to black
  TFTscreen.stroke(0,0,0);

  // Write value of sensor 1
  TFTscreen.setCursor(55,25);
  TFTscreen.print(sensorPrintout);

  // Write value of sensor 2
  TFTscreen.setCursor(55,50);
  TFTscreen.print(sensorPrintout2);
}

Code of the BME280 separately (works)

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

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 6

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme(BME_CS); // hardware SPI

unsigned long delayTime;

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

  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  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();
  delay(100); // let sensor boot up
}

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();
}

Code of the TFT screen with the BME280 (doesn't work)

// include the necessary libraries
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SPI.h>
#include <SD.h>
#include <TFT.h>   // Arduino LCD library
#include <Wire.h>

// pin definitions
#define bme_cs  6
#define sd_cs   7
#define rst     8
#define dc      9
#define lcd_cs 10
#define mosi   11
#define miso   12
#define sck    13

//var definitions
#define SEALEVELPRESSURE_HPA (1013.25)

//Define hardware SPI connection with BME280
Adafruit_BME280 bme(bme_cs); // hardware SPI

// Define screen pins
TFT TFTscreen = TFT(lcd_cs, dc, rst);

//Define variables
char sensorPrintout1[6];
char sensorPrintout2[6];
unsigned long delayTime;

// this variable represents the image to be drawn on screen
PImage logo;

void setup() {
  Serial.begin(9600);
  while (!Serial) {  }

  bool status;

  // Initializing SD card
  Serial.print("Initializing SD card...");
  if (!SD.begin(sd_cs)) {
    Serial.println("failed!");
    //while (1);
  } else {
    Serial.println("OK!");
  }

  //Initializing BME280
  Serial.print("Initializing BME280");
  status = bme.begin();  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  } else {
    Serial.println("BME 280 sensor found");      
  }

  // Start and clear TFT screen
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);

  // Lookup image on TFT screen
  logo = TFTscreen.loadImage("Logo.bmp");
  if (!logo.isValid()) {
    Serial.println("error while loading Logo.bmp");
  }
  if (logo.isValid() == false) {
    return;
  }

  //Draw logo on the screen      
  Serial.println("drawing image");
  TFTscreen.image(logo, 0, 0);

  // Change text color to white
  TFTscreen.stroke(255,255,255);

  //Write some text
  TFTscreen.setCursor(0,25);
  TFTscreen.print("temperatuur 1: ");
  TFTscreen.setCursor(100,25);
  TFTscreen.print((char)247);
  TFTscreen.print("C");

  //write some text
  TFTscreen.setCursor(0,50);
  TFTscreen.print("luchtvochtigheid 2: ");
  TFTscreen.setCursor(100,50);
  TFTscreen.print((char)37);
  TFTscreen.print("C");
}

void loop() {
  // Read value of temperature
  int value1 = bme.readTemperature();
  int value2 = bme.readHumidity();
  String sensorVal1 = String(value1);
  String sensorVal2 = String(value2);

  // Change sensor value to a character array
  sensorVal1.toCharArray(sensorPrintout1, 6);
  sensorVal2.toCharArray(sensorPrintout2, 6);

  // Change text color to white
  TFTscreen.stroke(255,255,255);

  // Write value of temperature sensor
  TFTscreen.setCursor(55,25);
  TFTscreen.print(sensorPrintout1);

  // Write value of humidity sensor
  TFTscreen.setCursor(55,50);
  TFTscreen.print(sensorPrintout2);

  // wait  500ms
  delay(1000);

  // Change text color to black (aka overwrite text)
  TFTscreen.stroke(0,0,0);

  // Write value of temperature sensor
  TFTscreen.setCursor(55,25);
  TFTscreen.print(sensorPrintout1);

  // Write value of humidity sensor
  TFTscreen.setCursor(55,50);
  TFTscreen.print(sensorPrintout2);
}

Now this is the serial output:

Initializing SD card...failed!
Initializing BME280Could not find a valid BME280 sensor, check wiring!

At first it only showed the first line, then it stopped because of the while(1) loop. So I put it in comment to see if the BME initializes on its own.

I also tested the screen+SDcard and the BME280 separately, which worked just fine.

Update

I tried to test the programs with the complete circuit. The program of the TFT screen works fine that way but when I try the program of the BME280 it doesn't work. I have to remove the TFT screen from the breadboard to make it work.

Update 2

After some measurements with the scope I determined that the MOSI is pulled to 0V when I connect the 5V to the TFT screen. I also saw that the MOSI output on the BME280 board is 3.3V instead of 5V.

Could it be that the conflict in voltages is the cause for all my troubles?

Circuit

  • And your question is...? – Majenko Dec 7 '17 at 14:52
  • 1
    Have you examined the libraries to see if they initialize the SPI hardware in conflicting ways? – Ignacio Vazquez-Abrams Dec 7 '17 at 16:10
  • @IgnacioVazquez-Abrams i have not how can i fix this – RubenDefour Dec 7 '17 at 16:54
  • Could you post the Serial output you get? – Gerben Dec 7 '17 at 16:57
  • I will edit the original to add the serial output – RubenDefour Dec 7 '17 at 16:58
0

Please check my blog post about this issue exactly.

The main idea is that the different SPI components do not respect the chip select and interfere with each other on the SPI bus. The way I solved it was to toggle between the different components using an array of switches- transistors in a way that in any given time only one component is connected to my Arduino (or any other master) through the SPI.

How to use multiple SPI devices with Arduino

While building my SmartHomeDIY project I encountered a problem trying to use multiple SPI devices connected to the same Arduino. Although the SPI bus should support multiple devices at the same time (toggling the Chip-Select line), this does not always work (mostly due to the part using the bus not respecting the chip select or other configuration issues). So after reading for some time and experimenting I came up with the following solution.

The above station is an IR recorder and sransmitter station. It can be set into recording state, which then saves the recorded IR-in data into and SDCard connected over SPI. But when not in recording mode it will listen over the RF24 (also connected via SPI) for commands. Once a command is given it will try to send the IR code request (for example turn TV on). To do that it will again have to move to SDCard mode and read the previously recorded data and retransmit it over the IR out LED.

So to solve this I have connected the SPI lines to couple of transistors/switches, then just CUT the lines of the part not being used at the moment and there for prevent the SPI lines collision.

Attached is the code and hardware layout to do just that.

Note that it does not matter which type of project you have. You can always do the same transistor-switch trick to cut of the problematic SPI lines while using the others.

A special note for the transistor configurations. It will not work if you pass as usually suggested, which means to set a logic level by design at the output of the transistor so that the base will toggle the out voltage (same as an amplifier).

Instead I set the signal to go trough the transistor, which is needed, so testing to select the transistor, which does not affect the actual signal (it will depend on the transistor type, spec and configuration...). So it took me some time to figure out the right transistor values and configuration.

For trial and error I used a logic analyzer with 8 logic lines or an oscilloscope.

I inspected the incoming signal and the outgoing signal to make sure the transistor does not temper with the incoming signal, so everything will continue to work as expected (the transistor is transparent to the actual data).

You could also use this logic multiplexer [8 Channel Logic Level Converter Convert TTL Bi-directional] to do the same job, which I have not tested yet. But I think my way is more fun! :)

  • Avoid links. Edit your answer and add the relevant information here. Links die, SE survive. – user31481 Jan 7 '18 at 22:58
2

Connect the BME280 board by I2C, it cannot be used in a multi-SPI setup. The problem is that the MISO line it not decoupled from the bus if CS is HIGH but constantly pulled HIGH. This will disturb other bus members.

  • Thank you very much. Is there another solution possible because in my project i need to use 2 BME280 boards. so I2C won't be much of a solution. – RubenDefour Dec 8 '17 at 14:45
  • most i2c devices will support more than 1 address, usually with a couple of pads on the board, connecting or breaking connections can change the address, so then you would be able to use 2 sensors on i2c – James Kent Jan 17 '18 at 11:03
  • The BME280 supports two I2C slave addresses by tying SDO to either GND or Vddio. If you need to connect more than 2 devices to the same master use an I2C multiplexer as the PCA9547. – Pylon Jan 18 '18 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.