• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Pierwszy samodzielny program. Pomocy!
#1
Question 
Witam, jestem początkującym programistą(jeżeli można to tak nazwać). Zacząłem pisać program sygnalizacji świetlnej, która na listwie RGB ma wyświetlać kolory, a na ekranie LCD 16x2 ma wyświetlać komunikaty.
Jeden kod wygląda tak:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h> 

Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, 3, NEO_GRB + NEO_KHZ800);
LiquidCrystal_I2C lcd(0x27,16,2);

#define guzik 5 
void setup() {
  pinMode(guzik, INPUT_PULLUP);
  linijka.begin();
  linijka.show();
  lcd.init();                 
  lcd.backlight();
  lcd.begin(16,2);
}

void loop() {
    czerwone();
    delay();
    nacisk();
    delay();
    przerwa();
    zielone();
    delay();
   
 }

 void nacisk(){
  if(digitalRead(guzik)==LOW){
      lcd.setCursor(0,0);
      lcd.print("  Swiatlo zaraz zmieni sie na zielone  ");
      for (int scrollCounter=0;scrollCounter<23;scrollCounter++)
      {
      lcd.scrollDisplayLeft();
      delay(500);
      }
      linijka.setPixelColor(3, linijka.Color(255, 255, 0));
      linijka.show(); 
      linijka.setPixelColor(4, linijka.Color(255, 255,0));
      linijka.show(); 
      delay(1000);
      lcd.clear();
  }
 }

 void zielone(){
  lcd.setCursor(0,0);
  lcd.print("    Zielone!   ");
  delay(500);
      linijka.setPixelColor(2, linijka.Color(0, 255, 0));
      linijka.show(); 
      linijka.setPixelColor(1, linijka.Color(0, 255,0));
      linijka.show(); 
      linijka.setPixelColor(0, linijka.Color(0, 255,0));
      linijka.show();
      delay(4000);
 }
 void czerwone(){
  lcd.setCursor(0,0);
  lcd.print("    Czerwone!   ");
  delay(500);
      linijka.setPixelColor(5, linijka.Color(255, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(6, linijka.Color(255, 0,0));
      linijka.show(); 
      linijka.setPixelColor(7, linijka.Color(255, 0,0));
      linijka.show();
      delay(4000);
 }
 void przerwa(){
        linijka.setPixelColor(5, linijka.Color(0, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(6, linijka.Color(0, 0,0));
      linijka.show(); 
      linijka.setPixelColor(7, linijka.Color(0, 0,0));
      linijka.show();
      linijka.setPixelColor(3, linijka.Color(0, 0, 0));
    linijka.show(); 
    linijka.setPixelColor(4, linijka.Color(0, 0,0));
    linijka.show();
 }
 

Jednakże nie potrafię obsługiwać się dobrze funkcjami i nie wiem jak włączyć jedną funkcje a następnie drugą.
Drugi kod działa za pierwszym razem czeka 5 sekund na czerwonym potem wyświetla zielone a podczas czekania na czerwonym jeżeli wcisnę guzik to wyświetla się komunikat i żółte światło:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h> 
unsigned long czas = 0;
unsigned long rczas = 0;
unsigned long wczas = 0;
Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, 3, NEO_GRB + NEO_KHZ800);
LiquidCrystal_I2C lcd(0x27,16,2);
#define guzik 5
void setup() {
  pinMode(guzik, INPUT_PULLUP);
  linijka.begin();
  linijka.show();
  lcd.init();                 
  lcd.backlight();
  lcd.begin(16,2);
}

void loop() {
  czas=millis();
  rczas=czas-wczas;
       lcd.setCursor(0,0);
       lcd.print("    Czerwone!   ");
       delay(500);
      linijka.setPixelColor(5, linijka.Color(255, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(6, linijka.Color(255, 0,0));
      linijka.show(); 
      linijka.setPixelColor(7, linijka.Color(255, 0,0));
      linijka.show();
      millis();
      
      if(digitalRead(guzik)==LOW){
      linijka.setPixelColor(5, linijka.Color(0, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(6, linijka.Color(0, 0,0));
      linijka.show(); 
      linijka.setPixelColor(7, linijka.Color(0, 0,0));
      linijka.show();
      linijka.setPixelColor(3, linijka.Color(0, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(4, linijka.Color(0, 0,0));
      linijka.show(); 
      linijka.setPixelColor(2, linijka.Color(0, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(1, linijka.Color(0, 0,0));
      linijka.show(); 
      linijka.setPixelColor(0, linijka.Color(0, 0,0));
      linijka.show(); 
      lcd.setCursor(0,0);
      lcd.print("  Swiatlo zaraz zmieni sie na zielone  ");
      for (int scrollCounter=0;scrollCounter<23;scrollCounter++)
      {
      lcd.scrollDisplayLeft();
      delay(500);
      }
      linijka.setPixelColor(3, linijka.Color(255, 255, 0));
      linijka.show(); 
      linijka.setPixelColor(4, linijka.Color(255, 255,0));
      linijka.show(); 
      delay(1000);
      lcd.clear();
      }
      if(rczas>=5000){
      linijka.setPixelColor(5, linijka.Color(0, 0, 0));
      linijka.show(); 
      linijka.setPixelColor(6, linijka.Color(0, 0,0));
      linijka.show(); 
      linijka.setPixelColor(7, linijka.Color(0, 0,0));
      linijka.show();
      linijka.setPixelColor(3, linijka.Color(0, 0, 0));
      linijka.show(); 
     linijka.setPixelColor(4, linijka.Color(0, 0,0));
      linijka.show();
      delay(1000);
  lcd.setCursor(0,0);
  lcd.print("    Zielone!   ");
  delay(500);
  linijka.setPixelColor(2, linijka.Color(0, 255, 0));
  linijka.show(); 
  linijka.setPixelColor(1, linijka.Color(0, 255,0));
  linijka.show(); 
  linijka.setPixelColor(0, linijka.Color(0, 255,0));
  linijka.show();
  millis();

      }


 
  setup();
}

Prosiłbym o jakieś rady co mogę poprawić, co mogę zastosować. Wierzę, że nie zwyzywacie mnie, tylko pomożecie jako doświadczeni koledzy zielonemu chłopakowi. Z góry dzięki!
 
Odpowiedź
#2
Na początek wywal (zastąp) wszystkie delay z kodu, który przez to się blokuje i zawiesza nic nie robiąc i czekając aż delay minie Smile
 
Odpowiedź
#3
Wywalić delay po prostu nie można, jakoś trzeba zarządzać czasem, lepiej jednak do tego użyć w Arduino millis(). Poczytaj kurs: https://forbot.pl/blog/kursy .
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#4
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
unsigned long czas = 0;
unsigned long wczas1 = 0;
unsigned long wczas2 = 0;
unsigned long wczas3 = 0;
unsigned long wczas4 = 0;
Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, 3, NEO_GRB + NEO_KHZ800);
LiquidCrystal_I2C lcd(0x27,16,2);
#define guzik 5
void setup() {
pinMode(guzik, INPUT_PULLUP);
linijka.begin();
linijka.show();
lcd.init();
lcd.backlight();
lcd.begin(16,2);
}

void loop() {
czas=millis();
if(czas-wczas1>=2500UL){
lcd.setCursor(0,0);
lcd.print(" Czerwone! ");
wczas1=czas;
linijka.setPixelColor(5, linijka.Color(255, 0, 0));
linijka.show();
linijka.setPixelColor(6, linijka.Color(255, 0,0));
linijka.show();
linijka.setPixelColor(7, linijka.Color(255, 0,0));
linijka.show();
}
if(czas-wczas2>=5000UL){
wczas2=czas;
lcd.clear();
linijka.setPixelColor(5, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(6, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(7, linijka.Color(0, 0,0));
linijka.show();
}




if(digitalRead(guzik)==LOW){
linijka.setPixelColor(5, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(6, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(7, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(3, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(4, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(2, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(1, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(0, linijka.Color(0, 0,0));
linijka.show();
lcd.setCursor(0,0);
lcd.print(" Swiatlo zaraz zmieni sie na zielone ");
for (int scrollCounter=0;scrollCounter<23;scrollCounter++)
{
lcd.scrollDisplayLeft();
delay(500);
}
linijka.setPixelColor(3, linijka.Color(255, 255, 0));
linijka.show();
linijka.setPixelColor(4, linijka.Color(255, 255,0));
linijka.show();
delay(1000);
lcd.clear();
linijka.setPixelColor(3, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(4, linijka.Color(0, 0,0));
linijka.show();
}
if(czas-wczas3>=7500UL){
wczas3=czas;
lcd.setCursor(0,0);
lcd.print(" Zielone! ");
linijka.setPixelColor(2, linijka.Color(0, 255, 0));
linijka.show();
linijka.setPixelColor(1, linijka.Color(0, 255,0));
linijka.show();
linijka.setPixelColor(0, linijka.Color(0, 255,0));
linijka.show();
}
if(czas-wczas4>=10000UL){
wczas4=czas;

linijka.setPixelColor(2, linijka.Color(0, 0, 0));
linijka.show();
linijka.setPixelColor(1, linijka.Color(0, 0,0));
linijka.show();
linijka.setPixelColor(0, linijka.Color(0, 0,0));
linijka.show();

}



setup();
}

Trochę zmieniłem kod, ale dalej nie funkcjonuje tak jakbym chciał. Nie potrafię zrozumieć forbota i funkcji millis().
 
Odpowiedź
#5
Ten kurs jest na 2 tygodnie jak masz dużo czasu, do każdej lekcji można zrobić swoich kilkadziesiąt wersji programu, jak zacząłeś od końca kursu to czego się spodziewasz? Zacznij kurs francuskiego od ostatniej książki i ostatniej lekcji, powodzenia...
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#6
Kurs przeszedłem cały, ponieważ zakupiłem od nich boxy. Niestety dalej nie potrafię wywołać poprawnie kilka funkcji jedna po drugiej i nie rozumiem millis().
 
Odpowiedź
#7
Wystarczy zrozumieć jak działa program. Pętla główna loop ma działać możliwie szybko bez żadnych delay. Dopóki jest pusta jest OK, teoretycznie kręci się tak szybko jak zegar czyli 16MHz, 16mln razy na sekundę nic nie robi, wchodzi do pętli i przeskakuje na początek (to też faktycznie coś trwa, ale pomijam). Po dodaniu każdej funkcji obrót pętli zwalnia tyle ile instrukcji musi wykonać, np. jeśli 10 funkcji zajmuje 1600 cykli zegara to pętla potrafi powtórzyć funkcje w loop już tylko 10000 razy/s. Masz przykład w Arduino do millis, 02. DIGITAL "blinkWithoutDelay".  Jeśli do takiej pętli bez kontroli czasu wstawisz funkcję zaświecenia diody i zgaszenia to nie zauważysz jej działania. LED będzie migał 10 tysięcy razy/s, zmiana co 500us jest nie do zauważenia. Po to jest delay, najbardziej prymitywny, mignięcie zauważalne to >50ms. Ale pętla wtedy zwalnia do 20 obiegów/s, co już jest nieakceptowalne. Można napisać tak program, że niektóre rzeczy wydarzą się dopiero wtedy, gdy upłynie określony czas, ale bez blokowania. Tu przydają się instrukcje if i funkcja millis(). Wynikiem działania funkcji millis jest ilość ms od początku działania programu. Przykładowo w tym szkicu blinkWithoutDelay pętla kręci się pierdylion razy/s i sprawdza czy od ostatniej zmiany pinu LED upłynęło 1000ms, jedna sekunda. Jeśli tak to zmienia jej stan na przeciwny. Analogicznie robi się wszystko, masz cały blok programu, który wykona się gdy minęło 10ms, 100ms, 2 minuty, sekundy parzyste, podzielne bez reszty przez 3 - do wszystkiego są odpowiednie operatory, porównania, itd. Gadasz z modemem, to jak mu zadasz pytanie nie czekasz 10s na odpowiedź, bo wiesz, że za tyle zwykle odpowiada, pętla się kręci i w każdym obrocie sprawdza czy odpowiedź przyszła, nie to zlicza czas timeout. Zliczy sobie 10s to powinna porzucić zadanie i rozpocząć od nowa. Zrobisz program tak, że czeka na odpowiedź i już nic się w nim nie wydarzy do końca świata, bo modem jest uszkodzony, niepodłączony, sam się zawiesił. Gdy sprawdzasz czy przycisk został wciśnięty to tak samo, nie robisz pauzy delayem na 30ms by wyeliminować drganie styków, odnotowujesz w zmiennej pierwsze zauważenie wciśnięcia i lecisz dalej, za 10ms sprawdzasz znowu, stan się zmienił to zerujesz ten blok programu i liczysz od nowa, wciśnięty dalej to podbijasz zmienną wciśnięcia, za trzecim razem jak dalej wciśnięty to znowu podbijasz wyżej. Inny blok programu odczytuje tę zmienną i jak ma więcej>2 to znaczy, że ma wykonać akcję od wciśnięcia tego przycisku i wyzerować zmienną, żeby znowu akcja nie wykonała się 10000x po wciśnięciu. Do wielu rzeczy są gotowe biblioteki, np. do przycisków bounce2, ale jak użyjesz gdzieś delay to wszystko się rozsypie, więc wszystko trzeba pisać w ten sposób.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości