Skocz do zawartości

szczepulek

Użytkownicy
  • Zawartość

    32
  • Rejestracja

  • Ostatnio

Reputacja

6 Neutralna

O szczepulek

  • Ranga
    3/10

Ostatnio na profilu byli

144 wyświetleń profilu
  1. rozwinięcie i wykorzystanie w praktyce.. zapraszam do tematu
  2. WSTĘP: ZASTRZEGAM SOBIE PRAWO DO WŁASNOŚCI KODÓW PROGRAMÓW ZAWARTYCH W TYM TEMACIE, KOD/PROGRAM MOŻNA UŻYWAĆ DO CELÓW PRYWATNYCH, LECZ NIE ZEZWALAM ABY WYKORZYSTANY ZOSTAŁ CELACH UCZESTNICTWA PRZEZ OSOBY TRZECIE W KONKURSACH, ARTYKUŁACH, LUB INNYCH PUBLIKACJACH BEZ MOJEJ ZGODY, ZABRANIA SIĘ TAKŻE PRZYPISANIE SOBIE CAŁOŚCI KODU, LUB JEGO CZĘŚCI A DOKŁADNIE PRZEZE MNIE OPRACOWANEGO, UNIKALNEGO OD POWSZECHNIE ZNANYCH Z KURSÓW PROGRAMOWANIA, SZKICÓW, ITP. (WŁASNOŚĆ INTELEKTUALNA) OK, udało mi się zakończyć projekt Podczas testów kilKa błędów wyszło, między innymi że podczas błędu ERR2 w linijce było zapytanie o adres z 2 czujnika, i jeszcze jakiś jeden błąd.. AHA! w funkcji obsługującej zmianę ustawień, po edycji i nie zapisaniu przeskoczenie do następnych stron Menu skutkowało blokadą zwiększania parametrów(+). Niestety... ale musiałem zrezygnować z czujników DS18B20... mają straszną wadę, są niesamowicie podatne na ładunki elektrostatyczne, niestety w miejscu zamontowania sporo produkcyjnych elementów z tworzyw sztucznych pociera o siebie wytwarzając potencjał. Pół biedy jak by tylko zakłócało działanie, ale czujnik GRZAŁ SIĘ DO OKOŁO 80 stopni C, znalazłem w sieci info że podłączając odwrotnie + i - to czujnik działa jak grzałka i się uszkadza. W moim wypadku ładunki jak by na - dawały większą wartość niż na plusie.. sam nie wiem, tak czy inaczej często dochodziło do problemów. Ostatecznie kod zmieniony został pod obsługę NTC w moim przypadku 5k Ohm, tolerancja 0,5%, temp ..-50..+150 *C, nie znałem parametru Beta wiec sam policzyłem, stosując kalkulator z jakiejś strony online, dla temp 0,2*C woda z lodem, i wrzątek 100*C w czajniku, u mnie około 3490. Przekłamanie około 0.5 st C po kalibracji. Przejdźmy do rzeczy.. Podaję 3 szkice, 2 dla układu Mega2560 będącego częścią główną ,nazwę to rejestrator, urządzenia do pomiarów, jest to także master dla komunikacji serial. Oraz jeden szkic dla układu ESP82-12E będącego "okienkiem" na świat wysyłającym dane do bazy danych, umiejscowionej w sieci LAN u mnie, Serwer powstał na komputerze z zainstalowanym XAMPP (apache+mysql). Dodam jeszcze że napisałem stronę w PHP która pobiera z tej bazy danych na serwerze wszystkie pomiary, Lecz mamy tam możliwość z bocznego Menu wybrać 'nr Linii'. i Wyświetlić segregowane wyniki. Na końcu prześlę kilka zdjęć i zrzutów z tabel z wynikami po kilku dniach użytkowania w warunkach produkcyjnych. Uwaga! w kodzie może być pewien nieład.. który w moich oczach jest porządkiem albo skróty myślowe jasne dla mnie, nie koniecznie dla was.. No ale co. Macie PRAWIE wszystko wyłożone na ławę. OFICJALNIE KODY PROGRAMÓW PONIŻEJ UWAŻAM ZA OSTATECZNE, I DZIAŁAJĄCE POPRAWNIE .. lecz nie jest to jednoznaczne że nie posiada błędów lub lepszych rozwiązań. UWAGA!!! Zmienione są niektóre piny ich kolejność i/lub przeznaczenie!!! SPRAWDŹ połączenia przed wgraniem na płytki!!!! Arduino MEGA2560 wersja z cz.temp. DS18B20 #include <EEPROM.h> #include <TM1637Display.h> //wersja 1.0 biblioteki #include <DS18B20.h> #include <OneWire.h> /* SSS L K (2019) v.5 S ZZZZ CCC ZZZZ EEE PPPP U U L EEE K K SSS Z C Z E___E P P U U L E___E K K S Z C Z E P P U U L E K K SSSS ZZZZ CCC ZZZZ EEE PPPP UUU LL EEE K K P KOMUNIKACJA PO SERIALU (SOFTWARE) Do komunikacji wykorzystano Nadawanie TX Arduino Mega 2560, odbior na Arduino Uno R3 Na Mega 2560 uzyto Serial1, mozna uzyc serial2, czy serial3. Na Uno piny 2-oraz 3. WAZNE !!! nie zapomnijcie polaczyc ze soba GND obu plytek. u mnie dziala to dobrze. Przy nadawaniu temperatura jest zamieniana na liczbe calkowita bez przecinka/kropki poprzez pomnozenie przez 100 wyniku pomiaru. By uniknac zmiany dlugosci wysylanych danych przy ujemnych temperaturach, do wyniku dodaje 30 stopni, ktore przy pozniejszemu dekodowaniu na odbiorniku odejmuje (te 30st.), Dzieki temu zabiegowi temperatura np 22.50 st.C, zamienione na calkowite ma wartosc 2250. a po dodaniu wczesniej do pomiaru 30 ma wartosc 5250. I do wysylania potrzebne sa 4 bajty. Bez tego wartosc -23.00 st.C po pomnozeniu ma wartosc -2300 czyli ze znakiem minusa mamy 5 bajtow. Po dodaniu do pomiaru 30 st mamy 13 st (-23+30= 13) podsumowujac, minimalna temp przesylana bez bledu dekodowania/ odczytu/ to temperatura -29.50, natomiast maksymalna to 69.50 (bo 70.00+ 30 = 100, po pomnozeniu przekracza 4 bajty) Może i to rozwiązanie mocno AMATORSKIE, ale działa :) teraz można ulepszac kod i przeksztalcac.. ! ! ! ! ! !! ! ! ! ! ! ! !! ! // kod dla ARDUINO MEGA 2560 (4 x Serial) w trybie nadawania na Serial1 MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit /adaptacja czesciowo dzieki Clovis Fritzen in 05/06/2017 */ #define ONE_WIRE_temp_in 2 //pin dla 1 czujnika ds18b20 #define ONE_WIRE_temp_out 3 //pin dla drugiego czujnika #define CLK1 5 //wyswietlacz nr1 8segm.4-cz dla wejscia powietrza - temp #define DIO1 6 //wyswietlacz nr1 8segm.4-cz #define CLK2 7 //wyswietlacz nr2 8segm.4-cz dla wyjscia powietrza - temp #define DIO2 8 //wyswietlacz nr2 8segm.4-cz int WhichScreen = 1; // This variable stores the current Screen number boolean hasChanged = true; //czy nastapila zmiana w menu/ odswierza wyswietlane dane pobierajac wartosci z tablic po modyfikacjach. boolean pokazMenu = 0; // 0 = glowna funkcja, czy tez domyslnie wyswietlane dane, przy 1 wiadomo co sie poawia jak nazwa zmiennej wskazuje const int resetPin = 9 ; //reset Mega2560 const int automatSwPin = 11 ; // PIN 11 ,podlaczony przez przekaznik w skrzynce kontrolnej const int ALtempLED = 50 ; // podlaczony przez przekaznik w skrzynce kontrolnej const int ALprzekaznik = 51; // Przekaznik sygn ALarmu const int LEDzapisz = 12; //alarmuje o braku zapisu ustawien const int buttonMenu = 33; // wywolanie Menu const int buttonOk = 32; // zatwierdz/zapisz key OK const int buttonUp = 31; // edycja key UP const int buttonDn = 30; // edycja key DOWN int stanAutoSwPin = 0; int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 120; // the debounce time; increase if the output flickers TM1637Display display_1(CLK1, DIO1); TM1637Display display_2(CLK2, DIO2); OneWire oneWire_in(ONE_WIRE_temp_in); OneWire oneWire_out(ONE_WIRE_temp_out); DS18B20 sensor_airin(&oneWire_in); DS18B20 sensor_airout(&oneWire_out); byte address1[8]; //dla ds18b20 czujnik 1 / in byte address2[8]; //dla czujnik 2 / out unsigned long time0 = 0; //zliczanie czasu pracy w automacie unsigned long time0blink = 0; // czasowka dla migajacej lampy sygnalizacyjnej word zwlokaPrzekazAL = 30000; //300000ms = 5 minut, zwloka nim wlaczy sie sygnalizator zewn alarmu unsigned long time1 = 0; //migajaca dioda powiadomien o zapisie unsigned long time2 = 0; // czasowka dla wyswietlacza LED Display 1 / odswiezanie unsigned long timeReset; // czasowka do momentu resetowania int actErr1 = 0; int actErr2 = 0; int zwlokaReset = 30000; //unsigned long time3 = 0; // testowe pocz loop ORAZ czas po zapisie 'buzki'/LED 'zapisz!' //unsigned long time4 = 0; // testowe koniec loop - pocz //unsigned long time5 = 0; // testowe str 1 - pocz //unsigned long time6 = 0; // testowe //unsigned long timeSrednia=0; //unsigned long przebieg = 1; //unsigned long timeSredniaSuma = 0; //unsigned long timeSredniaWynik = 0; //unsigned long dodawanie [1]; unsigned long autoExitMenu = 0; //wyjscie z menu automat (odczyt dla funkcji z millis) word autoExitCzas = 20000; // czas zwloi przed AUTOMATYCZNYM WYJSCIEM z menu, maksymalnie '65534' ms dla zmiennej typu 'word' boolean d1 = 0; // do migajacej diody zapis boolean d2 = 0; // do migajacej lampy sygnalizacyjnej uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit uint8_t wysw2LED[] = { 0x00, 0x00, 0x00, 0x00 }; String wyspom1 [11]; // [znSpecPoczatku][c1p1][c2p1][c3p1][AL0/1][c1p2][c2p2][c3p2][liniaC1][liniaC2][znSpecKonca] /* tabStrMenu - przechowywanie poszczegolnych ustawien dla kolejnych stron, 0 - niewykozystane, 1 - nr czujnika powiazany z alarmem, 2 - dla 1 strony czyli ALARM, 3 - przechowywany numer LINII; mozna tez przypisac do stron przez 's-1' w linii funkci menu */ int tabStrMenu[4]; // dane ze stron/menu LED // ilosc deklarowana = ilosc stron + 1; srtona 0 (case 0) nie przechowuje zadnej wartosci potrzebnej dla dzialaniaprogramu int eepromOdczyt[4]; // i tak wartosci w tabeli [0] - braka odpowiednika dla pamieci EEPROM/miejsca 0 nie ma poprostu w EEPROM, [1] w tabeli odpowiada miejsce (1) w pamieci eeprom itd... int i; char AL; char KOD; // zakodowane wartosci do wyslania Serial byte first3loopForTX; //pierwsze 3 petle programu-odliczanie //wyswietlanie segmentow dla ALc const uint8_t disp_cznr[] = { // dalej w kodzie czujnik nr 1=in 2=out SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F, // L SEG_D | SEG_E | SEG_G // c }; //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F , // L SEG_C | SEG_E | SEG_G // n }; const uint8_t disp_done[] = { SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O SEG_C | SEG_E | SEG_G, // n SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E }; const uint8_t disp_buzka[] = { SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 8 8-] SEG_G, // - SEG_A | SEG_B | SEG_C | SEG_D, // ] 0 }; const uint8_t disp_confirm[] = { SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // e SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d SEG_E | SEG_D, // i SEG_D | SEG_E | SEG_F | SEG_G // t }; /* P const uint8_t disp_confirm[] = { SEG_A | SEG_B | SEG_E | SEG_F | SEG_G, // c 0, // o 0, // n 0 // f }; */ void setup() { digitalWrite(resetPin, HIGH); delay(200); pinMode(buttonOk, INPUT_PULLUP); pinMode(buttonMenu, INPUT_PULLUP); pinMode(buttonUp, INPUT_PULLUP); pinMode(buttonDn, INPUT_PULLUP); pinMode(automatSwPin, INPUT_PULLUP); pinMode(LEDzapisz, OUTPUT); digitalWrite(LEDzapisz, LOW); pinMode(ALprzekaznik, OUTPUT); digitalWrite(ALprzekaznik, LOW); pinMode(ALtempLED, OUTPUT); digitalWrite(ALtempLED, LOW); pinMode(resetPin, OUTPUT); display_1.setBrightness(0x0c); //LED7Seg jasnosc wys 1, ponizej 2 display_2.setBrightness(0x0c); Serial.begin(9600); Serial1.begin(9600); // inic. serial 1 do wysylania danych na esp8266 sensor_airin.begin(9); // inicjacja, wartosc w nawiasach to rozdzielczosc czujnika od 9 do 12 sensor_airout.begin(9); oneWire_in.reset_search(); while (oneWire_in.search(address1)) { if (address1[0] != 0x28) continue; if (OneWire::crc8(address1, 7) != address1[7]) { Serial.println(F("1-Wire IN bus connection error!")); break; } } oneWire_out.reset_search(); while (oneWire_out.search(address2)) { if (address2[0] != 0x28) continue; if (OneWire::crc8(address2, 7) != address2[7]) { Serial.println(F("1-Wire OUT bus connection error!")); break; } } // PINy diagnostyczne //pinMode(40, OUTPUT); // czas trwania dla DS18b20 //pinMode(44, OUTPUT); //czas trwania dla LED-wysw sensor_airin.request(); sensor_airout.request(); if (EEPROM.read(1) > 2) //warunek, jesli nr czujnika odczytany w EEPROM jest wiekszy niz 2 --zapisz wartosc domyslna 1 { Serial.println("Zapisano domyslny numer czujnika dla alarmu"); EEPROM.write(1, 1); } for (i = 1; i <= 3; i++) // ilosc stron = 3 w tym przypadku, to i komorek pamieci 3 { tabStrMenu[i] = EEPROM.read(i); // i=1 alarm (sygnalizacja) przypisany dla czujnika 1 lub 2 (1= in, 2= out) // i=2 do testow domyslna wartosc dla alarmu, domyslnie pobierane z EEPROM do tabeli // i=3 domyslnie z eeprom - pobranie numeru linii do tabeli WhichScreen = 0; // aby menu startowalo od 1 str. } AL = '0'; // znacznik alarmu na znak 0 first3loopForTX = 1; //pierwsze wysylanie danych po Serial'u od uruchomienie programu time0 = millis(); // rozpoczecie zliczania (dla trybu Nara praca automat) timeReset = millis(); } void loop() { // time3 = millis(); int airinCalkow; int airoutCalkow; int comTempIN; int comTempOut; stanAutoSwPin = digitalRead(automatSwPin); // odczytaj stan na pine - przekaznik w Narze if (stanAutoSwPin == !LOW) // jesli wyl. automat.. time0 = millis(); // nadpisuj zliczanie (zerowanie) // digitalWrite(40, HIGH); //do pomiaru na oscyloskopie czasu trwania "start pomiaru odczytu DS18B20" // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ for (i = 1 ; i <= 3; i++) { eepromOdczyt[i] = EEPROM.read(i); //aktualnie zapisane w eeprom // Serial.println("wartosci zapisane w komorkak EEPROM:"); // Serial.println(eepromOdczyt[i]); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ( sensor_airin.available() ) { float tempIn = sensor_airin.readTemperature(address1); // odczyt temp float tempOut = sensor_airout.readTemperature(address2); /* Serial.println(tempOut); //wyswietla w serial monitor, ostatecznie bedzie usuniete */ // digitalWrite(40, LOW); //koniec pomiaru odczytu i przeliczenia na calkowita liczbe airinCalkow = tempIn * 100; //pozbycie sie kropki w wyniku pomiaru xx.xx airoutCalkow = tempOut * 100; //podobnie dla drugiego pomiaru comTempIN = (tempIn + 30) * 100; //pozbycie sie kropki w wyniku pomiaru xx.xx comTempOut = (tempOut + 30) * 100; //podobnie dla drugiego pomiaru sensor_airin.request(); sensor_airout.request(); } Serial.println("sens.dost?; adres sen1; adres sen2:"); Serial.println(sensor_airin.available()); // informacje do testow dzialania wysw w serial monitor, nie potzrebne potem. Serial.println(address1[0]); Serial.println(address2[0]); //obsluga wyswietlania pierwszego wyswietlacza dla czujnika 1 ,szczegulna uwage nalezy zwrocic na prawidlowe odwolanie sie do uint, i display // digitalWrite(44, HIGH); //start wyswietlanie wartosci na led_tm1637 // uwaga.. zamiana ulamka na calkowite i przez dodanie do wyniku +29 pozbycie sie ewentualnego znaku MINUS char ti1 = comTempIN / 1000 % 10 + 48; //dodanie 48 by uzyskac znak typu char char ti2 = comTempIN / 100 % 10 + 48; char ti3 = comTempIN / 10 % 10 + 48; char to1 = comTempOut / 1000 % 10 + 48; // L_._ dziesiatki char to2 = comTempOut / 100 % 10 + 48; // _L._ jednosci char to3 = comTempOut / 10 % 10 + 48; // __.L cz.dziesietne //jesli odczyt EEPROM nr czuj=1 i temp wej >= odczyt EEPROM dla temp alarmu 'lub' if (eepromOdczyt[1] == 1 && airinCalkow >= eepromOdczyt[2] * 100 || eepromOdczyt[1] == 2 && airoutCalkow >= eepromOdczyt[2] * 100) { AL = '1'; digitalWrite(ALtempLED, HIGH); //aktywacja diody sygnalizujacej o przekroczeniu temp max , takze praca maszyny w Automacie if (millis() - time0 > zwlokaPrzekazAL) { if (millis() - time0blink > 1250) { d2 = !d2; time0blink = millis(); } if (d2) { digitalWrite(ALprzekaznik, HIGH); //aktywacja przekaznika sygnalizacji alarmu po 5 min od wykrycia pracy w automacie } else { digitalWrite(ALprzekaznik, LOW); } } else { digitalWrite(ALprzekaznik, LOW); } } else { AL = '0'; digitalWrite(ALprzekaznik, LOW); // brak alarmu - wylacz przekaznik, diode sygn. digitalWrite(ALtempLED, LOW); } char Ln1 = eepromOdczyt[3] / 10 % 10 + 48; // 1 cyfra nr linii --dodanie 48 by uzyskac znak typu char char Ln2 = eepromOdczyt[3] % 10 + 48; //2 cyfra nr linii /* Serial.println("pierwsze uruch petli loop?"); //test Serial.println(firstSerialTX); //test Serial.println("ln1 ln2"); Serial.println(Ln1); Serial.println(Ln2); */ // digitalWrite(44, LOW); //koniec pomiaru czasu funkcji wyswietlania na 2 szt modulu LED wyswietlacz tm1637 //pomiar na oscyloskopie /*kodowanie Alarmu i pracy nary w Auto/Recznym wyspom1[4] = KOD jesli kod pryjmuje wartosc 0 - tryb autom. | brak alarmu 1 - tryb autom. | alarm! 2 - tryb reczny/wyl | brak alarmu 3 - tryb reczny/wyl | alarm! na kod sklada sie AL i stanAutoSwPin (LOW = tryb autom) */ if (AL == '0' && stanAutoSwPin == LOW) { KOD = '0'; // brak alarmu, praca automat } if (AL == '1' && stanAutoSwPin == LOW) { KOD = '1'; } if (AL == '0' && stanAutoSwPin == HIGH) { KOD = '2'; } if (AL == '1' && stanAutoSwPin == HIGH) { KOD = '3'; } char wyspom1 [11]; // [znspec][c1p1][c2p1][c3p1][AL0/1][c1p2][c2p2][c3p2][liniaC1][liniaC2][znSpecKonca] //char wyspom2 [5]; wyspom1[0] = 0x7B; //zn specj nadawania wyspom1[1] = ti1; //odpowiada za dziesiatki 1 pomiaru wyspom1[2] = ti2; //odpowiada za jednosci 1 pomiaru wyspom1[3] = ti3; //odpowiada za czasci dziesietne 1 pomiaru, czyli po kropce wyspom1[4] = KOD; //czy aktywny alarm?? temperatury: 0 nie, 1 tak wyspom1[5] = to1; //odpowiada za dziesiatki 2 pomiaru wyspom1[6] = to2; //odpowiada za jednosci 2 pomiaru wyspom1[7] = to3; //odpowiada za czasci dziesietne 2 pomiaru, czyli po kropce wyspom1[8] = Ln1; // 1. cyfra nr linii wyspom1[9] = Ln2; // 2. cyfta nr linii wyspom1[10] = 0x7D; // znak specj zakonczenia nadawania /* konfiguraca przycisku Menu */ if (digitalRead(buttonMenu) == LOW && pokazMenu == 0) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { pokazMenu = 1; //uruchamia Menu delay(15); } // komunikacja if (wyspom1[1] != '0' && wyspom1[2] != '0' && wyspom1[3] != '0' || first3loopForTX >= 3) // podczas startu programu na plytce wartosci sa rowne 0 0 0 , jesli wartosci sa inne to wysyla na SERIAL dane { Serial1.write(wyspom1, 11); // wysyla paczke do drugiego urzadzenia na Serial nr (serial1) Serial.println("na com"); for (int j = 0; j < 11; j++) { Serial.print(wyspom1[j]); } Serial.println(" "); } else { Serial.println("! blad wartosci do wyslania lub wykonanie petli 'loop' mniej niz 3 razy od starcie!"); // zdazalo sie ze pierwsze 3 pomiary po uruchomieniu byly losowe zafalszowane dlatego pierwsze trzy pomijam if (first3loopForTX < 3) //dodaje 1 do czasu wykonania 3co najmniej 3 petli { first3loopForTX++; //przebieg = 1; //testy czasowe obiegu petli } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // kontrolka o nie zapisaniu do pamieci parametrow z menu. if (eepromOdczyt[1] != tabStrMenu[1] || eepromOdczyt[2] != tabStrMenu[2] || eepromOdczyt[3] != tabStrMenu[3]) // kontrolka miga dla braku zapisu nr czujnika { if (millis() - time1 > 250) { d1 = !d1; time1 = millis(); } } if (d1) { digitalWrite(LEDzapisz, HIGH); } else { digitalWrite(LEDzapisz, LOW); } if (eepromOdczyt[1] == tabStrMenu[1] && eepromOdczyt[2] == tabStrMenu[2] && eepromOdczyt[3] == tabStrMenu[3]) // " && AL != '1' " do testu przekaznika podczas alarmu , sygnalizacja na LED pin 13 { digitalWrite(LEDzapisz, LOW); } // jesli (domyslnie na starcie) mamy 0 to wykonaj program, wlasciwy..czy tez ten ktory ma sie glownie wykonywac if (pokazMenu == 0) { //GLOWNY PROGRAM //poczatek gl prog if ( airinCalkow < -9900 || airinCalkow == 0) { wysw1LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E wysw1LED[1] = (SEG_E | SEG_G); // r wysw1LED[2] = (SEG_E | SEG_G); // r wysw1LED[3] = display_1.encodeDigit(1); // 1 display_1.setSegments(wysw1LED); // Err1 actErr1 = 1; //ponowne wyszukanie czujnika i przypisanie pod address oneWire_in.reset_search(); while (oneWire_in.search(address1)) { if (address1[0] != 0x28) continue; if (OneWire::crc8(address1, 7) != address1[7]) { Serial.println(F("1-Wire IN bus connection error!")); break; } } } else { wysw1LED[0] = display_1.encodeDigit(airinCalkow / 1000 % 10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym wysw1LED[1] = display_1.encodeDigit(airinCalkow / 100 % 10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym wysw1LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam wysw1LED[3] = display_1.encodeDigit(airinCalkow / 10 % 10); //pierwsza cyfra czesci dziesietnych actErr1 = 0; } //obsluga wyswietlania drugiego wyswietlacza dla czujnika 2 if (airoutCalkow < -9999 || airoutCalkow == 0) { wysw2LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E wysw2LED[1] = (SEG_E | SEG_G); // r wysw2LED[2] = (SEG_E | SEG_G); // r wysw2LED[3] = display_2.encodeDigit(2); // 2 display_2.setSegments(wysw2LED); // Err2 actErr2 = 1; //ponowne wyszukanie czujnika i przypisanie pod addres oneWire_out.reset_search(); while (oneWire_out.search(address2)) { if (address2[0] != 0x28) //// pooprawa błedu address1 na adress2 /sprawdzic podczas dzialania(!) continue; if (OneWire::crc8(address2, 7) != address2[7]) { Serial.println(F("1-Wire OUT bus connection error!")); break; } } } else { wysw2LED[0] = display_2.encodeDigit(airoutCalkow / 1000 % 10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[1] = display_2.encodeDigit(airoutCalkow / 100 % 10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam wysw2LED[3] = display_2.encodeDigit(airoutCalkow / 10 % 10); //pierwsza cyfra czesci dziesietnych // display_2.setSegments(wysw2LED); // wyswietlenie temperatury na pierwszym wyswietlaczu actErr2 = 0; } if (millis() - time2 >= 125) // co 125ms odswierzenie wyswietlaczy { display_1.setSegments(wysw1LED); // wyswietlenie temperatury na pierwszym wyswietlaczu display_2.setSegments(wysw2LED); time2 = millis(); } // koniec gl prog hasChanged = true; // ustawiam na true, aby po wlaczeniu na menu pojawila sie na wyswietlaczu strona ustawien, bez tego zostaje zamrozony wynik ostatniego pomiaru z wejscia analogowego if (actErr1 == 1 || actErr2 == 1) { if (millis() - timeReset > zwlokaReset) digitalWrite(resetPin, LOW); } else { timeReset = millis(); digitalWrite(resetPin, HIGH); } } else // jesli zmienna pokazMenu ma wartosc inna niz zero.. w tym wypadku tylko moze byc to 1 wykonaj.. wyswietlenie menu { int s = WhichScreen; // UWAGA! nalezy zadeklarowac tablice o liczbie elementow nie mniejszej niz ilosc stron. /* konfiguraca przycisku Up/gora */ if (digitalRead(buttonUp) == LOW && WhichScreen == s) // zmiana parametrow UP/dodaj { //Serial.print("UP dla strona nr :"); //Serial.println(WhichScreen); if (WhichScreen == s) { if (tabStrMenu[s] < 99 && s != 1) // gorna granica wyboru 99, oprocz strony dla nr czujnika gdzie max to 2. { tabStrMenu[s]++; //dodaj o jeden wiecej } if (s == 1 && tabStrMenu[s] < 2) // gorna granica wyboru 99, oprocz strony dla nr czujnika gdzie max to 2. { tabStrMenu[s]++; //dodaj o jeden wiecej } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; //odswierza wyswietlacz LED delay (20); } } /* konfiguraca przycisku dol/minus */ if (digitalRead(buttonDn) == LOW && WhichScreen == s) // zmiana parametrow DOWN/odejmij { if (WhichScreen == s) { if (tabStrMenu[s] > 1) // { tabStrMenu[s]--; } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; delay(20); } } /* konfiguracja przycisku Ok/Zapisz */ if (digitalRead(buttonOk) == LOW && WhichScreen == s && WhichScreen > 0) // od strony 1 zapis do komorki 's' = stronie { if (WhichScreen == s) { if (eepromOdczyt[s] == 255) //warunek gdy wartosc domyslna wynosi 255 (nowa plytka nie nadpisywana pamiec) uzyj polecenia zapisz WRITE { EEPROM.write(s, 35); // zapisyj na wartosc domyslna alarmu / linii produ. na: 35 tabStrMenu[s] = eepromOdczyt[s]; // uaktualnienie wpisanej wartosci z pamieci do tablicy wyswietlajacej display_1.setSegments(disp_done); Serial.println("\n nadpisano po raz PIERWSZY \n strona i komorka nr:"); Serial.println(s); hasChanged = true; digitalWrite(LEDzapisz, LOW); digitalWrite(LEDzapisz, HIGH); delay(75); digitalWrite(LEDzapisz, LOW); delay(50); digitalWrite(LEDzapisz, HIGH); delay(75); } else { if (eepromOdczyt[s] != tabStrMenu[s]) { EEPROM.update(s, tabStrMenu[s]); Serial.println("uaktualniono wartosc w pamieci..."); display_1.setSegments(disp_done); digitalWrite(LEDzapisz, HIGH); display_2.setSegments(disp_buzka); hasChanged = true; delay(1300); digitalWrite(LEDzapisz, LOW); //wygasza diode zapisu display_2.clear(); hasChanged = true; } } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; delay (25); } } if (millis() - autoExitMenu > autoExitCzas) //warunek wyprowadza z menu, jesli brak aktywnosci podana ilosc czasu (ms) { for (int k = 1; k <= 3; k++) //dla stron 1-3 (LNr, czNr, alTemp) przywrocenie ustawien domyslnych jesli roznia sie od nastawionych i zapisanych w eeprom, oraz wyl diody sygnalizacyjnej 'zapisz' if (eepromOdczyt[k] != tabStrMenu[k]) tabStrMenu[k] = eepromOdczyt[k]; pokazMenu = 0; digitalWrite(LEDzapisz, LOW); autoExitMenu = millis(); } if (hasChanged == true) { switch (WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; case 4: { /* Dzieki temu warunkowi, bedac na OSTATNIEJ wyswietlanej stronie, jesli wprowadzimy modyfikacje parametrow na ktorejs ze stron, i nie zapiszemy ich przy wychodzeniu z menu zostana przywrocone domyslne wartosci zapisane w eeprom. kontrolka od zapisu gasnie. */ for (i = 1 ; i <= 3; i++) if (eepromOdczyt[i] != tabStrMenu[i]) { tabStrMenu[i] = eepromOdczyt[i]; } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu pokazMenu = 0; //wracamy do wyswietlania z glownej pętli funkcji } break; /* Dla wiekszej ilosci wyswietlania pozycji menu case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonMenu); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 4) { //ilosc wszystkich stron ..doliczamy tez ta wracajaca do pierwotnej funkcji wykonywania WhichScreen = 1; } } /* wylicza czas petli programu time4= millis()-time3; timeSrednia=dodawanie[0]; dodawanie[0]=timeSrednia+time4; timeSredniaWynik=dodawanie[0]/przebieg; Serial.println("ŚrEdNiA:"); Serial.println(timeSredniaWynik); Serial.println(" "); przebieg++; */ } // KONIEC void loop() !!; ################################################# void firstScreen() // pierwsza strona opcji // nr czujnika dla alarmu { display_1.setSegments(disp_cznr, 3, 0); // wyswietla wartosc cz1 lub czujnik 2, w zaleznosci ile ich podlaczymy display_1.showNumberDec(tabStrMenu[1], false, 1, 3); //wyswietla graniczna temp. alarmu if (tabStrMenu[1] != eepromOdczyt[1]) { display_2.setSegments(disp_confirm); // wyswietlenie Edit na drugim wyswietlaczu w menu } else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } } void secondScreen() // druga str opcji itd itp { // display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(tabStrMenu[2], false, 2, 2); //wyswietla graniczna temp. alarmu if (tabStrMenu[2] != eepromOdczyt[2]) { display_2.setSegments(disp_confirm); }// wyswietlenie Edit na drugim wyswietlaczu w menu else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } // time5=millis()-time3; // Serial.println("Str2"); // Serial.println(time5); // Serial.print("STRONA 2 Alarm od:"); // test w serial // Serial.println(tabStrMenu[2]); } void thirdScreen() // trzecia str opcji itd itp { display_1.showNumberDec(tabStrMenu[3], false, 2, 2); // wartosc przechowywana dla Nr Linii // display_1.showNumberDecEx(tabStrMenu[3],0, true); // wartosc przechowywana dla Nr Linii display_1.setSegments(disp_linia, 2, 0); if (tabStrMenu[3] != eepromOdczyt[3]) { display_2.setSegments(disp_confirm); // wyswietlenie Edit na drugim wyswietlaczu w menu } else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } // Serial.print("STRONA 3 linia nr:"); // test w serial // Serial.println(tabStrMenu[3]); } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami, ponizej rozpiska dla wyswietlacza LCD !!! void fourthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("This is screen 4"); lcd.setCursor(0,1); lcd.print("Just press btn"); } void fifthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Fifth screen"); lcd.setCursor(0,1); lcd.print("i2C LCD screen"); } void sixthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("THE last screen"); lcd.setCursor(0,1); lcd.print(" Sixth and last"); } */ Arduino MEGA2560 wersja z cz. temp. NTC 5K #include <EEPROM.h> #include <TM1637Display.h> //wersja 1.0 biblioteki // WERSJA DLA NTC 5k ohm; toler 0,5%; Beta wyliczona 3490 /* SSS L K (2019) v.6 S ZZZZ CCC ZZZZ EEE PPPP U U L EEE K K SSS Z C Z E___E P P U U L E___E K K S Z C Z E P P U U L E K K SSSS ZZZZ CCC ZZZZ EEE PPPP UUU LL EEE K K P KOMUNIKACJA PO SERIALU (SOFTWARE) Do komunikacji wykorzystano Nadawanie TX Arduino Mega 2560, odbior na Arduino Uno R3 Na Mega 2560 uzyto Serial1, mozna uzyc serial2, czy serial3. Na Uno piny 2-oraz 3. WAZNE !!! nie zapomnijcie polaczyc ze soba GND obu plytek. u mnie dziala to dobrze. Przy nadawaniu temperatura jest zamieniana na liczbe calkowita bez przecinka/kropki poprzez pomnozenie przez 100 wyniku pomiaru. By uniknac zmiany dlugosci wysylanych danych przy ujemnych temperaturach, do wyniku dodaje 30 stopni, ktore przy pozniejszemu dekodowaniu na odbiorniku odejmuje (te 30st.), Dzieki temu zabiegowi temperatura np 22.50 st.C, zamienione na calkowite ma wartosc 2250. a po dodaniu wczesniej do pomiaru 30 ma wartosc 5250. I do wysylania potrzebne sa 4 bajty. Bez tego wartosc -23.00 st.C po pomnozeniu ma wartosc -2300 czyli ze znakiem minusa mamy 5 bajtow. Po dodaniu do pomiaru 30 st mamy 13 st (-23+30= 13) podsumowujac, minimalna temp przesylana bez bledu dekodowania/ odczytu/ to temperatura -29.50, natomiast maksymalna to 69.50 (bo 70.00+ 30 = 100, po pomnozeniu przekracza 4 bajty) Może i to rozwiązanie mocno AMATORSKIE, ale działa :) teraz można ulepszac kod i przeksztalcac.. ! ! ! ! ! !! ! ! ! ! ! ! !! ! // kod dla ARDUINO MEGA 2560 (4 x Serial) w trybie nadawania na Serial1 MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit /adaptacja czesciowo dzieki Clovis Fritzen in 05/06/2017 */ // Czujniki temp analogowe NCT 5k (0.3stC =14280 Ohm; 100stC =482 Ohm, beta 3485-3490) // which analog pin to connect //czujnik 1 IN na pinie analogowym A0 #define THERMISTORPIN_1 A0 // resistance at 25 degrees C #define THERMISTORNOMINAL_1 5000 // temp. for nominal resistance (almost always 25 C) #define TEMPERATURENOMINAL_1 25 // how many samples to take and average, more takes longer // but is more 'smooth' #define NUMSAMPLES_1 5 // do usredniania wynikow tutaj 5-ciu // The beta coefficient of the thermistor (usually 3000-4000) #define BCOEFFICIENT_1 3485 // the value of the 'other' resistor / rezystor ma dokładność 5% powinno się uzyć 1% toleranci, tutj wpisuje wartosc z pomiaru multimetrem #define SERIESRESISTOR_1 5020 //czujnik 2 out na pinie analogowym A2 #define THERMISTORPIN_2 A2 // resistance at 25 degrees C wartosc rezystancji dla... #define THERMISTORNOMINAL_2 5000 // temp. for nominal resistance (almost always 25 C) ...temperatury 25*C #define TEMPERATURENOMINAL_2 25 // how many samples to take and average, more takes longer // but is more 'smooth' #define NUMSAMPLES_2 5 // The beta coefficient of the thermistor (usually 3000-4000) #define BCOEFFICIENT_2 3485 //3485 // the value of the 'other' resistor #define SERIESRESISTOR_2 4990 #define CLK1 5 //wyswietlacz nr1 8segm.4-cz dla wejscia powietrza - temp #define DIO1 6 //wyswietlacz nr1 8segm.4-cz #define CLK2 7 //wyswietlacz nr2 8segm.4-cz dla wyjscia powietrza - temp #define DIO2 8 //wyswietlacz nr2 8segm.4-cz //bufor wynikow pomiarow temp czujniki 1 i 2 int samples_1[NUMSAMPLES_1]; int samples_2[NUMSAMPLES_2]; //do pomiarow temp , sredniej, i konwersji z czujnikow temp NTC5 uint8_t m; float average_1; uint8_t n; float average_2; int comTempIN; int comTempOut; int WhichScreen = 1; // This variable stores the current Screen number boolean hasChanged = true; //czy nastapila zmiana w menu/ odswierza wyswietlane dane pobierajac wartosci z tablic po modyfikacjach. boolean pokazMenu = 0; // 0 = glowna funkcja, czy tez domyslnie wyswietlane dane, przy 1 wiadomo co sie poawia jak nazwa zmiennej wskazuje const int resetPin = 9 ; //reset Mega2560 const int automatSwPin = 11 ; // PIN 11 ,podlaczony przez przekaznik w skrzynce kontrolnej const int ALtempLED = 50 ; // podlaczony przez przekaznik w skrzynce kontrolnej const int ALprzekaznik = 51; // Przekaznik sygn ALarmu const int LEDzapisz = 12; //alarmuje o braku zapisu ustawien const int buttonMenu = 33; // wywolanie Menu const int buttonOk = 32; // zatwierdz/zapisz key OK const int buttonUp = 31; // edycja key UP const int buttonDn = 30; // edycja key DOWN int stanAutoSwPin = 0; int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 120; // the debounce time; increase if the output flickers TM1637Display display_1(CLK1, DIO1); TM1637Display display_2(CLK2, DIO2); unsigned long time0 = 0; //zliczanie czasu pracy w automacie unsigned long time0blink = 0; // czasowka dla migajacej lampy sygnalizacyjnej word zwlokaPrzekazAL = 30000; //300000ms = 5 minut, zwloka nim wlaczy sie sygnalizator zewn alarmu unsigned long time1 = 0; //migajaca dioda powiadomien o zapisie unsigned long time2 = 0; // czasowka dla wyswietlacza LED Display 1 / odswiezanie unsigned long timeReset; // czasowka do momentu resetowania int actErr1 = 0; int actErr2 = 0; float zwlokaReset = 660000; // czas zwloki do resetu, RESET wykonywany podajac niski stan LOW z PINu nr 9 na PIN Reset unsigned long autoExitMenu = 0; //wyjscie z menu automat (odczyt dla funkcji z millis) word autoExitCzas = 20000; // czas zwloi przed AUTOMATYCZNYM WYJSCIEM z menu, maksymalnie '65534' ms dla zmiennej typu 'word' boolean d1 = 0; // do migajacej diody zapis boolean d2 = 0; // do migajacej lampy sygnalizacyjnej uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit uint8_t wysw2LED[] = { 0x00, 0x00, 0x00, 0x00 }; String wyspom1 [11]; // [znSpecPoczatku][c1p1][c2p1][c3p1][AL0/1][c1p2][c2p2][c3p2][liniaC1][liniaC2][znSpecKonca] /* tabStrMenu - przechowywanie poszczegolnych ustawien dla kolejnych stron, 0 - niewykozystane, 1 - nr czujnika powiazany z alarmem, 2 - dla 1 strony czyli ALARM, 3 - przechowywany numer LINII; mozna tez przypisac do stron przez 's-1' w linii funkci menu */ int tabStrMenu[4]; // dane ze stron/menu LED // ilosc deklarowana = ilosc stron + 1; srtona 0 (case 0) nie przechowuje zadnej wartosci potrzebnej dla dzialaniaprogramu int eepromOdczyt[4]; // i tak wartosci w tabeli [0] - braka odpowiednika dla pamieci EEPROM/miejsca 0 nie ma poprostu w EEPROM, [1] w tabeli odpowiada miejsce (1) w pamieci eeprom itd... int i; char AL; char KOD; // zakodowane wartosci do wyslania Serial byte first3loopForTX; //pierwsze 3 petle programu-odliczanie //wyswietlanie segmentow dla ALc const uint8_t disp_cznr[] = { // dalej w kodzie czujnik nr 1=in 2=out SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F, // L SEG_D | SEG_E | SEG_G // c }; //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F , // L SEG_C | SEG_E | SEG_G // n }; const uint8_t disp_done[] = { SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O SEG_C | SEG_E | SEG_G, // n SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E }; const uint8_t disp_buzka[] = { SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 8 8-] SEG_G, // - SEG_A | SEG_B | SEG_C | SEG_D, // ] 0 }; const uint8_t disp_confirm[] = { SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // e SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d SEG_E | SEG_D, // i SEG_D | SEG_E | SEG_F | SEG_G // t }; void setup() { digitalWrite(resetPin, HIGH); delay(200); pinMode(buttonOk, INPUT_PULLUP); pinMode(buttonMenu, INPUT_PULLUP); pinMode(buttonUp, INPUT_PULLUP); pinMode(buttonDn, INPUT_PULLUP); pinMode(automatSwPin, INPUT_PULLUP); pinMode(LEDzapisz, OUTPUT); digitalWrite(LEDzapisz, LOW); pinMode(ALprzekaznik, OUTPUT); digitalWrite(ALprzekaznik, LOW); pinMode(ALtempLED, OUTPUT); digitalWrite(ALtempLED, LOW); pinMode(resetPin, OUTPUT); display_1.setBrightness(0x0c); //LED7Seg jasnosc wys 1, ponizej 2 display_2.setBrightness(0x0c); Serial.begin(9600); Serial1.begin(9600); // inic. serial 1 do wysylania danych na esp8266 if (EEPROM.read(1) > 2) //warunek, jesli nr czujnika odczytany w EEPROM jest wiekszy niz 2 --zapisz wartosc domyslna 1 { Serial.println("Zapisano domyslny numer czujnika dla alarmu"); EEPROM.write(1, 1); } for (i = 1; i <= 3; i++) // ilosc stron = 3 w tym przypadku, to i komorek pamieci 3 { tabStrMenu[i] = EEPROM.read(i); // i=1 alarm (sygnalizacja) przypisany dla czujnika 1 lub 2 (1= in, 2= out) // i=2 do testow domyslna wartosc dla alarmu, domyslnie pobierane z EEPROM do tabeli // i=3 domyslnie z eeprom - pobranie numeru linii do tabeli WhichScreen = 0; // aby menu startowalo od 1 str. } AL = '0'; // znacznik alarmu na znak 0 first3loopForTX = 1; //pierwsze wysylanie danych po Serial'u od uruchomienie programu time0 = millis(); // rozpoczecie zliczania (dla trybu Nara praca automat) timeReset = millis(); // dla automatycznego restartu gdy jest blad Err } void loop() { int airinCalkow; int airoutCalkow; stanAutoSwPin = digitalRead(automatSwPin); // odczytaj stan na pine - przekaznik w Narze if (stanAutoSwPin == !LOW) // jesli wyl. automat.. time0 = millis(); // nadpisuj zliczanie (zerowanie) // digitalWrite(40, HIGH); //do pomiaru na oscyloskopie czasu trwania "start pomiaru odczytu DS18B20" // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ for (i = 1 ; i <= 3; i++) { eepromOdczyt[i] = EEPROM.read(i); //aktualnie zapisane w eeprom // Serial.println("wartosci zapisane w komorkak EEPROM:"); // Serial.println(eepromOdczyt[i]); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // digitalWrite(40, LOW); //koniec pomiaru odczytu i przeliczenia na calkowita liczbe // CZ nr 1 odczyt konwersja // take N samples in a row, with a slight delay for (m = 0; m < NUMSAMPLES_1; m++) { samples_1[m] = analogRead(THERMISTORPIN_1); delay(10); } // average all the samples out average_1 = 0; for (m = 0; m < NUMSAMPLES_1; m++) { average_1 += samples_1[m]; } average_1 /= NUMSAMPLES_1; // Serial.print("Average analog reading 1 (A0)"); //testy odczytu ntc // Serial.println(average_1); // convert the value to resistance average_1 = 1023 / average_1 - 1; average_1 = SERIESRESISTOR_1 / average_1; // Serial.print("Thermistor resistance 1"); // Serial.println(average_1); float tempIn; tempIn = average_1 / THERMISTORNOMINAL_1; // (R/Ro) tempIn = log(tempIn); // ln(R/Ro) tempIn /= BCOEFFICIENT_1; // 1/B * ln(R/Ro) tempIn += 1.0 / (TEMPERATURENOMINAL_1 + 273.15); // + (1/To) tempIn = 1.0 / tempIn; // Invert tempIn -= 273.15; // convert to C // Serial.print("Temperature 1 "); // Serial.print(tempIn); // Serial.println(" *C"); // CZ nr 2 odczyt konwersja // take N samples in a row, with a slight delay for (n = 0; n < NUMSAMPLES_2; n++) { samples_2[n] = analogRead(THERMISTORPIN_2); delay(10); } // average all the samples out average_2 = 0; for (n = 0; n < NUMSAMPLES_2; n++) { average_2 += samples_2[n]; } average_2 /= NUMSAMPLES_2; // Serial.print("Average analog reading 2 (A2)"); // Serial.println(average_2); // convert the value to resistance average_2 = 1023 / average_2 - 1; average_2 = SERIESRESISTOR_2 / average_2; // Serial.print("Thermistor resistance 2 "); // Serial.println(average_2); float tempOut; tempOut = average_2 / THERMISTORNOMINAL_2; // (R/Ro) tempOut = log(tempOut); // ln(R/Ro) tempOut /= BCOEFFICIENT_2; // 1/B * ln(R/Ro) tempOut += 1.0 / (TEMPERATURENOMINAL_2 + 273.15); // + (1/To) tempOut = 1.0 / tempOut; // Invert tempOut -= 273.15; // convert to C // Serial.print("Temperatura 2 "); // Serial.print(tempOut); // Serial.println(" *C"); airinCalkow = tempIn * 100; //pozbycie sie kropki w wyniku pomiaru xx.xx airoutCalkow = tempOut * 100; //podobnie dla drugiego pomiaru comTempIN = (tempIn + 30) * 100; //pozbycie sie kropki w wyniku pomiaru xx.xx comTempOut = (tempOut + 30) * 100; //podobnie dla drugiego pomiaru //obsluga wyswietlania pierwszego wyswietlacza dla czujnika 1 ,szczegulna uwage nalezy zwrocic na prawidlowe odwolanie sie do uint, i display // digitalWrite(44, HIGH); //start wyswietlanie wartosci na led_tm1637 - testy oscyloskop // uwaga.. zamiana ulamka na calkowite i przez dodanie do wyniku +30 pozbycie sie ewentualnego znaku MINUS ; dodanie +48 dla znaku ASCI char ti1 = comTempIN / 1000 % 10 + 48; //dodanie 48 by uzyskac znak typu char char ti2 = comTempIN / 100 % 10 + 48; char ti3 = comTempIN / 10 % 10 + 48; char to1 = comTempOut / 1000 % 10 + 48; // L_._ dziesiatki char to2 = comTempOut / 100 % 10 + 48; // _L._ jednosci char to3 = comTempOut / 10 % 10 + 48; // __.L cz.dziesietne //jesli odczyt EEPROM nr czuj=1 i temp wej >= odczyt EEPROM dla temp alarmu 'lub' if (eepromOdczyt[1] == 1 && airinCalkow >= eepromOdczyt[2] * 100 || eepromOdczyt[1] == 2 && airoutCalkow >= eepromOdczyt[2] * 100) { AL = '1'; digitalWrite(ALtempLED, HIGH); //aktywacja diody sygnalizujacej o przekroczeniu temp max , takze praca maszyny w Automacie if (millis() - time0 > zwlokaPrzekazAL) { if (millis() - time0blink > 1250) { d2 = !d2; time0blink = millis(); } if (d2) { digitalWrite(ALprzekaznik, HIGH); //aktywacja przekaznika sygnalizacji alarmu po 5 min od wykrycia pracy w automacie } else { digitalWrite(ALprzekaznik, LOW); } } else { digitalWrite(ALprzekaznik, LOW); } } else { AL = '0'; digitalWrite(ALprzekaznik, LOW); // brak alarmu - wylacz przekaznik, diode sygn. digitalWrite(ALtempLED, LOW); } char Ln1 = eepromOdczyt[3] / 10 % 10 + 48; // 1 cyfra nr linii --dodanie 48 by uzyskac znak typu char char Ln2 = eepromOdczyt[3] % 10 + 48; //2 cyfra nr linii // digitalWrite(44, LOW); //koniec pomiaru czasu funkcji wyswietlania na 2 szt modulu LED wyswietlacz tm1637 //pomiar na oscyloskopie /*kodowanie Alarmu i pracy nary w Auto/Recznym wyspom1[4] = KOD jesli kod pryjmuje wartosc 0 - tryb autom. | brak alarmu 1 - tryb autom. | alarm! 2 - tryb reczny/wyl | brak alarmu 3 - tryb reczny/wyl | alarm! na kod sklada sie AL i stanAutoSwPin (LOW = tryb autom) */ if (AL == '0' && stanAutoSwPin == LOW) { KOD = '0'; // brak alarmu, praca automat } if (AL == '1' && stanAutoSwPin == LOW) { KOD = '1'; } if (AL == '0' && stanAutoSwPin == HIGH) { KOD = '2'; } if (AL == '1' && stanAutoSwPin == HIGH) { KOD = '3'; } char wyspom1 [11]; // [znspec][c1p1][c2p1][c3p1][AL0/1][c1p2][c2p2][c3p2][liniaC1][liniaC2][znSpecKonca] //char wyspom2 [5]; wyspom1[0] = 0x7B; //zn specj nadawania wyspom1[1] = ti1; //odpowiada za dziesiatki 1 pomiaru wyspom1[2] = ti2; //odpowiada za jednosci 1 pomiaru wyspom1[3] = ti3; //odpowiada za czasci dziesietne 1 pomiaru, czyli po kropce wyspom1[4] = KOD; //czy aktywny alarm?? temperatury: 0 nie, 1 tak wyspom1[5] = to1; //odpowiada za dziesiatki 2 pomiaru wyspom1[6] = to2; //odpowiada za jednosci 2 pomiaru wyspom1[7] = to3; //odpowiada za czasci dziesietne 2 pomiaru, czyli po kropce wyspom1[8] = Ln1; // 1. cyfra nr linii wyspom1[9] = Ln2; // 2. cyfta nr linii wyspom1[10] = 0x7D; // znak specj zakonczenia nadawania /* konfiguraca przycisku Menu */ if (digitalRead(buttonMenu) == LOW && pokazMenu == 0) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { pokazMenu = 1; //uruchamia Menu delay(15); } // komunikacja if (wyspom1[1] != '0' && wyspom1[2] != '0' && wyspom1[3] != '0' || first3loopForTX >= 3) // podczas startu programu na plytce wartosci sa rowne 0 0 0 , jesli wartosci sa inne to wysyla na SERIAL dane { Serial1.write(wyspom1, 11); // wysyla paczke do drugiego urzadzenia na Serial nr (serial1) Serial.println("na com"); for (int j = 0; j < 11; j++) { Serial.print(wyspom1[j]); } Serial.println(" "); } else { Serial.println("! blad wartosci do wyslania lub wykonanie petli 'loop' mniej niz 3 razy od starcie!"); if (first3loopForTX < 3) //dodaje 1 do czasu wykonania 3co najmniej 3 petli { first3loopForTX++; } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // kontrolka o nie zapisaniu do pamieci parametrow z menu. if (eepromOdczyt[1] != tabStrMenu[1] || eepromOdczyt[2] != tabStrMenu[2] || eepromOdczyt[3] != tabStrMenu[3]) // kontrolka miga dla braku zapisu nr czujnika { if (millis() - time1 > 250) { d1 = !d1; time1 = millis(); } } if (d1) { digitalWrite(LEDzapisz, HIGH); } else { digitalWrite(LEDzapisz, LOW); } if (eepromOdczyt[1] == tabStrMenu[1] && eepromOdczyt[2] == tabStrMenu[2] && eepromOdczyt[3] == tabStrMenu[3]) // " && AL != '1' " do testu przekaznika podczas alarmu , sygnalizacja na LED pin 13 { digitalWrite(LEDzapisz, LOW); } // jesli (domyslnie na starcie) mamy 0 to wykonaj program, wlasciwy..czy tez ten ktory ma sie glownie wykonywac if (pokazMenu == 0) { //GLOWNY PROGRAM //poczatek gl prog if ( airinCalkow < -9900 || airinCalkow == 0) { wysw1LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E wysw1LED[1] = (SEG_E | SEG_G); // r wysw1LED[2] = (SEG_E | SEG_G); // r wysw1LED[3] = display_1.encodeDigit(1); // 1 display_1.setSegments(wysw1LED); // Err1 actErr1 = 1; } else { wysw1LED[0] = display_1.encodeDigit(airinCalkow / 1000 % 10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym wysw1LED[1] = display_1.encodeDigit(airinCalkow / 100 % 10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym wysw1LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam wysw1LED[3] = display_1.encodeDigit(airinCalkow / 10 % 10); //pierwsza cyfra czesci dziesietnych actErr1 = 0; } //obsluga wyswietlania drugiego wyswietlacza dla czujnika 2 if (airoutCalkow < -9999 || airoutCalkow == 0) { wysw2LED[0] = (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G); // E wysw2LED[1] = (SEG_E | SEG_G); // r wysw2LED[2] = (SEG_E | SEG_G); // r wysw2LED[3] = display_2.encodeDigit(2); // 2 display_2.setSegments(wysw2LED); // Err2 actErr2 = 1; } else { wysw2LED[0] = display_2.encodeDigit(airoutCalkow / 1000 % 10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[1] = display_2.encodeDigit(airoutCalkow / 100 % 10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam wysw2LED[3] = display_2.encodeDigit(airoutCalkow / 10 % 10); //pierwsza cyfra czesci dziesietnych // display_2.setSegments(wysw2LED); // wyswietlenie temperatury na pierwszym wyswietlaczu actErr2 = 0; } if (millis() - time2 >= 125) // co 125ms odswierzenie wyswietlaczy { display_1.setSegments(wysw1LED); // wyswietlenie temperatury na pierwszym wyswietlaczu display_2.setSegments(wysw2LED); time2 = millis(); } // koniec glownej czesci programu *************************** hasChanged = true; // ustawiam na true, aby po wlaczeniu na menu pojawila sie na wyswietlaczu strona ustawien, bez tego zostaje zamrozony wynik ostatniego pomiaru z wejscia analogowego if (actErr1 == 1 || actErr2 == 1) { if (millis() - timeReset > zwlokaReset) digitalWrite(resetPin, LOW); } else { timeReset = millis(); digitalWrite(resetPin, HIGH); } } else // jesli zmienna pokazMenu ma wartosc inna niz zero.. w tym wypadku tylko moze byc to 1 wykonaj.. wyswietlenie menu { int s = WhichScreen; // UWAGA! nalezy zadeklarowac tablice o liczbie elementow nie mniejszej niz ilosc stron. /* konfiguraca przycisku Up/gora */ if (digitalRead(buttonUp) == LOW && WhichScreen == s) // zmiana parametrow UP/dodaj { //Serial.print("UP dla strona nr :"); //Serial.println(WhichScreen); if (WhichScreen == s) { if (tabStrMenu[s] < 99 && s != 1) // gorna granica wyboru 99, oprocz strony dla nr czujnika gdzie max to 2. { tabStrMenu[s]++; //dodaj o jeden wiecej } if (s == 1 && tabStrMenu[s] < 2) // gorna granica wyboru 99, oprocz strony dla nr czujnika gdzie max to 2. { tabStrMenu[s]++; //dodaj o jeden wiecej } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; //odswierza wyswietlacz LED delay (20); } } /* konfiguraca przycisku dol/minus */ if (digitalRead(buttonDn) == LOW && WhichScreen == s) // zmiana parametrow DOWN/odejmij { if (WhichScreen == s) { if (tabStrMenu[s] > 1) // { tabStrMenu[s]--; } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; delay(20); } } /* konfiguracja przycisku Ok/Zapisz */ if (digitalRead(buttonOk) == LOW && WhichScreen == s && WhichScreen > 0) // od strony 1 zapis do komorki 's' = stronie { if (WhichScreen == s) { if (eepromOdczyt[s] == 255) //warunek gdy wartosc domyslna wynosi 255 (nowa plytka nie nadpisywana pamiec) uzyj polecenia zapisz WRITE { EEPROM.write(s, 35); // zapisyj na wartosc domyslna alarmu / linii produ. na: 35 tabStrMenu[s] = eepromOdczyt[s]; // uaktualnienie wpisanej wartosci z pamieci do tablicy wyswietlajacej display_1.setSegments(disp_done); Serial.println("\n nadpisano po raz PIERWSZY \n strona i komorka nr:"); Serial.println(s); hasChanged = true; digitalWrite(LEDzapisz, LOW); digitalWrite(LEDzapisz, HIGH); delay(75); digitalWrite(LEDzapisz, LOW); delay(50); digitalWrite(LEDzapisz, HIGH); delay(75); } else { if (eepromOdczyt[s] != tabStrMenu[s]) { EEPROM.update(s, tabStrMenu[s]); Serial.println("uaktualniono wartosc w pamieci..."); display_1.setSegments(disp_done); digitalWrite(LEDzapisz, HIGH); display_2.setSegments(disp_buzka); hasChanged = true; delay(1300); digitalWrite(LEDzapisz, LOW); //wygasza diode zapisu display_2.clear(); hasChanged = true; } } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu hasChanged = true; delay (25); } } if (millis() - autoExitMenu > autoExitCzas) //warunek wyprowadza z menu, jesli brak aktywnosci podana ilosc czasu (ms) { for (int k = 1; k <= 3; k++) //dla stron 1-3 (LNr, czNr, alTemp) przywrocenie ustawien domyslnych jesli roznia sie od nastawionych i zapisanych w eeprom, oraz wyl diody sygnalizacyjnej 'zapisz' if (eepromOdczyt[k] != tabStrMenu[k]) tabStrMenu[k] = eepromOdczyt[k]; pokazMenu = 0; digitalWrite(LEDzapisz, LOW); autoExitMenu = millis(); } if (hasChanged == true) { switch (WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; case 4: { /* Dzieki temu warunkowi, bedac na OSTATNIEJ wyswietlanej stronie, jesli wprowadzimy modyfikacje parametrow na ktorejs ze stron, i nie zapiszemy ich przy wychodzeniu z menu zostana przywrocone domyslne wartosci zapisane w eeprom. kontrolka od zapisu gasnie. */ for (i = 1 ; i <= 3; i++) if (eepromOdczyt[i] != tabStrMenu[i]) { tabStrMenu[i] = eepromOdczyt[i]; } autoExitMenu = millis(); // zerowanie braku aktywnosci w menu pokazMenu = 0; //wracamy do wyswietlania z glownej pętli funkcji } break; /* Dla wiekszej ilosci wyswietlania pozycji menu case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonMenu); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 4) { //ilosc wszystkich stron ..doliczamy tez ta wracajaca do pierwotnej funkcji wykonywania WhichScreen = 1; } } } // KONIEC void loop() !!; ################################################# void firstScreen() // pierwsza strona opcji // nr czujnika dla alarmu { display_1.setSegments(disp_cznr, 3, 0); // wyswietla wartosc cz1 lub czujnik 2, w zaleznosci ile ich podlaczymy display_1.showNumberDec(tabStrMenu[1], false, 1, 3); //wyswietla graniczna temp. alarmu if (tabStrMenu[1] != eepromOdczyt[1]) { display_2.setSegments(disp_confirm); // wyswietlenie Edit na drugim wyswietlaczu w menu } else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } } void secondScreen() // druga str opcji itd itp { // display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(tabStrMenu[2], false, 2, 2); //wyswietla graniczna temp. alarmu if (tabStrMenu[2] != eepromOdczyt[2]) { display_2.setSegments(disp_confirm); }// wyswietlenie Edit na drugim wyswietlaczu w menu else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } } void thirdScreen() // trzecia str opcji itd itp { display_1.showNumberDec(tabStrMenu[3], false, 2, 2); // wartosc przechowywana dla Nr Linii // display_1.showNumberDecEx(tabStrMenu[3],0, true); // wartosc przechowywana dla Nr Linii display_1.setSegments(disp_linia, 2, 0); if (tabStrMenu[3] != eepromOdczyt[3]) { display_2.setSegments(disp_confirm); // wyswietlenie Edit na drugim wyswietlaczu w menu } else { if (millis() - time2 > 100) { // display_1.clear(); display_2.clear(); time2 = millis(); } } } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami, ponizej rozpiska dla wyswietlacza LCD !!! void fourthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("This is screen 4"); lcd.setCursor(0,1); lcd.print("Just press btn"); } void fifthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Fifth screen"); lcd.setCursor(0,1); lcd.print("i2C LCD screen"); } void sixthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("THE last screen"); lcd.setCursor(0,1); lcd.print(" Sixth and last"); } */ Odbiór danych z MEGA2560 i przesłanie do serwera danych. ESP8266-12E #include <SoftwareSerial.h> #include <ESP8266WiFi.h> /* SSS L K (2019) S ZZZZ CCC ZZZZ EEE PPPP U U L EEE K K SSS Z C Z E___ P P U U L E___ K K S Z C Z E P P U U L E K K SSSS ZZZZ CCC ZZZZ EEE PPPP UUU LL EEE K K P KOMUNIKACJA PO SERIALU (SOFTWARE) //ESP8266 Do komunikacji wykorzystano Nadawanie TX Arduino Mega 2560, odbior na ESP8266-12E Na Mega 2560 uzyto Serial1, mozna uzyc serial2, czy serial3. Na ESP piny 2-oraz 3. WAZNE !!! nie zapomnijcie polaczyc ze soba GND obu plytek. u mnie dziala to dobrze. Przy nadawaniu temperatura jest zamieniana na liczbe calkowita bez przecinka/kropki poprzez pomnozenie przez 100 wyniku pomiaru. By uniknac zmiany dlugosci wysylanych danych przy ujemnych temperaturach, do wyniku dodaje 30 stopni, ktore przy pozniejszemu dekodowaniu na odbiorniku odejmuje (te 30st.), Dzieki temu zabiegowi temperatura np 22.50 st.C, zamienione na calkowite ma wartosc 2250. a po dodaniu wczesniej do pomiaru 30 ma wartosc 5250. I do wysylania potrzebne sa 4 bajty. Bez tego wartosc -23.00 st.C po pomnozeniu ma wartosc -2300 czyli ze znakiem minusa mamy 5 bajtow. Po dodaniu do pomiaru 30 st mamy 13 st (-23+30= 13) podsumowujac, minimalna temp przesylana bez bledu dekodowania/ odczytu/ to temperatura -29.50, natomiast maksymalna to 69.50 (bo 70.00+ 30 = 100, po pomnozeniu przekracza 4 bajty) Może i to rozwiązanie mocno AMATORSKIE, ale działa :) teraz można ulepszac kod i przeksztalcac.. */ #define D7 (13) //LED wysylam #define D8 (15) // Led_Error #define D5 (14) //rx odbior danych /* SoftwareSerial mySerial; //rx pin 2, tx pin 3 */ // WIFI ################################################## const char* ssid = "ssidTwojejSieciWiFi"; const char* password = "hasloDoSieci"; const char* host = "192.168.1.111"; // Host , adres bazy danych int automatPraca; // stan nary, pobierana informacja z SERIAL (Mega 2560) //sprawdzanie czy maszyna w trybie automatycznym (zwarty PIN16 do maszy) //unsigned long timeTrybAuto = 0; unsigned long timeAddDB = 0; //wysylaj po okreslonym czasie dane pobrane z SoftwareSerial do bazy danych unsigned long czasAutomatPraca; unsigned long timeErr; SoftwareSerial mySerial(14, SW_SERIAL_UNUSED_PIN); char buff[11]; //Initialized variable to store recieved data // bufor na odbierane dane, w moim przypadku 11 znaków do odbioru byte count; float tempOdczyt1; float tempOdczyt2; unsigned long czasDoWyslania; //ilosc czasu ( ms) po jaki wysylane sa pomiary temp do bazy danych int ALOdczyt; char KOD; int PracaAutoOdczyt; int LnOdczyt; char ALmysql; void setup () { czasDoWyslania = 300000; czasAutomatPraca = 0; timeAddDB = millis(); PracaAutoOdczyt = 1; pinMode(D8, OUTPUT); // LED zolta - error pinMode(D7, OUTPUT); // LED niebieska panelu - wysyłanie delay(1000); // Open serial communications and wait for port to open: Serial.begin(9600); Serial.println("Start"); mySerial.begin(9600); // Start laczenia sie do wifi Serial.println(); Serial.println(); Serial.print("polacz z siecia "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi polaczone"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void loop() { buff[0] = 0; //proba if (mySerial.available() > 0) { buff[0] = mySerial.read(); // if (buff[0] == 0x7B) //sprawdza czy pierwszy bajt jest poprawny i jest to znak 0x7B (HEX) czyli "{" count = 1; while (count < 11) if (mySerial.available() > 0) // jesli transmisja na serial software aktywna przechodzi dalej. { buff[count] = mySerial.read(); //odczyt z serial software count++; } // 0x7D znak specjalny konczacy, 0x65 ('A') znak konczacy podczas pracy w AUTOMACIE if (count == 12 && buff[10] == 0x7D ) // kontrola ostatniego bajtu/znaku (9 znak), w przypadku prawidłowego znaku kontynuacja { for (byte i = 0; i < 11; i++) //zapisujemy do tabeli buff kolejne znaki odebrane { Serial.print(buff[i]); Serial.print(","); } } } if (buff[0] == 0x7B && buff[10] == 0x7D) { // [0] zn spec 0x7b, [1]- ti1, ti2, AL, to1, to2, to3, Ln1, Ln2, zn spec 0x7d Serial.println(); Serial.println("T1:"); //float tempOdczyt1 = (((buff[1] - 48) * 100) + ((buff[2] - 48) * 10) + ((buff[3] - 48) + 0.001)) / 10 - 30; Serial.println(tempOdczyt1); KOD = buff[4]; Serial.println("kod to:"); Serial.println(KOD); // KOD (ALOdczyt) - rozszyfrowanie if (KOD == '0') { ALOdczyt = 0; PracaAutoOdczyt = 1; } if (KOD == '1') { ALOdczyt = 1; PracaAutoOdczyt = 1; } if (KOD == '2') { ALOdczyt = 0; PracaAutoOdczyt = 0; } if (KOD == '3') { ALOdczyt = 1; PracaAutoOdczyt = 0; } Serial.println("AL:"); //int Serial.println(ALOdczyt); Serial.println("Nara w tr.Auto:"); Serial.println(PracaAutoOdczyt); Serial.println("T2:"); //float tempOdczyt2 = (((buff[5] - 48) * 100) + ((buff[6] - 48) * 10) + ((buff[7] - 48) + 0.001)) / 10 - 30; Serial.println(tempOdczyt2); Serial.println("LiniaNR:"); //int LnOdczyt = (((buff[8] - 48) * 10) + (buff[9] - 48)); Serial.println(LnOdczyt); Serial.println("dane gotowe do wysłania.."); czasAutomatPraca = millis() - timeAddDB; // czas pracy w automatycznym trybie Serial.println(czasAutomatPraca); if (czasAutomatPraca > czasDoWyslania && PracaAutoOdczyt == 1) // wysylanie po okreslonym czasie pod warunkiem ze w automacie maszyna { if (-50 < tempOdczyt1 < 90 && -50 < tempOdczyt2 < 90 && LnOdczyt < 100) // pomin esli wykracza poza zakres { // Dane na serwer ! Serial.print("connecting to "); Serial.println(host); digitalWrite(D8, LOW); // Use WiFiClient class to create TCP connections WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { digitalWrite(D8, HIGH); Serial.println("connection failed"); if (czasAutomatPraca > 1.25*czasDoWyslania) timeAddDB = millis(); return; } digitalWrite(D7, HIGH); //LED kontrolny na panelu, informacja poczatek transmisji // tworzenie zapytania do URL String url = "/wyslijpomiar.php?"; //jest to strona na serwerze sluzaca do wysylania poprzez GET parametrow temp itp do bazy danych poprzez INSERT zagniezdzony w kodzie zrodlowym pliku wyslijpomiar.php // Send request Serial.print("Requesting URL: "); Serial.println(url); if (ALOdczyt == 0) // wysylanie odczytanych z seriala wartosci na serwer, jesli bra alarmu nie podajemy zadnych parametrow dla &alarm= wtedy bedzie umieszczony bit 0 w bazie. { client.print(String("GET ") + url + "linia_nr=" + LnOdczyt + "&temperatura1=" + tempOdczyt1 + "&temperatura2=" + tempOdczyt2 + "&alarm=" + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); } else { client.print(String("GET ") + url + "linia_nr=" + LnOdczyt + "&temperatura1=" + tempOdczyt1 + "&temperatura2=" + tempOdczyt2 + "&alarm=1" + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); } unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > 5000) { digitalWrite(D8, HIGH); Serial.println(">>> Client Timeout !"); client.stop(); return; } } // Read all the lines from the answer while (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } // Close connecting Serial.println(); Serial.println("zamyanie polaczenia"); timeAddDB = millis(); // zapis obecnego czasu pracy procesora, ponowne zliczanie czasu dla wyslania danych do bazy } } digitalWrite(D7, LOW); //led koniec transmisji } for (int j = 0 ; j > 11; j++) { buff[j] = 0; } Serial.println("czekam.."); if (PracaAutoOdczyt == 0) timeAddDB = millis(); } Teraz zapis poprzez PHP do serwera: plik w katalogu serwera WWW o nazwie wyslijpomiar.php a w nim, <?php session_start(); $host = "localhost"; //$id_user=$_SESSION['pomiary']; $username="pomiary"; $password="hasloTwoje"; $database="naratemperatury"; $polaczenie = @new mysqli($host,$username,$password,$database); if($polaczenie->connect_errno!=0) //sprawdza czy nawiazano polaczenie { echo "Error ".$polaczenie->connect_errno; //blad gdy polaczenie nie nawiazane } else { //wstawiamy przez GET który mamy skonf też w kodzie dla ESP8266 parametry wartości pomiarów if($polaczenie->query("INSERT INTO pomiary (id, data, linia_nr, temperatura1, temperatura2, temperatura3, alarm) VALUES (NULL, NULL, '$_GET[linia_nr]','$_GET[temperatura1]','$_GET[temperatura2]',NULL,'$_GET[alarm]')")) { echo "udalo sie"; } else { echo "nie udalo sie"; } $polaczenie->close(); //konczy polaczenie } ?> Wynik wyświetlanych danych z bazy danych przez PHP i w programie .exe (Delphi), struktura tabeli w MySQL; w załącznikach
  3. W moim wypadku ardu tylko do wysyłania. A esp do odbioru.. nasłuchiwania po serialu. Dalej śle po wifi co 5 min wyłapane dane z pomiarami i poprzez stronę php do bazy danych. Dla moich potrzeb te czasy są wystarczające do komfortowej pracy z monitorem temperatur. Z całym szacunkiem do wszystkich. Prosił bym aby nie toczyć tutaj wojen słownych. Tylko skupmy się na projekcie powtarzam ..z całym szacunkiem
  4. Na obecna chwilę poprzez odczyt millis na poczatku i na końcu loop obliczyłem średnią 28ms. Powiem tak, dla mnie to spory sukces przeskoczyć z tych 1568 ms na 118 a teraz do tych 30 ms. Wiem że da się to jeszcze przyspieszyć ale jak na bibliotekach standardowych myślę całkiem nieźle. Wyświetlacze odwiedzane co 125ms. Pewnie jeszcze pogrzebie i zejdę tych kilka ms niżej. Co do programu na obecną chwilę: Przyspieszenie interfejsu Wyświetlanie 2 wartości temperatur Dwa termometry ds18b20 obsługiwane bez potrzeby wpisywania ręcznie adresów Menu wyświetlane na LED 4 digits 7 segm. Tm1637 Menu obsługiwane 4 przyciskami, Menu(next), Up/dodaj, Down/ujmij, OK/Zapisz. Podczas edycji miga kontrolka(LED) o konieczności zapisania parametru nowego (porównanie do zawartości EEPROM. Przy braku aktywności w Menu po 20 sek powrót do wyświetlania temperatur, jeśli parametru zmieniono a nie zapisano -powrót do ustawień odczytanych z eeprom. Jeśli nie zapiszemy parametrów i przeskoczymy całe Menu ..to jak wyżej. Sprawdzenie na bierząco czy nie przekroczono max temp w przypadku przekroczenia - sygnał na przekaźnik. Możliwość wybrania Alarmu dla jednego z czujników z poziomu Menu. Wybranie linii /ID dla tego zestawu monitorującego. Obsługa pamięci eeprom (opcje update dla oszczędzania ilości zapisów, porósnania wyświetlanych informacji z zawartością pamięci. W przypadku wgrania na nową płytkę programu przy pierwszym uruchomieniu nadanie wartości domyślnych w pamięci. Wysyłanie przez Serial1 (znaki kontrolne początek i koniec przesyłanych danych. Na 11 znakach wysłane temp1 i temp2. Stan ALarmu. Nr Linii/id) Wysyłanie co około 28-30ms.
  5. od ostatniego czasu udzielania sie w tym temacie spoooro sie zmieniło w kodzie i działaniu programu, na plus oczywiście, @RFM przyjacielu, mówiłeś że te 43 ms na wyświetlacze to bardzo dużo, masz rację, zauważyłem to kiedy dodałem kilka warunków do programu, i menu przedewszystkim, to jak reagowały klawisze.. a raczej nie reagowały Świetnie było widać lagi kiedy w tle są wysyłane na serialu dane, a główna strona czy raczej pętla odpowiedzialna za wyświetlanie 2 temperatur była w użyciu (pokazMenu=0); Serial monitor wyrzucał nieregularnie linijki , zauważalne skokowe wyświetlanie podglądu danych. Do myślenia dało mi dlaczego po wyświetleniu menu nie ma tego efektu a dane w serial monitorze szaleją jedyny wniosek, wyświetlanie menu jest odświeżane przy zmianie naciśnięciu jakiegoś klawisza. Kilka postów wstecz wspomniałeś o użyciu millis() i co jakiś czas odpytywać temperaturę, zaświtało mi w głowie, a co jak by tak co jakiś czas wyrzucać komendę Display.. Wrzuciłem to w warunek z millis() i BOMBA Wszystko odżyło, klawisze lepiej reagują, i serial.write/ serial.print działają płynnie. Przykładowa wstawka wysw2LED[0] = display_2.encodeDigit(airoutCalkow/1000%10); //wyswietla cyfre dziesiatek z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[1] = display_2.encodeDigit(airoutCalkow/100%10); //wyswietla cyfre jednosci z pomiaru cz.1 na wyswietlaczu pierwszym wysw2LED[2] = (SEG_A | SEG_B | SEG_F | SEG_G); // znak stopni zamiast kropki ktore brak w wyswietlaczu ktory posiadam wysw2LED[3] = display_2.encodeDigit(airoutCalkow/10%10); //pierwsza cyfra czesci dziesietnych // display_2.setSegments(wysw2LED); // wyswietlenie temperatury na pierwszym wyswietlaczu TO WŁAŚNIE LAGUJE TA LINIA /* po wrzuceniu tej linii kodu jak ponizej ,cały program pędzi jak Passaciak TDI na 4000obr/min z dwiema turbinami */ if (millis() - time4 >=100) { display_2.setSegments(wysw2LED); // wyswietlenie temperatury na pierwszym wyswietlaczu time4 = millis(); }
  6. Uaktualnienie informacji, zastosowałem menu do swojego projektu pomiaru temperatur, w miedzyczsie dokonałem kilku jeszcze zmian. Dodano/zmieniono: alarmowanie o nie zapisaniu zmiennej w ustawieniach przez blink na PIN 13 (miganie przy użyciu millis(), nie jest to takie trudne jak na początku się wydawało) DZIEKI @RFM za motywację próbowałem miganie na wyświetlaczach ale przez sposób ich sterowania efekt był mizerny. dodano regułkę podczas przebywania na jednej ze stron Menu i braku aktywności któregokolwiek z klawiszy przez określony czas (u mnie 15 sek, maks. 65 sek z zmienna typu WORD) samoczynnie powraca do funkcji podstawowej, czyli wyświetlania u mnie temperatur czujników. ukończyłem, 2 minuty.. if(millis() - autoExitMenu > autoExitCzas) //warunek wyprowadza z menu, jesli brak aktywnosci podana ilosc czasu (ms) { if (eepromOdczyt[s] != tabStrMenu[s]) // jeśli wartość w pamięci, i w tablicy przechowujacej obecne nastawy są różne to... tabStrMenu[s] = eepromOdczyt[s]; // zapisz do tablicy odczyt z eeprom, pokazMenu = 0; // przejdz do glownej funkcji autoExitMenu = millis(); // kasowanie odliczania braku aktywnosci, a raczej zapisanie obecnego czasu dzialania do obliczania. } /* czas zapisu do EEPROM w arduino to chyba 3ms, nie wiem ile zamuje odczyt, na wszelki wypadek na poczatku petli glownej przypisalem do tablicy eepromOdczyt[] wartosci odczytane z EEPROM.read(); kilka razy odnosze sie w swoim kodzie do tych wartosci, wiec jesli to ma znaczenie to przyoszczedze kilka ms, jesli nie, to i tak nic sie nie stalo ;-P */ animacje przy zapisaniu do eeprom i zatwierdzeniu. Gdy skończę wcześniejszy projekt umieszczę kod ze zmianami..
  7. a jednak, coś jeszcze :D.. dotychczasowy program wymagał przycisku by wejść w menu, wyjść z menu. przycisku by przeskakiwać pomiędzy stronami menu, przycisku do podnoszenia w górę zmiennych, i zmniejszających zmienne. w sumie 4, no nie ukrywam że 5 też dojdzie do zatwierdzania / zapisywania ustawień do eeprom. Tak czy inaczej można się pozbyć jednego do przeskakiwania po stronach i użyć do tego wyzwalającego menu. W chwili wciśnięcia zamiast zmieniać stan zapamiętany dla zmiennej pokazMenu, ustawiamy na 1. W wyniku czego ładuje się strona 1, nasłuchujemy zamiast buttonPin, nadal buttonMenu. po przyciśnięciu go zamiast wrócić do głównej cześci programu z manu, przeskakujemy na następną stronę drugą, trzecią itd.. w zależności ile ich ustawiono jeżeli jak ja używacie 2 stron, dodajemy jeszcze trzecią, i w linii case 3: //przykładowa ostatnia strona { pokazMenu = 0; //powracamy do głównej części programu } break; jak w przykładzie, wpisanie pokazMenu =0; ustawia warunek spełniający wymagania dla głównej części funkcji działającej domyślnie. by to działało należy zmienić jeszcze te części kodu: if (digitalRead(33) == LOW) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { pokazMenu = !pokazMenu; // ..zmienia prawde logiczna w zmiennej typu boolean na przeciwna, czyli 1 na 0 lub 0 na 1 delay(250); } na: if (digitalRead(33) == LOW) //pin buttonMenu { // pokazMenu = !pokazMenu; // ..zmienia prawde logiczna w zmiennej typu boolean na przeciwna, czyli 1 na 0 lub 0 na 1 pokazMenu = 1; //obsluga 1 przyciskiem, i ostatnia strona powrot do glownego programu delay(250); } i nasłuchujemy ten sam button dla zmiany stron int reading = digitalRead(buttonMenu); // obsluga jednym klawiszem do menu if (reading != lastButtonState) { Wstawiony film to prezentacja działania z osobnymi klawiszami do wejscia/wyjscia menu i osobnego do zmiany stron. vid-20191028-menuLED7seg.zip
  8. Dodana kolejna funkcjonalność, dla zmiany parametrów dla danej zakładki / CASE i wyświetlenie parametrów zmiennej po zmianie. Aby uzyskać te udogodnienia należy zaraz po dodać następujący kod, /* deklarujemy z którego PINu ma być sygnał niski/LOW/0 oraz poprzez '&&' (warunek AND/ i) dodajemy WhichScreen, liczba 2 w tym wypadku mowi ze aby funkcja zadzialala MUSI byc atywna strona 2, dzieki temu dodane dzialania , funkcje, itp beda realizowane wylacznie dla tego okna, zapobiegajac przypadkowej edycji wartosci u mnie 'alarmHigh'. W innym wypadku bedac na stronie 3 niechcacy mozna by zmienic parametry alarmu */ if (digitalRead(31) == LOW && WhichScreen == 2) //pierwszy warunek dla wejscia PIN 31 = 0 i strony wyswietlanej 2 if (WhichScreen == 2) //drugi warunek wstawiony tylko dla pewnosci, bez niego podczas przeskakiwania miedzy funkcjami pomiaru i menu petla byla wykonywana { alarmHigh[1]++; //tutaj akurat podnosze o 1 wartosc alarmu, i zapisywane jest do tablicy hasChanged = true; // odswierza dana strone na ktorej sa wprowadzane zmiany poprawiajac wyswietlanie zmiennych } } Oczywiście dla wygody można użyć jednej tablicy do wszystkich stron, aby nie rozrastał się kod.. i tak oto pod zmienną s można przypisać numer strony wyświetlanej, oraz miejsce w tabeli.. No dobra, poniżej całkowity kod, z utworzoną tablicą dla parametrów każdej strony tabStrMenu[noleży_wpisać_ilosc_stron], Wykasowane nie potrzebne części kodu z testów. #include <TM1637Display.h> /* ! ! ! ! ! ! ! ! ! ! ! !! !! ! ! ! ! ! * UWAGA MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit * * ! ! ! ! ! !! ! ! ! ! ! ! !! ! * * This code create a MENU structure on a 16x2 LCD screen. * Six (6) different screens are implemented, and you can travel * thru them by pressing a button on Arduino PIN 4. Each press * of the button advances one (1) screen. * * Made by Clovis Fritzen in 05/06/2017 * http://www.FritzenMaker.com * http://www.FritzenLab.com.br */ #define CLK1 5 //wyswietlacz nr1 8segm.4-cz #define DIO1 6 //wyswietlacz nr1 8segm.4-cz int WhichScreen =1; // This variable stores the current Screen number boolean hasChanged = true; boolean pokazMenu = 0; const int buttonPin = 37; // the number of the pushbutton pin const int buttonMenu = 33; // wywolanie menu const int buttonOk = 32; // zatwierdz/zapisz key OK const int buttonUp = 31; // edycja key UP const int buttonDn = 30; // edycja key DOWN int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 75; // the debounce time; increase if the output flickers /* tabStrMenu - przechowywanie poszczegolnych ustawien dla kolejnych stron, 0 - niewykozystane, 1 - dla 1 strony czyli ALARM, 2 - przechowywany numer LINII; mozna tez przypisac do stron przez 's-1' w linii funkci menu */ int tabStrMenu[3]; // dane ze stron/menu LED // ilosc deklarowana = ilosc stron + 1; int value; //testowe TM1637Display display_1(CLK1, DIO1); // ustawienia wyjsc dla wyswietlacza na tm1637 uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F ,// L 0 // O }; /* int test[2]; // tylko gdy potrzebuesz wartosci do Case */ void setup() { // lcd.init(); // initialize the lcd 0x20 lub 0x38?? // lcd.backlight(); // z LCD pinMode(buttonPin, INPUT_PULLUP); pinMode(buttonMenu, INPUT_PULLUP); pinMode(buttonUp, INPUT_PULLUP); pinMode(buttonDn, INPUT_PULLUP); display_1.setBrightness(0x0b); //LED7Seg jasnosc Serial.begin(9600); tabStrMenu[1]=33; //do testow domyslna wartosc dla alarmu, domyslnie pobierane z EEPROM tabStrMenu[2]=8; //domyslnie z eeprom - pobranie numeru linii WhichScreen =0; // aby menu startowalo od 1 str. } void loop() { int value = analogRead(2); // pomiar na analogowym wejsciu losowej Serial.print(F("Wejscie analogowe 2 ma wartosc: ")); // to na nic tu nie potrzebne Serial.println(value); /* test[1] = value; //zapis do tablicy potrzebny aby w CASE mozna bylo odczytac wartosc, po wrzuceniu do warunku na poczatku funkcji loop nie porzebne. */ if (digitalRead(33) == LOW) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { pokazMenu = !pokazMenu; // ..zmienia prawde logiczna w zmiennej typu boolean na przeciwna, czyli 1 na 0 lub 0 na 1 delay(250); } // jesli (domyslnie na starcie) mamy 0 to wykonaj program, wlasciwy..czy tez ten ktory ma sie glownie wykonywac if (pokazMenu == 0) { //GLOWNY PROGRAM display_1.showNumberDec(value); //info domslna strona a raczej wyswietlacz, z w tym przypadku do testow wartoscia napiecia na analogowym pinie hasChanged = true; // ustawiam na true, aby po wlaczeniu na menu pojawila sie na wyswietlaczu strona ustawien, bez tego zostaje zamrozony wynik ostatniego pomiaru z wejscia analogowego } else // jesli zmienna pokazMenu ma wartosc inna niz zero.. w tym wypadku tylko moze byc to 1 wykonaj.. wyswietlenie menu { int s = WhichScreen; // UWAGA! nalezy zadeklarowac tablice o liczbie elementow nie mniejszej niz ilosc stron. if (digitalRead(31) == LOW && WhichScreen == s) // zmiana parametrow UP/dodaj { Serial.print("strona nr :"); Serial.println(WhichScreen); if (WhichScreen == s) { tabStrMenu[s]++; hasChanged = true; delay (25); } } if (digitalRead(30) == LOW && WhichScreen == s) // zmiana parametrow DOWN/odejmij { if (WhichScreen == s) { tabStrMenu[s]--; hasChanged = true; delay(25); } } if (hasChanged == true) { switch(WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; /* Dla wiekszej ilosci wyswietlania pozycji menu * case 3: { thirdScreen(); } break; case 4: { fourthScreen(); } break; case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 2){ //ilosc wszystkich stron WhichScreen = 1; } } } void firstScreen() // pierwsza strona opcji { display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(tabStrMenu[1], false, 2, 2); //wyswietla graniczna temp. alarmu Serial.print("Alarm od:"); // test w serial Serial.println(tabStrMenu[1]); } void secondScreen() // druga str opcji itd itp { display_1.clear(); display_1.showNumberDecEx(tabStrMenu[2],0, true); // wartosc przechowywana dla Nr Linii display_1.setSegments(disp_linia, 2, 0); Serial.print("linia nr:"); // test w serial Serial.println(tabStrMenu[2]); } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami, ponizej rozpiska dla wyswietlacza LCD !!! void fourthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("This is screen 4"); lcd.setCursor(0,1); lcd.print("Just press btn"); } void fifthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Fifth screen"); lcd.setCursor(0,1); lcd.print("i2C LCD screen"); } void sixthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("THE last screen"); lcd.setCursor(0,1); lcd.print(" Sixth and last"); } */ Myślę że tyle wystarczy w temacie MENU dla 4-Digits Display LED
  9. Poprawiony kod... po dodaniu klawisza przełączającego zmienną pokazMenu na true/false, oraz warunku if..else uwzględniającego tą zmienną i powodującą wykonanie kodu dla programu właściwego .. np wyświetlanie wartości na wejściu analogowym (przy pokazMenu=0) lub kodu dla menu (pokazMenu=1). Domyślnie po starcie wartość zmiennej jest zapisana jako 0. #include <TM1637Display.h> /* Napisał: Szczepulek * UWAGA MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit * kod oryginalny dla cieklokrystalicznych https://github.com/FritzenLab/LCD-Screen-Menu-System/tree/master/LCD-Screen-Menu * Clovis Fritzen in 05/06/2017 */ #define CLK1 5 //wyswietlacz nr1 8segm.4-cz #define DIO1 6 //wyswietlacz nr1 8segm.4-cz int WhichScreen =1; // Nr strony przechowywany w zmiennej //This variable stores the current Screen number boolean hasChanged = true; boolean pokazMenu = 0; // zmienna do przelaczania miedzy menu a reszta programu const int buttonPin = 4; // PIN dla przycisku // the number of the pushbutton pin const int buttonMenu = 5; // wywolanie menu z przycisku do GND int buttonState; // status przycisku obecny - odczyt // the current reading from the input pin int lastButtonState = LOW; // poprzedni stan na przycisku unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers TM1637Display display_1(CLK1, DIO1); // ustawienia wyjsc dla wyswietlacza na tm1637 uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F ,// L 0 // O }; void setup() { pinMode(buttonPin, INPUT_PULLUP); pinMode(buttonMenu, INPUT_PULLUP); display_1.setBrightness(0x0a); //LED7Seg jasnosc Serial.begin(9600); WhichScreen = 0; //aby przy starcie zaczynało na pierwszej opcji menu } void loop() { int value = analogRead(2); // pomiar na analogowym wejsciu losowej if (digitalRead(33) == LOW) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { delay(250); pokazMenu = !pokazMenu; // ..zmienia prawde logiczna w zmiennej typu boolean na przeciwna, czyli 1 na 0 lub 0 na 1 } /* pierwsza czesc programu , czyli robi co tam chcecie, pomiary, wyswietlanie w czasie rzeczywistym itp */ if (pokazMenu == 0) // jesli (domyslnie na starcie) mamy 0 to wykonaj program, wlasciwy..czy tez ten ktory ma sie glownie wykonywac { display_1.showNumberDec(value); //info domslna strona a raczej wyswietlacz, z w tym przypadku do testow wartoscia napiecia na analogowym pinie hasChanged = true; // ustawiam na true, aby po wlaczeniu na menu pojawila sie na wyswietlaczu strona ustawien, bez tego zostaje zamrozony wynik ostatniego pomiaru z wejscia analogowego } /* no a tutaj juz sam kod do menu */ else { if (hasChanged == true) { //wykonanie menu wszystko w dol switch(WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; /* Dla wiekszej ilosci wyswietlania pozycji menu * case 4: { fourthScreen(); } break; case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 3){ // UWAGA! jesli masz wiecej stron niz 3, musiasz zmienic warunek wpisujac wartosc rowna ilosci stron WhichScreen = 1; } } } void firstScreen() { display_1.clear(); Serial.println("glowny ekran"); // test w serial display_1.showNumberDec(99, false, 2, 2); } void secondScreen() { display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu int alarmHigh = 30; display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(alarmHigh, false, 2, 2); Serial.print("alarm:"); // test w serial Serial.println(alarmHigh); } void thirdScreen() { display_1.clear(); int liniaNr = 7; display_1.showNumberDecEx(liniaNr,0, true); display_1.setSegments(disp_linia, 2, 0); Serial.print("linia nr:"); // test w serial Serial.println(liniaNr); } /* //dla większej ilosci przejsc miedzy wyswietlanymi informacjami/stronami !!! void fourthScreen() { //tresc 4 strony } void fifthScreen() { //tresc 5 strony } void sixthScreen() { //tresc 6 strony } */
  10. Aktualizacja powyższego kodu, menu inicjowane osobnym klawiszem, i na nim przełączanie pomiędzy ustawieniami a wyświetlaniem na bieżąco jakichs tam parametrów, w tym wypadku do testu wartość na wejściu analogowym. #include <TM1637Display.h> /* ! ! ! ! ! ! ! ! ! ! ! !! !! ! ! ! ! ! * UWAGA MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit * * ! ! ! ! ! !! ! ! ! ! ! ! !! ! * * This code create a MENU structure on a 16x2 LCD screen. * Six (6) different screens are implemented, and you can travel * thru them by pressing a button on Arduino PIN 4. Each press * of the button advances one (1) screen. * * Made by Clovis Fritzen in 05/06/2017 * http://www.FritzenMaker.com * http://www.FritzenLab.com.br */ #define CLK1 5 //wyswietlacz nr1 8segm.4-cz #define DIO1 6 //wyswietlacz nr1 8segm.4-cz int WhichScreen =1; // This variable stores the current Screen number boolean hasChanged = true; boolean pokazMenu = 0; const int buttonPin = 37; // the number of the pushbutton pin const int buttonMenu = 33; // wywolanie menu int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 45; // the debounce time; increase if the output flickers int value; //testowe TM1637Display display_1(CLK1, DIO1); // ustawienia wyjsc dla wyswietlacza na tm1637 uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F ,// L 0 // O }; const uint8_t disp_set[] = { SEG_A | SEG_C | SEG_D | SEG_F | SEG_G ,// S SEG_A | SEG_C | SEG_E | SEG_F | SEG_G , // E SEG_D | SEG_E | SEG_F | SEG_G }; int test[2]; void setup() { // lcd.init();// initialize the lcd 0x20 lub 0x38?? // lcd.backlight(); pinMode(buttonPin, INPUT_PULLUP); pinMode(buttonMenu, INPUT_PULLUP); display_1.setBrightness(0x0a); //LED7Seg Serial.begin(9600); WhichScreen = 0; //aby przy starcie zaczynało na pierwszej opcji menu } void loop() { int value = analogRead(2); // pomiar na analogowym wejsciu losowej Serial.print(F("Wejscie analogowe 2 ma wartosc: ")); // to na nic tu nie potrzebne Serial.println(value); test[1] = value; //zapis do tablicy potrzebny aby w CASE mozna bylo odczytac wartosc, po wrzuceniu do warunku na poczatku funkcji loop nie porzebne. Serial.println(test[1]); if (digitalRead(33) == LOW) // sprawdza czy na pinie 33 stan LOW niski, jesli tak to .. { delay(250); pokazMenu = !pokazMenu; // ..zmienia prawde logiczna w zmiennej typu boolean na przeciwna, czyli 1 na 0 lub 0 na 1 } if (pokazMenu == 0) // jesli (domyslnie na starcie) mamy 0 to wykonaj program, wlasciwy..czy tez ten ktory ma sie glownie wykonywac { display_1.showNumberDec(test[1]); //info domslna strona a raczej wyswietlacz, z w tym przypadku do testow wartoscia napiecia na analogowym pinie hasChanged = true; // ustawiam na true, aby po wlaczeniu na menu pojawila sie na wyswietlaczu strona ustawien, bez tego zostaje zamrozony wynik ostatniego pomiaru z wejscia analogowego } else // jesli zmienna pokazMenu ma wartosc inna niz zero.. w tym wypadku tylko moze byc to 1 wykonaj.. wyswietlenie menu { if (hasChanged == true) { switch(WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; /* Dla wiekszej ilosci wyswietlania pozycji menu * case 4: { fourthScreen(); } break; case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 3){ WhichScreen = 1; } } } void firstScreen() // pierwsza strona opcji { display_1.clear(); Serial.println("glowny ekran"); // test w serial display_1.showNumberDec(1246); delete []test; } void secondScreen() // druga str opcji itd itp { display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu int alarmHigh = 30; display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(alarmHigh, false, 2, 2); Serial.print("alarm:"); // test w serial Serial.println(alarmHigh); } void thirdScreen() { display_1.clear(); int liniaNr = 7; display_1.showNumberDecEx(liniaNr,0, true); display_1.setSegments(disp_linia, 2, 0); Serial.print("linia nr:"); // test w serial Serial.println(liniaNr); } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami, ponizej rozpiska dla wyswietlacza LCD !!! void fourthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("This is screen 4"); lcd.setCursor(0,1); lcd.print("Just press btn"); } void fifthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Fifth screen"); lcd.setCursor(0,1); lcd.print("i2C LCD screen"); } void sixthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("THE last screen"); lcd.setCursor(0,1); lcd.print(" Sixth and last"); } */
  11. okej, nie jest to rozwiązanie satysfakcjonujące, jeśli ma byś statyczne wyświetlanie ok. W momencie gdy dodam np. int value = analogRead(2); Serial.print(F("Wejscie analogowe 2 ma wartosc: ")); Serial.println(value) w pętli loop. to będzie sobie wyświetlać serial w monitorze wartości, lecz wyswietlając w case1 (1 strona) te zmienna value, nie zmienia się, nie odświeża jej nawet po przeskoczeniu przez wszystkie strony. No to się pocieszyłem
  12. W osobnym temacie samo menu do wykorzystania z wyświetlaczami 7 segmentowymi, pozwala się przełączać pomiędzy kolejnymi "stronami" w pętli np.: 1 - 2 - 3 - 4 - 1 - 2 - 3 -... Button podpięty pod PIN w przykładzie 4 (INPUT_PULLUP) i zwierający z masą GND. #include <TM1637Display.h> /* Napisał: Szczepulek * UWAGA MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit * kod oryginalny dla cieklokrystalicznych https://github.com/FritzenLab/LCD-Screen-Menu-System/tree/master/LCD-Screen-Menu * Clovis Fritzen in 05/06/2017 */ #define CLK1 5 //wyswietlacz nr1 8segm.4-cz #define DIO1 6 //wyswietlacz nr1 8segm.4-cz int WhichScreen =1; // Nr strony przechowywany w zmiennej //This variable stores the current Screen number boolean hasChanged = true; const int buttonPin = 4; // PIN dla przycisku // the number of the pushbutton pin int buttonState; // status przycisku obecny - odczyt // the current reading from the input pin int lastButtonState = LOW; // poprzedni stan na przycisku unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers TM1637Display display_1(CLK1, DIO1); // ustawienia wyjsc dla wyswietlacza na tm1637 uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F ,// L 0 // O }; void setup() { pinMode(buttonPin, INPUT_PULLUP); display_1.setBrightness(0x0a); //LED7Seg jasnosc Serial.begin(9600); WhichScreen = 0; //aby przy starcie zaczynało na pierwszej opcji menu } void loop() { if (hasChanged == true) { switch(WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; /* Dla wiekszej ilosci wyswietlania pozycji menu * case 4: { fourthScreen(); } break; case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 3){ // UWAGA! jesli masz wiecej stron niz 3, musiasz zmienic warunek wpisujac wartosc rowna ilosci stron WhichScreen = 1; } } void firstScreen() { display_1.clear(); Serial.println("glowny ekran"); // test w serial display_1.showNumberDec(99, false, 2, 2); } void secondScreen() { display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu int alarmHigh = 30; display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(alarmHigh, false, 2, 2); Serial.print("alarm:"); // test w serial Serial.println(alarmHigh); } void thirdScreen() { display_1.clear(); int liniaNr = 7; display_1.showNumberDecEx(liniaNr,0, true); display_1.setSegments(disp_linia, 2, 0); Serial.print("linia nr:"); // test w serial Serial.println(liniaNr); } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami/stronami !!! void fourthScreen() { //tresc 4 strony } void fifthScreen() { //tresc 5 strony } void sixthScreen() { //tresc 6 strony } */
  13. Menu dla 7 segmentowego wyświetlacza.. a no właśnie, nie wiem skąd wcześniej brało mi się 8 segmentowy może ze względu na kropkę występującą DP, ale mniejsza z tym, i tak wiemy o co chodzi.. W poszukiwaniu jakiegoś przykładu na tych wyświetlaczach, no ne znalazłem takowego.. (przykładu) Podjąłem się próby przekształcenia bardzo uproszczonego Menu dla LCD pod moje potrzeby.. i tak oto to wygląda: #include <TM1637Display.h> /* ! ! ! ! ! ! ! ! ! ! ! !! !! ! ! ! ! ! * UWAGA MODYFIKACJA KODU Z LCD NA LED 7 segmentowy 4-digit * * ! ! ! ! ! !! ! ! ! ! ! ! !! ! * * kod oryginalny https://github.com/FritzenLab/LCD-Screen-Menu-System/tree/master/LCD-Screen-Menu * * Made by Clovis Fritzen in 05/06/2017 * http://www.FritzenMaker.com * http://www.FritzenLab.com.br */ #define CLK1 5 //wyswietlacz nr1 8segm.4-cz #define DIO1 6 //wyswietlacz nr1 8segm.4-cz int WhichScreen =1; // This variable stores the current Screen number boolean hasChanged = true; const int buttonPin = 37; // the number of the pushbutton pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers TM1637Display display_1(CLK1, DIO1); // ustawienia wyjsc dla wyswietlacza na tm1637 uint8_t wysw1LED[] = { 0x00, 0x00, 0x00, 0x00 }; //Dla LEDDispl4digit //wyswietlenie segmentow dla AL const uint8_t disp_alarm[] = { SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G , // A SEG_D | SEG_E | SEG_F // L }; //wyswietlenie segmentow dla L const uint8_t disp_linia[] = { SEG_D | SEG_E | SEG_F ,// L 0 // O }; void setup() { // lcd.init();// initialize the lcd 0x20 lub 0x38?? // lcd.backlight(); pinMode(buttonPin, INPUT_PULLUP); display_1.setBrightness(0x0a); //LED7Seg Serial.begin(9600); WhichScreen = 0; //aby przy starcie zaczynało na pierwszej opcji menu } void loop() { if (hasChanged == true) { switch(WhichScreen) { case 1: { firstScreen(); } break; case 2: { secondScreen(); } break; case 3: { thirdScreen(); } break; /* Dla wiekszej ilosci wyswietlania pozycji menu * case 4: { fourthScreen(); } break; case 5: { fifthScreen(); } break; case 6: { sixthScreen(); } break; */ case 0: //konczacy zapis menu { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; WhichScreen++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (WhichScreen > 3){ WhichScreen = 1; } } void firstScreen() { display_1.clear(); Serial.println("glowny ekran"); // test w serial display_1.showNumberDec(99, false, 2, 2); } void secondScreen() { display_1.clear(); //konieczne by nie nakladaly sie na siebie znaki/liczby z poprzedniego menu int alarmHigh = 30; display_1.setSegments(disp_alarm, 2, 0); display_1.showNumberDec(alarmHigh, false, 2, 2); Serial.print("alarm:"); // test w serial Serial.println(alarmHigh); } void thirdScreen() { display_1.clear(); int liniaNr = 7; display_1.showNumberDecEx(liniaNr,0, true); display_1.setSegments(disp_linia, 2, 0); Serial.print("linia nr:"); // test w serial Serial.println(liniaNr); } /* dla większej ilosci przejsc miedzy wyswietlanymi informacjami, ponizej rozpiska dla wyswietlacza LCD !!! void fourthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("This is screen 4"); lcd.setCursor(0,1); lcd.print("Just press btn"); } void fifthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Fifth screen"); lcd.setCursor(0,1); lcd.print("i2C LCD screen"); } void sixthScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print("THE last screen"); lcd.setCursor(0,1); lcd.print(" Sixth and last"); } */ Nie próbowałem jeszcze z integracją do mojego projektu. Button podpięty z: Pinem 37 - GND
  14. Niestety mam problem jak ugryźć MENU, ale na 4 cyfrowym wyświetlaczu LCD. Nie znalazłem w internetach czegoś takiego, na LCD tego mnóstwo. exit , dn, up , ok --klawisze podlaczone na jakichs tam pinach.. domyslnie wyswietlana temperatura [20*5] klik 'ok' >> - [AL:30] klik 'up' do drugiej opcji - [L 07] klik 'up'/ 'dn' przenosi ponownie do [AL:30] // 30 wartość pobrana z eeprom(alarmHigh,0) Będąc na [L 07] // 07 pobrane z eeprom(liniaNr,1) klik ok >> edycja numeru linii 'up' +1,' dn' -1 podczas wejscia do menu, po 5 sek nieaktywnosci powrot do wyswietlania temperatury. klik 'ok' >> zapis do eeprom (liniaNr,1) tak samo na pozycji AL edycja +/- 1. I zapis. po kliknieciu 'exit' PS.: tak tak, wiem.. wykorzystam już millis() a delay w odstawkę. Przynajmniej te w moim kodzie nie bibliotekach.
×
×
  • Utwórz nowe...