// Touch senzor s LED podsvetlenim a specialnimi druhy nastaveni sviceni // // verze: 23.10.2021 //============================================================================================================= // Zapojeni: //============= // // TTP223 // +-\__/-+ // vystup (Q) 1| |6 GND (rezim DIRECT) // GND 2| |5 Vcc // SENZOR 3| |4 Vcc (aktivni vystup je LOW) // +------+ // // / / ATtiny85 // +-\__/-+ // logicky vystup 2. cidla - PB5 1| |8 Vcc // kom_RX - PB3 2| |7 PB2 - 2. TTP223 (Q) // 1. TTP223 (Q) - PB4 3| |6 PB1 - logicky vystup 1. cidla // GND 4| |5 PB0 - vystup na jednu nebo dve Neopixel RGB LED // +------+ //============================================================================================================= #include #include #include #define pin_LED 0 #define pin_vystup_0 1 #define pin_vystup_1 5 #define pin_cidlo_0 4 #define pin_cidlo_1 2 #define pin_kom_RX 3 Adafruit_NeoPixel RGBLED = Adafruit_NeoPixel(2, pin_LED, NEO_GRB + NEO_KHZ800); SoftwareSerial kom(pin_kom_RX,pin_vystup_0); byte barva_A_R[2], barva_A_G[2], barva_A_B[2] ; // promenne pro slozky barvev pro obe LED v aktivnim stavu byte barva_N_R[2], barva_N_G[2], barva_N_B[2] ; // promenne pro slozky barvev pro obe LED v neaktivnim stavu boolean rezim[2]; // rezim tlacitek (tohggle = false ; direct = true) boolean OUT_logika[2]; // logika vystupu (aktivni LOW = false ; aktivní HIGH = true) byte blik[2]; // rychlost blikani (0 neblika, 1 blika rychle .... 255 blika pomalu) boolean aktivita[2]; // znacka, jestli je kanal v aktivnim stavu (nezavisle na nastavene logice vystupu) unsigned long posledni_blik[2]; // promenna pro odpocet casovani pri blikani LED boolean LED_sviti[2]; // pomocna promenna pro aktualni stav blikajici LED boolean auto_LED[2]; // automaticke, nebo prime rizeni LED byte pin_cidlo[2]; // cisla pinu, na kterych jsou pripojena cidla byte pin_vystup[2]; // cisla vystupnich pinu boolean blok_stav[2]; // pomocna promenna pro rezim "stiskem zapni / stiskem vypni" byte adresa; // adresa 1. tlacitka (druhe tlacitko ma adresu o 1 vyssi) boolean stav; byte preset; // je mozne prednastavit az 3 sady barev LED, ulozit je do EEPROM a pak je jen jednoduse pepinat misto hlavni sady unsigned long delka_pulzu; // pro rizeni pomoci delky impulzu unsigned long start_pulzu; // znacka, kdy doslo k sestupne hrane na ridicim pinu boolean hrana = HIGH; // znacka hrany boolean ovladani_komunikaci; // tlacitka je mozne ovladat impulzem (LOW), nebo komunikaci (HIGH) //============================================================================ void setup() { pin_cidlo[0] = pin_cidlo_0; // pro jednodussi program musi byt cisla pinu uvedena v poli pin_cidlo[1] = pin_cidlo_1; pin_vystup[0] = pin_vystup_0; pin_vystup[1] = pin_vystup_1; kom.begin(9600); RGBLED.begin(); RGBLED.show(); pinMode(pin_vystup[0], OUTPUT); pinMode(pin_vystup[1], OUTPUT); pinMode(pin_cidlo[0], INPUT_PULLUP); pinMode(pin_cidlo[1], INPUT_PULLUP); digitalWrite(pin_vystup[0] , LOW); if (EEPROM.read(0) == 255) EEPROM_default(); default_read_EEPROM(); Serial.setTimeout(20); ovladani_komunikaci = digitalRead(pin_kom_RX); // volba zpusobu ovladani se provadi po zapnuti napajeni (kdyz je pin v LOW, bude se ovladat impulzem, kdyz je pin v HIGH, bude se ovladat komunikaci) } //============================================================================ //============================================================================ // rychla hlavni smycka void loop() { if (ovladani_komunikaci == false) // ovladani ruzne dlouhymi impulzy { if (digitalRead(pin_kom_RX) == LOW and hrana == HIGH) { start_pulzu = millis(); hrana = LOW; } if (digitalRead(pin_kom_RX) == HIGH and hrana == LOW) { delka_pulzu = millis() - start_pulzu; hrana = HIGH; if ( 30 < delka_pulzu and delka_pulzu < 50) copy_preset(0, 21); // 40ms ... funkce '1X' if ( 50 < delka_pulzu and delka_pulzu < 70) copy_preset(1, 21); // 60ms ... funkce '2X' if ( 70 < delka_pulzu and delka_pulzu < 90) copy_preset(0, 29); // 80ms ... funkce '1Y' if ( 90 < delka_pulzu and delka_pulzu < 110) copy_preset(1, 29); // 100ms ... funkce '2Y' if ( 110 < delka_pulzu and delka_pulzu < 130) copy_preset(0, 37); // 120ms ... funkce '1Z' if ( 130 < delka_pulzu and delka_pulzu < 150) copy_preset(1, 37); // 140ms ... funkce '2Z' if ( 150 < delka_pulzu and delka_pulzu < 170) copy_preset(0, 5); // 160ms ... funkce '1O' if ( 170 < delka_pulzu and delka_pulzu < 190) copy_preset(1, 13); // 180ms ... funkce '2O' if ( 280 < delka_pulzu and delka_pulzu < 320) ovladani_komunikaci = true; // 300ms ... prepnuti na ovladani komunikaci } } else // ovladani_komunikaci je TRUE { if (kom.available()>0) { delay(10); byte prvni_znak = kom.peek(); if (prvni_znak == '@') // specialni pripad pro zmenu adresy. Priklad: '@ 100' { prvni_znak = kom.read(); // prvni znak ('@') se bez uzitku vyhodi byte index = kom.parseInt(); // za nim nasleduje nova adresa if (index > 0 and index < 251) // adresa musi byt v rozsahu 1 az 250 { adresa = index; EEPROM.write(0,adresa); } while (kom.available()) kom.read(); // vsechno ostatni se z prijimaciho bufferu maze } if (prvni_znak == 'R') // nastaveni vsech kanalu na defaultni hodnoty { EEPROM_default(); default_read_EEPROM(); while (kom.available()) kom.read(); // vsechno ostatni se z prijimaciho bufferu maze } if (prvni_znak == 'I') // prepnuti na ovladani pomoci ruzne dlouhych impulzu { ovladani_komunikaci = false; while (kom.available()) kom.read(); // vsechno ostatni se z prijimaciho bufferu maze } if (prvni_znak == 'X') // specialni pripad pro nastaveni presetu 1 { prvni_znak = kom.read(); // prvni znak ('X') se bez uzitku vyhodi byte fce = kom.read(); // druhy znak udava funkci serial_preset(21,fce); } if (prvni_znak == 'Y') // specialni pripad pro nastaveni presetu 2 { prvni_znak = kom.read(); // prvni znak ('Y') se bez uzitku vyhodi byte fce = kom.read(); // druhy znak udava funkci serial_preset(29,fce); } if (prvni_znak == 'Z') // specialni pripad pro nastaveni presetu 3 { prvni_znak = kom.read(); // prvni znak ('Z') se bez uzitku vyhodi byte fce = kom.read(); // druhy znak udava funkci serial_preset(37,fce); } byte index = kom.parseInt(); // prvni cislo (retezec cisel) udava index cidla if (index >= adresa and index <= adresa+1) // povoleny je pouze rozsah (adresa) az (adresa +1) { byte fce = kom.read(); // druhy znak udava funkci if (fce == 'T') // 'T' .... zmena rezimu na "Stiskem zapni / stiskem vypni" { rezim[index-adresa] = false; zapis_rezim(index-adresa); } if (fce == 'D') // 'D' .... zmena rezimu na "Stiskem zapni / uvolnenim vypni" { rezim[index-adresa] = true; zapis_rezim(index-adresa); } if (fce == 'M') // 'M' .... Manualni aktivace LED (nezavisle na stisku tlacitka) { auto_LED[index-adresa] = false; zapis_autoLED(index-adresa); } if (fce == 'm') // 'm' .... Manualni aktivace LED (nezavisle na stisku tlacitka) - BEZ ZAIPSU DO EEPROM { auto_LED[index-adresa] = false; } if (fce == 'U') // 'U' .... aUtomaticke ovladani LED podle stisku tlacitka) { auto_LED[index-adresa] = true; zapis_autoLED(index-adresa); } if (fce == 'u') // 'u' .... automaticke ovladani LED podle stisku tlacitka) - BEZ ZAIPSU DO EEPROM { auto_LED[index-adresa] = true; } if (fce == 'A') // 'A r,g,b' .... nastaveni aktivni barvy { barva_A_R[index-adresa] = kom.parseInt(); barva_A_G[index-adresa] = kom.parseInt(); barva_A_B[index-adresa] = kom.parseInt(); zapis_barvu_A(index-adresa); } if (fce == 'a') // 'a r,g,b' .... nastaveni aktivni barvy - BEZ ZAPISU DO EEPROM! { barva_A_R[index-adresa] = kom.parseInt(); barva_A_G[index-adresa] = kom.parseInt(); barva_A_B[index-adresa] = kom.parseInt(); } if (fce == 'N') // 'N r,g,b' .... nastaveni neaktivni barvy { barva_N_R[index-adresa] = kom.parseInt(); barva_N_G[index-adresa] = kom.parseInt(); barva_N_B[index-adresa] = kom.parseInt(); zapis_barvu_N(index-adresa); } if (fce == 'n') // 'n r,g,b' .... nastaveni neaktivni barvy - BEZ ZAPISU DO EEPROM! { barva_N_R[index-adresa] = kom.parseInt(); barva_N_G[index-adresa] = kom.parseInt(); barva_N_B[index-adresa] = kom.parseInt(); } if (fce == 'F') // 'F' .... blikani { blik[index-adresa] = kom.parseInt(); zapis_blik(index-adresa); } if (fce == 'f') // 'f' .... blikani - BEZ ZAPISU DO EEPROM! { blik[index-adresa] = kom.parseInt(); zapis_blik(index-adresa); } if (fce == 'H') // 'H' .... aktivni vystup je v HIGH { OUT_logika[index-adresa] = HIGH; zapis_logiku(index-adresa); } if (fce == 'L') // 'L' .... aktivni vystup je v LOW { OUT_logika[index-adresa] = LOW; zapis_logiku(index-adresa); } if (fce == 'O') // 'O' .... nastaveni promennych na defaultni hodnoty ulozene v zakladni EEPROM { if (index-adresa == 0) copy_preset(0 , 5); if (index-adresa == 1) copy_preset(1 , 13); } if (fce == 'X') // 'X' .... nastaveni promennych na 1. preset { copy_preset(index-adresa, 21); } if (fce == 'Y') // 'X' .... nastaveni promennych na 1. preset { copy_preset(index-adresa, 29); } if (fce == 'Z') // 'Z' .... nastaveni promennych na 1. preset { copy_preset(index-adresa, 37); } // if (fce == 'Q') // debug vypis EEPROM // { // for (byte i = 0; i < 50 ; i++) // { // kom.print(i); // kom.print("... "); // kom.println(EEPROM.read(i)); // } // } } while (kom.available()) kom.read(); // vsechno ostatni se z prijimaciho bufferu maze } } for (byte kan = 0 ; kan < 2 ; kan ++) // postupne se vyhodnoti oba kanaly { //----------------------------------------------- // kod pro urceni aktivniho / neaktivniho stavu stav = digitalRead(pin_cidlo[kan]); if(rezim[kan] == true) // rezim DIRECT (stiskem zapni / uvolnenim vypni) { if (stav == LOW) aktivita[kan] = true; else aktivita[kan] = false; } else // rezim TOGGLE (stiskem zapni / stiskem vypni) { if (stav == LOW) // je stisknuto { if (blok_stav[kan] == false) // je povolena zmena aktivity { aktivita[kan] = !aktivita[kan]; // dojde k prepnuti aktivity blok_stav[kan] = true; // zmena aktivity se blokuje az do dalsiho uvolneni tlacitka } } else // tlacitko je uvolneno { blok_stav[kan] = false; // povoluje se zmena aktivity } } //----------------------------------------------- // obsluha RGB LED if (blik[kan] > 0) // Blikani je nezavisle na stisku tlacitka (prepina se aktivni / neaktivni barva) { if (millis() - posledni_blik[kan] > blik[kan] * 10) { posledni_blik[kan] = millis(); if (LED_sviti[kan] == false) { LED_sviti[kan] = true; RGBLED.setPixelColor(kan,barva_A_R[kan],barva_A_G[kan],barva_A_B[kan]); } else { LED_sviti[kan] = false; RGBLED.setPixelColor(kan,barva_N_R[kan],barva_N_G[kan],barva_N_B[kan]); } RGBLED.show(); } } else // blikani neni povolene { if (aktivita[kan] == true or auto_LED[kan] == false) // pro aktivni stav kanalu se nastavi aktivni barva LED { RGBLED.setPixelColor(kan,barva_A_R[kan],barva_A_G[kan],barva_A_B[kan]); RGBLED.show(); } else // pro neaktivni stav kanalu se nastavi neaktivni barva LED { RGBLED.setPixelColor(kan,barva_N_R[kan],barva_N_G[kan],barva_N_B[kan]); RGBLED.show(); } } //----------------------------------------------- // obsluha vystupniho pinu if (aktivita[kan] == OUT_logika[kan]) digitalWrite(pin_vystup[kan], HIGH); // (pozitivni logika s aktivnim vystupem, nebo negativni logika s neaktivnim vystupem) else digitalWrite(pin_vystup[kan], LOW); // (pozitivni logika s neaktivnim vystupem, nebo negativni logika s aktivnim vystupem) } } //============================================================================ //============================================================================ // Prepne rezim tlacitka na "stiskem zapni / stiskem vypni" nebo "stiskem zapni / uvolnenim vypni" void zapis_rezim(byte kanal) { EEPROM.write(kanal + 1 , rezim[kanal]); } //============================================================================ //============================================================================ // Zapise vystupni logiku do EEPROM void zapis_logiku(byte kanal) { EEPROM.write(kanal+ 3 , OUT_logika[kanal]); } //============================================================================ //============================================================================ // Zapise stav primeho (nebo automatickeho) rizeni LED do EEPROM void zapis_autoLED(byte kanal) { EEPROM.write((kanal * 8) + 5 , auto_LED[kanal]); } //============================================================================ //============================================================================ // Zapise blikaci stav do EEPROM void zapis_blik(byte kanal) { EEPROM.write((kanal * 8) + 6 , blik[kanal]); } //============================================================================ //============================================================================ // Zapise aktivni barvu do EEPROM void zapis_barvu_A(byte kanal) { EEPROM.write((kanal * 8) + 7 , barva_A_R[kanal]); EEPROM.write((kanal * 8) + 8 , barva_A_G[kanal]); EEPROM.write((kanal * 8) + 9 , barva_A_B[kanal]); } //============================================================================ //============================================================================ // Zapise neaktivni barvu do EEPROM void zapis_barvu_N(byte kanal) { EEPROM.write((kanal * 8) + 10, barva_N_R[kanal]); EEPROM.write((kanal * 8) + 11, barva_N_G[kanal]); EEPROM.write((kanal * 8) + 12, barva_N_B[kanal]); } //============================================================================ //============================================================================ // prednastavi do EEPROM barvy a blikani pro LED void serial_preset(byte adresa_EE , byte fce) { if (fce == 'M') // 'M' .... Manualni aktivace LED (nezavisle na stisku tlacitka) { EEPROM.write(adresa_EE ,0); } if (fce == 'U') // 'U' .... aUtomaticke ovladani LED podle stisku tlacitka) { EEPROM.write(adresa_EE ,1); } if (fce == 'F') // 'F' .... blikani { EEPROM.write(adresa_EE + 1 ,kom.parseInt()); } if (fce == 'A') // 'A r,g,b' .... nastaveni aktivni barvy { EEPROM.write(adresa_EE + 2 , kom.parseInt()); EEPROM.write(adresa_EE + 3 , kom.parseInt()); EEPROM.write(adresa_EE + 4 , kom.parseInt()); } if (fce == 'N') // 'N r,g,b' .... nastaveni neaktivni barvy { EEPROM.write(adresa_EE + 5 , kom.parseInt()); EEPROM.write(adresa_EE + 6 , kom.parseInt()); EEPROM.write(adresa_EE + 7 , kom.parseInt()); } while (kom.available()) kom.read(); // vsechno ostatni se z prijimaciho bufferu maze } //============================================================================ // vytahne z EEPROM barvy a blikani pro LED ze zadaneho presetu void copy_preset(byte kanal , byte adresa_EE) // umisteni v EEPRONM na adresach: { // K1 K2 PX PY PZ auto_LED[kanal] = EEPROM.read(adresa_EE); // 5 13 21 29 37 blik[kanal] = EEPROM.read(adresa_EE + 1); // 6 14 22 30 38 barva_A_R[kanal] = EEPROM.read(adresa_EE + 2); // 7 15 23 31 39 barva_A_G[kanal] = EEPROM.read(adresa_EE + 3); // 8 16 24 32 40 barva_A_B[kanal] = EEPROM.read(adresa_EE + 4); // 9 17 25 33 41 barva_N_R[kanal] = EEPROM.read(adresa_EE + 5); // 10 18 26 34 42 barva_N_G[kanal] = EEPROM.read(adresa_EE + 6); // 11 19 27 35 43 barva_N_B[kanal] = EEPROM.read(adresa_EE + 7); // 12 20 28 36 44 } //============================================================================ //============================================================================ // nacteni defaultniho nastavení z EEPROM void default_read_EEPROM(void) { adresa = EEPROM.read(0); rezim[0] = EEPROM.read(1); rezim[1] = EEPROM.read(2); OUT_logika[0] = EEPROM.read(3); OUT_logika[1] = EEPROM.read(4); copy_preset(0 , 5); copy_preset(1 , 13); } //============================================================================ // pri prvnim spusteni se vsechny pouzite bunky v EEPROM prednastavi na nejake normalni hodnoty void EEPROM_default(void) { EEPROM.write( 0, 1); // adresa kanalu: 1 a 2 EEPROM.write( 1, 1); // kanal 1: rezim DIRECT (stiskem zapni / uvolnenim vypni) EEPROM.write( 2, 1); // kanal 2: rezim DIRECT (stiskem zapni / uvolnenim vypni) EEPROM.write( 3, 1); // kanal 1: vystupni logika : aktivni HIGH EEPROM.write( 4, 1); // kanal 2: vystupni logika : aktivni HIGH // prvni kanal bude mit neaktivni barvu zelenou a aktivni cervenou EEPROM.write( 5, 1); // kanal 1: automaticke ovladani LED EEPROM.write( 6, 0); // kanal 1: bez blikani EEPROM.write( 7,100); // kanal 1: aktivni barva slozka R EEPROM.write( 8, 0); // kanal 1: aktivni barva slozka G EEPROM.write( 9, 0); // kanal 1: aktivni barva slozka B EEPROM.write(10, 0); // kanal 1: neaktivni barva slozka R EEPROM.write(11,100); // kanal 1: neaktivni barva slozka G EEPROM.write(12, 0); // kanal 1: neaktivni barva slozka B // druhy kanal bude mit neaktivni barvu zelenou a aktivni cervenou (stejne jako prvni kanal) EEPROM.write(13, 1); // kanal 2: automaticke ovladani LED EEPROM.write(14, 0); // kanal 2: bez blikani EEPROM.write(15,100); // kanal 2: aktivni barva slozka R EEPROM.write(16, 0); // kanal 2: aktivni barva slozka G EEPROM.write(17, 0); // kanal 2: aktivni barva slozka B EEPROM.write(18, 0); // kanal 2: neaktivni barva slozka R EEPROM.write(19,100); // kanal 2: neaktivni barva slozka G EEPROM.write(20, 0); // kanal 2: neaktivni barva slozka B // prednastaveny rezim 'X' neaktivni barva zluta, aktivni azurova EEPROM.write(21, 1); // preset X: automaticke ovladani LED EEPROM.write(22, 0); // preset X: bez blikani EEPROM.write(23, 0); // preset X: aktivni barva slozka R EEPROM.write(24, 50); // preset X: aktivni barva slozka G EEPROM.write(25, 50); // preset X: aktivni barva slozka B EEPROM.write(26, 50); // preset X: neaktivni barva slozka R EEPROM.write(27, 50); // preset X: neaktivni barva slozka G EEPROM.write(28, 0); // preset X: neaktivni barva slozka B // prednastaveny rezim 'Y' neaktivni barva bila, aktivni barva modra EEPROM.write(29, 1); // preset Y: automaticke ovladani LED EEPROM.write(30, 0); // preset Y: bez blikani EEPROM.write(31, 0); // preset Y: aktivni barva slozka R EEPROM.write(32, 0); // preset Y: aktivni barva slozka G EEPROM.write(33,100); // preset Y: aktivni barva slozka B EEPROM.write(34, 20); // preset Y: neaktivni barva slozka R EEPROM.write(35, 20); // preset Y: neaktivni barva slozka G EEPROM.write(36, 20); // preset Y: neaktivni barva slozka B // prednastaveny rezim 'Z' cervene blikani EEPROM.write(37, 1); // preset Y: automaticke ovladani LED EEPROM.write(38, 50); // preset Y: blikani s periodou 1s (1:1) EEPROM.write(39,100); // preset Y: aktivni barva slozka R EEPROM.write(40, 0); // preset Y: aktivni barva slozka G EEPROM.write(41, 0); // preset Y: aktivni barva slozka B EEPROM.write(42, 0); // preset Y: neaktivni barva slozka R EEPROM.write(43, 0); // preset Y: neaktivni barva slozka G EEPROM.write(44, 0); // preset Y: neaktivni barva slozka B }