Любой цвет можно создать комбинацией трех цветов: красного, зеленого и синего, поэтому используя трехцветный светодиод (RGB LED) можно сформировать любой цвет. Но трехцветный светодиод имеет три отдельных контакта, поэтому нужно использовать и три контакта микроконтроллера чтобы подключить его. В связи с этим просто физически невозможно подключить несколько сотен светодиодов к одному микроконтроллеру.
Для преодоления этой проблемы компания Adafruit создала специальную светодиодную ленту (NeoPixel LED Strip). В этом случае требуется всего три контакта чтобы управлять несколькими подобными лентами. Два контакта будут задействованы для подачи питания и земли и один для передачи данных (Data In - DI). Контакт Data IN используется для адресации и управления различными светодиодами в ленте: их цветом, яркостью и т.д. Это удобно делать с помощью платы Arduino, чем мы и займемся в этой статье. Об этой ленте больше информации можно узнать на официальном сайте Adafruit. На Amazon'е ее можно купить по следующей ссылке - https://www.amazon.com/Adafruit-NeoPixel-Digital-RGB-Strip/dp/B00R5CDGWA.
В этой статье мы будем управлять светодиодной лентой (NeoPixel LED) с помощью Arduino и сенсорного TFT ЖК дисплея (TFT LCD touch Screen). Мы создадим 7 сенсорных кнопок различных цветов на TFT ЖК дисплее с диагональю 2.4 дюйма и когда мы будем нажимать одну из этих кнопок, то светодиодная лента будет светиться этим цветом (цветом кнопки, которую мы нажали). В данном проекте мы использовали светодиодную ленту с 30 трехцветными светодиодами. Также можете прочитать статью о подключении TFT ЖК дисплея к Arduino для лучшего понимания материала данной статьи.
Но лента из трехцветных светодиодов может светиться абсолютно любым цветом, поэтому при желании количество кнопок различных цветов на экране TFT ЖК дисплея вы можете увеличить. Также с помощью изменения программного кода в этот проект можно добавить различные эффекты мигания и иллюминации подобной ленты.
Необходимые компоненты
- Плата Arduino Mega (или другая) (купить на AliExpress) (Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158).
- Шилд TFT ЖК дисплея диагональю 2.4 дюйма с контроллером SPFD5408 (2.4 inch TFT LCD Shield with SPFD5408 controller) (купить на AliExpress) (Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158).
- Светодиодная лента с трехцветными светодиодами (NeoPixel RGB LED Strip).
- Соединительные провода.
- USB кабель или адаптер на 12 V 1A.
Соединения в схеме
В нашем проекте необходимо будет соединить контакт 5V платы Arduino с контактом NeoPixel’s 5V (ленты) и контакт GND платы Arduino Mega с контактом GND NeoPixel’s (ленты). Затем соединить контакт данных ленты (NeoPixel DI pin) с цифровым контактом 36 платы Arduino Mega. Затем осторожно соединить шилд TFT ЖК дисплея с платой Arduino таким образом чтобы контакт GND платы Arduino лежал ниже GND ЖК дисплея, а контакт 5V Arduino был соединен с контактом 5V ЖК дисплея.
Также не перепутайте контакты GND и 5V светодиодной ленты при подсоединении их к плате Arduino, иначе вы можете повредить светодиодную ленту. Вместо Arduino Mega вы можете использовать и другие платы Arduino.
В следующей таблице представлены необходимые соединения между платой Arduino и светодиодной лентой.
контакты Arduino | контакты NeoPixel Strip |
5v | 5v |
GND | GND |
цифровой контакт № 36 | DI (data in) |
Объяснение работы схемы
Работа схемы очень проста. Просто нажмите кнопку нужного вам цвета на TFT ЖК дисплее и светодиодная лента зажгется этим цветом. Код программы написан таким образом чтобы вы могли повторять эту операцию до бесконечности без необходимости сброса Arduino Mega. Структурная схема проекта показана на следующем рисунке.
При нажатии какой либо кнопки на экране TFT ЖК дисплея данные передаются в Arduino, а плата Arduino затем передает соответствующие команды светодиодной ленте (NeoPixel Strip). То есть светодиодная лента загорится зеленым цветом если мы нажмем кнопку зеленого цвета на TFT ЖК дисплее.
Исходный код программы
Для подключения и корректного функционирования используемого нами TFT ЖК дисплея нам понадобится библиотека для работы с ним, которую можно скачать по ссылке - https://github.com/JoaoLopesF/SPFD5408. На открывшейся странице нажмите ‘Clone or download’ и затем ‘Download ZIP’. Скачанный архив добавьте в папку библиотек Arduino на вашем компьютере.
#include <SPFD5408_Adafruit_GFX.h> // Core graphics library
#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPFD5408_TouchScreen.h>
Перед тем, как тестировать работу всей схемы, сначала проверьте корректность работы TFT ЖК дисплея. Для этого загрузите в плату Arduino пример из скачанной библиотеки для работы с дисплеем и проверьте правильно ли он работает. Сначала выполните графический тест, потом калибровочный тест и затем тест на рисование. Только после этого переходите к тестированию схемы, рассматриваемой в данной статье.
Для работы со светодиодной лентой (NeoPixel RGB LED) также скачайте библиотеку по следующей ссылке - https://github.com/adafruit/Adafruit_NeoPixel.
#include <Adafruit_NeoPixel.h>
Как было описано выше цифровой контакт 36 платы Arduino MEGA подключен к контакту DI светодиодной ленты, поэтому в программе инициализируем контакт 36. Также желательно инициализировать и количество светодиодов в используемой нами светодиодной ленте – 30 шт.
#define PIN 36
#define NUM_LEDS 30
Дадим удобные имена используемым цветам на ЖК дисплее. Для своего дисплея вы можете использовать и другие цвета.
#define BLACK 0x0000
#define YELLOW 0x001F
#define GREEN 0xF800
#define RED 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define BLUE 0xFFE0
#define WHITE 0xFFFF
Также в коде программы желательно задать такие параметры кнопок как их размер и местоположение.
uint16_t width = 0;
uint16_t height = 0;
uint16_t x = 40;
uint16_t y = height - 20;
uint16_t w = 75;
uint16_t h = 20;
Параметр h используется для регулирования размера кнопок на ЖК дисплее. Если вы сделаете h=40, то тогда размер кнопок увеличится вдвое. Параметр y – это координата y ЖК дисплея.
Сенсорные кнопки обозначаются цифрами как указано в следующем участке кода.
#define BUTTONS 9
#define BUTTON_Red 0
#define BUTTON_DarkRed 1
#define BUTTON_RED 2
#define BUTTON_DarkGreen 3
#define BUTTON_DeepRed 4
#define BUTTON_Blue 5
#define BUTTON_LightBlue 6
#define BUTTON_LightBlue1 7
Также необходимо определить ряд функций чтобы зажигать светодиодную ленту в нужные нам цвета.
void EmitCyan();
void EmitWhite();
void EmitGreen();
void EmitYellow();
void EmitPink();
void EmitBlack();
Для того чтобы определить RGB значения для нужного вам цвета (то есть значения/доли красного, синего и зеленого цветов), можно воспользоваться вот этим сервисом. Введите там нужный вам цвет и сервис выдаст вам нужные RGB значения. Потом просто подставьте эти RGB значения в выше определенные функции (которые зажигают светодиодную ленту в нужный вам цвет).
Функция void initializeButtons() используется для задания цвета кнопок и текста на них, а также для их размещения в необходимом месте на экране ЖК дисплея.
void initializeButtons() {
uint16_t x = 40;
uint16_t y = height - 20;
uint16_t w = 75;
uint16_t h = 40;
uint8_t spacing_x = 5
..... .....
.... ......
Функция void showCalibration() используется чтобы нарисовать кнопки на экране ЖК дисплея.
void showCalibration() {
tft.setCursor (40, 0);
for (uint8_t i = 0; i < 8; i++) {
buttons[i].drawButton();
}
}
Далее приведен полный текст программы. Он немного длинноват, но я думаю с учетом приведенных пояснений вам будет несложно его понять.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
#include <Adafruit_NeoPixel.h> #include <math.h> #include <SPFD5408_Adafruit_GFX.h> // Core graphics library #include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library #include <SPFD5408_TouchScreen.h> // *** SPFD5408 change -- End #if defined(__SAM3X8E__) #undef __FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif #define YP A1 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 7 // can be a digital pin #define XP 6 // can be a digital pin #define PIN 36 #define NUM_LEDS 30 #define BRIGHTNESS 80 // Calibrate values #define TS_MINX 125 #define TS_MINY 85 #define TS_MAXX 965 #define TS_MAXY 905 //для повышения точности работы нашего TFT ЖК дисплея желательно знать сопротивление между его контактами X+ и X-, которое можно измерить мультиметром. Если же вы не знает это сопротивление, то просто подставляйте 300 Ом как в приведенной функции TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); #define LCD_CS A3 #define LCD_CD A2 #define LCD_WR A1 #define LCD_RD A0 // optional #define LCD_RESET A4 // Assign human-readable names to some common 16-bit color values (даем "человечные" имена цветам): #define BLACK 0x0000 #define YELLOW 0x001F #define GREEN 0xF800 #define RED 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define BLUE 0xFFE0 #define WHITE 0xFFFF void EmitCyan(); void EmitWhite(); void EmitGreen(); void EmitYellow(); void EmitPink(); void EmitBlack(); uint16_t width = 0; uint16_t height = 0; uint16_t x = 40; uint16_t y = height - 20; uint16_t w = 75; uint16_t h = 20; Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); #define BOXSIZE 40 #define PENRADIUS 3 #define BUTTONS 9 #define BUTTON_Red 0 #define BUTTON_DarkRed 1 #define BUTTON_RED 2 #define BUTTON_DarkGreen 3 #define BUTTON_DeepRed 4 #define BUTTON_Blue 5 #define BUTTON_LightBlue 6 #define BUTTON_LightBlue1 7 Adafruit_GFX_Button buttons[BUTTONS]; uint16_t buttons_y = 0; #define MINPRESSURE 10 #define MAXPRESSURE 1000 void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println(F("Paint!")); tft.reset(); tft.begin(0x9341); // SDFP5408 strip.begin(); strip.show(); // Initialize all pixels to 'off' tft.setRotation(0); // Need for the Mega, please changed for your choice or rotation initial tft.fillScreen(BLACK); tft.setCursor (40, 20); tft.setTextSize (5); tft.setTextColor(WHITE); tft.println("COLORS"); tft.setCursor (65, 85); width = tft.width() - 1; height = tft.height() - 100; initializeButtons(); showCalibration(); } void loop() { // put your main code here, to run repeatedly: // Test of calibration int i = 0; TSPoint p; // Wait a touch digitalWrite(13, HIGH); p = waitOneTouch(); digitalWrite(13, LOW); p.x = mapXValue(p); p.y = mapYValue(p); for (uint8_t b = 0; b <BUTTONS; b++) { if (buttons[b].contains(p.x, p.y)) { // Action switch (b) { case BUTTON_Red: EmitPink(); showCalibration(); break; case BUTTON_DarkRed: EmitCyan(); showCalibration(); break; case BUTTON_RED: EmitBlack(); showCalibration(); break; case BUTTON_DarkGreen: EmitGreen(); showCalibration(); break; case BUTTON_Blue: EmitBlue(); showCalibration(); break; case BUTTON_LightBlue: EmitYellow(); showCalibration(); break; case BUTTON_DeepRed: EmitDeepRed(); showCalibration(); break; } } } } void initializeButtons() { uint16_t x = 40; uint16_t y = height - 20; uint16_t w = 75; uint16_t h = 40; uint8_t spacing_x = 5; uint8_t textSize = 2; char buttonlabels[7][20] = {"PINK", "CYAN", "WHITE", "GREEN", "RED", "BLUE", "YELLOW"}; uint16_t buttoncolors[15] = {RED, GREEN, BLACK, MAGENTA, CYAN, BLUE, YELLOW}; for (uint8_t b = 0; b < 9; b++) { if (b < 3) { buttons[b].initButton(&tft, // TFT object x + b * (w + spacing_x), y, // x, y, w, h, BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); Serial.print( h); }// text if (b == 3) { uint16_t x = 40; uint16_t y = height + 30 ; uint16_t w = 75; uint16_t h = 40; buttons[b].initButton(&tft, // TFT object x + 0 * (w + spacing_x) , y, // x, y, w, h, BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); } if (b == 4) { uint16_t x = 40; uint16_t y = height + 30 ; uint16_t w = 75; uint16_t h = 40; buttons[b].initButton(&tft, // TFT object x + 1 * (w + spacing_x) , y, // x, y, w, h, BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); } if (b == 5) { uint16_t x = 40; uint16_t y = height + 30 ; uint16_t w = 75; uint16_t h = 40; buttons[b].initButton(&tft, // TFT object x + 2 * (w + spacing_x) , y, // x, y, w, h, BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); } if (b == 6) { uint16_t x = 40; uint16_t y = height + 80 ; uint16_t w = 75; uint16_t h = 20; buttons[b].initButton(&tft, // TFT object x + 0 * (w + spacing_x) , y, // x, y, w, h,BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); } if (b == 7) { uint16_t x = 40; uint16_t y = height + 80 ; uint16_t w = 75; uint16_t h = 40; buttons[b].initButton(&tft, // TFT object x + 2 * (w + spacing_x) , y, // x, y, w, h,BLACK, buttoncolors[b], WHITE, // w, h, outline, fill, buttonlabels[b], textSize); } } // Save the y position to avoid draws buttons_y = y; } // Map the coordinate X uint16_t mapXValue(TSPoint p) { uint16_t x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); //Correct offset of touch. Manual calibration //x+=1; return x; } uint16_t mapYValue(TSPoint p) { uint16_t y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); //Correct offset of touch. Manual calibration //y-=2; return y; } TSPoint waitOneTouch() { TSPoint p; do { p = ts.getPoint(); pinMode(XM, OUTPUT); //Pins configures again for TFT control pinMode(YP, OUTPUT); } while ((p.z < MINPRESSURE ) || (p.z > MAXPRESSURE)); return p; } void showCalibration() { tft.setCursor (40, 0); for (uint8_t i = 0; i < 8; i++) { buttons[i].drawButton(); } } void EmitDeepRed() { for(int i=0;i<30;i++) { strip. setPixelColor(i, 255, 0, 0); strip.show(); } } void EmitCyan() { for(int i=0;i<30;i++) { strip. setPixelColor(i,0, 255, 255); strip.show(); } } void EmitWhite() { for(int i=0;i<30;i++) { strip. setPixelColor(i,255, 255, 255); strip.show(); } } void EmitGreen() { for(int i=0;i<30;i++) { strip. setPixelColor(i,0, 255, 0); strip.show(); } } void EmitBlue() { for(int i=0;i<30;i++) { strip. setPixelColor(i,0, 0, 255); strip.show(); } } void EmitYellow() { for(int i=0;i<30;i++) { strip. setPixelColor(i,255, 255, 0); strip.show(); } } void EmitPink() { for(int i=0;i<30;i++) { strip. setPixelColor(i,255, 0, 255); strip.show(); } } void EmitBlack() { for(int i=0;i<30;i++) { strip. setPixelColor(i,255, 255, 255); strip.show(); } } |