ILI9341 LCD display and Arduino Uno/Nano without level shifters

I really like playing with my ILI9341 LCD screens with 3.3V Arduino ProMini because no voltage level shifting is needed:

After my last 3.3V Arduino Pro Mini has entered a state not allowing to flash a program I was left with Uno and Nano Arduinos that (normally) require some level shifting.

I did so with my Uno turning the LCD into a live speedometer with history for (another) Arduino robot running in my motor test station. While this works nicely:

I really do not like the (huge) amount of cabling to/from the level shifters:

A while ago I found out that a (cheap Chinese clone) Arduino Nano can run with 3.7V Lipo battery on slightly more than 3.3V:

And I have USB2UART modules allowing to switch between 3.3V and 5V, which can be used to just give 3.3V as well. Given both I found a way to combine a Nano and ILI9341 LCD without(!) level shifters involved. The only drawback is that switching cables is needed when going from programming to running and back (in order to avoid 5V damage on ILI9341 LCD display).

For programming I disconnect the GND cables from Nano to 3.3V USB2UART and ILI9341 LCD, and connect the Nano USB programming (5V) cable:

For running I disconnect the Nano USB programming (5V) cable, and connect the GND cables from Nano to USB2UART and LCD display:

Works like a charme, and as far as I understand (I am a software guy) this avoids 5V harm to ILI9341 LCD display.
(Absolute maximum rating for VCC is 4.6V according display spec)

Hermann.

P.S: I tried to program Arduino Nano via USB2UART (like I do with ProMini), but without success.

P.P.S: Connecting RX and TX as well allows even "Serial.print()" to work (at 3.3V):

You can run your module with 1k0 series resistors to the 5V Arduino. Much simpler than level shifters.

But the easiest of all is to run at 3.3V in the first place. If your Arduino has modest current, the USB-TTL dongles can supply the 3.3V. Use the 5V output to supply the backlight through a small resistor.

You can always hand-wire some protoboard to accept your cheap 3.3V TFT and mount a proper level shifter chip. Add female headers to accept a Pro Mini / Nano / Uno ...

Hand wiring an "Adapter" is quite hard work. Especially when you can buy a ready made UNO shield that has all the correct electronics. I have done both methods.

David.

Hi David,

You can run your module with 1k0 series resistors to the 5V Arduino. Much simpler than level shifters.

the whole point of this thread was to avoid level shifters and resistors for the 6 data lines to TFT display completely.

Since it is a Nano I just wanted to modify the USB cable in a way that only 3.3V hit the Nano (which is no problem for cheap China clone Nanos). That way the Nano (as my 3.3V ProMini previously) runs on same level as display and there are no problems.

A colleague told me to use a silicon diode to subtract 0.7V, and to use 2 of them in series to reduce more.

I did that with two 1N4001 diodes and a micro switch allowing to select 1 or 2 diodes in the red 5V USB line:

Measuring VCC of USB cable at the Arduino end was too tricky for me.
So I did measure VCC on Arduino VCC pin versus Arduino GND pin.

With a second unmodified cable I did read 4.75V, with micro switch selecting 1 diode 4.05V, and with switch selecting two diodes 3.35V:

This is definitely no problem for the 3.3V LCD TFT display (that has 4.6V as absolute maximum rating).
I did measure VCC versus GND pin directly at LCD display, 3.11V:

For me this is the simple solution I was looking for, just use the "3.3V cable" for Nano with 3.3V TFT display.

Just for completeness, I tested flashing programs as well as doing output to Serial console, no problems.
The USB hardware in laptop seems also to be OK with the reduced voltage levels of D+ and D- USB lines.

Hermann.

You are obviously obssessed with disobeying data sheets.

You can either use level shifters or series resistors. Any thing else means that you do not want it to work.. Just run it at 3.3V.

David.

Hi,

You are obviously obssessed with disobeying data sheets.

not really, until 2 weeks ago I did use 3.3V ProMini for playing with 3.3V display. But since my last ProMini died two weeks ago, new 1.48$ 3.3V ProMinis while being really cheap will take some weeks from China to arrive.

So what can happen?
Currently everything runs fine and nothing needs to be changed.
Just in case the Nano will suffer from run at 3.35V, it did cost 2.48$ and can be replaced.
If I am correct the laptop USB port cannot suffer from reduced 3.35V level on D+ and D- data lines.
The worst that can happen is that data transfer to/from Nano will not work (reliably).
And since display gets the 3.3V it needs no risk there.

Hermann.

P.S:
Because I saw demo comparing ILI9341_due library performance with normal/extended/dma mode I ordered a 12€ Arduino Due today, and that does run at 3.3V natively (and has 96KB ram, 512KB flash, 32bit @84MHz, dma, ...).

The USB will be fine with 3.0V to 3.6V for its D+ and D- lines. These are the absolute limits.

The TFT will be fine at 3.3V.
You can even run with 5V GPIO if you use series resistors or a level shifter chip.

You implied that you did not want to use either method. Which means that you just have to wait for your 3.3V Pro Minis to arrive.

David.

Just learned again that TFT display does not work with too much voltage.
I had to discharge the LiPo battery to 3.79V before the TFT display started to show more than a white screen

Hermann.

Why do you want to risk damaging your TFT?

You could connect your LiPo to the VCC pin on the display. Then power your Pro Mini from the 3.3V regulator on the display pcb. Supply the backlight directly from the LiPo via a small resistor.

This will give you 3.3V logic for the TFT and SD. Your Pro Mini will work fine at 16Mhz and 3.3V

Obviously, you can not use the LiPo and USB at the same time. Disconnect your display when uploading a new sketch.

David.

Thanks for the information wrt securely running on LiPo only.

Still waiting for the 3.3V powered micro controllers to be delivered, I am using the "3.3V USB cable" described above for weeks now. And everything works fine, with it I was able to investigate how to create a screentsot and store it on SD card, see this (long) thread:
http://forum.arduino.cc/index.php?topic=357013.0

Since both diodes just subtract a constant voltage from input USB voltage I thought about a voltage regulator based solution, "3.3V USB cable"++.

I had a spare LD33V and read in spec about its application circuit:

After having bought the two needed capacitors I was able to start.
I played with a mini breadboard and then realized that it could be placed inside a spare box I had:

It was too big to fit in easily, so I head to remove the plastic thread of screews.
Also the 10uF as well as the male connectors were too high to fit.
So I had to bend everything to fit into the box.

Since I was not in the mood of big soldering I did the minimal.
Because interception of VCC and GND lines was needed this time, I did cut the USB cable.
Then I soldered little male connectors to the 2 VCC (red) and 2 GND (black) cables.
And connected D+ (green) and D- (white) lines again, all secured with heat shrink tubes.

The microswitch this time allows to switch between 3.3V and 5V and is accessible externally:

Because I had removed the plastic threads of screws, I sealed the box with super glue (I always use superglue for everything). Sealing was really necessary because I had to press very hard to keep all pieces and cables inside the box.

This is the final result in use:

I did measure the old "3.3V USB cable" and it showed 3.32V.
An unmodified Nano USB cable did give 4.71V.

The new "3.3V USB cable"++ gives 3.02V (measured at Nano GND/VCC pins).
Not sure why 3.02V, without the capacitors LD33V gives 3.33V.
But if spec tells me to add capacitors I will do.

The advantage of "3.3V USB cable"++ seems to be that it will always give 3.02V, regardless of what laptop USB voltage provided.

For getting the display to show picture I had to change one connection over the cabling used before:

Before I used Vin to provide TFT LCD backlight voltage -- not a good practice to use input pins for output.

With "3.3V USB cable"++ the voltage on Vin was only 2.45V, not enough. So I connected to pin D3 and set digital pin 3 to HIGH, the 2.97V I measured were enough to make display work (I like #breadboardless Arduino female-female wirings).

Hermann.

Yesterday I succeeded in making my 3(!) Arduino Due's (12$ each) work.

Now I tried to run the simple "graphicstest" program with Arduino Due instead of Nano with 3.3V USB cable.
Since Due runs on 3.3V no level shifters or other stuff is needed:

Some connection changes are needed according to SPI Arduino doc (section Connections):

Unlike Uno/Nano hardware SPI is not on pins 11/12/13 but on 4/10/52.

So I changed the 11->4, 12->10 13->52 and moved 10->11.
In addition I used pin 7 on HIGH as 2nd 3.3V output for display LED connection.
These are the little changes in "graphicstest":

...
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 11 // 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_due tft = ILI9341_due(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
...

These are the effective connections from 2.2" display to Due:

SCK - Arduino Pin 52
SDO(MISO) - Arduino Pin 10
SDI(MOSI) - Arduino Pin 4
CS - Arduino Pin 11
D/C - Arduino Pin 9 
RESET - Arduino Pin 8
LED - Arduino Pin 7
VCC - Arduino 3.3V
GND - Arduino GND

Unfortunately I only get a white display, and Serial Monitor output shows that something is wrong:

What am I missing, how can I get Due work with 2.2" display?

Hermann.

Have a look at the Due pinout.

First thing you got wrong are the SPI pins. 4,10,52 are pins for HW CS (Chip Select) which you have to use if you want to utilize Extended SPI mode.
The proper SPI pins are on the SPI header (the one in the middle of the board).

The second thing I would change immediately is sourcing of 3.3V from pin 7. Due pins are Low current or High current (you can see them on the Due pinout, look at the legend). Even though pin 7 is a high current one, it can only source 15mA. If you source more, you can damage Due. I would guess your LED backlight is drawing more than 15mA. Due has much lower current limits on it's pins than Uno or Mega.

Thank you so much for correcting me!

I did connect as you said, and soldered a little 3.3V extender for connecting VCC and LED.
Now all is fine (big photo):

And the comparison of Due with Nano is phantastic, factors between 3.82 and 8.27!!

I do have two questions:

  • I tested with the other ICSP headers, they did not work, is that correct?
  • Are there any pins (like 11/12/13 for Nano) that can be used for Due instead of ICSP headers?

Just for completeness, display2due connections:

SCK - Arduino ICSP1.3
SDO(MISO) - Arduino ICSP1.1
SDI(MOSI) - Arduino ICSP1.4
CS - Arduino Pin 10
D/C - Arduino Pin 9 
RESET - Arduino Pin 8
LED - Arduino 3.3V
VCC - Arduino 3.3V
GND - Arduino ICSP1.6

Hermann,

HermannSW:
I do have two questions:

  • I tested with the other ICSP headers, they did not work, is that correct?
  • Are there any pins (like 11/12/13 for Nano) that can be used for Due instead of ICSP headers?

In regards to ICSP, this is what I found:

ICSP header that looks like a second SPI port is actually for programming the Atmega16U2 on the board which assists with programming the SAM3X chip through the second USB port.

And there are no other pins on Due that can be used for SPI. SPI is only available through the SPI header. This also makes it incompatible with some Mega shields that use alternative pins instead of the SPI header.

Btw. you can try to change
#define ILI9341_SPI_CLKDIVIDER 2 // for Due
to 1 in ILI9341_due_config.h and see if it still works for you. Should be even faster.

On the arduino Due you can transport SPI signals to 11, 12 and 13 pin. Like Gameduino 2 for example, this TFT shield can work it on Due like as arduino UNO shield.

This is a part of code in GD2.ccp

#if defined(__DUE__)
#define MOSI  11
#define MISO  12
#define SCK   13    // B.27

class ASPI_t {
public:
  void begin(void) {
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);
    pinMode(SCK, OUTPUT);
    digitalWrite(SCK, 0);

    // PIOB->PIO_PER = PIO_PB27;
    // PIOB->PIO_CODR = PIO_PB27;
    // PIOB->PIO_PUDR = PIO_PB27;
  }
  byte transfer(byte x ) {
    byte r = 0;
    for (byte i = 8; i; i--) {
      if (x & 0x80)
        PIOD->PIO_SODR = PIO_PD7;
      else
        PIOD->PIO_CODR = PIO_PD7;
      // digitalWrite(MOSI, (x >> 7) & 1);
      x <<= 1;
      // digitalWrite(SCK, 1);
      PIOB->PIO_SODR = PIO_PB27;
      r <<= 1;
      r |= digitalRead(MISO);
      // digitalWrite(SCK, 0);
      PIOB->PIO_CODR = PIO_PB27;
    }
    return r;
  }
};

Gameduino 2 on arduino Due

Marek,

thanks for the ICSP2 information.

Btw. you can try to change
#define ILI9341_SPI_CLKDIVIDER 2 // for Due
to 1 in ILI9341_due_config.h and see if it still works for you. Should be even faster.

That is cool -- it works for me as far as I can say visually -- it is all so quick now!

Here are the runtimes in µs and factors -- speedups between 4.67 and 14.68 between Nano and Due:

Hermann.

Hi TFTLCDCyg,

I did run this simple code

  Serial.begin(9600);
  
  Serial.println(MISO);
  Serial.println(MOSI);
  Serial.println(SCK);
  Serial.println(SS);
#if defined(__SAM3X8E__)
  Serial.println("d");
#endif

and it outputs this on Mega 2560

50
51
52
53

and this on Due:

74
75
76
10
d

I found several "#define"s under "libraries/Firmata/src/Boards.h" for Arduino IDE 1.6.4.
While IS_PIN_SPI is defined for many boards, it is not defined for DUE.

#define IS_PIN_SPI(p)           ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)

It seems you were able to redefine which pins are associated with SPI in Gameduino.
Is that possible for 1.6.4 IDE as well?
If so, where to modify?

Hermann.

Hi Marek,

while my previous posting showed additional speedup by setting ILI9341_SPI_CLKDIVIDER to 1, that setting does not work when using the SD card attached to 2.2" display for sdFatTftBitmap demo of ILI9341_due graphics library with Arduino Due (incorrect display).

Arduino Due is really fast, a single picture gets loaded from SD card and displayed in 140ms!

This video of same same demo with same display but Arduino Nano shows the big speedup:

I only have the numbers just determined for Arduino Due:

...
1116
Loading image 'giraffe.565'
Loaded in 139 ms
Loading image 'soldHous.565'
Loaded in 140 ms
Loading image 'gloomyTe.565'
Loaded in 139 ms
Loading image 'motivati.565'
Loaded in 140 ms
Loading image 'smokeP.565'
Loaded in 139 ms
Loading image 'origP.565'
Loaded in 139 ms
Loading image 'radioP.565'
Loaded in 139 ms
Loading image 'stopP.565'
Loaded in 140 ms
1116
Loading image 'giraffe.565'
Loaded in 139 ms
...

Just used rowvid.com to determine time taken to display the 8 pictures with Nano (5.5s-13.7s in video).
With Nano a single picture takes 1025ms to load and display.
So Due gives a speedup of 7.32 compared to Nano and would allow for >7fps video display ...

Hermann.

HermannSW:
Hi Marek,

while my previous posting showed additional speedup by setting ILI9341_SPI_CLKDIVIDER to 1, that setting does not work when using the SD card attached to 2.2" display for sdFatTftBitmap demo of ILI9341_due graphics library with Arduino Due (incorrect display).

Yeah, I was getting the same most of the time too. I think it was working for me with divider 1 for Due SPI and half speed for SD SPI only once. I also mentioned it in the documentation: "I was getting distorted images when I tried to use the full speed for either of the SPIs.". I am not sure what the reason is, I did not get time to investigate it. Maybe the SPI signals (their slopes or something) are somehow influenced by the SD card (since it's on the same bus) and TFT is then not able to register them. Considering the display is suppose to work at 10MHz clock at max (according to datasheet) it's great that it still works at 80MHz (well..most of the time).