Skocz do zawartości

Kurs Arduino II - #4 - przerwania, kontaktron, czujnik PIR


Komentator

Pomocna odpowiedź

12 minut temu, farmaceuta napisał:

kod powyzej u mnie dziala bez zarzutu

Jednemu działa, drugiemu nie.

Zasadnicza sprawa - w procedurach obsługi przerwania (ISR) nie powinno używać się funkcji, które same polegają na przerwaniach,  w szczególności dotyczy to Serial.print()  (a także np. delay()).

Procedura ISR powinna być krótka, szybko się wykonywać, a wszystko inne powinno być w loop().

W przypadku ESP32 jest to jeszcze bardziej istotne ze względu na obsługę wifi.

Link do komentarza
Share on other sites

5 minut temu, PierotB napisał:

@farmaceuta a w jakim celu dałeś zwłokę 200ms? W tym wypadku jeśli impulsy będą podawane poniżej tego czasu nie będą liczone. Prawda?

Dokladnie tak...to taki popularny filtr programowy dla drgania styków od guzików np....ten czas oczywiście trzeba dobrać według własnego projektu (częstotliwości "wciśnięć")

Link do komentarza
Share on other sites

Witam, mam problem z czujnikiem PIR. Wszystko jest podłączone prawidłowo, a kod został skopiowany z artykułu. Problem polega na tym, że czujnik nie wykrywa ruchu. Żadne machanie ręką ani nic. Dopiero jak poruszam tą pokrywą (okrągłą plastikową kopułą) to losowo czasem zapali się czerwony kolor na diodzie RGB. Nie wiem czemu tak się dzieje. Dodam, że potencjometry również są skręcone tak jak pisało w artykule.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay


#define LED_R 9
#define LED_G 10
#define LED_B 11
String zamkniete = "Okno zamknięte ";
String otwarte = "Okno otwarte";
#define KONTAKTRON 0
int buzzer = A0;
int dt=100;

void setup() {
  pinMode(LED_R, OUTPUT);  //Poszczególne piny sterujące diodą jako wyjścia
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(buzzer, OUTPUT);

  pinMode(KONTAKTRON, INPUT_PULLUP);  //Kontaktron jako wejście
  Serial.begin(9600);
  digitalWrite(LED_R, LOW);  //Dioda wyłączona
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
}

void loop() {
  if (digitalRead(KONTAKTRON) == LOW) {  //Jeśli czujnik zwarty
    digitalWrite(LED_R, LOW);            //Stan OK - dioda zielona
    digitalWrite(LED_G, HIGH);
    Serial.println(zamkniete);
    digitalWrite(buzzer,LOW);
  } else {
    digitalWrite(LED_R, HIGH);  //Stan ALARM - dioda czerwona
    digitalWrite(LED_G, LOW);
    Serial.println(otwarte);
    tone(buzzer,1000);
    delay(dt);
    noTone(buzzer);
    delay(dt);

  }
}

Mój sposób na zadanie domowe 4.1 

Miałem problem ponieważ mój program nie chciał mi się załadować ale wystarczyło odpiąć kabel od pinu 0 na arduino i po załadowaniu programu podłączyć go ponownie. Jest ktoś w stanie wyjaśnić dlaczego tak się stało ??

 

Link do komentarza
Share on other sites

Mam pytanie co do przerwań . Korzystam z RISING i nie wiem czy dobrze zrozumiałem artykuł . Chodzi mi o to że po zmianie stanu z 0 na 1 taki stan juz pozostanie , czyli cały czas powinna świecić się dioda czerwona ? Nie będzie to tak jak w poprzedniej części z PIR gdzie chwile po odnotowaniu ruchu dioda wracała do koloru zielonego ? Będę wdzięczny za naprostowanie tematu . Dzięki 


#define LED_R 10
#define LED_G 11
#define LED_B 12
String zamkniete = "Okno zamknięte ";
String otwarte = "Okno otwarte";
#define KONTAKTRON 0
int buzzer = A0;
int dt = 2000;
int yellow = 13;
int PIR = 2;

void setup() {
  pinMode(LED_R, OUTPUT);  //Poszczególne piny sterujące diodą jako wyjścia
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(yellow, OUTPUT);
  digitalWrite(yellow, LOW);
  pinMode(PIR, INPUT);
  pinMode(KONTAKTRON, INPUT_PULLUP);  //Kontaktron jako wejście
  Serial.begin(9600);
  digitalWrite(LED_R, LOW);  //Dioda wyłączona
  digitalWrite(LED_G, HIGH);
  digitalWrite(LED_B, LOW);

  attachInterrupt(digitalPinToInterrupt(PIR), alarm, RISING);  //Przerwanie reagujące na zbocze rosnące
}

void loop() {
  digitalWrite(yellow, HIGH);
  delay(dt);
  digitalWrite(yellow, LOW);
  delay(dt);
}
void alarm() {
  digitalWrite(LED_R, HIGH);
  digitalWrite(LED_G, LOW);
}

 

  • Lubię! 1
Link do komentarza
Share on other sites

18 godzin temu, hhube napisał:

Chodzi mi o to że po zmianie stanu z 0 na 1 taki stan juz pozostanie , czyli cały czas powinna świecić się dioda czerwona ?

@hhube myślę że zadanie masz zrobione dobrze - testujesz obsługę przerwań.

Link do komentarza
Share on other sites

Cześć wszystkim 🙂

Moje solucje do zadań:

4.1 
 

#define KONTRAKTON 2
bool isOpen = false;

void setup() {
  pinMode(KONTRAKTON, INPUT_PULLUP); // Kontrakton jako wejście
  pinMode(A5, OUTPUT); // Konfiguracja A5 jako wyjście dla Buzzera
}

void loop() {


  if (digitalRead(KONTRAKTON) == HIGH){ // Jeśli czujnik zwarty
    tone(A5, 4300);
    delay(150);
    tone(A5, 3500);
    delay(150);
    isOpen = true;
  } else if (digitalRead(KONTRAKTON) == HIGH || isOpen == true){
    tone(A5, 4300);
    delay(150);
    tone(A5, 3500);
    delay(150);
  } else{
    noTone(A5);
  }

}

4.2 

#include "pitches.h"

#define LED_R 10
#define LED_G 11
#define LED_B 12

#define PIR 2

int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};


void setup() {
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(3, OUTPUT);

  pinMode(PIR, INPUT); // PIR jako wejście

  digitalWrite(LED_R, LOW);
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
}

void loop() {
  if (digitalRead(PIR) == LOW){
    digitalWrite(LED_R, LOW);
    digitalWrite(LED_G, HIGH);
    noTone(3);
  } else{
    digitalWrite(LED_R, HIGH);
    digitalWrite(LED_G,LOW);
    // Pitches.h library
    for(int thisNote = 0; thisNote < 8; thisNote++){
      int noteDuration = 1000 / noteDurations[thisNote];
      tone(3, melody[thisNote], noteDuration);

      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      noTone(3);
    }
  }
  
  
}

4.3

#define LED_R 10
#define LED_G 11
#define LED_B 12
#define LED_SYG 13
 
#define KONTAKTRON 3

#define PIR 2
 
void setup() {
  attachInterrupt(digitalPinToInterrupt(PIR), alarm, FALLING); // Przerwanie reagujące na zbocze rosnące

  pinMode(LED_R, OUTPUT); //Poszczególne piny sterujące diodą jako wyjścia
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(LED_SYG, OUTPUT);
  
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  
  digitalWrite(LED_R, LOW); //Dioda wyłączona
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
  digitalWrite(LED_SYG , LOW);
}
 
void loop() {
  digitalWrite(LED_SYG, HIGH);
  delay(2000);
  digitalWrite(LED_SYG, LOW);
  delay(2000);
}

void alarm() {
  digitalWrite(LED_R, HIGH);
  digitalWrite(LED_G, LOW);
}

4.4

#define LED_R 10
#define LED_G 11
#define LED_B 12

#define PIR 2
int turnCounter = 0;
 
void setup() {
  attachInterrupt(digitalPinToInterrupt(PIR), changeColor, FALLING); // Przerwanie reagujące na zbocze rosnące

  pinMode(LED_R, OUTPUT); //Poszczególne piny sterujące diodą jako wyjścia
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  
  digitalWrite(LED_R, LOW); //Dioda wyłączona
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);

  Serial.begin(9600);
}
 
void loop() {
  if (turnCounter % 2 == 0){
    digitalWrite(LED_B, HIGH);
  } else if (turnCounter % 2 != 0){
    digitalWrite(LED_B, LOW);
  }
}

void changeColor() {
  turnCounter++;
}

 

Swoją drogą miałem problem z zadaniem, w którym trzeba było użyć kontaktronu czyli bodajże zadanie 4.1
Przez to, że kontrakton był podłączony do PINu 0 czyli RX to nie mogłem wgrać programu. Zakładam, że spowodowane było to otrzymywaniem z dwóch źródeł danych czyli z USB oraz z samego kontraktonu.

Musiałem przebić kontrakton na PIN 2, aby wgrać poprawnie nową wersję oprogramowania.

  • Lubię! 1
Link do komentarza
Share on other sites

19 godzin temu, FTNewbie napisał:

Przez to, że kontrakton był podłączony do PINu 0 czyli RX to nie mogłem wgrać programu. Zakładam, że spowodowane było to otrzymywaniem z dwóch źródeł danych czyli z USB oraz z samego kontraktonu.

@FTNewbie jeśli kontaktron był przewodził (magnes zamykał obwód) to wtedy komunikacja przez UART nie była możliwa. Jednak samo rozłączenie kontaktronu (odsunięcie magnesu) powinno już rozwiązać ten problem.

  • Lubię! 1
Link do komentarza
Share on other sites

Dnia 17.11.2018 o 14:57, Treker napisał:

@Rafgart, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

 

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.

 

Miło słyszeć, że kurs jest pomocny 🙂

Jeśli chodzi o Twój problem to akurat testowanie go przez UART (w taki sposób) nie jest zbyt dobrym wyborem. Pin 0, który testujesz jest wykorzystywany do komunikacji przez UART i nie powinno się w takim przypadku podłączać do niego żadnych elementów (mogą zakłócać komunikację). Lepiej zrobić test takim programem:

int incomingByte = 0; 

void setup() {
    Serial.begin(9600); 
}

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    Serial.print((char)incomingByte);
  }
}

Wgraj go i uruchom monitor portu szeregowego. Wszystko co wyślesz do Arduino powinno natychmiast wrócić do PC i być wyświetlone jako dane odebrane. Dzięki temu sprawdzisz działanie całego UARTu (czyli przy okazji sprawdzisz pin 0 oraz pin 1). Daj znać czy taki program u Ciebie działa. Pamiętaj tylko, aby ustawić w monitorze portu szeregowego odpowiednią prędkość transmisji tj. 9600. Sprawdziłem kod przed chwilą na Arduino UNO i działa na 100%.

Hej, możesz wyjaśnić co masz na myśli? mówiąc: 

Pin 0, który testujesz jest wykorzystywany do komunikacji przez UART i nie powinno się w takim przypadku podłączać do niego żadnych elementów (mogą zakłócać komunikację).

Osobiście napotkałem problem, używając kontaktronu podłączonego do pinu (0) podciągniętego INPUT_PULLUP. Przykładowo mam wgrany program i chce wyczyścić go poprzez wgranie pustego programu i właśnie natknąłem się na taki problem.

Czy podłączanie kontaktronu do pinu (0) i GND jest na pewno bezpieczne?     

Link do komentarza
Share on other sites

Dnia 19.05.2024 o 12:33, mn860618 napisał:

Czy podłączanie kontaktronu do pinu (0) i GND jest na pewno bezpieczne?     

Tak, jest to bezpieczne. Zakłóca jedynie komunikację przez UART. Jeśli nie korzystamy z UART to możemy tego wyprowadzenia korzystać jak z normalnego GPIO.

Link do komentarza
Share on other sites

Dnia 29.02.2020 o 13:29, SOYER napisał:

Mnie ciekawi inna rzecz, trochę w temacie, a trochę poza nim. 

Ustawiamy SoftwareSeriala, podłączamy, NA TEJ SAMEJ PARZE PINÓW, dwa różne urządzenia, wiemy na pewno(?), że Arduino gada ALBO  z jednym ALBO z drugim, nigdy(?) jednocześnie z dwoma naraz, będzie działać? 

Jak cię ciekawią takie tematy to musisz odnaleźć odpowiedz chyba gdzie indziej moim zdaniem, mógłbym polecić jedna książkę chyba że ktoś może wie lepiej będę ciekaw. Książka się nazywa: Digital-Computer-Electronics-Albert-Paul-Malvino-and-Jerald-A-Brown

Link do komentarza
Share on other sites

Zadanie domowe 4.1

Wykorzystaj buzzer bez generatora (omówiony podczas poprzedniego odcinka kursu) i napisz program, który będzie uruchamiał alarm dźwiękowy natychmiast po rozchyleniu kontaktronu. Jego ponowne zetknięcie (np. poprzez zamknięcie drzwi) nie powinno wyłączać sygnału dźwiękowego.

 

#define LED_R 10
#define LED_G 11
#define LED_B 12
#define KONTAKTRON 2
#define ALARM A5
bool SYRENA = false;

void setup() {
  pinMode(LED_R, OUTPUT); //Poszczególne piny sterujące diodą jako wyjścia
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  pinMode(ALARM, OUTPUT); // Konfiguracja A5  jako wyjście
 
  digitalWrite(LED_R, LOW); //Dioda wyłączona
  digitalWrite(LED_G, LOW);
  digitalWrite(LED_B, LOW);
  digitalWrite(ALARM, LOW);

}
void loop() {
  if (digitalRead(KONTAKTRON) == LOW && SYRENA == false) { //Jeśli czujnik zwarty
    digitalWrite(LED_R, LOW); //Stan OK - dioda zielona
    digitalWrite(LED_G, HIGH);

  } else if(digitalRead(KONTAKTRON) == HIGH || SYRENA == true) {
    tone(ALARM, 4000); //Wygeneruj sygnał o częstotliwości 1000 Hz na pinie A5, który trwa 2000 ms
    delay(100);  
    noTone(ALARM);
    delay(100);
    digitalWrite(LED_R, HIGH); //Stan ALARM - dioda czerwona
    digitalWrite(LED_G, LOW);
    SYRENA = true; // blokujemy sygnal syreny jako włączony. Warunek jest wciąż spełniony
  }
  }

 

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...