Grove 1.2-inch IPS Display v1.0

Anybody know how to set this display up to run 2 wire on the XIAO ESP32

The example code is for an old arduino using Ports and throws compile errors

The other libraries for tft ST7789 use the more wire setup, also i am using XIAO Grove Expansion Board so i need to use pin sets that are on that board connector


just black screen

Can anyone help me with this?

Hi there,
I’m pretty sure it’s not I2C , but SPI with not MISO(9) SCL would be (8)SCLK and MOSI(10) for SDA
ie. no Address associated with it being I2C but try a scanner run first to verify it’s not an I2C obscured address device. Also note with any spi device the init needs to Assert the pins prior to the SPI.begin();
GL :slight_smile: PJ :v:

If it’s the RGB-OLED ST7789 ver. 1.0
I have one around this pile somewhere If I’m able to locate it I’ll try it out and post. :v:

Yes… V1.0… no IIC

I think you are right, that is about as far as my troubleshooting has got me

The problem being that XIAO Expansion boards do not expose 8 and 10 together in a port
So i need a software solution

Can i define any pin, i think that was what the original “Fast” lib was trying to do was bit bang the output… I am sure it is something simple i dont know YET… lol I tried many different libs and have not gotten it to work, and i think a large part of the problem is the grove connector,… no one else is writing libs or tutorials to service this ecosystem

I am wondering if their is a 2 wire constructor that i do not know

Remember I posed the question of Grove SPI on the Discord… but did not get any engagement!

Maybe Citric would know… but I try not to monopolize

I dont like being Helplessly Hopeless … or Hoplessly Helpless…

Hi there,
So I found an old UNO I had. Hooked it up ,copy & pasted code ,compiled and worked without edit.

#include <Adafruit_GFX.h>
#include <Arduino_ST7789_Fast.h>

#define SCK   7
#define SDA   8

Arduino_ST7789 lcd = Arduino_ST7789(SCK, SDA);

void setup(void)

    lcd.setCursor(0, 0);
    lcd.println("HELLO WORLD");

void loop()


compiler output…

FQBN: arduino:avr:uno
Using board 'uno' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6
Using core 'arduino' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6

Detecting libraries used...
Using library Adafruit GFX Library at version 1.11.9 in folder: D:\Arduino_projects\libraries\Adafruit_GFX_Library 
Using library Adafruit BusIO at version 1.16.1 in folder: D:\Arduino_projects\libraries\Adafruit_BusIO 
Using library Wire at version 1.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\Wire 
Using library SPI at version 1.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\SPI 
Using library Fast ST7789 Library at version 1.0.4 in folder: D:\Arduino_projects\libraries\Fast_ST7789_Library 
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\39D9A1C7B5D071B7F4BC89D551846045/sketch_jun23c.ino.elf"
Sketch uses 7514 bytes (23%) of program storage space. Maximum is 32256 bytes.
Global variables use 258 bytes (12%) of dynamic memory, leaving 1790 bytes for local variables. Maximum is 2048 bytes.
"C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude" "-CC:\Users\Dude\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf" -v -V -patmega328p -carduino "-PCOM16" -b115200 -D "-Uflash:w:C:\Users\Dude\AppData\Local\Temp\arduino\sketches\39D9A1C7B5D071B7F4BC89D551846045/sketch_jun23c.ino.hex:i"

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean,
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\Dude\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM16
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "C:\Users\Dude\AppData\Local\Temp\arduino\sketches\39D9A1C7B5D071B7F4BC89D551846045/sketch_jun23c.ino.hex"
avrdude: writing flash (7514 bytes):

Writing | ################################################## | 100% 1.21s

avrdude: 7514 bytes of flash written

avrdude done.  Thank you.

Looks good, BRIGHT!! I’ll try the Nrf52840 and ESP32’s as time permits. Long and short of it is it’s not I2C and probably needs SPI to run on the others.
GL :slight_smile: PJ
time for refreshment

1 Like

Thanks boss… I also have been working… I pulled out my male and female dupont connector to Grove connectors and hardwired

Also working on a source code that had a bunch of unnecessary extras and trying to clean it up … right now the code is blocking my serial montor… as soon as the code uploads the USB link goes down… i think the code is manipulating the pins the USB is on…

what pin do i tell the code to use for chip select and reset if i am not using them

Hi there,
-1 for the reset , makes it use the arduino’s or mcu’s , You must define a CS even if you don’t use one the LIB requires it. also you have to Set and reset the SCL and SDA pins prior to the Begin();(that’s what the FAST lib is doing also.
on the uno it only worked on the PINS allowed to be spi pins, the i2c pins were a no go as well.
GL :slight_smile: PJ

  This is a library for the ST7789 IPS SPI display.


#include <Adafruit_GFX.h>    // Core graphics library by Adafruit
#include <Arduino_ST7789.h> // Hardware-specific library for ST7789 (with or without CS pin)
#include <SPI.h>

#define TFT_DC    -1
#define TFT_RST   -1

#define TFT_MOSI  10   // for hardware SPI data pin (all of available pins)
#define TFT_SCLK  8   // for hardware SPI sclk pin (all of available pins)
Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK); //for display without CS pin
//Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin

float p = 3.1415926;

void setup(void) 
{//Begin Main Setup

  Serial.println("Hello! ST7789 TFT Test");
  tft.init(240, 240);   // initialize a ST7789 chip, 240x240 pixels

}//  End Main Setup

void testlines(uint16_t color) 
{//Begin testlines
  for (int16_t x=0; x < tft.width(); x+=6) 
	{//Begin for
    tft.drawLine(0, 0, x, tft.height()-1, color);
  }//  End for
  for (int16_t y=0; y < tft.height(); y+=6) 	
	{//Begin for
    tft.drawLine(0, 0, tft.width()-1, y, color);
  }//  End for

  for (int16_t x=0; x < tft.width(); x+=6) 	
	{//Begin for
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
  }//  End for
  for (int16_t y=0; y < tft.height(); y+=6) 	
	{//Begin for
    tft.drawLine(tft.width()-1, 0, 0, y, color);
  }//  End for

  for (int16_t x=0; x < tft.width(); x+=6) 
	{//Begin for
    tft.drawLine(0, tft.height()-1, x, 0, color);
  }//  End for
  for (int16_t y=0; y < tft.height(); y+=6) 	
	{//Begin for
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
  }//  End for

  for (int16_t x=0; x < tft.width(); x+=6) 
	{//Begin for
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
  }//  End for
  for (int16_t y=0; y < tft.height(); y+=6) 
	{//Begin for
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
  }//  End for
}//  End testlines

void testdrawtext(char *text, uint16_t color) 
{//Begin testdrawtext
  tft.setCursor(0, 0);
}//  End testdrawtext

void testfastlines(uint16_t color1, uint16_t color2) 
{//Begin testfastlines
  for (int16_t y=0; y < tft.height(); y+=5) 
	{//Begin for
    tft.drawFastHLine(0, y, tft.width(), color1);
  }//  End for
  for (int16_t x=0; x < tft.width(); x+=5) 
	{//Begin for
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }//  End for
}//  End testfastlines

void testdrawrects(uint16_t color) 
{//Begin testdrawrects
  for (int16_t x=0; x < tft.width(); x+=6) 
	{//Begin for
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }//  End for
}//  End testdrawrects

void testfillrects(uint16_t color1, uint16_t color2) 
{//Begin testfillrects
  for (int16_t x=tft.width()-1; x > 6; x-=6) 
	{//Begin for
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }//  End for
}//  End testfillrects

void testfillcircles(uint8_t radius, uint16_t color) 
{//Begin testfillcircles
  for (int16_t x=radius; x < tft.width(); x+=radius*2) 
	{//Begin for-1
    for (int16_t y=radius; y < tft.height(); y+=radius*2) 
		{//Begin for-2
      tft.fillCircle(x, y, radius, color);
    }//  End for-2
  }//  End for-1
}//  End testfillcircles

void testdrawcircles(uint8_t radius, uint16_t color) 
{//Begin testdrawcircles
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) 
	{//Begin for-1
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) 
		{//Begin for-2
      tft.drawCircle(x, y, radius, color);
    }//  End for-2
  }//  End for-1
}//  End testdrawcircles

void testtriangles() 
{//Begin testtriangles
  int color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) 
	{//Begin for
    tft.drawTriangle(w, y, y, x, z, x, color);
  }//  End for
}//  End testtriangles

void testroundrects() 
{//Begin testroundrects
  int color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) 
	{//Begin for-1
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) 
		{//Begin for-2
      tft.drawRoundRect(x, y, w, h, 5, color);
    }//  End for-2
  }//  End for-1
}// End testroundrects

void tftPrintTest() 
{//Begin tftPrintTest
  tft.setCursor(0, 30);
  tft.println("Hello DSTIKE");
  tft.println("Hello DSTIKE");
  tft.println("Hello DSTIKE");
  tft.setCursor(0, 0);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.print(millis() / 1000);
  tft.print(" seconds.");
}//  End tftPrintTest

void mediabuttons() 
{//Begin mediabuttons
  // play
  tft.fillRoundRect(25, 10, 78, 60, 8, WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, RED);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, GREEN);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, BLUE);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, GREEN);
  tft.setCursor(60, 200);
}//  End mediabuttons

void tftLoop(void)
{//Begin tftLoop
  Serial.println("Begin TFT Loop");

  uint16_t time = millis();
  time = millis() - time;

  Serial.println(time, DEC);

  // large block of text
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", WHITE);

  // tft print function

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, GREEN);

  // line draw test

  // optimized lines
  testfastlines(RED, BLUE);


  testfillrects(YELLOW, MAGENTA);

  testfillcircles(10, BLUE);
  testdrawcircles(10, WHITE);




}//  End tftLoop

void loop() 
{//Begin Main Loop Function
	tftLoop(); //tft Demo Loop
}//  End Main Loop Function

I got this working on XIAO ESP32C3… i get the serial monitor feedback… but screen is backlight on but screen black

GL :slight_smile: PJ

1 Like

So you didn’t get it going then?, look at using the older LIBs, check the compiler output.
all the examples appear to work properly.

Pins need to be the right ones too. :+1:

GL :slight_smile: PJ

Thanks PJGatto for reminding me sometimes you just have to go back to basics

I dug out my old Atruino Uno… what da?

1 Like

Im now trying to use tft_espi same as round display to work on esp devices… still working on user config file

Hi there,
Yea , I dabbled a bit with TFT_eSPI.lib, but you still need to do some SPI transaction code in front of it to get it to work, FYI. Also RUN the “Read_User_Setup.ino” (in examples, under diags) code after you edit your config.h to see the settings.
I have found they must be SPot on and agree with the PINOUTs to work.
GL :slight_smile: PJ

output like this.

TFT_eSPI ver = 2.4.2
Processor    = Generic
Transactions = Yes
Interface    = SPI
Display driver = 7789
Display width  = 240
Display height = 320

MOSI    = GPIO -1
MISO    = GPIO -1
SCK     = GPIO -1
TFT_CS   = GPIO -1
TFT_DC   = GPIO -1

Font GLCD   loaded
Font 2      loaded
Font 4      loaded
Font 6      loaded
Font 7      loaded
Font 8      loaded
Smooth font enabled

Display SPI frequency = 10.00

Go watch this Video , to help you make sense of it all.

do you know how to declare the user setup in the code and not the lib? I am thinking an include… but which one do you remove? i know the lib has some error checking to keep you from double defining…

It’s in the first few lines of the TFT_eSPI.h thats loaded by the include of the main LIB. LiB say’s
#include user setups selects.h" kinda thing.
GL :slight_smile: PJ

also when you are done with edits. copy "USER_SETUP.h " to the root LIBRARY folder for it to take.

Im gonna just put it in with all the other setups in User Setups Folder… I think
I just dont want to mess up my XIAO Round display code…

Hi there,
Yes I copy all of them to a seperate folder as backup, If you change or roll back versions it wipes them out, FYI. :stuck_out_tongue_closed_eyes: :face_with_peeking_eye: :v:

1 Like

You know i got the ball example to work… but the basic hello world still throws an error… What da?