Skocz do zawartości

Kurs Arduino II - #3 - syrena alarmowa, MOSFET w praktyce


Pomocna odpowiedź

Witam, piszę w sprawie problemów z kodem którego celem jest sprawdzanie głośności buzzera.

Po przejrzeniu wszystkich komentarzy pod artykułem (59 na czas pisania tego komentarza) zauważyłem że tylko najnowsze odnoszą się do problemów z tym przykładem. Dlatego dla informacji podaję wersje IDE z którego korzystam - Arduino 1.8.19 (aktualnie najnowsza wersja).

Miałem ten sam problem co @emiemi8 oraz @StefanekP. Postanowiłem się nieco bliżej temu przyjrzeć i przeanalizować co jest nie tak. A to wnioski do których doszedłem:

Pierwszym problemem jest błąd w samym kodzie który doprowadza do niezamierzonego zapętlenia się programu.

Krótkie przypomnienie czym i jak działają typy i zmienne: (tylko istotne dla przypadku elementy)

Typy określają rodzaj oraz zakres informacji które przechowywane są w zmiennych danego typu. Przekroczenie zakresu powoduje "przejście" na przeciwny koniec zakresu danego typu. Które nazywane jest przepełnieniem zmiennej.

Typ int (integers) w arduino uno zapisywany jest na 2 bajtach (16 bitów) co daje nam zakres od -32 768 do 32 757 a jej "przepełnienie" wygląda następująco:

 32 766 -> 32 767 -> -32 768 (górny zakres)

-32 767 -> -32 768 -> 32 767 (dolny zakres)

Więc przykład z artykułu nigdy nie zakończy pętli for dla zadanego warunku:

...
int czestotliwosc = 0; // zakres -32768 - 32767
for (czestotliwosc = 31; czestotliwosc < 65535; czestotliwosc++) { 
...

Jednak program powinien pomimo błędnego działania  dawać podobny efekt jedynie zakres częstotliwości powinien być krótszy o połowę. Tak się jednak nie dzieje w moim przypadku i jak to opisał @StefanekP

 

Dnia 16.09.2021 o 18:33, StefanekP napisał:

buzzer cały czas wydaje coraz cichsze dźwięki.

Postanowiłem to sprawdzić i dopisałem parę linijek żeby móc podejrzeć co się dzieje.

void setup() {
  pinMode(A5, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int czestotliwosc = 0;
  for (czestotliwosc = 31; czestotliwosc < 65535 ; czestotliwosc++){
    tone(A5, czestotliwosc);
    if(czestotliwosc % 1000 == 0){
      Serial.println(czestotliwosc);
    }
  }
}

A to jest tego wynik: ProgramLog.thumb.png.09bb16ef06b46c032cd4e533073589fa.png

porównanie w pętli dalej interpretuje zmienną "czestotliwosc" jako int i bierze 2bajty  oraz dopasowuje je do zakresu co powoduje zapętlenie się programu natomiast sama zmienna jest interpretowana już inaczej i (prawdopodobnie) zaczyna nadpisywać dalsze części programu co finalnie kończy się jego "wysypaniem" i zatrzymaniem. Takie działanie jest już powodowane błędem w samym oprogramowaniu. 

Co do samego przykładu z kursu aby zaczęło działać (błędnie) wystarczy przenieść deklaracje zmiennej poza obręb funkcji loop() co z jakiegoś powodu zaczyna poprawnie interpretować zmienną i wartości wypisywane zapętlają się zgodnie z zakresem 🤔

void setup() {
  pinMode(A5, OUTPUT);
  Serial.begin(9600);
}

int czestotliwosc = 0; // <- tutaj już działa
void loop() { 
  for (czestotliwosc = 31; czestotliwosc < 65535 ; czestotliwosc++){
    tone(A5, czestotliwosc);
    if(czestotliwosc % 1000 == 0){
      Serial.println(czestotliwosc);
    }
  }
}

Natomiast żeby program zaczął poprawnie działać należy dopisać modyfikator "unsigned" lub zmienić typ na "long":

void setup() {
  pinMode(A5, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  unsigned int czestotliwosc = 0;
  //lub
  // long czestotliwosc = 0;
  for (czestotliwosc = 31; czestotliwosc < 65535 ; czestotliwosc++){
    tone(A5, czestotliwosc);
    if(czestotliwosc % 1000 == 0){
      Serial.println(czestotliwosc);
    }
  }
}

Dodam jeszcze że błąd w oprogramowaniu nie tyczy się tylko złej definicji typu w metodzie loop() lecz jest bardziej złożony. Natomiast moje poszukiwania tutaj kończę.

Jako ciekawostkę powiem że z jakiegoś powodu poniższy kod powoduje poprawne przepełnianie się zmiennej "czestotliwosc" ale tylko jako wypisanie jej w konsoli bo po pewnym czasie dalej konsola się zawierza.

void setup() {
  pinMode(A5, OUTPUT);
  Serial.begin(9600);
  int test = 32767;
  Serial.println(test);
  test++;
  Serial.println(test);
}

void loop() {
  int czestotliwosc = 0;
  for (czestotliwosc = 31; czestotliwosc < 65535 ; czestotliwosc++){
    tone(A5, czestotliwosc);
    if(czestotliwosc % 1000 == 0){
      Serial.println(czestotliwosc);
    }
  }
}

 

  • Lubię! 2

@MaciejG dziękuję za analizę tematu, zapisałem, aby sprawdzić to podczas przyszłej aktualizacji kursu - sprawdzę co tam dokładnie się dzieje i dlaczego dopiero od niedawna pojawia się z tym problem.

  • 1 rok później...

Zacząłem dzisiaj z tym buzzerem, tematu nie skończyłem, bo co innego na głowie...

Ale pod ten dzisiejszy dzień sobie zagrałem. 😁

 

 

  • Lubię! 1

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...