Настольная RGB лампа с часами, температурой и регулировкой яркости и цвета.
- Войдите на сайт для отправки комментариев
Наконец-то она заработала. Начал знакомство с Arduino с 20 декабря, имея кучу выходных (праздники), облазив кучу сайтов (в основном с нашего форума), более-менее освоив IDE, запустил Arduino Nano. С участием 1.8 inch TFT color display (HY-1.8 SPI), часы DS1302, датчик температуры и влажности DHT11, Bluetooth модуль HC-05, энкодер с кнопкой и кучей проводов.
Цель. Достаточно мощные светодиоды 5 - 10Вт, в настольном светильнике , что бы можно было использовать и как мощный источник света. Регулировка яркости и цвета (не всегда настроение красное, бывает слегка зеленое). Можно использовать как довесок к будильнику - просыпаешься и подсветка есть, приятного, утреннего цвета. Со смартфона управлять светом - ну, всяко бывает... Опять же термометр (как без него?).
В планах поменять часы на DS1307 (DS1302 не смог правильно подключить - спешат, при питании от 5 вольт сбои в показаниях). Пробовать другой датчик температуры и влажности (DHT11 не корректно работает с библиотекой PWM.h (тема "analogWrite() на любом выводе") - при опросе датчика мигают светодиоды) или использовать дополнительно контроллер на PWM. Добавить фукций при работе с Bluetooth -ом. Сейчас в качестве светодиодов использую ленту 60 штук SMD на метр, управление BUZ11 (были под рукой и не греются).
Скетч собран из разных источников и, бесспорно, не идеален. После компиляции 21 460 байт. Наверняка упростить можно (в будущем, наверное). Вывод инфы на экран и в блютуз больше для наглядности. Убедится, что работает.
Надеюсь на предложения по усовершенствованию.
Вот, собственно код...
/* Скетч с подключением библиотеки ШИМ - на все выходы аналоговые выходы 14 - 19 описание метода http://arduino.ru/forum/programmirovanie/analogwrite-na-lyubom-vyvode + рандом лампа настроения (нажать на кнопку энкодера) скорость изменения цвета переменная time + управление яркостью RGB светодиодов через Bluetooth или Serial (переход в режим: передать лат.'A') */ #include <PWM.h> // ПОДКЛ.БИБЛИОТЕКУ ШИМ-НА ВСЕ ВЫХОДЫ #include <Adafruit_GFX.h> // библиотека для TFT дисплеяAdafruit Grafik #include <Adafruit_ST7735.h> // Adafruit ST7735 #include <SPI.h> #include <DS1302.h> // библиотека часов DS1302 rtc(2, 7, 4); // Инициализация библиотеки с указанием // пинов подключения к Arduino платы часов #include "DHT.h" #include <EEPROM.h> // Библиотека записи в память //#include <SerialInput.h> // работа с сериал и bluetooth #define DHTPIN 3 // what pin we're connected to #define cs 10 // Arduino-Pin an Display CS #define dc 9 // Arduino-Pin an #define rst 8 // Arduino Reset-Pin #define PIN_A 14 //2 энкодер А #define PIN_B 15 // 3 энкодер В #define PIN_C 16 // КНОПКА ЭНКОДЕРА // Uncomment whatever type you're using! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); // Display-Bibliothek Setup volatile bool PinAH = 0; volatile bool PinBH = 0; volatile bool PinAB = 0; volatile bool PinBA = 0; int Enc_v = 0; int encValue=0; int fadeAmount = 5; // шаг изменения яркости LED int brightness=120; // при старте средняя яркость int color,i,value,time=100; // how long does it take each step int kn = 0; // переменная значений кнопки int kn_ret=0; // возврат из loop rgb() int flag=0; int r=0; int g=0; int b=0; int old_t; int old_h; Time t; // Инициализация структуры String old_time; // для проверки времени очищать дисплей или нет String date_old; // новая дата - очистка дисплея char incomingByte; int bt=0; // входящие данные для БТ DHT dht(DHTPIN, DHTTYPE); void setup(){ Serial.begin(9600); // Serial.println("Ready"); digitalWrite(PIN_A, HIGH); //подтяжка digitalWrite(PIN_B, HIGH); //подтяжка digitalWrite(PIN_C, HIGH); //подтяжка //digitalWrite(PIN, HIGH); //подтяжка analog.Mode(17, OUTPUT); // R analog.Mode(18, OUTPUT); // G analog.Mode(19, OUTPUT); // B dht.begin(); tft.initR(INITR_BLACKTAB); // ST7735-Chip инициализация дисплея rtc.halt(false); // Установка режимов rtc.writeProtect(false); // работы часов // Следующих три строки нужно закомментировать после // установки времени и загрузить скетч в плату повторно // rtc.setDOW(THURSDAY); // Установка дня недели // rtc.setTime(16, 39, 30); // Установка времени 10:59:10 // rtc.setDate(2, 1, 2014); // Установка даты 20 июля 2013// tft.fillScreen(ST7735_BLACK); // vremia(); } void loop(){ knopka(); if (old_time != rtc.getTimeStr(FORMAT_SHORT)) //---- проверяем, { // если время изменилось, то выводим на экран vremia(); // функция вывода часов на дисплей temra(); // вывод температуры } //---------------- if(Serial.available()){ delay(2); value=Serial.read(); switch (value) { case 'A': bluser(); break; case 'L': // На потом... digitalWrite(led_pin, LOW); break; case 'M': //На потом....led_mix(); break; } } } void knopka(){ if(digitalRead(PIN_C)==HIGH&&flag==0)//если кнопка нажата // и перемення flag равна 0 , то ... { flag=1; kn++; //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие // плюс защита от "дребезга" 100% } if(digitalRead(PIN_C)==LOW&&flag==1)//если кнопка НЕ нажата //и переменная flag равна - 1 ,то ... { flag=0; //kn=0; //обнуляем переменную flag } if (kn > 2) { kn=1; } if (kn_ret==1) { return; } //kn_ret=0; // Serial.print("kn = ");Serial.println(kn); switch (kn) { case 1: encoder(); break; case 2: rgb(); break; } return; }// ------ end void knopka void encoder() // ----- start encoder ------ { tft.fillRect(0,120,int((brightness/2)),5,ST7735_WHITE);// рисуем линию analog.Write(17, brightness); // устанавливаем яркость analog.Write(18, brightness); // устанавливаем яркость analog.Write(19, brightness); // устанавливаем яркость if(digitalRead(PIN_A)== HIGH && PinBH == 0 && PinBA == 0) { PinAH = 1; PinAB = 1; if(digitalRead(PIN_B)== HIGH) { PinBH = 1; Enc_v--; if(brightness - fadeAmount >= 0) brightness -= fadeAmount; } } if(digitalRead(PIN_A)== LOW && digitalRead(PIN_B)== LOW){ PinAH = 0; PinBH = 0; PinAB = 0; PinBA = 0; } if(digitalRead(PIN_B)== HIGH && PinAH == 0 && PinAB == 0) { PinBH = 1; PinBA = 1; if(digitalRead(PIN_A)== HIGH) { PinAH = 1; Enc_v++; if(brightness + fadeAmount <= 255) brightness += fadeAmount; } } if(digitalRead(PIN_A)== LOW && digitalRead(PIN_B)== LOW){ PinAH = 0; PinBH = 0; PinAB = 0; PinBA = 0; } if(encValue != Enc_v){ if(Enc_v <= 255) Enc_v = 255; if(Enc_v >= 0) Enc_v = 0; encValue = Enc_v; tft.fillRect(0,120,128,5,ST7735_BLACK); //полоса уровня энкодера analog.Write(17, brightness); // устанавливаем яркость analog.Write(18, brightness); // устанавливаем яркость analog.Write(19, brightness); // устанавливаем яркость tft.fillRect(0,120,int(brightness/2),5,ST7735_WHITE); //полоса уровня энкодера } return; }// конец void ecoder // ----- start mood light ----------- void rgb() { //tft.fillRect(0,120,128,5,ST7735_BLACK); //вытираем линию int color,i,value,time=300; // how long does it take each step color=random(1,4); // which color to dim now value=random(0,256); // new value of that color switch(color) { case 1: tft.fillCircle(int(value/2),122, 2, ST7735_BLUE); if(r>value) for(i=r;i>value;i--) { rgb(i,g,b); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } for(i=r;i<value;i++) { rgb(i,g,b); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } r=value; break; case 2: tft.fillCircle(int(value/2),122, 2, ST7735_RED); if(g>value) for(i=g;i>value;i--) { rgb(r,i,b); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } else for(i=g;i<value;i++) { rgb(r,i,b); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } g=value; break; case 3: tft.fillCircle(int(value/2),122, 2, ST7735_GREEN); if(b>value) for(i=b;i>value;i--) { rgb(r,g,i); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } else for(i=b;i<value;i++) { rgb(r,g,i); // delay(time); for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } b=value; break; } for (int i1=0; i1 <= time; i1++){ if (kn==1) { break; } kn_ret=1; knopka(); } kn_ret=0; } void rgb(int r, int g, int b) { analog.Write(17,r); analog.Write(18,g); analog.Write(19,b); } void vremia() { t = rtc.getTime(); // Получение времени и его запись в структуру t if (rtc.getTimeStr(FORMAT_SHORT)==("00:00")) { return; } tft.setTextSize(1); tft.setTextColor(ST7735_YELLOW); tft.setCursor(0,10); tft.print(" Hello!!! Do not worry!!!"); if (old_time != rtc.getTimeStr(FORMAT_SHORT)) //---- проверяем, { // если время изменилось, то старое рисуем черным цветом tft.setTextSize(3); tft.setCursor(20,25); tft.setTextColor(ST7735_BLACK); tft.print(old_time); tft.setTextSize(1); tft.setCursor(34,60); tft.print("00.00.2000"); //rtc.getDateStr()); tft.setCursor(45,50); tft.print("Xxxxxxxxxxx"); //rtc.getDOWStr()); } //---------------- tft.setTextSize(3); tft.setCursor(20,25); tft.setTextColor(ST7735_YELLOW); tft.print(rtc.getTimeStr(FORMAT_SHORT)); tft.setTextSize(1); tft.setCursor(34,60); tft.print(rtc.getDateStr()); tft.setCursor(45,50); tft.print(rtc.getDOWStr()); if (date_old != rtc.getDateStr(FORMAT_SHORT)) //---- проверяем, { // если дата изменилось, то очистка экрана tft.fillScreen(ST7735_BLACK); } //---------------- // tft.print(rtc.getDateStr()); old_time = rtc.getTimeStr(FORMAT_SHORT); date_old = rtc.getDateStr(FORMAT_SHORT); } // ------------ конец время void temra() { // ----- температура и влажность ---- float h = dht.readHumidity(); float t = dht.readTemperature(); // check if returns are valid, if they are NaN (not a number) then something went wrong! if (isnan(t) || isnan(h)) { // Serial.println("Failed to read from DHT"); tft.setTextSize(2); tft.setCursor(30,90); tft.setTextColor(ST7735_BLACK); tft.print("XX"); tft.setCursor(30,90); tft.setTextColor(ST7735_RED); tft.print(" don't work :("); } else { tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(15,90); tft.print(old_t); tft.print("C "); tft.print(old_h); tft.print("%"); tft.setCursor(15,90); tft.setTextColor(ST7735_RED); tft.print(int (t)); tft.print("C "); tft.print(int (h)); tft.print("%"); old_t=int(t); old_h=int(h); } } void bluser(){ // ----------------------------- bt=1; //переменная для выхода из БТ выход когда 0 //r=50; g=50; b=50; // начальные значения для ШИМ r=EEPROM.read(1); g=EEPROM.read(2); b=EEPROM.read(3); analog.Write(17,r); analog.Write(18,g); analog.Write(19,b); Serial.print("R="); Serial.print(r); Serial.print(" G="); Serial.print(g); Serial.print(" B"); Serial.println(b); tft.fillScreen(ST7735_BLACK); tft.setTextSize(1); tft.setTextColor(ST7735_RED); tft.setCursor(0,0); tft.print("Bluetooth is active "); tft.setCursor(0,10); tft.print("Send E to exit!"); tft.setCursor(0,20); tft.print("Send H to Help!"); Serial.print("Send E to exit! "); Serial.println("Send H to Help!"); // и выводим обратно сообщение do { tft.setTextSize(1); tft.setTextColor(ST7735_RED); tft.setCursor(0,0); tft.print("Bluetooth is active "); tft.drawLine(121,2,127,8,ST7735_RED); tft.drawLine(127,8,124,11,ST7735_RED); tft.drawLine(124,11,124,0,ST7735_RED);// значёк Bluetooth tft.drawLine(124,0,127,3,ST7735_RED); tft.drawLine(127,3,121,9,ST7735_RED); tft.setTextSize(1); tft.setTextColor(ST7735_WHITE); tft.setCursor(0,0); tft.print("Bluetooth is active "); tft.drawLine(121,2,127,8,ST7735_GREEN); tft.drawLine(127,8,124,11,ST7735_GREEN); tft.drawLine(124,11,124,0,ST7735_GREEN); tft.drawLine(124,0,127,3,ST7735_GREEN); tft.drawLine(127,3,121,9,ST7735_GREEN); value=Serial.read(); switch (value) { case '1': Serial.print("Red +1 = "); Serial.println(r); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,30); tft.print(r); r=r+5; if(r >= 255) r = 255; analog.Write(17,r); tft.setTextSize(2); tft.setTextColor(ST7735_RED); tft.setCursor(50,30); tft.print(r); break; case '2': Serial.print("Red -1 = "); Serial.println(r); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,30); tft.print(r); r=r-5; if(r <= 0) r = 0; analog.Write(17,r); tft.setTextSize(2); tft.setTextColor(ST7735_RED); tft.setCursor(50,30); tft.print(r); break; case '3': Serial.print("Green +1 = "); Serial.println(g); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,50); tft.print(g); g=g+5; if(g >= 255) g = 255; analog.Write(18,g); tft.setTextSize(2); tft.setTextColor(ST7735_GREEN); tft.setCursor(50,50); tft.print(g); break; case '4': Serial.print("Green -1 = "); Serial.println(g); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,50); tft.print(g); g=g-5; if(g <= 0) g = 0; analog.Write(18,g); tft.setTextSize(2); tft.setTextColor(ST7735_GREEN); tft.setCursor(50,50); tft.print(g); break; case '5': Serial.print("Blue +1 = "); Serial.println(b); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,70); tft.print(b); b=b+5; if(b >= 255) b = 255; analog.Write(19,b); tft.setTextSize(2); tft.setTextColor(ST7735_BLUE); tft.setCursor(50,70); tft.print(b); break; case '6': Serial.print("Blue -1 = "); Serial.println(b); tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(50,70); tft.print(b); b=b-5; if(b <= 0) b = 0; analog.Write(19,b); tft.setTextSize(2); tft.setTextColor(ST7735_BLUE); tft.setCursor(50,70); tft.print(b); break; case 'E': Serial.println("exit BT. Send 'A' to return"); bt=0; break; // Выход в главное меню case 'H': help(); break; // ---- вывод на экран ---- } } while (!bt==0); //пока 1 - работает БТ---------!Serial.available()); tft.fillScreen(ST7735_BLACK); tft.setTextSize(1); tft.setTextColor(ST7735_WHITE); tft.setCursor(0,20); tft.print("Save color to EERPOM ..."); Serial.print("R="); Serial.print(r); Serial.print(" G="); Serial.print(g); Serial.print(" B="); Serial.println(b); tft.setCursor(0,30); tft.print("Exit Bluetooth. Bye!"); EEPROM.write(1, r); EEPROM.write(2, g); EEPROM.write(3, b); delay(1500); tft.fillScreen(ST7735_BLACK); return; } void help(){ Serial.println("Help! Help! Help!!!"); Serial.println("A - enter bluetooth mode."); Serial.println("E - exit bluetooth mode."); Serial.println("H - this text message"); Serial.println("Red +- 1/2, G +- 3/4 B +- 5/6"); }