• 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
Sterownik RGB
#1
Witam, na wstępie zaznaczę (jak prawie każdy w tym dziale), że dopiero zaczynam swoją przygodę z arduino, i będę wdzięczny za wyrozumiałość. Teraz przejdę do rzeczy, borykam się z pewnym problemem, który uniemożliwia poprawną pracę sterownika (samoróbka, arduino wraz z odbiornikiem Rop02 będą odpowiedzialne za sterowanie). Ogólny zamysł jest taki:
Po wciśnięciu przycisku stan na wyjściu nr. 4 powinen się zmienić z niskiego na wysoki i w nim pozostać.
Przy następnym wciśnięciu pin4=LOW pin5=HIGH, następnie pin5=LOW pin6=HIGH i podczas ostatniego naciśnięcia wszystkie wyjścia cyfrowe powinny zmienić stan na niski. Niestety zamiast tego program wykonuje całą sekwencję po kolei bez zatrzymania się w pętli. W tym celu umieściłem opóznienie w pętli, które miało nie pozwolić na wykonanie wszystkich instrukcji zawartych w while, przy pojedynczym naciśnięciu przycisku. Niestety nic to nie dało, dlatego zwracam się z jednym pytaniem:
Z jakiego powodu pętla wykonuje się kilkukrotnie przy pojedynczym kliknięciu? Przecież stan niski na wejściu występuje przez milisekundy (tak długo jak trzymam przycisk) a delay powinen temu skutecznie zaradzić. Wiem, wiem delay jest fe, ale aktualnie nie znam zgrabniejszego rozwiązania.  Zdaje sobie sprawę, że kod który zamieszczam nie ma prawa zadziałać tak jak to opisałem, ale chodzi mi tylko o tego while, to on jest dla mnie głównym problemem. Oczywiście nie proszę o gotowca, jedynie wskazówkę. Poniżej zamieszczam kod i z góry dziękuje za wszystkie odpowiedzi, pozdrawiam. Big Grin


Kod:
#define BUTTON 2 //PRZYCISK         2
#define RED 4    //DIODY CZERWONE   4
#define GREEN 5  //DIODY ZIELONE    5
#define BLUE 6   //DIODY NIEBIESKIE 6


int PIN=3;
int PINw=2;      
int buttonState=0;

void setup () {
 Serial.begin(9600);
 pinMode(2,INPUT_PULLUP);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT);

 digitalWrite(RED,LOW);              //OFF
 digitalWrite(GREEN,LOW);
 digitalWrite(BLUE,LOW);
 }

void loop() {
 buttonState=digitalRead(BUTTON);   //zmienna przyjmuje wartosc pinu 2
 
 
   
 while(buttonState==LOW) {          //wykonuj jezeli przycisk jest wcisniety
   PIN++;                           //inkrementuj zmienna PIN
   PINw++;                          //inkrementuj zmienna PIN2
   Serial.println(PIN);
   digitalWrite(PIN,HIGH);          //Podaj stan wysoki na Pin:
   digitalWrite(PINw,LOW);          //Podaj stan niski na Pin:
   delay(500);
   
   if(PIN==6)
   break;
 }
 if(PIN==6) {                        //jezeli PIN>=6 wroc do wartosci poczatkowej
 PIN=PIN-3;
 PINw=PINw-3;
 }
 digitalWrite(RED,LOW);             //OFF
 digitalWrite(GREEN,LOW);
 digitalWrite(BLUE,LOW);
 
 }
 
Odpowiedź
#2
(09-12-2018, 08:03)HeksoN napisał(a): Z jakiego powodu pętla wykonuje się kilkukrotnie przy pojedynczym kliknięciu?

Odpowiedź na pytanie znajdziesz w dowolnym kursie Arduino.
 
Odpowiedź
#3
Jak nie znasz lepszego podejścia do przycisków niż delay to poznaj bibliotekę bounce2: https://github.com/thomasfredericks/Bounce2 , poznaj millis w kursie na Forbot (nie zrozumiesz jak nie przejdziesz całego kursu, nawet tych elementów, które pozornie nie są Ci teraz potrzebne, bo każdy odsłania nieco niezbędnej teorii):  https://forbot.pl/blog/kursy.
Wciśnięcie przycisku trawa kilka ms, sprawdzenie i wykonanie poleceń kilka us. Może to zrobić tysiące razy przy jednym maźnięciu paluchem po przycisku. I żeby tego uniknąć używanie delay jest jak włożenie patyka w szprychy - jest fe. Bez zrozumienia kursu i poznania bibliotek będziesz wymyślał  koło na nowo kręcąc się w kółko.
Można też zrobić tak, że po pierwszym wykryciu wciśnięcia przycisku wszystkie inne są ignorowane, choć program pracuje bez blokowania pętli (przykład z millis()):
Kod:
const int buzzer=13;
const int button=2;
boolean stanbuzzera=0;

void setup() {
// put your setup code here, to run once:
pinMode(buzzer,OUTPUT);
pinMode(button,INPUT_PULLUP);

}

void loop() {
// put your main code here, to run repeatedly:
if(!digitalRead(2)||stanbuzzera)  dzwiek(500,10,buzzer);
 


}

void dzwiek(uint16_t dlugosc, uint16_t pikniec, uint16_t pin) //(dlugosc piku, ile pikniec, na ktory pin)
{
static uint16_t aktualnyPik=0;
static boolean stanpoprzedni=0;
static uint32_t lasttime=0;
uint32_t currenttime=millis();
// na razie zakladam 5 pikniec co 1000ms
if(currenttime-lasttime>=(uint32_t)dlugosc)
{
lasttime=currenttime;
if( aktualnyPik++ <(pikniec*2))//mnozymy *2 by pikniec bylo 10, nie zmian stanu
{
  digitalWrite(pin,!digitalRead(pin));
  stanbuzzera=1;
}
else
{
 aktualnyPik=0;
 stanbuzzera=0;
}

}

}
Chyba że użyjesz gdzie delay, to przestanie działać.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości