**crosspost from github.com/adafruit/ILI9340** can't drive two displays simultanously

Status
Not open for further replies.

pjakobs

Member
Hi Board,

I wonder if anyone has ever tried to use two SPI connected ILI9340 displays in parallel.
For me, it just doesn't work, please have a look at the issue I've opened over on github https://github.com/adafruit/Adafruit_ILI9340/issues/20

Abstract:
Short description:
driving two ILI9340 displays in parallel doesn't work, only one display shows content

Details
I'm not sure if this is a display driver issue or an SPI issue (although: switching from HW to SW SPI doesn't help, making SPI itself less probable) but:

I'm trying to run two (or potentially more) ILI9340 displays from one single micro. For that, I wire them up parallel on the SPI bus (MOSI, MISO, SCLK) but give them dedicated RST, D/C and CS signals.

I believe(!) that I'm obeying the rules for hardware SPI pins on the teensy:

Code:
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8
#define _led 6
#define _cs1 15
#define _rst1 21
#define _dc1 20

I'm sure my wiring is correct because when I don't instantiate one of the displays, the other one will work fine.
Looking at the logic analyzer, I can see that both displays are being driven, which lets me think that maybe the initialization for the 2nd instance fails? (although, interestingly, no matter in which order they are instantiated, the one with the lower dc/rst/cs pin numbers wins - if the behaviour wasn't identical in software SPI, I would assume it's a limitation of the hardware SPI implementation)

kind regards

oh, full code:
Code:
#include <SPI.h>
#include <Adafruit_GFX.h>
//#include <spi4teensy3>
#include "Adafruit_ILI9340.h"
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <Gauges.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/digital7italic12pt7b.h>
#include <Fonts/digital7italic18pt7b.h>
#include <Fonts/digital7monoitalic12pt7b.h>
#include <Fonts/digital7monoitalic18pt7b.h>

#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs   10
#define _dc   9
#define _rst  8
#define _led  6
#define _cs1  15
#define _rst1 21
#define _dc1  20

// Common 16-bit colors:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF


Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs1, _dc1, _rst1);
Adafruit_ILI9340 tft1  = Adafruit_ILI9340(_cs,  _dc, _rst);

//Adafruit_SSD1306 tft1 = Adafruit_SSD1306();
//Adafruit_ILI9340 tft  = Adafruit_ILI9340(_cs,   _dc,  _mosi, _sclk, _rst,  _miso);
//Adafruit_ILI9340 tft1 = Adafruit_ILI9340(_cs1,  _dc1, _mosi, _sclk, _rst1, _miso);
integerGauge Gspeed = integerGauge(&tft1, 20, 20, 75, 40);
integerGauge Gtemp  = integerGauge(&tft1, 0, 0, 128, 32);
textGauge    Glabel = textGauge(&tft1, 95, 20, 65, 40);

void setup() {
  Serial.begin(9600);
  delay(200);
  //tft.begin();
  tft1.begin();
  tft.begin();
  
  //tft1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  tft.setRotation(3);
  tft.clearDisplay();
  tft1.setRotation(3);
  tft1.clearDisplay();
//  Serial.printf("starting TFT with buffer at 0x%x\n", &tft);
  pinMode(_led, OUTPUT);
  analogWrite(_led, 255);

  Gspeed.setAutoRedraw(true);
  Gspeed.setFormatString(String("%3i"));
  Gspeed.setFGColor(WHITE);
  Gspeed.setBGColor(BLACK);
  Gspeed.setBorder(4);
  Gspeed.setBorderColor(GREEN);
  Gspeed.setCursor(10, 26);
  //Gspeed.setFont(&FreeMonoBold18pt7b);
  Gspeed.setFont(&digital7monoitalic18pt7b);
  Gspeed.redraw();

  Glabel.setAutoRedraw(true);
  //Glabel.setFormatString(String("%2iC"));
  Glabel.setValue("km/h");
  Glabel.setFGColor(WHITE);
  Glabel.setBGColor(BLACK);
  Glabel.setBorder(4);
  Glabel.setBorderColor(RED);
  Glabel.setCursor(4, 26);
  Glabel.setFont(&FreeSans12pt7b);
  Glabel.redraw();

  Gtemp.setAutoRedraw(true);
  Gtemp.setFormatString(String("%2ideg"));
  Gtemp.setFGColor(1);
  Gtemp.setBGColor(0);
  Gtemp.setCursor(5, 18);
  Gtemp.setFont(&FreeMonoBold18pt7b);
  Gtemp.redraw();
  //oled.display();
  //oled.printf("starting");
  delay(1000);
}

void loop() {
  // put your main code here, to run repeatedly:
  time_t t0, t1;

  Gtemp.setDisplay(&tft1);
  Gtemp.setPosition(20,80);
  Gtemp.setFGColor(WHITE);
  Gtemp.setBGColor(BLUE);
  Gtemp.setBorder(0);
  Gtemp.setBorderColor(YELLOW); 
  //oled.clearDisplay();
  
  //tft.fillScreen(BLUE);
  tft1.fillScreen(BLACK);
  Gtemp.redraw();
  Glabel.redraw();
  Gspeed.redraw();
  for (int i = 0; i <= 199; i++) {
    t0 = micros();
    Gspeed.setValue(i);
    t1 = micros();
    Serial.printf("(speed) update took %ius\n", t1 - t0);
    t0 = micros();
    Gtemp.setValue((int)(i / 10));
    t1 = micros();
    Serial.printf("(temp-tft1) update took %ius\n", t1 - t0);
    
  }
  Gtemp.setDisplay(&tft1);
  Gtemp.setPosition(20,80);
  Gtemp.setFGColor(WHITE);
  Gtemp.setBGColor(BLUE);
  
  //oled.display();
  //tft.fillScreen(BLUE);
  Gtemp.redraw();
  Glabel.redraw();
  Gspeed.redraw();
  for (int i = 200; i >= 1; i--) {
    t0 = micros();
    Gspeed.setValue(i);
    t1 = micros();
    Serial.printf("update took %ius\n", t1 - t0);
    t0 = micros();
    Gtemp.setValue((int)(i / 10));
    t1 = micros();
    Serial.printf("(temp tft) update took %ius\n", t1 - t0);
    
  }
  Glabel.setValue("mls/h");
}

the gauges library, for reference, is here https://github.com/pljakobs/Arduino_Gauges

pj
 
Last edited:
Again hard to say much... Without seeing your code...

I have not tried with this display, have used multiple ili9341 displays...

I believe you can use any IO pins for CS with this driver as it uses SPI.transfer which does not make use of hardware CS capabilities.

If I were trying this, the first thing I would do would be to:

Add at the start of your program something like:
Code:
pinMode(_cs, OUTPUT);
pinMode(_cs1, OUTPUT);
digitalWrite(_cs, HIGH);
digitalWrite(_cs1, HIGH);

Do this before calling off to the begin() method as to make sure neither of them have their CS floating, and may pick up parts or all of the init of the other display...
 
Hi Kurt,

the display driver seems to use hardware SPI, at least there's a significant speed difference between specifying the _mosi/_miso/_sclk pins when defining the instance and not (at least 4x pixel performance)

I have added the pinMode definitions but that didn't change a thing.

Over on github, I was able to paste signal traces and at first glance, both displays are correctly addressed. My feeling is, that the initialization fails on one of the displays.

pj
 
when I don't instantiate one of the displays, the other one will work fine

This seems to indicate that there are static or global (member?) variables in the display module/library, which get confused by multiple instances.
I took a quick look in Adafruit_ILI9340 and Adafruit_GFX and couldn't find any, but that doesn't mean I didn't miss them :)

the display driver seems to use hardware SPI

That is correct, but the "Chip Select" signal is not being driven by the hardware SPI. For cases where the Teensy is the master, this doesn't matter, because hardware chip select is only important when it's a slave, and need to start receiving/sending data on interrupt when the chip select input goes low.


You seem to already have a Saleae Logic on the bus, so if I were you, I'd keep looking at the traffic during initialization and compare the bytes that go out for the two displays; if there is a discrepancy, then look at where those bytes are supposed to come from in the code.
Also, look at the data/command and reset lines being toggled correctly.
 
It might also help to know if you are using the version of the adafruit_ili9340 library that comes with Teensyduino or if you downloaded a version from Adafruit.

There appears to be a few threads talking about running multiple ones. So hopefully it is not a hardware issue with these displays where they hold some signal state...

I don't remember seeing which Teensy you are using. Several of the Teensy boards support multiple SPI busses. So it might be possible to run them on different busses. Note: however the current library is hard coded for SPI, so would take a bit of work.

Also at least with the version that ships with Teensyduino, I don't think the library has been updated to use SPI.beginTransaction/endTransaction, So wondering if adding that might help...

Also you might want to take a look at the library: https://github.com/sumotoy/TFT_ILI93XX
 
Last edited:
Status
Not open for further replies.
Back
Top