Светофор на ардуино с цветным дисплеем TFT 1.8″ ST7735

| Пин дисплея | Пин Arduino UNO |
|---|---|
| VCC | 5V |
| GND | GND |
| SCL (SCK) | 13 |
| SDA (MOSI) | 11 |
| RST (RES) | 9 |
| DC (RS) | 8 |
| CS | 10 |
| BLK (LED) | 3.3V или 5V (подсветка) |
Я сделал новый интересный проект — светофор на ардуино. Светофор отображается на цветном дисплее, максимально копируя настоящие светофоры.
На картинке показано, как выглядят цифры и сигналы на дисплее с этим скетчем. Вертикальная ориентация, верх со стороны пинов.
Распиновка, подключение дисплея в таблице справа. Проект собран на Arduino Uno/Nano и дисплее TFT LCD 1.8″ ST7735 SPI.
Скетч ниже:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#define TFT_CS 10
#define TFT_DC 8
#define TFT_RST 9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#define COLOR_BG ST77XX_BLACK
#define COLOR_GRAY tft.color565(0x30, 0x30, 0x30)
#define COLOR_RED ST77XX_RED
#define COLOR_YELLOW ST77XX_YELLOW
#define COLOR_GREEN ST77XX_GREEN
const int CENTER_X = 64;
const int TOP_Y = 25;
const int MID_Y = 80;
const int BOT_Y = 135;
int RedSig = 5;
int GreenSig = 15;
void drawSignal(int x, int y, uint16_t color, bool state) {
uint16_t drawColor = state ? color : COLOR_GRAY;
const int radius = 22;
tft.fillCircle(x, y, radius, COLOR_BG);
int rings[7] = {42, 36, 30, 24, 16, 10, 4};
float ringRadii[7] = {25, 21, 17, 13, 9, 5, 2.5};
for (int ring = 0; ring < 6; ring++) {
int numPoints = rings[ring];
float r = ringRadii[ring];
for (int i = 0; i < numPoints; i++) {
float angle = (TWO_PI * i) / numPoints - PI/2;
int px = x + round(r * cos(angle));
int py = y + round(r * sin(angle));
// Точка 3x3 крестиком
tft.drawPixel(px, py, drawColor);
tft.drawPixel(px - 1, py - 1, drawColor);
tft.drawPixel(px + 1, py - 1, drawColor);
tft.drawPixel(px - 1, py + 1, drawColor);
tft.drawPixel(px + 1, py + 1, drawColor);
}
}
}
void drawDot(int x, int y, uint16_t color) {
tft.drawPixel(x, y, color);
tft.drawPixel(x - 1, y - 1, color);
tft.drawPixel(x + 1, y - 1, color);
tft.drawPixel(x - 1, y + 1, color);
tft.drawPixel(x + 1, y + 1, color);
}
void drawSegment(int x, int y, int w, int h, uint16_t color) {
int spacing = 2;
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
int px = x + col * spacing * 2;
int py = y + row * spacing * 2;
drawDot(px, py, color);
}
}
}
void drawDigit(int x, int y, int digit, uint16_t color) {
int spacing = 2;
int segLen = 5 * spacing * 2; // 20 пикселей
int gap = 2;
int aX = x + gap; int aY = y; // A - верх
int bX = x + segLen + gap; int bY = y + gap; // B - правый верх
int cX = x + segLen + gap; int cY = y + segLen + gap * 2; // C - правый низ
int dX = x + gap; int dY = y + segLen * 2 + gap * 3; // D - низ
int eX = x; int eY = y + segLen + gap * 2; // E - левый низ
int fX = x; int fY = y + gap; // F - левый верх
int gX = x + gap; int gY = y + segLen + gap; // G - середина
bool seg[10][7] = {
{1,1,1,1,1,1,0}, // 0
{0,1,1,0,0,0,0}, // 1
{1,1,0,1,1,0,1}, // 2
{1,1,1,1,0,0,1}, // 3
{0,1,1,0,0,1,1}, // 4
{1,0,1,1,0,1,1}, // 5
{1,0,1,1,1,1,1}, // 6
{1,1,1,0,0,0,0}, // 7
{1,1,1,1,1,1,1}, // 8
{1,1,1,1,0,1,1} // 9
};
uint16_t col;
col = seg[digit][0] ? color : COLOR_GRAY;
drawSegment(aX, aY, 6, 1, col); // A
col = seg[digit][1] ? color : COLOR_GRAY;
drawSegment(bX, bY, 1, 6, col); // B
col = seg[digit][2] ? color : COLOR_GRAY;
drawSegment(cX, cY, 1, 6, col); // C
col = seg[digit][3] ? color : COLOR_GRAY;
drawSegment(dX, dY, 6, 1, col); // D
col = seg[digit][4] ? color : COLOR_GRAY;
drawSegment(eX, eY, 1, 6, col); // E
col = seg[digit][5] ? color : COLOR_GRAY;
drawSegment(fX, fY, 1, 6, col); // F
col = seg[digit][6] ? color : COLOR_GRAY;
drawSegment(gX, gY, 6, 1, col); // G
}
void drawNumber(int value, char color) {
int x = CENTER_X;
int y = MID_Y;
uint16_t digitColor;
if (color == 'R') {
digitColor = COLOR_RED;
} else if (color == 'G') {
digitColor = COLOR_GREEN;
} else {
digitColor = COLOR_YELLOW;
}
int spacing = 2;
int segLen = 5 * spacing * 2; // 20
int gap = 2;
int digitW = segLen + gap * 2; // 24
int digitH = segLen * 2 + gap * 3; // 46
int totalW = digitW * 2 + 4;
int startX = x - totalW / 2;
int startY = y - digitH / 2;
if (value == -1) {
drawDigit(startX, startY, 8, COLOR_GRAY);
drawDigit(startX + digitW + 4, startY, 8, COLOR_GRAY);
return;
}
if (value < 0) value = 0;
if (value > 99) value = 99;
int tens = value / 10;
int units = value % 10;
drawDigit(startX, startY, 8, COLOR_GRAY);
drawDigit(startX + digitW + 4, startY, 8, COLOR_GRAY);
drawDigit(startX, startY, tens, digitColor);
drawDigit(startX + digitW + 4, startY, units, digitColor);
}
void setup() {
tft.initR(INITR_BLACKTAB);
tft.setRotation(2);
tft.fillScreen(COLOR_BG);
drawSignal(CENTER_X, TOP_Y, COLOR_GRAY, 0);
drawSignal(CENTER_X, MID_Y, COLOR_GRAY, 0);
drawSignal(CENTER_X, BOT_Y, COLOR_GRAY, 0);
}
void loop() {
drawSignal(CENTER_X, MID_Y, COLOR_GRAY, 0);
drawSignal(CENTER_X, TOP_Y, COLOR_RED, 1);
for (int i = RedSig; i >= 1; i--) {
drawNumber(i, 'R');
delay(1000);
}
drawSignal(CENTER_X, TOP_Y, COLOR_GRAY, 0);
drawSignal(CENTER_X, BOT_Y, COLOR_GREEN, 1);
for (int i = GreenSig; i >= 4; i--) {
drawNumber(i, 'G');
delay(1000);
}
for (int i = 3; i >= 1; i--) {
drawNumber(i, 'G');
drawSignal(CENTER_X, BOT_Y, COLOR_GREEN, 1);
delay(500);
drawNumber(-1, 'G');
drawSignal(CENTER_X, BOT_Y, COLOR_GREEN, 0);
delay(500);
}
drawNumber(-1, 'G');
drawSignal(CENTER_X, MID_Y, COLOR_YELLOW, 1);
delay(2000);
}





