Cheap Yellow Display Window

by jonathanr4242 in Circuits > Arduino

320 Views, 1 Favorites, 0 Comments

Cheap Yellow Display Window

openning_shot_resize.png
ESP32 Cheap Yellow Display Window

I built a “window” using ESP32 Cheap Yellow Displays (CYDs) as the glass panels.

The setup uses:

  1. 16 CYDs arranged in a 4×4 grid
  2. A Raspberry Pi Zero with a camera on a servo pan-tilt
  3. The Pi captures video, splits it into tiles, and streams each tile to a display

Each screen shows a portion of the image, so together they act like a digital window.

Touching a screen moves the camera, so you can “look around” like a real window.

The full code is here:

https://github.com/jonathanrandall/CYD_window


How It Works (Quick Overview)

  1. The Raspberry Pi captures video
  2. It splits the image into a grid (default 4×4)
  3. Each display subscribes to a specific tile. For example, the display at position (0,0) receives the top-left image.
  4. Touch input from a CYD sends a command back to the Pi
  5. The Pi moves the camera using the servos

Supplies

supplies_1.JPEG
cyds.JPEG

Supplies

You will need:

  1. Raspberry Pi Zero WH (WiFi + headers required)
  2. Raspberry Pi Camera
  3. 2 × Servos (MG996R is preferred but SG90 should also work)
  4. Servo pan-tilt bracket
  5. PCA9685 servo driver (I2C)
  6. 16 × Cheap Yellow Displays (ESP32)
  7. Adjustable buck converter (~6V for servos)
  8. 3 X 5V regulators (for Pi and CYDs)
  9. Batteries (2S or 3S LiPo)
  10. Switch
  11. WAGO connectors
  12. Wire (12–16 AWG for power)
  13. Jumper wires
  14. Wood (or other material) for frame

Note: There are many ways to power and build this. For example, the Pi can run from a power bank, and the frame can be wood, aluminium, or 3D printed.

Setup the Raspberry Pi

Install dependencies:


sudo apt update
sudo apt install python3-pip python3-opencv python3-numpy python3-picamera2
pip3 install adafruit-blinka
pip3 install adafruit-circuitpython-pca9685


Enable I2C:

sudo raspi-config
# Interface Options → I2C → Enable


Clone the repo:

git clone https://github.com/jonathanrandall/CYD_window.git


Getting the Camera Streaming

pi_zero_stream3.png

In this step we get the Raspberry Pi camera streaming sub-images over the network. We test that everything is working on the Pi before connecting the ESP32 Cheap Yellow Display. This step is important. It allows you to debug networking and streaming issues before adding the ESP32 displays.


Place these files on your Pi:

~/rnt_stream/
├── stream_server7.py
└── test_servo.py


Run the stream:

python3 stream_server7.py


Open in your browser:

http://your_pi_name.local:7123/index.html


Using the .local hostname avoids issues where the Pi’s IP address changes. This is important because the ESP32 code uses a hard coded address.


Expected Result

  1. A 4×4 grid of live camera images. You can change the grid_size parameter in the python code to vary this.
  2. Smooth updates (not necessarily high FPS)

If It Doesn’t Work

  1. Try using the IP instead:
hostname -I
  1. Check WiFi connection
  2. Make sure port 7123 is reachable


You should see the camera stream to a 4x4 grid (16 images). The grid size is set to 4 in the python code.

grid_size = 4

Building the Servo Pan-Tilt

pan_tilt5.JPEG
pan_tilt2.JPEG
pan_tilt3.JPEG
pan_tilt4.JPEG

In this step we assemble the servo pan-tilt mechanism and mount the raspberry pi, raspberry pi camera and pca9685 servo driver on it. The freecad file and STL files shown in the images are in the git repo for this project (directory print_files_3D). In the next step, we will set up the power/battery connections for the pan-tilt mechanism.

Assemble:

  1. Pan-tilt bracket with 2 servos and (optional) 3d printed base mount.
  2. Camera mount (3d printed mount also holds raspberry pi)
  3. Raspberry Pi + camera
  4. PCA9685

Important

Center the servos before assembling (use a servo tester or script).

Wiring (PCA9685 → Pi)

  1. SDA → GPIO2
  2. SCL → GPIO3
  3. VCC → 3.3V
  4. GND → GND

Powering the Raspberry Pi Zero and the Servos

power_servo.JPEG

In this step, we set up the battery connection for the pi zero WH and the servos. For this step I use two voltage converters, a variable buck converter set at 6V for the servos, and a fixed 5V converter for the pi. While it is possible to run both off the 5V converter, its not recommended because the current draw from the servos can cause ripple on the pi voltage. The pi needs a good quality voltage signal.

Use:

  1. 5V regulator → Raspberry Pi
  2. ~6V buck converter → servos

Why separate supplies?

Servos draw high current spikes, which can cause voltage drops and instability on the Pi.

Wiring Overview

  1. Battery → switch → WAGO
  2. WAGO → regulators
  3. 5V → Pi
  4. 6V → PCA9685 (V+)
  5. Servos → PCA9685

Expected Result

  1. Pi boots normally
  2. Servos don’t jitter or reset the Pi


Other power options are possible. For example, a power bank may work for the pi zero W, but the servos will still require a separate supply.


At this point we should have:

  1. the servo driver and the pi connected to the battery
  2. the servos connected to the servo driver
  3. the servo driver connected to the i2c of the pi.

Test the Servos

pi demo

In this step we get the servos up and running.

Run:

python3 test_servo.py

Observe direction:

  1. Note which way the camera moves when duty cycle value increases

Now test via browser:

http://your_pi_name.local:7123/touch00

Expected Result

  1. Camera moves diagonally to face bottom right

This is intentional: touching a part of the “window” moves the camera in the direction you would naturally look.

For example touch00 is the command the top-left touchscreen tile will send to the Raspberry Pi when it is pressed. We want the top-left screen to move the camera diagonally down and to the right, because that corresponds to the direction you would look if this were a real window. The code is set up, so if you touch one of the corner CYDs, the servos move in the opposite diagonal from that corner, if you touch the top (not corner) the servos move down and if you touch the right side, the servos move left.

Try:

touch01
touch11


If Direction Is Wrong Adjust the servo direction (if needed)

If the servo moves in the wrong direction, you can reverse it by editing the stream_server7.py file: Change the + or - signs for SERVO_STEP in the function:

move_servos_for_touch(row, col)

This allows you to match the servo movement to your specific servo orientation.

Run at Startup (Optional)

It's a bit of a drag to have to remote into the pi every time it turns on and off and restart the python script. In this step, we get the pi to start the streaming server at start up. So, all we have to do is power on the pi and the program will start. This is achieved with a systemd service.


First create the service file:

sudo nano /etc/systemd/system/stream_server7.service


Then enter the following text into the file. Don't forget to change the directory path "/hom/jonny/rnt_stream/" to match the location of your python file.

[Unit]
Description=Stream Server 7
After=network-online.target multi-user.target
Wants=network-online.target

[Service]
Type=simple
User=jonny
WorkingDirectory=/home/jonny/rnt_stream
ExecStart=/usr/bin/python3 /home/jonny/rnt_stream/stream_server7.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target


Now enable the service with the following commands. Don't forget to restart.

sudo systemctl daemon-reload
sudo systemctl enable stream_server7.service
sudo systemctl start stream_server7.service
sudo systemctl status stream_server7.service


Note:

To stop the service you can type

sudo systemctl stop stream_server7.service


To disable the service type

sudo systemctl disable stream_server7.service

Setup the Cheap Yellow Displays

one cyd demo

In this step we will get the ESP32 Cheap Yellow Display displaying the video stream from the raspberry pi. The code for this step is in the esp32_tft_side_v2 directory of the github repo. Each display automatically requests a different tile based on its configured position.

Use Arduino IDE:

  1. Board: ESP32 Dev Module
  2. Library: TFT_eSPI

Update:

const char* base_url = "http://your_pi_name.local:7123/stream";
const char* base_touch_url = "http://your_pi_name.local:7123/touch";


Set WiFi credentials in the .ino.

Upload to all 16 CYDs.

Expected Result

  1. Each screen shows part of the image


Note:

I'm using Bodmer's TFT_eSPI library for the display on the Arduino IDE. The library should be installed in your Arduino/libraries directory. On my machine the full path is:

/home/jonny/Arduino/libraries/TFT_eSPI/


You will need to update the User_Setup.h file. For most cheap yellow displays, the User_Setup.h in the github repo should work.

Building the Frame

frame_built.JPEG

Parts for this step:

  1. Six wooden beads, approximately 60cm (24 inches) each: four for the horizontal crossbars and two for the vertical crossbars. I used 12mm X 12mm square timber beads. Tip: Measure out the placement of the CYDs before cutting the beads down.
  2. Paint. I'm using red spray paint.
  3. 32 X M3 screws and nylon standoffs. The CYD has an M3 mounting hole. I'm using 20mm M3 screws and 15mm standoffs.
  4. Wood screws to join the frame together. You will need to choose your screw length according to your bead dimension.
  5. Drill.


Steps for Making the frame:

  1. Paint and/or decorate the wooden beads or before putting together.
  2. Take the top (horizontal) bead and drill the holes for the CYDs. I drilled the right hole for the first CYD (top right), and then used the CYD to measure the correct distance between the holes. I've left around 35mm (1.4 inches) between adjacent CYDs measuring from mount to mount. In retrospect, I probably would've made the spacing bit smaller.
  3. Drill smaller crossbar attachment holes on the left and right hand side of the bead. These will be used to attach the vertical crossbars.
  4. With the next three horizontal wooden beads, stack them with the top bar on top, so that you can use the top bar as a stencil to drill the remaining holes. This will ensure all holes are lined up..
  5. On each of the two vertical crossbars, drill four holes about 70mm (2.8 inches) apart.
  6. Attach to vertical crossbars at the left and right ends of the horizontal crossbars with wood screws, making sure that everything is lined up neatly.
  7. Attach the nylon standoffs to the frame, so that it is ready to mount the CYDs on.

Powering the Cheap Yellow Displays

power1.JPEG
power2.JPEG
power3.JPEG
battery_for_screens.JPEG
frame_power.JPEG

Each CYD uses:

  1. GND
  2. VCC (5V)

The I2C cable can be used for power:

  1. Red = VCC
  2. Black = GND
  3. SDA/SCL not used

Wiring Strategy

  1. Split into rows
  2. Use WAGO connectors
  3. Feed from 5V regulators

Important Note

You may need:

  1. Multiple regulators
  2. Separate batteries

If you see:

  1. flickering
  2. slow startup
  3. random resets

→ this is almost always a power issue


Now, get the screens receiving the image.

Power up the raspberry pi and servos. The pi should be configured to run the python code at startup.

Switch on the battery that is connected to the CYDs. The CYDs should start receiving the images. It may look jumbled because the positions are not configured.

Configure the Screens

screen configure

On startup, each CYD shows a colored grid.

You have ~2 seconds to select its position.

Process

  1. Tap the correct tile in the grid that corresponds to the screen position
  2. Repeat for all screens

Notes

  1. You may need to restart a few times
  2. Configuration is saved after so there is no need to reconfigure unless you move one of the screens


Final Setup

ESP32 Cheap Yellow Display Window

Steps:

  1. Mount the frame
  2. Place the camera
  3. Power on Pi first
  4. Wait for stream
  5. Power on CYDs

Expected Result

  1. Full “window” image
  2. Touching screens moves the camera


Common Problems

Screens glitching

→ Power issue (most common)

Can’t access .local

→ Use IP address instead

Servos moving wrong way

→ Adjust SERVO_STEP

Slow startup

→ Normal with multiple displays + WiFi

Final Notes

  1. Works best with strong WiFi
  2. You can change grid size in code
  3. Frame design is flexible — wood, aluminium, or 3D print