Skocz do zawartości

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


Komentator

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
Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.