Program działa tylko w połowie. - Wersja do druku +- Arduino Polska Forum (https://forum.arduinopolska.pl) +-- Dział: Korzystanie z Arduino (https://forum.arduinopolska.pl/dzial-korzystanie-z-arduino) +--- Dział: Programowanie w Arduino (https://forum.arduinopolska.pl/dzial-programowanie-w-arduino) +--- Wątek: Program działa tylko w połowie. (/watek-program-dzia%C5%82a-tylko-w-po%C5%82owie) |
Program działa tylko w połowie. - Helsinki - 06-01-2024 Witam wszystkich, chciałbym się zapytać czy jest mi ktoś w stanie pomóc z kodem, który według mnie powinien działać, lecz niestety w połowie wykonania case'ów program przestaje działać do momentu funkcji resetującej. Chodzi o to, aby po uruchomieniu programu moduł pomiaru prądu ACS712 30A mierzył dany prąd i wyświetlał wartość na wyświetlaczu LCD 4x20 (ta część kodu działa) oraz przy wykorzystaniu przekaźnika 6 kanałowego po odpowiednim czasie zapalał parami żarówki (przez 10 sekund - zapalona 1 i 2 żarówka, wyłączenie żarówek, na następne 10 sekund zapalać kolejne dwie czyli 3 i 4, wyłączyć je oraz zapalić 5 i 6 i wyłączyć. Ostatnim krokiem programu jest zapalenie wszystkich zarówek i analogicznie zgaszenie ich po 10 sekundach. Program na delay działa, lecz niestety pomiary występują tylko po wykonaniu całej pętli loop. Program napisany na case zmienia to działanie i resetuje program po 51s, lecz niestety w momencie zapalenia 5 i 6 żarówki w serial monitorze występują tylko pomiary prądu i brakuje kroku wyłącz 5 i 6 zarowke oraz calego dotyczącego wszystkich żarówek, po czym resetuje sie zgodnie po 51 sekundach. Czy ktos jest w stanie mi pomoc i podpowiedziec dlaczego program nie działa w 100% dobrze? Kod załączam w załączniku oraz na samym końcu postu. Działanie wg. serial monitora: Zarowki wylaczone Amps = 1.406 Zarowki 1 i 2 zapalone. Amps = 1.258 Amps = 1.258 Amps = 1.184 Amps = 1.184 Amps = 1.184 Zarowki 1 i 2 zgaszone. Amps = 1.332 Zarowki 3 i 4 zapalone. Amps = 1.184 Amps = 1.258 Amps = 1.184 Amps = 1.184 Amps = 1.110 Zarowki 3 i 4 zgaszone. Amps = 1.258 Zarowki 5 i 6 zapalone. Amps = 1.184 Amps = 1.258 Amps = 1.258 Amps = 1.184 Amps = 1.110 Amps = 1.258 Amps = 1.258 Amps = 1.332 Amps = 1.258 Amps = 1.184 Amps = 1.258 Amps = 1.258 Czas zresetowany. KOD: #include <Arduino.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 20, 4); const int zarowka1 = 7; const int zarowka2 = 6; const int zarowka3 = 5; const int zarowka4 = 4; const int zarowka5 = 3; const int zarowka6 = 2; const int analogIn = A0; int mVperAmp = 66; int RawValue = 0; int ACSoffset = 2500; double Voltage = 0; double Amps = 0; unsigned long ostatniPomiar = 0; const int czasPomiarowy = 2000; unsigned long zapamietanyCzas = 0; unsigned long aktualnyCzas = 0; const int wylacz = 2000; const int wlacz12 = 3000; const int wylacz12 = 13000; const int wlacz34 = 15000; const int wylacz34 = 25000; const int wlacz56 = 27000; const int wylacz56 = 37000; const int wlacz123456 = 39000; const int wylacz123456 = 49000; unsigned long resetInterval = 51000; unsigned long startTime = 0; enum StanZarowek { WYLACZONE, WLACZ_ZAROWKI_12, WYLACZ_ZAROWKI_12, WLACZ_ZAROWKI_34, WYLACZ_ZAROWKI_34, WLACZ_ZAROWKI_56, WYLACZ_ZAROWKI_56, WLACZ_ZAROWKI_123456, WYLACZ_ZAROWKI_123456 }; StanZarowek aktualnyStan = WYLACZONE; void setup() { Serial.begin(9600); lcd.init(); lcd.begin(20, 4); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Pomiar prądu i napięcia!"); startTime = millis(); pinMode(zarowka1, OUTPUT); pinMode(zarowka2, OUTPUT); pinMode(zarowka3, OUTPUT); pinMode(zarowka4, OUTPUT); pinMode(zarowka5, OUTPUT); pinMode(zarowka6, OUTPUT); } void loop() { aktualnyCzas = millis(); unsigned long elapsedTime = aktualnyCzas - startTime; // POMIAR PRĄDU: if (aktualnyCzas - ostatniPomiar >= czasPomiarowy) { ostatniPomiar = aktualnyCzas; RawValue = analogRead(analogIn); Voltage = (RawValue / 1024.0) * 5000; Amps = ((Voltage - ACSoffset) / mVperAmp); Serial.print("\t Amps = "); Serial.println(Amps, 3); displayCurrent(Amps); } // ZAPALANIE ŻARÓWEK: switch (aktualnyStan) { case WYLACZONE: if (elapsedTime >= WYLACZONE) { digitalWrite(zarowka1, HIGH); digitalWrite(zarowka2, HIGH); digitalWrite(zarowka3, HIGH); digitalWrite(zarowka4, HIGH); digitalWrite(zarowka5, HIGH); digitalWrite(zarowka6, HIGH); Serial.println("Zarowki wylaczone"); aktualnyStan = WLACZ_ZAROWKI_12; } break; case WLACZ_ZAROWKI_12: if (elapsedTime >= wlacz12) { digitalWrite(zarowka1, LOW); digitalWrite(zarowka2, LOW); Serial.println("Zarowki 1 i 2 zapalone."); aktualnyStan = WYLACZ_ZAROWKI_12; } break; case WYLACZ_ZAROWKI_12: if (elapsedTime >= wylacz12) { digitalWrite(zarowka1, HIGH); digitalWrite(zarowka2, HIGH); Serial.println("Zarowki 1 i 2 zgaszone."); aktualnyStan = WLACZ_ZAROWKI_34; } break; case WLACZ_ZAROWKI_34: if (elapsedTime >= wlacz34) { digitalWrite(zarowka3, LOW); digitalWrite(zarowka4, LOW); Serial.println("Zarowki 3 i 4 zapalone."); aktualnyStan = WYLACZ_ZAROWKI_34; } break; case WYLACZ_ZAROWKI_34: if (elapsedTime >= wylacz34) { digitalWrite(zarowka3, HIGH); digitalWrite(zarowka4, HIGH); Serial.println("Zarowki 3 i 4 zgaszone."); aktualnyStan = WLACZ_ZAROWKI_56; } break; case WLACZ_ZAROWKI_56: if (elapsedTime >= wlacz56) { digitalWrite(zarowka5, LOW); digitalWrite(zarowka6, LOW); Serial.println("Zarowki 5 i 6 zapalone."); aktualnyStan = WYLACZ_ZAROWKI_56; } break; case WYLACZ_ZAROWKI_56: if (elapsedTime >= wylacz56) { digitalWrite(zarowka5, HIGH); digitalWrite(zarowka6, HIGH); Serial.println("Zarowki 5 i 6 zgaszone."); aktualnyStan = WLACZ_ZAROWKI_123456; } break; case WLACZ_ZAROWKI_123456: if (elapsedTime >= wlacz123456) { digitalWrite(zarowka1, LOW); digitalWrite(zarowka2, LOW); digitalWrite(zarowka3, LOW); digitalWrite(zarowka4, LOW); digitalWrite(zarowka5, LOW); digitalWrite(zarowka6, LOW); Serial.println("Wszystkie zarowki zapalone."); aktualnyStan = WYLACZ_ZAROWKI_123456; } break; case WYLACZ_ZAROWKI_123456: if (elapsedTime >= wylacz123456) { digitalWrite(zarowka1, HIGH); digitalWrite(zarowka2, HIGH); digitalWrite(zarowka3, HIGH); digitalWrite(zarowka4, HIGH); digitalWrite(zarowka5, HIGH); digitalWrite(zarowka6, HIGH); Serial.println("Wszystkie zarowki zgaszone."); aktualnyStan = WYLACZONE; } break; } // RESET MILLIS CO 51 SEKUND: if (elapsedTime >= resetInterval) { startTime = aktualnyCzas; Serial.println("Czas zresetowany."); aktualnyStan = WYLACZONE; } delay(10); // Dodaj krótką pauzę dla stabilności } // WYŚWIETLANIE PRĄDU NA LCD 4x20: void displayCurrent(float Amps) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Prad: "); lcd.print(Amps); lcd.print(" A"); } RE: Program działa tylko w połowie. - Irvin - 06-01-2024 Nie wiem po co mieszasz switch case i ify, przecież po to jest jedno by nie robić drugiego. Po prostu w pętli zliczasz sobie do zmiennej sekundy, tak jak masz w przykładzie BlinkWithoutDelay, co 1s zmieniasz stan led, to Ty sobie robisz w to miejsce sekundy++, co 10s przełączasz na kolejny case, czyli zmienną sterującą aktualnyStan++. RE: Program działa tylko w połowie. - Helsinki - 06-01-2024 Dałbyś radę pomóc mi w napisaniu tego kodu według instrukcji jaką napisałeś? RE: Program działa tylko w połowie. - oscarX - 06-01-2024 (06-01-2024, 17:55)Helsinki napisał(a): KOD: Przejrzałem kod i niestety nie zauważyłem czegoś, co mogło by spowodować opisane rezultaty. Znalazłem taką jedną niejasność - w przedstawion fragmencie chyba powynno być wylacz (małymi literkami - taki zdefiniowany int) niż WYLACZONE (wielkimi - to wartość enum). Ale to tylko włacza odpowienią sekcje w innym momencie. Taka porada - skoro tyle piszesz to wypisuj też w pętli aktualną wartość tej zmiennej stanu aktualnyStan i ten elapsedTime. Masz tam longi więc teoretycznie nic się powinno przepełniać przez 50 dni, ale ja bym sprawdził. O, chyba znalazłem: Te stałe (momenty czasu) przekraczające 32768 daj unsigned int (wystarczy do 65536) albo long. Najlepiej zrób wszystkie long - dla jednorodności kodu. No i jeszcze można by dać wszystko w tabelkach przejść i wyjść zamiast takiego kodu copy-paste. RE: Program działa tylko w połowie. - Irvin - 07-01-2024 Jak się ulongi przepełnią po 54 dniach, ale gdy operację są robione na uint32_t to zliczanie i porównanie będzie dalej działać prawidłowo, tylko mają to być ulongi/uint32_t. Złe działanie programu pewnie wynika z tego resetu, jest niepotrzebny, zmienisz czasy poszczególnych casów to musisz sobie tu wyliczyć ile trwa pełny obieg i zmienić ten czas, nie chce mi się go zliczać, ale mogłeś to zrobić używanymi zmiennymi w casach sumując je, a nie wpisując 51, potem musisz pamiętać, że jak zmienisz jakiś czas to jeszcze tam wrócić i poprawić. Z opisu wynikało, że chcesz każdy stan zmienić co 10s, wtedy wystarczyłoby wywołać case co 10s i po jednokrotnym ustawieniu stanów led przełączyć na kolejny. Ale chcesz mieć inne czasy, to wybierasz sobie wymaganą rozdzielczość, widzę że masz 1s choć niepotrzebnie zapisywaną w ms, wywołujesz część z case co 1s, zliczasz wywołania w każdym case i po spełnieniu warunku, tu faktycznie ify są potrzebne, przełaczasz na kolejny case. Jak masz mieć większą rozdzielczość to można tak samo zliczać co 10 czy 100ms, zrobić sobie kolejną flagę/znacznik nowego okresu 10ms czy 100ms. Możesz sobie zobaczyć jak to działa, podstawić swoje czasy w caseTime, tylko w sekundach. https://wokwi.com/projects/386245628558953473 RE: Program działa tylko w połowie. - Helsinki - 07-01-2024 Dziękuję bardzo za pomoc , w razie co mam dwa kody. Wczoraj jeszcze udało mi się napisać jeden z nich. We wtorek test, bo potrzebuję to do swojej pracy dyplomowej. RE: Program działa tylko w połowie. - Irvin - 07-01-2024 Strasznie was męczą w tych szkołach, to jest temat co najmniej na pracę doktorską . |