Skip to Content

Scribble on CrowPanel Pico 4.3″ Display

Scribble on CrowPanel Pico 4.3″ Display

In this tutorial you will learn how to get started with the CrowPanel Pico 4.3″ Display from ELECROW. The CrowPanel displays are great, since the have pretty much everything you need already built in. This includes a touch screen, an RP2040, a TF Card slot, a battery connector with charger, an I2C interface and even a buzzer.

However, the first steps in using the CrowPanel Pico can be a bit challenging. Hopefully this tutorial with some simple code examples will help you.

Note that we are specifically talking about the 4.3″ display version. The other, smaller screens in the CrowPanel Pico series use different display drivers and touch screens and the code examples will not work for those.

Let’s get started with the required part.

Required Parts

Obviously we will need the CrowPanel Pico 4.3″ Display. And if you want to connect some external hardware to test the GPIO port; some cables, resistors, LEDs and a breadboard will come in handy.

CrowPanel Pico 4.3″ Display

USB C Cable

Dupont wire set

Dupont Wire Set

Half_breadboard56a

Breadboard

Resistor & LED kit

Makerguides.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to products on Amazon.com. As an Amazon Associate we earn from qualifying purchases.

Features of the CrowPanel Pico 4.3″ Display

ELECROW offers various CrowPanel displays with integrated microcontrollers such as the ESP32 or the RP2040. For the ESP32 based displays have a look at our tutorials CrowPanel 2.8″ ESP32 Display : Easy Setup Guide and Digital Clock with CrowPanel 3.5″ ESP32 Display.

CrowPanel Pico 4.3" Display
CrowPanel Pico 4.3″ Display (source)

In this tutorial we will write some code for the CrowPanel Pico 4.3″ Display, which is an RP2040 based display. Compared to the ESP32 the RP2040 chip is less powerful but also cheaper, which is reflected in the price of the CrowPanel Pico displays.

Specification

The main specifications of the CrowPanel Pico 4.3″ Display are as follows:

  • 4.3″Pico Display: 320*240 resolution, IPS Panel, capacitive touch and support multi-touch
  • Raspberry Pi RP2040 Microcontroller (ARM Cortex-M0+): 32-bit dual-core chip with a maximum clock frequency of 133 MHz.
  • BW16 Wireless connection: Support 4GHz IEEE 802.11b/g/n and 5GHz spectrum range, support Bluetooth 5.0 and BLE
  • Energy Efficiency: Supports low-power sleep and hibernation modes, promoting energy conservation and environmental consciousness.
  • Interfaces: I2C, UART, IO ports, USB, a lithium battery interface, and a buzzer alarm

Other CrowPanel Pico Displays

As mentioned, there are several other CrowPanel Pico Displays with different display sizes but all of them are using the RP2040 as microcontroller.

Other CrowPanel Pico Displays
Other CrowPanel Pico Displays (source)

The CrowPanel Pico 4.3″ Display (marked yellow) used in this tutorial stands out due to its IPS Panel, the capacitive touch screen and the larger number of connectors.

Connectors of the CrowPanel Pico 4.3″ Display

In this section we will describe the pinout of the different connectors of the display in more detail. If you look at the back of the CrowPanel Pico 4.3″ Display you can see that there are 5 white connectors, a GPIO port, a USB and UART port, a TF card slot and two buttons (boot, reset).

Back of CrowPanel Pico 4.3" Display
Back of CrowPanel Pico 4.3″ Display

Note that the labels for the boot and reset button on the back are mixed up. If you open the housing and look at the board inside, you can see that the top button is actually “reset” and the button below is “boot” as indicated on the silk screen.

CrowPanel Pico 4.3" Display Board
CrowPanel Pico 4.3″ Display Board (source)

The labelling of the pins for the GPIO port at the top is also incorrect. It has only 15 labels but there are 16 pins (the label for GPIO2 is missing), which according to the schematics and the silk screen are as follows:

Silk screen for GPIO port
Silk screen for GPIO port (source)

So, from the front of the GPIO port the pinout is as shown below:

Pinout of GPIO port
Pinout of GPIO port

Next to the GPIO port are three connectors I2C, ADC and GPIO_2 that expose the following GPIO pins:

Pinout of GPIO_D, ADC and I2C connectors
Pinout of GPIO_D, ADC and I2C connectors (top)

As you can see there are unused pins for the GPIO_D and I2C connectors. GPIO26, GPIO27, and GPIO28 are ADC pins that can be used to read analog signals. Finally there is another GPIO_D port at the side of the board, which has the following pinout:

Pinout of GPIO_D port (side)
Pinout of GPIO_D port (side)

Otherwise, there is a connector for a LiPo battery, and the USB and UART connectors.

Installation of RP2040 Core

Before you can program the RP2040 within a CrowPanel Pico Display you first need to install the RP2040 core. Go to File -> Preferences and open the Preferences Dialog

File -> Preferences Menu
File -> Preferences Menu

In the Preferences Dialog go to the Settings Tab. At the bottom you will see “Additional boards manager URLs:”. Click on the button to the right (marked yellow) to open the URL editor

Settings Tab in Preferences Dialog
Settings Tab in Preferences Dialog

In the URL editor add the following URL to the list (marked yellow below):
“https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json”

Add package_rp2040_index URL to board manager
Add package_rp2040_index URL to board manager

As you can see above, I have also installed the ESP8266 and the ESP32 cores but you need only the RP2040 core for this project.

Installation of RP2040 Boards

Next we need to install the RP2040 Boards. Go to Tools -> Board -> Board Manager and search for pico into the search bar. Install the Raspberry Pi Pico/RP2040 boards by Earle F. Philhower. After installation it should look like this.

Raspberry Pi Pico/RP2040 board
Install Raspberry Pi Pico/RP2040 board

Select Adafruit Feather RP2040 DVI board

Once the installation of the RP2040 core is completed go the Board Manager and select the “Adafruit Feather RP2040 DVI” board as shown below:

Adafruit Feather RP2040 DVI in Bord Manager

Now we should be ready to program the CrowPanel Pico Display.

Testing the GPIO_D port of CrowPanel Pico 4.3″ Display

Let’s start with a simple Blink program to test that we can actually program the display. Connect an LED with a resistor (100…220Ω) to the GPIO_D port at the side of the display as shown below

Connecting LED to GPIO_D
Connecting LED to GPIO_D

The cathode of the LED needs to be connected to the GND pin of the GPIO_D port and the right most pin of the port is GPIO22, which needs to be connected to the resistor and positive LED pin.

Then upload the following blink program to the board (Adafruit Feather RP2040 DVI) and the LED should start blinking.

const int ledPin = 22;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
}

There is no need to hold the boot or reset button to switch the board into programming mode.

Note that the GPIO22 pin is a PWM pin, so you could also dim the LED. Here is the corresponding loop() function to test this.

void loop() {
  for (int b=0; b<=255; b++) {
    analogWrite(ledPin, b);
    delay(10);
  }
}

If this all works we now can try something a bit more interesting. In the next sections, we first write to the display, then we test the touchscreen and finally we implement a simple Scribble application.

Write on CrowPanel Pico 4.3″ Display

Before we can draw or write anything on the Pico Display we need to install the PicoDVI library. Open the Library Manager, search for PicoDVI and install the PicoDVI – Adafruit Fork by Luke Wren as shown below:

PicoDVI Library installed in Library Manager
PicoDVI Library installed in Library Manager

Once the library is installed we can write to and draw on the display. Below a short test program that writes the text “Makerguides” on the display:

// Display code example for CrowPanel Pico 4.3" Display
// by Makerguides

#include <PicoDVI.h>

DVIGFX16 disp(DVI_RES_320x240p60, picodvi_dvi_cfg);

void setup() {
  if (!disp.begin())
    ;
  disp.setRotation(0);
  disp.fillScreen(0x0000);
  disp.setTextSize(3);
  disp.setCursor(10, 10);
  disp.print("Makerguides");
}

void loop() {
}

The code starts by including the PicoDVI library and creating the display object.

#include <PicoDVI.h>

DVIGFX16 disp(DVI_RES_320x240p60, picodvi_dvi_cfg);

The most important part here is to set the correct resolution (DVI_RES_320x240p60) that matches the hardware resolution of the display. In our case this is 320×240 pixels. Note that the PicoDVI library offers constructors for framebuffers with different depths. Here we defining a 16bit (DVIGFX16) framebuffer, but there is also DVIGFX8 and DVIGFX1.

In the setup function we wait for the display, set the display orientation, fill the background with a black color, set the text size, and finally write the text at cursor position (10,10).

void setup() {
  if (!disp.begin())
    ;
  disp.setRotation(0);
  disp.fillScreen(0x0000);
  disp.setTextSize(3);
  disp.setCursor(10, 10);
  disp.print("Makerguides");
}

If you upload the code you should see the text “Makerguides” on your display as shown below.

Text written to CrowPanel Pico Display
Text written to CrowPanel Pico Display

Note that PicoDVI Library is derived from Adafruit-GFX-Library and has many more functions. For instance, you can choose different fonts and draw graphics as well. We will use some of these functions to implement our Scribble application.

In the next section, however, we first will get the touchscreen working.

Use Touchscreen of CrowPanel Pico 4.3″ Display

According to the code examples for the CrowPanel Pico 4.3″ Display, the touchscreen can be controlled with the gt911-arduino library by TANCtec. However, neither the code example (TouchPrint.ino) worked; nor could I get my code working with the original gt911-arduino library. Some, issue with setting SDA and SCL pins in the Wire library that I didn’t bother chasing down.

However, what worked was to copy the files TAMC_GT911.h and TAMC_GT911.c of the code example TouchPrint to a new project folder (MyTouchPrint) and use the code I show you below. Your project folder should look like this and you can download my MyTouchPrint example here.

Contents of MyTouchPrint project folder
Contents of MyTouchPrint project folder

The following code simply prints out the coordinates (and the size of the touch) on the touchscreen where a new touch was detected.

// Touchscreen code example for CrowPanel Pico 4.3" Display
// by Makerguides
#include "TAMC_GT911.h"

#define TS_SCL 21
#define TS_SDA 20
#define TS_INT 25
#define TS_RST 29
#define TS_WIDTH 800
#define TS_HEIGHT 480

TAMC_GT911 ts = TAMC_GT911(TS_SDA, TS_SCL, TS_INT, TS_RST, TS_WIDTH, TS_HEIGHT);

void ts_init() {
  ts.begin();
  ts.setRotation(ROTATION_INVERTED);
  delay(100);
}

void ts_process() {
  static uint16_t ox = 0, oy = 0;
  uint16_t x = ts.points[0].x;
  uint16_t y = ts.points[0].y;
  uint8_t s = ts.points[0].size;
  if (x != ox || y != oy) {
    ox = x; oy = y;
    Serial.printf("P: %4d %4d (%d)\n", x, y, s);
  }
}

void setup() {
  Serial.begin(9600);
  ts_init();
}

void loop() {
  ts.read();
  if (ts.isTouched) {
    ts_process();
  }
}

The code starts by including the TAMC_GT911 library, which files we have copied to the MyTouchPrint project folder. We then define the pins the touchscreen is controlled by and the size of the touchscreen (800×400). Finally, we use these constants to create the touchscreen object TAMC_GT911 ts.

#include "TAMC_GT911.h"

#define TS_SCL 21
#define TS_SDA 20
#define TS_INT 25
#define TS_RST 29
#define TS_WIDTH 800
#define TS_HEIGHT 480

TAMC_GT911 ts = TAMC_GT911(TS_SDA, TS_SCL, TS_INT, TS_RST, TS_WIDTH, TS_HEIGHT);

ts_init function

The ts_init() function initializes the touch screen by calling ts.begin() and setting the screen orientation (portrait mode). I added a short delay, since the touchscreen tended to detect random touch events at the start.

void ts_init() {
  ts.begin();
  ts.setRotation(ROTATION_INVERTED);
  delay(100);
}

ts_process function

The ts_process(), processes touch events. It remembers the previous touch coordinates (ox, oy) and only reacts to new touches. If the new touch coordinates (x, y) are different from the previous ones (ox, oy), it prints out the coordinates and size of the touch.

void ts_process() {
  static uint16_t ox = 0, oy = 0;
  uint16_t x = ts.points[0].x;
  uint16_t y = ts.points[0].y;
  uint8_t s = ts.points[0].size;
  if (x != ox || y != oy) {
    ox = x; oy = y;
    Serial.printf("P: %4d %4d (%d)\n", x, y, s);
  }
}

The GT911 touchscreen controller is really neat. Not only can it detect the size of a touch (thumb vs fingertip), it is also multitouch capable and can detect up to 5 simultaneous touches. Though, the code above only reports the first one (points[0]).

setup function

In the setup() function, we just initialize the serial communication and the touchscreen. Make sure to set the baud rate for your Serial Monitor to 9600 baud.

void setup() {
  Serial.begin(9600);
  ts_init();
}

loop function

Finally, we have the loop() function. It reads the touchscreen, checks if a touch was detected and if so, processes it.

void loop() {
  ts.read();
  if (ts.isTouched) {
    ts_process();
  }
}

Output on Serial Monitor

If you upload code and then touch the four corners of the display screen you should see touch coordinates similar to the following ones printed to the Serial Monitor.

Touch coordinates printed to Serial Monitor
Touch coordinates printed to Serial Monitor

Issues

I occasionally encountered strange issues, where either the touchscreen did not register touches or reported “auto-switch to second address”, which didn’t help either. The GT911 supports two I2C addresses: 0xBA/0xBB and 0x28/0x29, and the TAMC_GT911 library tries the second address if it cannot find the touchscreen at the first address.

Resetting or unplugging the display helped and the issue occurred rarely. But there seems to be some reliability issue and I don’t know what is causing it. The display was powered via USB, so it can’t be the power supply.

Scribble on CrowPanel Pico 4.3″ Display

By now you have learned how to write to the display and how to detect touches. Let’s combine this and build a little Scribble application that allows the user using a finger to draw on the display.

It will be a minimal example, supporting only one drawing color but you could easily extend it to multiple colors and multitouch. Here is the complete code.

// Scribble code example for CrowPanel Pico 4.3" Display
// by Makerguides

#include "PicoDVI.h"
#include "TAMC_GT911.h"

#define TS_SCL 21
#define TS_SDA 20
#define TS_INT 25
#define TS_RST 29
#define TS_WIDTH 800
#define TS_HEIGHT 480

DVIGFX16 disp(DVI_RES_320x240p60, picodvi_dvi_cfg);
TAMC_GT911 ts = TAMC_GT911(TS_SDA, TS_SCL, TS_INT, TS_RST, TS_WIDTH, TS_HEIGHT);

uint16_t rgb(byte r, byte g, byte b) {
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

void ts_init() {
  ts.begin();
  ts.setRotation(ROTATION_INVERTED);
  delay(100);
}

void ts_process() {
  static uint16_t ox = 0, oy = 0;
  uint16_t x = ts.points[0].x;
  uint16_t y = ts.points[0].y;
  uint8_t s = ts.points[0].size;
  if (x != ox || y != oy) {
    ox = x; oy = y;
    int16_t sx = map(x, 0, TS_WIDTH, 0, disp.width());
    int16_t sy = map(y, 0, TS_HEIGHT, 0, disp.height());
    tone(19, 100, 10);
    disp.fillCircle(sx, sy, s / 3, rgb(255, 255, 100));
  }
}

void disp_init() {
  if (!disp.begin())
    ;
  disp.setRotation(0);
  disp.fillScreen(rgb(0, 0, 0));
  disp.setTextSize(1);
  disp.setCursor(10, 10);
  disp.print("Scribble");
}

void setup() {
  disp_init();
  ts_init();
}

void loop() {
  ts.read();
  if (ts.isTouched) {
    ts_process();
  }
}

As before, you will need to have installed the PicoDVI. And the TAMC_GT911.h and TAMC_GT911.c files need to be copied into you project folder.

Libraries and Objects

Creating the display object DVIGFX16 disp and the touchscreen object TAMC_GT911 ts, is the same as in the display and touchscreen examples before.

rgb function

The rgb() function converts an RGB color to an RGB565 (or 16 bit) color, which are the color codes the PicoDVI library is using. You could use an RGB55 color picker to find the code for specific colors but RGB colors are more common and easier to use. I therefore implemented this simple converter function that converts an RGB color to an RGB565 color.

uint16_t rgb(byte r, byte g, byte b) {
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

ts_init function

The ts_init() remains as before. It starts the touchscreen and sets the orientation. For other screen orientations have a look at the TAMC_GT911.h file.

ts_process function

The ts_process() function is slightly extended compared to the touchscreen example shown before. Specifically, it converts the higher resolution (800, 480) touchscreen coordinates to the lower resolution (320, 240) display coordinates using the map function.

void ts_process() {
  static uint16_t ox = 0, oy = 0;
  uint16_t x = ts.points[0].x;
  uint16_t y = ts.points[0].y;
  uint8_t s = ts.points[0].size;
  if (x != ox || y != oy) {
    ox = x; oy = y;
    int16_t sx = map(x, 0, TS_WIDTH, 0, disp.width());
    int16_t sy = map(y, 0, TS_HEIGHT, 0, disp.height());
    tone(19, 100, 10);
    disp.fillCircle(sx, sy, s / 3, rgb(255, 255, 100));
  }
}

Once a touch is detected, it plays a short sound using the tone() function, and then draws a yellow circle at the converted touch coordinates (sx, sy) with a radius proportional to touch size (s/3).

The code uses the internal buzzer that is connected to GPIO19. I didn’t have to set the pin mode to OUTPUT for the buzzer pin, but maybe it is better to do that anyway.

disp_init function

The disp_init() functions initializes the display and the only differences is that we are writing the text “Scribble” instead of “Makerguides”. This simply tells us, that the application is ready. But you could also play a sound instead.

setup and loop functions

In the setup() function we call the initializer functions for the display and the loop() function remains unchanged.

Example screen output

If you upload the code and touch the screen you should be able to draw “circles” with different diameters using your fingertip or thumb as shown below:

Circles drawn on display at touch points
Circles drawn on display at touch points

Since the screen resolution is 320×240 and does not match the screen dimensions the “circles” appear as ellipses.

And that completes this tutorial. You now have a little Scribble application that you can extend to your liking.

Conclusions

In this tutorial you learned how to control the CrowPanel Pico 4.3″ Display. Specifically, we looked at code examples on how to detect touches and how to draw on the screen.

The CrowPanel Pico 4.3″ has an IPS display with good viewing angles and colors. The PicoDVI library, which is fork of the Adafruit-GFX-Library was simple to set up and is much easier to get started with than the provided SquareLine Studio example code. On the other hand, SquareLine Studio allows you to create much more advanced and attractive user interfaces.

The capacitive touchscreen of the CrowPanel Pico 4.3″ Display is sensitive and can detect size and multitouch – enabling gesture recognition such as pinching or rotation. However, the provided code example didn’t work for me and figuring out how to actually detect touches was quite time consuming. I hope the example in this tutorial helps.

Similarly, I hope the documentation of the GPIO_D, ADC and I2C is useful and will make it easier to use the display in your projects. If you have any questions, feel free to leave them in the comment section.

Happy tinkering ; )