Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

AVR, C++ - Niepoprawna praca pętli for

metalMANiu 05 Sie 2016 11:47 1026 10
  • #1 05 Sie 2016 11:47
    metalMANiu
    Poziom 16  

    Witam,
    mój problem polega na tym, że kilka linijek kodu zamieniłem na pętle for. Logicznie rzecz biorąc nie różnią się one od siebie niczym, ale mimo to wyświetlacz LCD pokazuje mi inne wyniki. Proszę spojrzeć:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    I z powyższym kodem wciskanie klawisza przypisanego do elementu tab_key[0] daje oczekiwany przeze mnie rezultat, tzn. na LCD co 0,3 sekundy wyświetlają się kolejno:
    0,00
    10000,00
    20000,00
    30000,00
    40000,00
    50000,00
    60000,00
    70000,00
    80000,00
    90000,00

    Proszę teraz spojrzeć na zgodny z powyższym kod, ale zapisany przy pomocy pętli for:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przyznacie, Koledzy, że jest to dokładnie ten sam kod? A jednak wyniki na wyświetlaczu przedstawiają się inaczej, tzn.:
    0,00
    10000,00
    20000,00
    30000,00
    39999,00
    49999,99
    59999,99
    69999,99
    79999,99
    89999,99

    Mikrokontroler to ATmega328 zamontowana w chińskim klonie Arduino nano (nigdy nie miałem przekonania do Arduino i jest to moje pierwsze starcie z tą platformą).
    Bardzo dziękuję za wszelką pomoc.
    Tradycyjnie rozdaję punkty pomocnym.
    Pozdrawiam!

    0 10
  • Pomocny post
    #2 05 Sie 2016 11:58
    grko
    Poziom 32  

    @metalMANiu Kod logicznie się różni. Otóż wynik wyrażenia: pow(10,(4-0)) jest znany na etapie kompilacji. Wynik tego jest wstawiany. Dla wersji z for wynik jest obliczany w czasie działania programu. Stąd te nieznaczne różnice w wyniku końcowym.

    0
  • #3 05 Sie 2016 12:20
    metalMANiu
    Poziom 16  

    No to wszystko jasne! Więc jak powinienem zapisać ten kod? Program nie jest jeszcze skończony i zależy mi na tym, żeby w razie jakichś modyfikacji robić jak najmniej podstawień.

    0
  • #4 05 Sie 2016 12:25
    grko
    Poziom 32  

    Pytanie co chcesz osiągnąć. w zasadzie nie powinieneś robić założeń typu:
    pow(10,(4-0)) == 10000

    powinieneś zakładać że:
    pow(10,(4-0)) == 10000 +/- epsilon

    Wynika to po prostu z arytmetyki liczb zmiennoprzecinkowych (w zasadzie tego, że nie każdą liczbę można zapisać w postaci zmiennoprzecinkowej)

    0
  • #5 05 Sie 2016 12:47
    tos18
    Poziom 36  

    Pytanie czy na pewno potrzebna Ci jest arytmetyka zmiennoprzecinkowa ?
    Czy może da się wszystkie obliczenia zrobić na liczbach całkowitych 100 razy większych używając typu long int ? Dopiero podczas wyświetlania wstawiając odpowiednio przecinek poprzez wyświetlenie części całkowitej z dzielenia zmiennej przez 100 wstawienie przecinka i wyświetlenie reszty z dzielenia przez 100.

    0
  • #6 05 Sie 2016 12:47
    metalMANiu
    Poziom 16  

    Zależy mi na tym, aby klawiaturą (drabinka rezystorowa) określać pewną liczbę.
    1. Mikrokontroler będzie miał za zadanie sterować tranzystorem.
    2. Tranzystor będzie przepuszczał impulsy z generatora na sterownik silnika krokowego.
    3. Mikrokontroler załączy tranzystor po wprowadzeniu liczby i wyłączy, gdy wykryje, że przepuszczona liczba impulsów zrównała się z wprowadzoną liczbą.

    Szczerze to nie potrzebuję liczb zmiennoprzecinkowych, ale użyłem double, ponieważ sprawia najmniej problemów z wyświetleniem na LCD przy użyciu gotowych bibliotek.

    0
  • #7 05 Sie 2016 14:55
    tos18
    Poziom 36  

    Jak widzisz nie koniecznie najmniej. Trzymam się najdalej jak to możliwe od liczb zmiennoprzecinkowych i nie narzekam.
    W jakim zakresie liczby będą zmieniane ?

    Dlaczego nie zadeklarujesz sobie tablicy
    unsigned int mnoznik[4]={1,10,100,1000}
    zamiast potęgowania ?
    wówczas:

    Code:

    for(int i=0;i<5;i++)
         {
          liczba_imp=liczba_imp+mnoznik[i]*tab_key[i];
         }





    Może uda Ci się zrezygnować z używania math.h

    Czy nie lepiej zamiast przepuszczać impulsy z generatora - generować je w programie (od razu zadaną ilość) ?

    1
  • #8 05 Sie 2016 16:37
    metalMANiu
    Poziom 16  

    tos18 napisał:
    Jak widzisz nie koniecznie najmniej. Trzymam się najdalej jak to możliwe od liczb zmiennoprzecinkowych i nie narzekam.
    Właśnie chciałem użyć int (zmiennoprzecinkowych nie potrzebuję w całym tym projekcie), ale trochę bałem się konwersji, tzn. że wszystko napiszę ze zmiennymi int a następnie nie poradzę sobie z konwersją do typu obsługiwanego przez ten LCD (20x4).

    tos18 napisał:
    W jakim zakresie liczby będą zmieniane ?
    Generalnie przez lwią część programu liczby nie wykroczą poza wartość 1024. Dopiero pod koniec programu wystąpi właśnie pętla, którą tutaj przedstawiłem i w wyniku jej działania można otrzymać liczbę o wartości maksymalnej 99999.

    Pomysł z tablicą {1,10,100,1000,...} dosłownie mnie powalił! To tak proste i banalne, że aż genialne. Czemu sam na to nie wpadłem? Nie wiem.

    tos18 napisał:
    Czy nie lepiej zamiast przepuszczać impulsy z generatora - generować je w programie (od razu zadaną ilość) ?
    Nie będzie lepiej, bo:
    - generator już powstał
    - częstotliwość impulsów ma być regulowana potencjometrem
    Nie miałem i pewnie nie będę miał na tyle zdolności, żeby złożyć te dwa moduły w jedno urządzenie. Musiałbym kazać procesorowi wykonywać kody dla dwóch urządzeń a ponadto generować impulsy o stałej szerokości zależnej od odczytu ADC.

    0
  • Pomocny post
    #9 05 Sie 2016 20:46
    tos18
    Poziom 36  

    Wszystko jest do zrobienia.

    Wyświetlanie int - potrafisz wyświetlać teksty lub pojedyncze znaki ? cyfra to też znak. Dla pojedynczej cyfry wystarczy dodać 48 do wartości i wysłać to jako znak.
    Narzędziem tu okaże się dzielenie i reszta z dzielenia.

    Częstotliwość potencjometrem - w jakim zakresie ?
    przecież masz w procesorku potężne narzędzia jakimi są liczniki sprzętowe oraz przerwania.

    0
  • #10 10 Sie 2016 11:06
    metalMANiu
    Poziom 16  

    tos18 napisał:

    Częstotliwość potencjometrem - w jakim zakresie ?
    przecież masz w procesorku potężne narzędzia jakimi są liczniki sprzętowe oraz przerwania

    Zakres od 300 Hz do 30 kHz, czyli bardzo niewielki.
    Wiesz Kolego, nie mam zbyt dużego doświadczenia z mikrokontrolerami. Lubię je, ale wykorzystuje ich 10% możliwości, bo zazwyczaj tyle mi zawsze wystarczało :)
    Dzięki za pomoc, tematu nie zamykam, bo projekt jeszcze nieskończony.

    0
  • #11 10 Sie 2016 14:14
    tos18
    Poziom 36  

    Ja też orłem w tym temacie nie jestem.
    Poszukaj programu kavrcalc. jest bardzo pomocny przy konfigurowaniu liczników - timerów sprzętowych.
    Ten zakres częstotliwości ogarnia z dobrą dokładnością licznik 16bitowy więc jeśli go nie używasz to masz jak znalazł.

    Tu jest kopalnia wiedzy:
    http://mikrokontrolery.blogspot.com/p/spis-tresci.html

    0