Logo

dev-resources.site

for different kinds of informations.

Ulanzi TC001 - ESP32 Programming / Custom Arduino firmware

Published at
12/14/2024
Categories
arduino
esp32
Author
calumk
Categories
2 categories in total
arduino
open
esp32
open
Author
6 person written this
calumk
open
Ulanzi TC001 - ESP32 Programming / Custom Arduino firmware

I found quite a lot of tutorials on using the Ulanzi TC001 with a firmware like AWTRIX, but not much information on simply programming it from scratch.
It wasnt too dificult to figure out, but, i thought it would be nice to document a few things here, so that others might be encouraged to give this nice little unit a try.

So this is a collection of notes designed to assist anyone who wants to do some "from scratch" programming, with the help of a few libraries, of course.


Setup

You can program the Ulanzi TC001 using a standard Arduino IDE.

Install the ESP32 boards in the board manager.

ESP32 Espressif

Then select board time "NODEMCU-32S"

When you download to the board, you will get a high pitch noise. Im not sure why, but in order to fix this, you need to add the following lines to your setup function.

  pinMode(15, INPUT_PULLDOWN); //Stops the High pitch noise!
  pinMode(27, INPUT_PULLUP); // Does something with the buttons
  pinMode(26, INPUT_PULLUP); // Does something with the buttons
Enter fullscreen mode Exit fullscreen mode

Getting Started

A simple program can be written that shows how the pixels are arranged. They can be though of as essentially a strip of LEDs, that runs each row in alternating directions
001 -> 032
064 <- 033

Back and Forth

#include <FastLED.h>

#define NUM_LEDS 256
#define DATA_PIN 32

CRGB leds[NUM_LEDS];

void setup() {

  pinMode(15, INPUT_PULLDOWN); //Stops the High pitch noise!
  pinMode(27, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);

  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);
}

void loop() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Red;
    FastLED.show();
    delay(50);
    leds[i] = CRGB::Black;
  }
}
Enter fullscreen mode Exit fullscreen mode

To fix this, we can use a helper function function "setLED" which will allow us to set any pixel simply by referring to its X,Y position, and will deal with the alternating direction of the rows.

void setLED(int x, int y, CRGB color) {
  if (x < 0 || x >= MATRIX_WIDTH || y < 0 || y >= MATRIX_HEIGHT) return;
  int index = (y % 2 == 0) ? y * MATRIX_WIDTH + x : (y + 1) * MATRIX_WIDTH - 1 - x;
  leds[index] = color;
}
Enter fullscreen mode Exit fullscreen mode

Correct

Here is an example of filling the display in the expected order:

#include <FastLED.h>

#define NUM_LEDS 256
#define DATA_PIN 32

#define MATRIX_WIDTH 32
#define MATRIX_HEIGHT 8

CRGB leds[NUM_LEDS];

void setup() {
  pinMode(15, INPUT_PULLDOWN);
  pinMode(27, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);

  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);
}

void setLED(int x, int y, CRGB color) {
  if (x < 0 || x >= MATRIX_WIDTH || y < 0 || y >= MATRIX_HEIGHT) return;
  int index = (y % 2 == 0) ? y * MATRIX_WIDTH + x : (y + 1) * MATRIX_WIDTH - 1 - x;
  leds[index] = color;
}

void loop() {
  // Loop Through each pixel and turn it on
  for (int i = 0; i < MATRIX_HEIGHT; i++) {
    for (int j = 0; j < MATRIX_WIDTH; j++) {
        setLED(j,i,CRGB::Red);
        FastLED.show();
        delay(50);
    }
  }

  // Set all LEDs to black
  for(int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Black; 
  }
}


Enter fullscreen mode Exit fullscreen mode

Its then fairly simple to add extra features, and begin to build a usable system.

Time

The following code will allow you to display the time!

#include <FastLED.h>
#include <WiFi.h>
#include <time.h>

#define NUM_LEDS 256
#define DATA_PIN 32
#define MATRIX_WIDTH 32
#define MATRIX_HEIGHT 8

const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 3600;

CRGB leds[NUM_LEDS];

// 3x5 font for digits
const uint8_t digits[10][5] = {
  {0b111, 0b101, 0b101, 0b101, 0b111}, // 0
  {0b010, 0b110, 0b010, 0b010, 0b111}, // 1
  {0b111, 0b001, 0b111, 0b100, 0b111}, // 2
  {0b111, 0b001, 0b111, 0b001, 0b111}, // 3
  {0b101, 0b101, 0b111, 0b001, 0b001}, // 4
  {0b111, 0b100, 0b111, 0b001, 0b111}, // 5
  {0b111, 0b100, 0b111, 0b101, 0b111}, // 6
  {0b111, 0b001, 0b010, 0b010, 0b010}, // 7
  {0b111, 0b101, 0b111, 0b101, 0b111}, // 8
  {0b111, 0b101, 0b111, 0b001, 0b111}  // 9
};

void setup() {
  Serial.begin(115200);
  pinMode(15, INPUT_PULLDOWN);
  pinMode(27, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);

  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to WiFi");

  // Init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}

void setLED(int x, int y, CRGB color) {
  if (x < 0 || x >= MATRIX_WIDTH || y < 0 || y >= MATRIX_HEIGHT) return;
  int index = (y % 2 == 0) ? y * MATRIX_WIDTH + x : (y + 1) * MATRIX_WIDTH - 1 - x;
  leds[index] = color;
}

void drawDigit(int x, int y, int digit, CRGB color) {
  for (int row = 0; row < 5; row++) {
    for (int col = 0; col < 3; col++) {
      if (digits[digit][row] & (1 << (2 - col))) {
        setLED(x + col, y + row, color);
      }
    }
  }
}

void drawTime(int hours, int minutes, int seconds, CRGB color) {
  drawDigit(0, 1, hours / 10, color);
  drawDigit(4, 1, hours % 10, color);
  setLED(8, 2, color);
  setLED(8, 4, color);
  drawDigit(10, 1, minutes / 10, color);
  drawDigit(14, 1, minutes % 10, color);
  setLED(18, 2, color);
  setLED(18, 4, color);
  drawDigit(20, 1, seconds / 10, color);
  drawDigit(24, 1, seconds % 10, color);
}

void loop() {
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }

  FastLED.clear();
  drawTime(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, CRGB::White);
  FastLED.show();
  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode
esp32 Article's
30 articles in total
Favicon
ESP32 Weather Dashboard with a WiFi Menu
Favicon
Prototipos rápidos con Wokwi, ESP32 y AWS IoT Core
Favicon
Smart Home Security: Advanced Motion Detection with CCTV
Favicon
Matter protocol on a budget
Favicon
Ulanzi TC001 - ESP32 Programming / Custom Arduino firmware
Favicon
Rust on a $2 dev board
Favicon
Sliding Puzzle Next Move Suggesting Simple DL Model with ESP32 TensorFlow Lite
Favicon
Time-for-space reluctance for the Wi-Fi AP scan for ESP8266
Favicon
I created a Realtime Voice Assistant for my ESP-32, here is my journey - Part 2 : Node, OpenAI, Langchain
Favicon
I created a Realtime Voice Assistant for my ESP-32, here is my journey - Part 1 : Hardware, PlatformIO & C++
Favicon
ESP32 Smart Garden: Automating Plant Care with IoT
Favicon
Smart Connectivity: Leveraging Wi-Fi and Bluetooth Coexistence in ESP32
Favicon
Building a DIY Smart Home Device: Get S**t Done
Favicon
Top ESP32 Projects To Start in 2024
Favicon
Why You Should Choose MicroPython for Prototyping and Research Work
Favicon
How to build a smart home system with ESP32
Favicon
Advanced ESP32: Exploring Key Features and Versatile Uses
Favicon
Developing IoT Application with ESP32
Favicon
Simple Arduino Framework Photo Frame Implementation with Photos Downloaded from the Internet via DumbDisplay
Favicon
DHT22 with MicroPython on ESP32
Favicon
MicroPython ESP32: Blink LED
Favicon
Using an OLED Display with MicroPython on ESP32
Favicon
Interfacing HC-SR04 Ultrasonic Sensor with ESP32 Using MicroPython
Favicon
Configurar Arduino IDE para ESP32 en Windows 10 💻
Favicon
Arduino IDE 2 上傳檔案到 ESP32/ESP8266 的外掛
Favicon
ESP32 WiFiManager MQTT ArduinoJson 7
Favicon
How to Code with Lua on ESP32 with XEdge32
Favicon
Tiny E-Ink Picture Display
Favicon
Esp32 Rust Board on Macos M-chip in Docker
Favicon
ESP32 WiFiManager MQTT Spiffs config ArduinoJson 7

Featured ones: