• 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
Problem z zerowaniem licznika
#1
Mam problem z bardzo prostą funkcją mianowicie kiedy kręcę enkoderem na wyświetlaczu co obrót dodawałem 1 a kiedy osiągnął pewną wartość to się zerwał, mniej więcej tak:

int suma = 0;

suma = suma + 1;
if (suma == 30){
suma = 0;
}

I to działało ale potrzebowałem miec większą rozdzielczość tego licznika więc użyłem float:

float suma = 0;

suma = suma + 0.10;
if (suma == 30.00){
suma = 0.00;
}


Niestety ten zapis nie działa licznik w ogóle się nie zeruje a w drugą stronę zaczyna pokazywać liczby ujemne. 

Proszę o pomoc.
 
Odpowiedź
#2
Może suma nie osiąga wartości 30?
Może osiąga, ale w tym czasie program jest gdzie indziej?
Ciężko stwierdzić nie mając schematu i kodu.

Na pewno zadziała: if(suma>30)
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#3
(10-09-2019, 08:29)Robson Kerman napisał(a): Może suma nie osiąga wartości 30?
Dla liczb zmiennoprzecinkowych == często nie mają zastosowania.

kataklysm napisał(a):potrzebowałem miec większą rozdzielczość tego licznika więc użyłem float:
W ten sposób nie zwiększysz rozdzielczości enkodera tylko sposób reprezentacji. W programach należy unikać liczb zmiennoprzecinkowych, zwłaszcza w powolnych AVR bez FPU. Jeśli dane chcesz reprezentować z rozdzielczością 0,01 użyj liczb stałoprzecinkowych. Jeśli chcesz zwiększyć rozdzielczość enkodera używaj obu zboczy sygnału z enkodera (rozdzielczość x 2) albo obu zboczy obu sygnałów (A i B) wtedy rozdzielczość zwiększysz 4 krotnie. Nie z każdym enkoderem to się uda, niektóre zatrzymują się tylko w takich pozycjach, że rozdzielczość można zwiększyć tylko 2 krotnie. Jeśli potrzeba jeszcze większa precyzja użyj innego enkodera, który daje więcej impulsów na obrót.
Porównanie trzeba realizować w procedurze przerwania od enkodera, w przeciwnym wypadku nie zawsze będzie wykonane poprawnie.
 
Odpowiedź
#4
Sprawdziłem to na takim przykładzie i stwierdziłem, że program nie działa tak jak pisał autor.



float suma = 0;
float a = 30;
float b = 0.5; //podstawiając za b = 0.5 program działa poprawnie dla b = 0.2 już nie

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

void loop() {


suma = suma + b;
Serial.println ( suma );
if (suma == a) // gdy tu zmieni się warunek na >= to działa poprawnie przy b = 0.1
{
Serial.println ( "suma = 30" );
suma = 0;
}
delay (100);
}

Dlaczego warunek == nie działa poprawnie dla float.

Sprawdziłem
Liczba 0.1 w systemie dwójkowym przyjmuje wartość przybliżoną a wielokrotna suma tej liczby, nie może być nigdy dokładnie 30 i stąd warunek (suma ==30) nigdy nie będzie spełniony. Trzeba dać warunek (suma >=30) lub (suma > 30).
 
Odpowiedź
#5
(10-09-2019, 11:57)Agregacik napisał(a): Sprawdziłem to na takim przykładzie i stwierdziłem, że program nie działa tak jak pisał autor.



float suma = 0;
float a = 30;
float b = 0.5; //podstawiając za b = 0.5 program działa poprawnie dla b = 0.2 już nie

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

void loop() {


suma = suma + b;
Serial.println ( suma );
if (suma == a) // gdy tu zmieni się warunek na >= to działa poprawnie przy b = 0.1
{
Serial.println ( "suma = 30" );
suma = 0;
}
delay (100);
}

Dlaczego warunek == nie działa poprawnie dla float.

Sprawdziłem
Liczba 0.1 w systemie dwójkowym przyjmuje wartość przybliżoną a wielokrotna suma tej liczby, nie może być nigdy dokładnie 30 i stąd warunek (suma ==30) nigdy nie będzie spełniony. Trzeba dać warunek (suma >=30) lub (suma > 30).


Zgadza się, ale < > działa więc sobie poradziłem. Dzięki wszystkim
 
Odpowiedź
#6
I dlatego wszędzie piszą, by unikać float'ów. W kodzie programu możesz mieć wartości 0-300 z typem np. int czy uint16_t, zastosowanie jest dużo szersze niż float, a gdy potrzeba pokazywać z przecinkiem użyć własną funkcją na kilka linijek.
Na liczby ujemne sam musisz napisać obsługę, że jak mniejsze od 0 to =0, dla typów bez znaku przekręci Ci licznik na koniec zakresu typu, np. 255 dla typu uint8_t.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości