2

I am trying to connect about 5 TFT's to my Arduino Uno and I got to the point of hooking two of them up without any issues. However, after a code upload, they stopped working. I then took all the code out and tested each in isolation and they still function. However, together only one of them displays data. The TFT's I am using are the ST7789v2 found here. https://www.waveshare.com/wiki/1.69inch_LCD_Module#Hardware_Connection_3

I have wired them up according to the schematic with "all" pins being shared except the CS pin. Each display has its own.

The code looks like this;

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>

#define TFT_CS1 10
#define TFT_CS2 3

#define TFT_RST        8 // Screens shared
#define TFT_DC         7 // Screens shared
#define TFT_BACKLIGHT  9 // Backlight for all screens

Adafruit_ST7789 tftHour1 = Adafruit_ST7789(TFT_CS1, TFT_DC, TFT_RST);
Adafruit_ST7789 tftHour2 = Adafruit_ST7789(TFT_CS2, TFT_DC, TFT_RST);

Adafruit_ST7789 setupScreen (Adafruit_ST7789 tft){
  tft.init(240, 280);
  tft.fillScreen(ST77XX_BLACK);
  return tft;
}

void setup(void) {
  tftHour1 = setupScreen(tftHour1);
  tftHour2 = setupScreen(tftHour2);
}

void loop(){
  tftHour1.print("1");
  tftHour2.print("2");
}

When this executes, display 2 shows output but display 1 does not. Weirdly if I take the CS from display 1 and pop it into the same line on the breadboard as CS2, and then put it back into its original position, display 1 and 2 seem to work. But only till the next power cycle or upload.

Also oddly, setting the colour of each screen works even if one is blue and the other is say green. Both change to their respective colours. But when I try to write text to them, only one of them has text.

If I comment the code for tftHour2, then tftHour1 starts showing text. If I swap the setup code for ftfHour1 and tftHour2, then the display that is last to init, is the one that shows the text and the other stays blank.

Like I said, I had all this working and then a simple font change upload and it all stopped working.

Any help on this is really appreciated.

I should mention that I am a programmer and very new to electronics so please keep it simple.

#Update. If I have separate RST pins then it works. But I need 5 screen and will run out of pins in that case. Is there a way to get around that?

5
  • your code is inconsistent ... there is a definition for two object names tftHour1 and tftHour2 and then you throw in an object name tft
    – jsotola
    Aug 30 at 1:06
  • so that's within a function where I can send it a tft object, init that and return. The name of the object, inside the function, is tft. it's for reusability and to cut down on the amount of code and thus space
    – griegs
    Aug 30 at 1:07
  • Off-topic: Your function setupScreen() takes a Adafruit_ST7789 as argument, that is perfect to use the same code. But 1st, why does the function need to return that argument? And 2nd, why do you overwrite the existing objects in tftHour1 and tftHour2 with themselves? Aug 30 at 6:01
  • I did that initially because I wasn't quite sure whether the Arduino IDE considered the passed object context as local or not. However, it makes no difference whether I return the object, and overwrite the global one, or not.
    – griegs
    Aug 30 at 6:17
  • @thebusybee he probably needs it because he is passing it as copy of original, so it doesn't affect the original object without making copy back into it :D Hint: he should use pass by reference (or pointer, but reference is more straightforward) void setupScreen (Adafruit_ST7789 & tft) { // now changes to tft will be changing original object too
    – KIIV
    Aug 30 at 7:04

1 Answer 1

1

According to the data sheet, the RST signal is accepted without an active CS, so when sharing this signal, all displays are reset if you initialize just one of them. That explains the behavior you observe.

You found the solution: Do not share the RST signal in all instances of Adafruit_ST7789.


Now you worry about the needed number of pins, and that is indeed an issue.

One possible solution is to use a decoder that takes n inputs to activate 1 of 2n outputs, like this:

schematic

simulate this circuit – Schematic created using CircuitLab

To control 5 RST lines you will need only 3 pins. Use a binary value to select one of the unused outputs to deactivate all RST lines.

The same is true of the CS lines.

However, the library in use does not support this kind of control. Therefore, I'm afraid that you need to consider another Arduino model with more pins.


As a work-around, you might want to try this alternative:

Assign the same Arduino pin to all instances of Adafruit_ST7789, as in your first attempt. But do not connect it to the RST inputs of the displays. Leave the Arduino pin unconnected.

Instead, use another Arduino pin and connect that to the displays. Then during initialization, reset all displays with your own code. See the data sheet for correct levels and timing.

Or try to connect the RST inputs of all displays to VCC, as they may work without an explicit hardware reset just fine.


In a comment you brought up the idea of using a multiplexer.

Without any other change, you would need the selection signals as additional pins to the multiple CS pins, in your case 3 more.

Instead you can also share the CS signal in the same way:

schematic

simulate this circuit

It is very important that you use multiplexers that output the inactive level as required by the displays on not selected outputs!

Even now you should instantiate as many Adafruit_ST7789 as you have displays, because each instance most probably stores internal information necessary for its correct working. But you can use the same pins on all of them.

Before you call any method of an instance, switch the multiplexers to the associated display.

To be sure that all data is completely transmitted, you might need a small delay after the called method. Perhaps the called method already blocks until all data is completely transmitted. You might try to read the library's source to learn more.

5
  • Assigning a single pin. I will try that because I can simply reset them at intervals when a value changes, for example, when the minute changes over. What if I used a multiplexer? Could I then hook up the RST and the CS to it? Unsure how that might work
    – griegs
    Aug 30 at 6:40
  • @griegs Unless the library code does set CS before doing the Reset, it won't work for you. And the question is if the TTFs can handle CS during RST. Maybe try NOT_A_PIN (or how it's named) for RST passed into tft objects and toggle the real RST pin for some time by yourself before going into TFT init functions
    – KIIV
    Aug 30 at 6:58
  • @griegs Is it necessary to reset a display before it can show new content? I don't think so, it would be quite strange. -- Concerning the multiplexer idea, I'll extend my answer. Aug 30 at 9:13
  • @griegs add a couple of gates so that the RST can be asserted only when CS is asserted ... that way you would need only one pin to drive the RST line
    – jsotola
    Aug 30 at 18:37
  • @thebusybee, pretty sure the screen does not require a reset to draw new content. I "could" reset once a day and simply black out the area I want to write to ahead of any write. Then at 2am, do a reset to clear the cache
    – griegs
    Aug 30 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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