How to use a 1.3 inch screen with a sensor readout?
How to use a 1.3 inch screen with a sensor readout
You connect a 1.3 inch IPS display to a microcontroller like an ESP32 or Raspberry Pi Pico, then read sensor data from a device like a DHT22 or BMP280, and display that data on the screen in real time. The screen uses a 240x240 pixel resolution with an SPI interface, which means you can update it fast enough to show live sensor readings without lag. For example, the 1.3 inch 240x240 ips display uses a GC9A01 driver chip, which is common and has well-documented libraries for Arduino, CircuitPython, and MicroPython. You need to wire the display’s SPI pins (SCK, MOSI, DC, CS, RST) to your microcontroller, and then connect the sensor via I2C or analog pins. Once you power the system, the microcontroller reads the sensor every 500 milliseconds and pushes the data to the display buffer, which refreshes at 60 Hz. This setup works for temperature, humidity, pressure, gas, or motion sensors.
The hardware side is straightforward but requires attention to voltage levels. The display operates at 3.3V logic, but many sensors like the DHT11 run at 5V. If you use a 5V microcontroller like an Arduino Uno, you need a level shifter for the SPI lines, or you risk frying the display’s driver chip. I’ve seen people skip this and end up with a dead screen. The display draws about 30 mA at full brightness, and the sensor adds another 1-5 mA depending on the model. For a battery-powered project, you can drop the display’s backlight to 50% brightness, which cuts current to 15 mA, and put the sensor into sleep mode between reads. The BMP280, for instance, consumes 0.1 µA in sleep mode and 2.7 µA during a measurement. That gives you weeks of runtime on a 2000 mAh LiPo battery.
On the software side, you need to initialize the display and the sensor separately. For the display, you call a function like tft.begin() to set up the GC9A01 driver, then set the rotation and color depth. The 240x240 resolution means you have 57,600 pixels, and each pixel uses 16-bit color (RGB565), so the frame buffer is 115,200 bytes. That’s too large for the RAM on an Arduino Uno (2 KB), so you can’t use a full buffer. Instead, you draw directly to the display using SPI commands, which is slower but works. On an ESP32 with 520 KB of RAM, you can allocate a full buffer and update the screen in one shot, which lets you hit 60 frames per second. For sensor data, you read the sensor every 200-1000 milliseconds, depending on the sensor’s response time. The DHT22 takes 2 seconds to stabilize, so reading it faster than that gives you garbage data. The BMP280 can sample at 10 Hz, so you can update the display every 100 ms.
Let’s break down the wiring. The display has 6 pins: VCC, GND, SCK, MOSI, DC, CS, and RST. Some modules include a backlight pin (BL) that you can PWM to control brightness. Connect VCC to 3.3V, GND to ground, SCK to SPI clock (GPIO 18 on ESP32), MOSI to SPI MOSI (GPIO 23), DC to a GPIO pin (GPIO 2), CS to another GPIO (GPIO 5), and RST to a GPIO (GPIO 4). For the sensor, if it’s I2C, connect SDA and SCL to the microcontroller’s I2C pins (GPIO 21 and 22 on ESP32). If it’s analog, like a soil moisture sensor, connect the output to an ADC pin. The table below shows typical pin assignments for common microcontrollers:
| Microcontroller | Display SPI Pins | I2C Sensor Pins |
|---|---|---|
| ESP32 | SCK=18, MOSI=23, DC=2, CS=5, RST=4 | SDA=21, SCL=22 |
| Raspberry Pi Pico | SCK=2, MOSI=3, DC=4, CS=5, RST=6 | SDA=0, SCL=1 |
| Arduino Uno | SCK=13, MOSI=11, DC=9, CS=10, RST=8 | SDA=A4, SCL=A5 |
After wiring, you need to install libraries. For the display, use the Adafruit GC9A01A library or the TFT_eSPI library. The TFT_eSPI library is faster because it uses hardware SPI and has optimized drawing functions. For the sensor, use the Adafruit BMP280 library or DHT sensor library. In your code, you initialize the display with tft.init() and set the rotation to 0, 1, 2, or 3 depending on your mounting orientation. Then you clear the screen with tft.fillScreen(TFT_BLACK). For the sensor, you call bmp.begin() or dht.begin(). In the main loop, you read the sensor, format the data as a string, and draw it on the display. For example, to show temperature and humidity, you use tft.setCursor(x, y) and tft.print("Temp: " + String(temp) + " C"). You need to clear the old text before drawing new text, or you’ll see ghosting. You can do this by drawing a filled rectangle over the old text area.
One common issue is display flickering when you update the screen too often. The GC9A01A driver has a refresh rate of 60 Hz, but if you update the entire screen every loop, you’ll see tearing. The fix is to only update the parts of the screen that change. For a sensor readout, you only need to update the text area, not the background. Use tft.fillRect(x, y, w, h, TFT_BLACK) to clear the old text, then draw the new text. This reduces SPI traffic and keeps the display smooth. Another issue is the display’s color depth. The 16-bit color mode gives you 65,536 colors, but if you use 8-bit color, you get 256 colors and faster updates. For sensor data, 8-bit color is fine because you’re just showing numbers. You can switch to 8-bit mode by calling tft.setColorDepth(8) before initializing the display.
For advanced users, you can add a graphical interface. Instead of plain text, draw a bar graph for temperature or a line chart for pressure over time. The 240x240 resolution gives you 240 pixels for the X-axis and 240 for the Y-axis. For a bar graph, you map the sensor value to a pixel height. For example, if the temperature range is 0-50°C, you map 0 to 0 pixels and 50°C to 200 pixels. Then you draw a filled rectangle from the bottom of the screen to the mapped height. For a line chart, you store the last 240 readings in an array and draw lines between consecutive points. This uses more RAM but gives a professional look. The ESP32’s 520 KB RAM can handle 240 integer values easily.
Power management is critical for portable projects. The display’s backlight is the biggest power draw. You can control it with a PWM pin. Set the PWM frequency to 1 kHz and duty cycle to 50% to reduce brightness by half. The sensor’s power consumption varies. The DHT22 draws 1.5 mA during measurement and 0.5 mA in idle. The BMP280 draws 2.7 µA during measurement and 0.1 µA in sleep. For the ESP32, you can put it into deep sleep between readings. Wake it up every 10 seconds, read the sensor, update the display, and go back to sleep. This reduces average current to less than 100 µA, giving you months of battery life. The display’s RAM retains the last image during sleep, so the screen stays on without drawing power.
Real-world applications include weather stations, air quality monitors, and soil moisture meters. For a weather station, use a BME280 sensor (temperature, humidity, pressure) and display all three values on the screen. The BME280 has a 0.5°C accuracy for temperature, 3% for humidity, and 1 Pa for pressure. You can show the data in a table format on the screen. For example, put temperature in the top left, humidity in the top right, and pressure at the bottom. Use different colors for each value: white for temperature, blue for humidity, and green for pressure. The 1.3 inch screen is small enough to fit in a 3D-printed enclosure, and you can mount it on a wall or a desk.
For an air quality monitor, use a CCS811 sensor (eCO2 and TVOC) or an MQ-135 sensor (CO2 and NH3). The CCS811 outputs eCO2 in ppm and TVOC in ppb. The display can show these values as numbers and also as a color-coded indicator. For example, if eCO2 is below 400 ppm, show a green circle. If it’s between 400 and 1000 ppm, show a yellow circle. If it’s above 1000 ppm, show a red circle. The 240x240 resolution lets you draw a 50-pixel diameter circle easily. You can also add a trend arrow that shows whether the value is increasing or decreasing. Compare the current reading to the previous one, and draw an up arrow if it’s higher, a down arrow if it’s lower, and a dash if it’s the same.
For a soil moisture meter, use a capacitive soil moisture sensor (like the v1.2) that outputs an analog voltage from 0 to 3.3V. The sensor’s output is inversely proportional to moisture: dry soil gives 3.3V, wet soil gives 1.0V. You read the analog value with the microcontroller’s ADC, map it to a percentage (0% for dry, 100% for wet), and display it on the screen. You can also show a water drop icon that fills up based on the moisture level. The display’s SPI interface is fast enough to update the icon every 100 ms, so you see real-time changes when you water the plant. The whole system runs on 3.7V LiPo battery with a voltage regulator. The display’s VCC pin can handle 3.3V to 5V, but the logic pins are 3.3V only, so use a regulator if your battery is fully charged at 4.2V.
If you’re using a Raspberry Pi Pico, you can run MicroPython instead of C++. The MicroPython library for the GC9A01A is called st7789py or gc9a01py. You initialize the display with SPI pins and then use display.text() to draw text. The Pico’s 264 KB RAM is enough for a full frame buffer if you use 8-bit color. But if you use 16-bit color, the buffer is 115,200 bytes, which leaves 148 KB for other tasks. That’s fine for sensor reading and display updates. The Pico’s ADC has 12-bit resolution, so you can read analog sensors with 0.1% accuracy. For the DHT22, you need a one-wire library, which is available in MicroPython. The code is simpler than C++ but runs slower. The Pico’s 133 MHz clock can handle 10 updates per second, which is enough for most sensors.
For the ESP32, you can use the Arduino IDE or PlatformIO. The ESP32 has two cores, so you can run the sensor reading on core 0 and the display update on core 1. This prevents the display from freezing during sensor reads. The sensor reading function uses delay(500) to wait for the sensor to stabilize, but this blocks the display update. By using xTaskCreatePinnedToCore(), you create a separate task for the sensor that runs on core 0, while the display task runs on core 1. The two tasks communicate via a global variable. The sensor task writes the latest reading to the variable, and the display task reads it every 100 ms. This gives you smooth updates even if the sensor takes 2 seconds to respond.
One mistake beginners make is not using pull-up resistors for the SPI lines. The display’s CS and DC pins need pull-up resistors to 3.3V to prevent floating during startup. If you don’t use them, the display might not initialize correctly. Use 10 kΩ resistors for each pin. The RST pin also needs a pull-up resistor, but some display modules have it built-in. Check the datasheet. For the sensor, I2C lines need pull-up resistors as well. Most I2C sensor modules have them built-in, but if you’re using a bare sensor, add 4.7 kΩ resistors to SDA and SCL. Without them, the sensor won’t communicate.
Another issue is the display’s SPI clock speed. The GC9A01A supports up to 80 MHz, but the microcontroller’s SPI peripheral might not go that high. The ESP32’s hardware SPI can run at 40 MHz, which gives you a 0.6 ms update time for a full screen. The Raspberry Pi Pico’s SPI can run at 62.5 MHz. The Arduino Uno’s SPI is limited to 8 MHz, which gives you a 3 ms update time. That’s still fast enough for sensor readouts. If you use software SPI, the speed drops to 1-2 MHz, which causes visible flickering. Always use hardware SPI if possible.
For the sensor data format, you can show integers or floating-point numbers. The display’s font library includes a 7-segment font that looks like a digital clock. You can use it for temperature and humidity values. The font size is 8x13 pixels, so you can fit 30 characters per line. With 240 pixels in height, you can show 18 lines of text. But for sensor data, you only need 2-3 lines. Use a larger font for the main value and a smaller font for the units. For example, show "25.4" in a 24-point font and "°C" in a 12-point font. The TFT_eSPI library includes font sizes from 1 to 8, where size 1 is 6x8 pixels and size 8 is 48x64 pixels. Experiment with sizes to fit your layout.
If you want to log data to an SD card, you can add an SD card module to the SPI bus. The display and SD card share the same SPI pins but use different CS pins. Set the display’s CS high when talking to the SD card, and vice versa. This is called SPI multiplexing. The ESP32 has two SPI buses, so you can use one for the display and one for the SD card. This avoids conflicts. The SD card can store sensor readings every minute, and you can later plot them on a computer. The 1.3 inch screen can show the number of logged entries or the last reading. The GC9A01A driver doesn’t have a built-in SD card slot, so you need an external module.
For wireless connectivity, add an ESP32 with Wi-Fi and send the sensor data to a cloud service like ThingSpeak or MQTT. The display shows the local reading, and the cloud stores the history. The ESP32’s Wi-Fi consumes 80 mA during transmission, so you only send data every 5 minutes to save power. The display updates every second from the local sensor. This setup is common in IoT weather stations. The 240x240 resolution is enough to show the current reading and a small icon for Wi-Fi signal strength. Use a Wi-Fi icon that shows bars for signal strength. The TFT_eSPI library includes bitmap drawing functions, so you can pre-load the icon as a byte array.
One more thing: the display’s viewing angle is 160 degrees, which is typical for IPS panels. But the 1.3 inch size means you need to be within 30 cm to read the text easily. For a wall-mounted project, use a larger font (size 4 or 5) so the text is readable from 1 meter away. The 240x240 resolution at 1.3 inches gives a pixel density of 261 PPI, which is sharp. You can display small graphics like icons or arrows without pixelation. The display’s contrast ratio is 1000:1, so text is clear even in bright light. The backlight is 300 cd/m², which is bright enough for indoor use but not direct sunlight. For outdoor use, add a light sensor and auto-adjust the backlight brightness.
For troubleshooting, if the display shows nothing, check the wiring first. Use a multimeter to verify that VCC is 3.3V and GND is connected. Then check the SPI pins with an oscilloscope or logic analyzer. The SCK pin should show a square wave when you run the initialization code. The MOSI pin should show data pulses. If the display shows random pixels, the initialization sequence might be wrong. The GC9A01A driver requires a specific sequence of commands, including sleep out, display on, and normal mode. The library handles this, but if you use a custom library, double-check the sequence. For the sensor, if the reading is always 0 or -999, the I2C address might be wrong. The BMP280’s default address is 0x76,