• 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
Długość impulsu analogowego
#1
Witam wszystkich,
niestety nie jestem w stanie sobie poradzić i muszę poprosić o pomoc.

Mam arduino leonardo, którego zadaniem jest sterowanie określoną sekwencją elektrozaworów. 
Wyzwoleniem funkcji jest wartość wynosi między 1000 a 1023 (takie są wahania niestety) wrzucona na jedno z analogowych wejść. Problem polega na tym, że ta wartość podawana jest przez różny czas i w różnych odstępach, przez co program nie działa tak jak powinien.
Moje pytanie brzmi zatem jak 1 sygnał traktować jako 1 i aby sekwencja wykonywała się tylko 1 raz a nie np. x razy kiedy sygnał trwa dłużej niż wykonywanie pętli:

Kod:
if (value > 1000)
{
  digitalWrite(12, HIGH);
Serial.println("elektrozawor 1 ON");
Serial.print(F("Wejscie analogowe 2 ma wartosc: "));
Serial.println(value);    //
digitalWrite(10,0); //dioda led zielona OFF

delay (220);
digitalWrite(12, LOW);
  Serial.println("elektrozawor 1 OFF");
}


Sygnał (wartość między 1000 - 1023) podawany jest zazwyczaj w odstępach 4-5 s, ale zdarza się że nieco krócej lub dłużej. Oprócz tego może trwać 4-5 s a czasami nawet 10 s. Nie mam pojęcia jak za każdym razem traktować to jako 1 i ten sam sygnał mając do dyspoyzcji tylko to, że stale, w danym czasie ta wartość to > 1000. 
Próbowałem dać nawet pętlę while w pętli if, ale to się zapętla i cały czas zachowuje się tak jakby ta wartość na wejściu była powyżej 1000.

Z góry dzięki za pomoc,
Janek
 
Odpowiedź
#2
Czekaj chwilę, bo nie bardzo rozumiem.
Co jakiś czas dostajesz z jakiegoś zewnętrznego źródła sygnał analogowy, chcesz zmierzyć jego wartość tylko raz podczas całej długości jego trwania i wysłać na serial monitor?

Może wykorzystaj przerwanie - ustaw na zbocze narastające, w obsłudze przerwania dajesz pomiar wartości i potem ten if(value > 1000).


Np coś takiego:
Kod:
volatile int value;

void setup(){
  pinMode(2, INPUT);  //Dostępne piny przerwań: 2, 3
  attachInterrupt(digitalPinToInterrupt(2), pomiar, RISING);  //Dostępne piny przerwań: 2, 3
  Serial.begin(9600);
}

void loop(){
 
}

void pomiar(){
  value = analogRead(A0);  //Dostępne piny pomiarowe: A0, A1, A2, A3, A4, A5
  if(value > 1000){
    digitalWrite(12, HIGH);
    Serial.println("elektrozawor 1 ON");
    Serial.print(F("Wejscie analogowe 2 ma wartosc: "));
    Serial.println(value);    //
    digitalWrite(10,0); //dioda led zielona OFF
   
    delay (220);
    digitalWrite(12, LOW);
    Serial.println("elektrozawor 1 OFF");
  }
}

Przerwania dostępne "od tak" są w Leonardo na pinach wymienionych w komentarzu w kodzie (oraz na 0 i 1, ale one są już użyte do transmisji szeregowej). Jeśli nie możesz użyć akurat tych bo np są już zajęte, można zrobić jeszcze przerwanie na pinach 8, 9, 10, 11, ale już z wykorzystaniem biblioteki PinChangeInterrupt. Jeśli chodzi o wejścia pomiarowe, są też dostępne inne, na innych, nieopisanych pinach. W tym wypadku użyłem pinu 2 jako wyzwalania pomiaru oraz pinu A0 jako wejścia dla pomiaru. Musisz te wejścia podłączyć razem pod jedno źródło. Sprawdź czy Ci to zadziała, kod pisany na kolanie  Tongue

Ogólnie w przerwaniach nie powinno się używać funkcji delay() bo przerwanie wstrzymuje wykonywanie kodu w pętli głównej loop(). Nie wiem jak wygląda Twój kod w całości, ale jeśli to ma spełniać jedynie powyższe funkcje, możesz nawet na początku przerwania, pod void pomiar(){ wstawić jakiś większy delay, np 1s żeby odczekać przed pomiarem aż wartość napięcia ze źródła się ustabilizuje, jeśli jest taka potrzeba.

A, no i jest jeszcze jedna kwestia - z racji, że wyzwalanie pomiaru następuje poprzez przerwanie, sygnały poniżej około 1.5V nie będą brane pod uwagę w ogóle (to wynika ze specyfikacji procesora, napięcie na wejściu cyfrowym jest traktowane jako jedynka logiczna dopiero powyżej 1.5V przy zasilaniu układu z 5V). W Twoim wypadku to raczej bez znaczenia bo i tak ustawiłeś próg pomiaru na 1000, co odpowiada napięciu ~4,88V. No i pamiętaj, że nie możesz podać na żadne z wejść napięcia większego niż 5V, czyli użyteczny pomiar jakiego możesz dokonać to jakieś 120mV z krokiem co około 5mV.
 
Odpowiedź
#3
A jak to zrobisz na przerwaniach jak sygnał wacha się 23 jednostek?? Nie możliwością są przerwania bo będzie wykrywało zawsze high..


Niech autor narysuje przebieg sygnału...
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#4
Rzuć okiem na mój kod.
 
Odpowiedź
#5
No widzę pomiar nigdy się nie wykona albo tylko raz podczas włączenia.... Żeby nastąpiło przerwanie różnica H/L sygnału powinna być ponad 700jednostek adc a on ma zaledwie 23...
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#6
Autor chyba chce, z jakiegoś powodu, mierzyć jedynie sygnały, których wartość przekroczy 4,88V zaznaczając również, że sygnały są cykliczne (a więc występuje pomiędzy nimi stan niski), a to w zupełności wystarczy aby ustawić stan wysoki na wejściu 2 i wywołać przerwanie, które z kolei uruchomi pomiar na A0. Zauważ, że wykorzystałem dwa osobne wejścia - jedno do wywołania przerwania, a drugie do pomiaru - oba są sterowane tym samym sygnałem.
 
Odpowiedź
#7
(17-08-2020, 08:25)Jan64 napisał(a): Witam wszystkich,
niestety nie jestem w stanie sobie poradzić i muszę poprosić o pomoc.


Wyzwoleniem funkcji jest wartość wynosi między 1000 a 1023 (takie są wahania niestety) wrzucona na jedno z analogowych wejść. 
Sygnał (wartość między 1000 - 1023) podawany jest zazwyczaj w odstępach 4-5 s, ale zdarza się że nieco krócej lub dłużej. 

Z góry dzięki za pomoc,
Janek

No ja to inaczej rozumię...
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#8
Napisałem przecież, że nie do końca rozumiem co autor chce osiągnąć Big Grin
Zinterpretowałem to w taki sposób, że sygnał podany na wejście pomiarowe zmienia się w czasie, a skoro autor użył funkcji warunkowej if(value > 1000) znaczy, że nie interesują go wartości poniżej 4,88V, wszak jego oryginalny kod będzie je ignorował.
Wyszedłem z założenia, że kod będzie prosty w swojej funkcjonalności, a więc i nie potrzeba żadnych bardziej wyszukanych metod. Skoro sygnał jest cykliczny, przerwanie może być wyzwalane za każdym razem kiedy się pojawi (zareaguje na zbocze narastające), ale kod wykona się tylko wtedy, kiedy wartość sygnału przekroczy te 4,88V.
Autor chciał aby kod wykonywał się raz, za każdym razem kiedy wartość sygnału przekroczy progową i to chyba udało mi się zrealizować poprzez reakcję na zbocze narastające, zakładając, że po sygnale o wartości >1000 nastąpi jego brak (stan niski).

Owszem, lepiej byłoby gdyby autor przedstawił wykres zmian sygnału w czasie - równie dobrze może mu chodzić o wykrywanie peak-ów występujących w ciągłym sygnale, wtedy możnaby darować sobie to przerwanie, ale trzebaby dodać jakąś flagę.
 
Odpowiedź
#9
A może autorowi chodzi o takie coś:

if (value > 1000 && start == 0)
{
start = 1;
digitalWrite(12, HIGH);
Serial.println("elektrozawor 1 ON");
Serial.print(F("Wejscie analogowe 2 ma wartosc: "));
Serial.println(value);    //
digitalWrite(10,0); //dioda led zielona OFF

delay (220);
digitalWrite(12, LOW);
Serial.println("elektrozawor 1 OFF");
}
if(value< 1000 && start == 1)
{
start = 0;
}
 
Odpowiedź
#10
O tym właśnie pisałem - porzucić przerwanie i dodać flagę (trzeba ją jeszcze zainicjalizować).
Możemy sobie gdybać, dopóki autor się nie wypowie to się nie dowiemy Big Grin Aczkolwiek ma już gotowe dwie różne interpretacje swojego problemu.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości