logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

BASCOM Licznik impulsów 0-999 na ATtiny2313 - problem z cyfrą setek po 255

Justyniunia 16 Sty 2025 13:38 591 9
REKLAMA
  • #1 21395548
    Justyniunia
    Poziom 36  
    Posty: 4230
    Pomógł: 397
    Ocena: 1322
    Witam.

    Mam problem z prostym licznikiem impulsów 0-999
    Otóż, po przekroczeniu wartości 255 cyfra setek wskakuje na 0 a dziesiątki i jedności liczą się dalej.
    Co może być nie tak?

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 21395561
    Jacek Rutkowski
    Poziom 28  
    Posty: 1330
    Pomógł: 69
    Ocena: 275
    @ElektrodaBot powyżej 255 licznik źle zlicza dając ) co może być źle w tym kodzie:
    Kod: Text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #3 21395568
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8903
    Pomógł: 368
    Ocena: 960
    LABEL_AI_GENERATED
    Jacek Rutkowski napisał:
    (...) ' 5
    Data 250 ' 6
    Data 131 ' 7
    Data 251 ' 8
    Data 219 ' 9
    Wstępna ocena dostępnych informacji
    W kodzie widzimy dwa liczniki (Liczba_ok i Liczba_nok) zadeklarowane jako zmienne typu Word, a także tablice na cyfry (Cyfra_ok i Cyfra_nok) jako typ Byte. Z punktu widzenia zakresu wartości samych liczników (od 0 do 999) nie powinno to powodować błędów – Word pozwala zliczać nawet do 65535. W kodzie jest też zmienna Wyswietlacz (typu Byte), której wartość steruje tym, która cyfra akurat trafia na wyświetlacz (Select Case).

    Problem opisywany przez autora sprowadza się do niepoprawnego wyświetlania/obsługi licznika, gdy wartości przekraczają 255. Najczęściej w takim wypadku dwie rzeczy mogą być źródłem błędu:
    1. Zmienna Wyswietlacz jako Byte „zawija się” z 255 na 0.
    2. Obsługa tablic Lookup lub tablic cyfr (Cyfra_ok, Cyfra_nok) nie uwzględnia wartości spoza założonego zakresu.

    Z analizy kodu wynika, że Liczba_ok i Liczba_nok są resetowane po przekroczeniu 999, więc same nie wyjdą poza zakres 0–999. Kluczem jest sprawdzenie, jak zachowuje się Wyswietlacz oraz czy odwołanie do tabeli Kody7seg ma zawsze poprawny indeks.

    Bezpośrednia odpowiedź na pytanie
    Najbardziej prawdopodobną przyczyną błędnego zachowania powyżej 255 jest to, że zmienna Wyswietlacz (typu Byte) przepełnia się i wraca do 0, a warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 tego nie przechwytuje (bo 0 wcale nie jest „>6”). W efekcie może pojawiać się nieoczekiwane zachowanie w sekcji Select Case – zamiast wartości 1..6 (dziesiątki/hornset?), program może trafić na Wyswietlacz=0 lub inne błędne wartości.

    Szczegółowa analiza problemu
    1. Zmienna Wyswietlacz jest wykorzystywana do multipleksowego wyświetlania kolejnych cyfr:
    » W przerwaniu Timer0:
    Incr Wyswietlacz : If Wyswietlacz > 6 Then Wyswietlacz = 1
    Po przekroczeniu wartości 6 Wyswietlacz wraca do 1, więc w normalnych warunkach pozostaje zawarte w przedziale 1..6.

    2. Jeśli jednak Wyswietlacz dojdzie do 255 i zostanie „inkrementowany” na wartość 256, to w typie Byte wartość ta fizycznie zawija się na 0 (256 w 8-bitach daje nadmiar, który „zetnie się” na 0). Warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 już go wtedy nie skoryguje, bo 0 nie jest „> 6”. W efekcie w Select Case Wyswietlacz może przyjąć wartość 0, która nie została obsłużona w kodzie:
    Select Case Wyswietlacz
    Case 1: ...
    Case 2: ...
    Case 3: ...
    Case 4: ...
    Case 5: ...
    Case 6: ...
    End Select
    Brakuje Case 0, przez co program może wykonywać się z nieprzewidywalnym skutkiem (np. ustawia niewłaściwe sygnały na porcie, co wizualnie może wyglądać jak „)”).

    3. Dzięki temu, że Liczba_ok oraz Liczba_nok to typ Word, obsługa zakresu 0..999 na poziomie arytmetyki jest poprawna – problem tkwi raczej w mechanizmie wyświetlania.

    Aktualne informacje i trendy
    Choć w wielu projektach tak prosta zmienna typu Byte do przełączania multipleksu wystarcza, coraz częściej stosuje się bardziej jednoznaczne zapisy (np. operator Mod lub pętlę for) albo mechanizmy chroniące przed przepełnieniem. Te praktyki są szczególnie popularne w nowszych implementacjach, aby kod był bezpieczniejszy i łatwiejszy w utrzymaniu.

    Wspierające wyjaśnienia i detale
    • Jeżeli wartość zmiennej Byte przekroczy 255, następuje przepełnienie, a faktycznie w rejestrze ląduje reszta z dzielenia przez 256 (256 % 256 = 0).
    • Z tego powodu warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 nie chroni, gdy Wyswietlacz przejdzie na 0.

    Aspekty etyczne i prawne
    Nie występują tu szczególne kwestie etyczne czy prawne; problem dotyczy prostego fragmentu kodu w Bascom.

    Praktyczne wskazówki
    • Najprostszym rozwiązaniem jest zmodyfikowanie sekcji obsługi Wyswietlacz tak, by zabezpieczyć się przed wartością 0:
    Incr Wyswietlacz
    If Wyswietlacz = 0 Then
    Wyswietlacz = 1
    End If
    If Wyswietlacz > 6 Then
    Wyswietlacz = 1
    End If

    • Alternatywnie można bezpośrednio nadać Wyswietlaczowi wartość w oparciu o operator Mod:
    Wyswietlacz = (Wyswietlacz Mod 6) + 1

    • Jeżeli ktoś woli powiększyć zakres zmiennej Wyswietlacz tak, by zapobiec przepełnieniom przy długim działaniu programu, można zadeklarować ją jako typ Word:
    Dim Wyswietlacz As Word

    Ewentualne zastrzeżenia lub uwagi dodatkowe
    W innych fragmentach kodu (np. rozbijanie liczby na cyfry) zdefiniowane typy Byte, Word czy tablice wyglądają prawidłowo dla zakresu 0..999, więc nie muszą być modyfikowane, o ile faktycznie chcemy wyświetlać tylko do 999. Gdyby docelowo licznik miał zliczać większe wartości (powyżej 9999 itp.), należałoby rozbudować zarówno tablice, jak i wyświetlanie.

    Sugestie dalszych badań
    • Upewnij się, że kod przerwania Timer0 nie konkuruje o zasoby z pętlą główną (czasem warto wyłączyć przerwania na czas operacji na zmiennych współdzielonych).
    • Warto dodać wyświetlanie tymczasowych wartości w monitorze lub symulatorze Bascoma, by na bieżąco sprawdzać, co dzieje się z Wyswietlaczem i licznikami.

    Krótkie podsumowanie
    Najprawdopodobniej za błędne wyświetlanie odpowiada zmienna Wyswietlacz, która jako Byte zawija się na 0 po przekroczeniu 255. Warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 nie „łapie” zera, więc program wchodzi w nieobsłużoną ścieżkę. Rozwiązaniem jest zabezpieczyć kod przed 0 (np. przez dodatkowy warunek lub operator Mod) albo zmienić Wyswietlacz na typ Word.

    Pytania do użytkownika (jeśli potrzebne)
    • Czy obserwujesz dokładnie ten sam błąd w chwili, gdy licznik teoretycznie powinien dojść do wartości 256, czy błąd pojawia się już wcześniej?
    • Czy weryfikowałeś w symulatorze lub przez wyświetlanie wartości zmiennej Wyswietlacz, jaka jest jej rzeczywista zawartość w momencie wystąpienia błędu?

    Pozdrawiam i życzę powodzenia w dalszych pracach! Jeśli pojawią się dodatkowe pytania lub wątpliwości, chętnie pomogę w ich rozwiązaniu.
    Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
  • REKLAMA
  • #4 21395583
    Kuniarz
    Moderator Projektowanie
    Posty: 4520
    Pomógł: 371
    Ocena: 826
    Nasza sztuczna inteligencja słusznie zauważyła możliwość przekręcania się zmiennej "Wyswietlacz" ale to nie to...
    Przyjrzałbym się $swstack = 8 czy nie zwiększyć np na 16. Kolejny trop to przeliczanie tutaj:
    Kod: Arduino
    Zaloguj się, aby zobaczyć kod


    Na próbę można w tablicę liczb wpisać 999 i zobaczyć czy się wyświetli poprawnie
    Pomogłem? Kup mi kawę.
  • Pomocny post
    #5 21395597
    inot
    Poziom 38  
    Posty: 3625
    Pomógł: 450
    Ocena: 819
    Bascom zawsze używa metody obliczeniowej, która należy do zmiennej wynikowej. Oznacza, że w tym przypadku Bascom wykonuje obliczenia na bajtach. Wartość obliczeniowa2 jest typu Word.
    Czyli
    (1) = Liczba_ok / 100

    zmienna Liczba_ok traktowana jest jako byte.
    Jedynym sposobem na konwersję jednego typu na inny jest po prostu przypisanie go w ten sposób
    Wartość obliczona2 = Wartość obliczona1.
  • #6 21395607
    Justyniunia
    Poziom 36  
    Posty: 4230
    Pomógł: 397
    Ocena: 1322
    W procedurze wyświetlania zapisany jest warunek wygaszanie zer nie znaczących, a po przekroczeniu 255 cyfra setek wyświetla 0 i ono nie gaśnie.
    Czyli zmienna liczy się nadal, co wskazuje rzeczywiście na problem z wyświetlaniem a nie liczeniem.

    Po wpisaniu "na twardo"
    Liczba_nok = 987
    Liczba_ok = 654
    wyświetlacz pokazuje 287 i 154
  • REKLAMA
  • Pomocny post
    #7 21395688
    inot
    Poziom 38  
    Posty: 3625
    Pomógł: 450
    Ocena: 819
    Wydaje mi się, że kompilator nie ma problemu z funkcją "mod" (dlatego też dwie ostatnie cyfry się zgadzają), tylko przy dzieleniu zmiennej typu word, dającej zmienną typu byte jako wynik.
  • #8 21395713
    Justyniunia
    Poziom 36  
    Posty: 4230
    Pomógł: 397
    Ocena: 1322
    Możesz mi napisać kawałek kodu z tym MOD jak to powinno wyglądać?
    Tylko użyj proszę nazw zmiennych jakich ja używam, OK?
    Ze 100x robiłam liczniki liczące setki, czy tysiące i nigdy nie było problemu.
    Dłuższa przerwa z BASCOM i wywalanie z komputera niepotrzebnych programów się właśnie zemściło...
  • #10 21395749
    Justyniunia
    Poziom 36  
    Posty: 4230
    Pomógł: 397
    Ocena: 1322
    Jest!
    Word nie, ale integer rozwiązał sprawę.

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik zgłosił problem z licznikiem impulsów 0-999 na mikrokontrolerze ATtiny2313, który po przekroczeniu wartości 255 wyświetla cyfrę setek jako 0, podczas gdy dziesiątki i jedności działają poprawnie. Analiza kodu wskazuje, że zmienne typu Byte mogą powodować "zawijanie się" wartości, co prowadzi do błędów w wyświetlaniu. Sugerowane rozwiązania obejmują zmianę typu zmiennych na Word oraz sprawdzenie obliczeń związanych z dzieleniem i operacjami modulo. Po wprowadzeniu poprawek, takich jak zmiana typu zmiennych na Integer, problem został rozwiązany.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA