Arduino Polska Forum

Pełna wersja: Sterowanie pilotem 433mhz
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witam,

chcę sterować przekaźnikami za pomocą pilota 433mhz. Projekt oparty jest na Arduino nano, rxb6 i przekaźniku. Chcę stworzyć takie sterowanie, że po wciśnięciu jednego przycisku załączam i wyłączam jeden przekaźnik. Oto kod:

Kod:
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
            
boolean stan = LOW;

void setup()
{
Serial.begin(9600);
  pinMode(3, OUTPUT);
  digitalWrite(3,LOW);

  mySwitch.enableReceive(0);
}

void loop()
{

  if (mySwitch.available())
  {
      int value = mySwitch.getReceivedValue();
      if ( mySwitch.getReceivedValue() == 1653416)
      {
      stan = !stan;
      Serial.println(stan);
      digitalWrite(3, stan);
      delay(100);a
      } 

      
  }

}
 
Po wgraniu powyższego kodu zrobiłem z przekaźnika ,, dzwonek ". Nie wiem jak wyjść z warunku if po wciśnięciu przycisku. Proszę o jakąś pomoc lub sugestię co robię źle.
Pokazujesz połowę programu, a problem może być w tej drugiej, gdzie odczytujesz stan przycisku. W obu częściach kodu trzeba nauczyć się mierzyć czas, na początek migać ledem z użyciem millis, eliminować drgania styków.
W nadajniku eliminujesz drgania styków i decydujesz czy jest sens wysłać kolejny komunikat, w odbiorniku tak samo eliminujesz komunikaty, które z dużą pewnością są skutkiem tego samego naciśnięcia.
W pokazanej części od biedy jest OK, jeśli nadajnik może nadawać dwa komunikaty, zmieniać je w kolejnych wciśnięciach.
Jak masz gotowy pilot komercyjny to wystarczy ignorować komunikaty w taki sam sposób jak eliminuje się drgania styków. Czyli zmieniłeś stan, zapisujesz czas, przez kolejne 200ms odbierasz komunikaty i je zerujesz - nic z nimi nie robisz.
Może nawet wystarczy tak jak w przykładzie blinkwithoutdelay wywołać kod raz na 200ms, bez tego delay.
(21-10-2023, 10:58)kopcor07 napisał(a): [ -> ]Witam,

chcę sterować przekaźnikami za pomocą pilota 433mhz. Projekt oparty jest na Arduino nano, rxb6 i przekaźniku. Chcę stworzyć takie sterowanie, że po wciśnięciu jednego przycisku załączam i wyłączam jeden przekaźnik. Oto kod:

Kod:
      int value = mySwitch.getReceivedValue();
      if ( mySwitch.getReceivedValue() == 1653416)
 
Po wgraniu powyższego kodu zrobiłem z przekaźnika ,, dzwonek ". Nie wiem jak wyjść z warunku if po wciśnięciu przycisku. Proszę o jakąś pomoc lub sugestię co robię źle.


W if-ie sprawdzaj zmienną value, nie wołaj drugi raz getReceivedValue(). Nie dostajesz ostrzeżenia od kompilatora, że wartość podstawiona do value nie jest nigdzie użyta?
(21-10-2023, 14:56)oscarX napisał(a): [ -> ]
(21-10-2023, 10:58)kopcor07 napisał(a): [ -> ]Witam,

chcę sterować przekaźnikami za pomocą pilota 433mhz. Projekt oparty jest na Arduino nano, rxb6 i przekaźniku. Chcę stworzyć takie sterowanie, że po wciśnięciu jednego przycisku załączam i wyłączam jeden przekaźnik. Oto kod:

Kod:
      int value = mySwitch.getReceivedValue();
      if ( mySwitch.getReceivedValue() == 1653416)
 
Po wgraniu powyższego kodu zrobiłem z przekaźnika ,, dzwonek ". Nie wiem jak wyjść z warunku if po wciśnięciu przycisku. Proszę o jakąś pomoc lub sugestię co robię źle.


W if-ie sprawdzaj zmienną value, nie wołaj drugi raz getReceivedValue(). Nie dostajesz ostrzeżenia od kompilatora, że wartość podstawiona do value nie jest nigdzie użyta?



Spawdzam value i zgłasza błąd:
Kod:
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
             
boolean stan = LOW;

void setup()
{
Serial.begin(9600);
  pinMode(3, OUTPUT);
  digitalWrite(3,LOW);

  mySwitch.enableReceive(0);
}

void loop()
{

  if (mySwitch.available())
  {
     
     // int value = mySwitch.getReceivedValue();
      if ( int value == 1653416)
      {
      stan = !stan;
      Serial.println(stan);
      digitalWrite(3, stan);
      delay(100);
      } 

       
  }

}

 
(21-10-2023, 14:03)kaczakat napisał(a): [ -> ]Pokazujesz połowę programu, a problem może być w tej drugiej, gdzie odczytujesz stan przycisku. W obu częściach kodu trzeba nauczyć się mierzyć czas, na początek migać ledem z użyciem millis, eliminować drgania styków.
W nadajniku eliminujesz drgania styków i decydujesz czy jest sens wysłać kolejny komunikat, w odbiorniku tak samo eliminujesz komunikaty, które z dużą pewnością są skutkiem tego samego naciśnięcia.
W pokazanej części od biedy jest OK, jeśli  nadajnik może nadawać dwa komunikaty, zmieniać je w kolejnych wciśnięciach.
Jak masz gotowy pilot komercyjny to wystarczy ignorować komunikaty w taki sam sposób jak eliminuje się drgania styków.  Czyli zmieniłeś stan, zapisujesz czas, przez kolejne 200ms odbierasz komunikaty i je zerujesz - nic z nimi nie robisz.
Może nawet wystarczy tak jak w przykładzie blinkwithoutdelay wywołać kod raz na 200ms, bez tego delay.


To jest cały kod. Pilot pod przyciskiem A geneuje tylko jeden kod : 1653416
(21-10-2023, 15:56)kopcor07 napisał(a): [ -> ]
(21-10-2023, 14:56)oscarX napisał(a): [ -> ]W if-ie sprawdzaj zmienną value, nie wołaj drugi raz getReceivedValue(). Nie dostajesz ostrzeżenia od kompilatora, że wartość podstawiona do value nie jest nigdzie użyta?



Spawdzam value i zgłasza błąd:
Kod:
void loop()
{

  if (mySwitch.available())
  {
     
     // int value = mySwitch.getReceivedValue();
      if ( int value == 1653416)
      {
      stan = !stan;
      Serial.println(stan);
      digitalWrite(3, stan);
      delay(100);
      } 

      
  }

}

 


Sorki, ale napisalem nieprawdę, zakładając, że jest logika jak w read - raz odczytana wartość przepada. Ale nie, sprawdziłem w źródłach i kod jest następujący:
Kod:
bool RCSwitch::available() {
  return RCSwitch::nReceivedValue != 0;
}

void RCSwitch::resetAvailable() {
  RCSwitch::nReceivedValue = 0;
}

unsigned long RCSwitch::getReceivedValue() {
  return RCSwitch::nReceivedValue;
}

Wnioski: - wołanie available() jest bez sensu - można od razu sprawdzać wynik getReceivedValue(), jak wynik jest != 0 to odczytano wartość. Ale potem należy wyzerować obiekt, by jedna wartość nie była odczytywana wielokrotnie - bo jej odczyt "nie jest niszczący". Ponieważ sprawdzasz wynik na jedną konkretną wartość to nie ma sensu wcześniej sprawdzać na zero. W sumie to pominąłeś wywołanie resetAvailable().

Sprawdź następujący fragment kodu:

Kod:
void loop()
{
    if ( mySwitch.getReceivedValue() == 1653416)
    {
        mySwitch.resetAvailable();
        stan = !stan;
        Serial.println(stan);
       digitalWrite(3, stan);
       delay(100);
    }
(21-10-2023, 20:28)oscarX napisał(a): [ -> ]
(21-10-2023, 15:56)kopcor07 napisał(a): [ -> ]
(21-10-2023, 14:56)oscarX napisał(a): [ -> ]W if-ie sprawdzaj zmienną value, nie wołaj drugi raz getReceivedValue(). Nie dostajesz ostrzeżenia od kompilatora, że wartość podstawiona do value nie jest nigdzie użyta?



Spawdzam value i zgłasza błąd:
Kod:
void loop()
{

  if (mySwitch.available())
  {
     
     // int value = mySwitch.getReceivedValue();
      if ( int value == 1653416)
      {
      stan = !stan;
      Serial.println(stan);
      digitalWrite(3, stan);
      delay(100);
      } 

      
  }

}

 


Sorki, ale napisalem nieprawdę, zakładając, że jest logika jak w read - raz odczytana wartość przepada. Ale nie, sprawdziłem w źródłach i kod jest następujący:
Kod:
bool RCSwitch::available() {
  return RCSwitch::nReceivedValue != 0;
}

void RCSwitch::resetAvailable() {
  RCSwitch::nReceivedValue = 0;
}

unsigned long RCSwitch::getReceivedValue() {
  return RCSwitch::nReceivedValue;
}

Wnioski: - wołanie available() jest bez sensu - można od razu sprawdzać wynik getReceivedValue(), jak wynik jest != 0 to odczytano wartość. Ale potem należy wyzerować obiekt, by jedna wartość nie była odczytywana wielokrotnie - bo jej odczyt "nie jest niszczący". Ponieważ sprawdzasz wynik na jedną konkretną wartość to nie ma sensu wcześniej sprawdzać na zero.  W sumie to pominąłeś wywołanie resetAvailable().

Sprawdź następujący fragment kodu:

Kod:
void loop()
{
    if ( mySwitch.getReceivedValue() == 1653416)
    {
        mySwitch.resetAvailable();
        stan = !stan;
        Serial.println(stan);
       digitalWrite(3, stan);
       delay(100);
    }

Działa Smile dziękuję, ale po dłuższym przytrzymaniu przycisku dalej mam ,, dzwonek ". Potrzebuje jeszcze jakiegoś opóźnienia dopóki przycisk nie zostanie puszczony. Myślałem, aby dodać to ,, while (mySwitch.getReceivedValue() == 1653416); " ale nie działa 
Kod:
void loop()
{
    if ( mySwitch.getReceivedValue() == 1653416)
    {
        mySwitch.resetAvailable();
        stan = !stan;
       digitalWrite(3, stan);
       while (mySwitch.getReceivedValue() == 1653416);
    }
   delay(100);
}
To nie jest taki przycisk bezpośrednio na płytce. To bardziej podobne jest do klawiatury komputera - ona wysyła do komputera kod naciśniecia klawisza i inny kod puszczenia klawisza. Dodatkowo trzymany klawisz wysyła co jakiś czas kod. Tutaj jest łączność radiowa, gdzie trzeba się dodatkowo liczyć z zakłóceniami. Nie znam dokładnie tematu, nie bawiłem się takim sterowaniem, przypuszczam, że działa to podobnie do pilota do TV - gdzie też mogą być zakłócenia, a wręcz można pilotem nie trafić w odbiornik.
Napisz prosty kod, który po prostu wypisze ci wszystkie kolejno odbierane z pilota kody i trzeba zobaczyć, czy są jakieś kody powtarzane przy trzymaniu, czy coś idzie przy puszczaniu itp. Ale ciągle istnieje możliwość, że nie da się rozróżnić przytrzymania przycisku od kolejnego naciśniecia.
No i moim zdaniem ta biblioteka jest dość słaba - trochę dziwny sposób odbioru poszczególnych kodów z pilota - brak tzw handshakingu - może gubić kody jeśli się jakiś czas jej nie odczytuje.
(22-10-2023, 01:37)oscarX napisał(a): [ -> ]To nie jest taki przycisk bezpośrednio na płytce. To bardziej podobne jest do klawiatury komputera - ona wysyła do komputera kod naciśniecia klawisza i inny kod puszczenia klawisza. Dodatkowo trzymany klawisz wysyła co jakiś czas kod. Tutaj jest łączność radiowa, gdzie trzeba się dodatkowo liczyć z zakłóceniami. Nie znam dokładnie tematu, nie bawiłem się takim sterowaniem, przypuszczam, że działa to podobnie do pilota do TV - gdzie też mogą być zakłócenia, a wręcz można pilotem nie trafić w odbiornik.
Napisz prosty kod, który po prostu wypisze ci wszystkie kolejno odbierane z pilota kody i trzeba zobaczyć, czy są jakieś kody powtarzane przy trzymaniu, czy coś idzie przy puszczaniu itp. Ale ciągle istnieje możliwość, że nie da się rozróżnić przytrzymania przycisku od kolejnego naciśniecia.
No i moim zdaniem ta biblioteka jest dość słaba - trochę dziwny sposób odbioru poszczególnych kodów z pilota - brak tzw handshakingu - może gubić kody jeśli się jakiś czas jej nie odczytuje.

 Po trzymaniu dowolnego przycisku generowany jest cały czas ten sam kod. Poniżej jest przykład dla przycisku A.

13:05:00.216 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 361 microseconds Protocol: 1
13:05:00.310 -> Raw data: 11184,356,1076,360,1076,368,1068,1116,332,1096,348,344,1092,348,1088,1096,348,344,1092,348,1088,1100,348,1084,360,1076,368,320,1112,1076,368,320,1116,1072,372,316,1116,1072,376,320,1120,1068,376,316,1120,324,1112,332,1104,
13:05:00.594 ->
13:05:00.594 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 361 microseconds Protocol: 1
13:05:00.734 -> Raw data: 11220,352,1080,364,1072,376,1064,1112,332,1100,348,344,1092,352,1088,1100,348,340,1096,348,1088,1100,348,1088,356,1084,364,328,1108,1076,368,320,1116,1072,372,316,1116,1072,372,320,1116,1068,376,316,1120,324,1112,332,1104,
13:05:00.968 ->
13:05:00.968 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 361 microseconds Protocol: 1
13:05:01.109 -> Raw data: 11208,356,1084,360,1076,368,1072,1116,332,1100,344,344,1092,348,1084,1100,348,340,1096,348,1088,1096,344,1084,356,1076,368,324,1108,1076,368,320,1112,1076,368,316,1116,1068,372,316,1124,1060,376,316,1116,324,1104,332,1100,
13:05:01.344 ->
13:05:01.344 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 360 microseconds Protocol: 1
13:05:01.484 -> Raw data: 11176,356,1076,364,1068,368,1068,1112,332,1096,348,344,1088,352,1084,1100,344,344,1092,348,1088,1096,348,1084,356,1076,368,320,1112,1072,368,320,1112,1072,372,316,1116,1068,372,316,1116,1068,372,316,1120,324,1112,332,1100,
13:05:01.719 ->
13:05:01.719 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 361 microseconds Protocol: 1
13:05:01.860 -> Raw data: 11196,360,1080,360,1076,368,1068,1112,332,1100,344,344,1092,352,1084,1096,348,344,1096,352,1084,1096,348,1084,356,1076,368,324,1108,1076,368,320,1116,1072,372,320,1116,1068,372,320,1116,1068,376,316,1116,328,1108,332,1112,
13:05:02.094 ->
13:05:02.094 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 361 microseconds Protocol: 1
13:05:02.235 -> Raw data: 11184,356,1080,360,1072,368,1068,1112,332,1104,340,344,1092,348,1084,1104,344,344,1092,348,1088,1100,344,1088,356,1076,368,320,1108,1072,368,320,1112,1068,372,316,1112,1072,368,316,1116,1068,372,316,1112,328,1104,332,1100,
13:05:02.469 ->
13:05:02.469 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 360 microseconds Protocol: 1
13:05:02.610 -> Raw data: 11192,356,1080,360,1076,368,1068,1112,332,1096,348,344,1092,348,1084,1096,348,344,1092,348,1084,1100,344,1084,356,1076,364,324,1112,1072,368,320,1112,1072,372,316,1116,1076,368,316,1116,1072,376,316,1116,324,1112,332,1100,
13:05:02.844 ->
13:05:02.844 -> Decimal: 1653416 (24Bit) Binary: 000110010011101010101000 Tri-State: not applicable PulseLength: 360 microseconds Protocol: 1
13:05:02.986 -> Raw data: 9972,532,500,776,672,660,1264,1448,452,1316,332,192,1092,352,1084,1100,344,344,1092,348,1088,1096,344,1088,356,1076,368,320,1112,1072,368,324,1112,1072,368,320,1116,1072,368,320,1120,1068,372,316,1120,1396,84,384,376,
13:05:03.220 ->
To jeszcze sprawdź, czy coś innego nie przychodzi w momencie puszczenia klawisza. Jednak ponieważ to jest transmisja radiowa, nawet jak coś innego jest wysyłane, to i tak należy liczyć się z tym, że może nie zostać poprawnie odebrane. Tak czy inaczej, trzeba oprzeć się na czasie. W logu, który wrzuciłeś w poprzednim poście widać, że kody przychodzą tak mniej więcej 2-3 razy na sekundę, czyli co 300-400ms. Wystarczy zapamiętać moment odebrania każdego kodu i działanie uzależnić od długości przerwy od poprzedniego kodu. Arduino samo z siebie liczy czas, jedną z funkcji jest millis() - zwraca czas w milisekundach (dla nas to akurat). Zeruje się po mniej więcej 50 dniach, więc to nie problem.

Kod:
unsigned long timestamp;

void loop()
{
   int value = mySwitch.getReceivedValue();
    if (value == 1653416)
    {
        unsigned long current = millis();
        resetAvailable();
        if (current - timestamp > 2000)  // 2 sekundy przerwy - przykladowo
        {
            stan = !stan;
            Serial.println(stan);
            digitalWrite(3, stan);
            // bez zadnych delay
        }
        else
        {
            // klawisz przytrzymany
        }
        timestamp = current;
    }
}

Dałem 2 sekundy minimalnej przerwy - kod powtarzania klawisza też może się zakłócić, więc trzeba więcej niż 1 brak kodu.
Stron: 1 2