Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATmega8][Bascom] - Sprawdzenie programu - nie działa poprawnie

piotrek_nn 25 May 2013 07:51 4326 18
Computer Controls
  • #1
    piotrek_nn
    Level 10  
    Witam ,

    Zaczynam przygodę z programowaniem. Powiem tak samo wgranie programu robię tak samo i działa na 100, wgrywałem avrdude plus nakładka AVR O burn mat.

    Problem leży chyba w kodzie poniżej podaję kod ściągnięty żywcem z kursu basom z strony http://www.forbot.pl/forum/topics20/kurs-bascom-lekcja3-zaczynamy-programowac-vt1091.htm#6436

    objaw jest taki iż zaprogramuję program to dioda świeci , przyciski nie odpowiadają , jedynie co zmieniłem to rodzaj procesora na atmega.

    wg mnie program jest logiczny i tak prosty że aż wstyd się pytać o pomoc ale walczę już dwa dni i nic nie wychodzi, także proszę o pomoc.

    Code: basic4gl
    Log in, to see the code

    Poprawiłem tytuł na zgodny z regulaminem p. 3.1.15.
    LordBlick
    Kamery 3D Time of Flight - zastosowania w przemyśle. Darmowe szkolenie 16.12.2021r. g. 10.00 Zarejestruj się
  • Computer Controls
  • Helpful post
    #2
    alien_audio
    Level 21  
    Witam.
    1./ Jeżeli definiujemy piny jako wejście najlepiej używać instrukcji

    config pinb.0=input ' przycisk pierwszy
    config pinb.1=input ' przycisk drugi

    config portd.0=input ' pin sterujący diodą LED


    2./ Podłączenie przycisków do plusa zasilanie tak jak w tym kursie jest złe.
    przyciski powinny być podłączone do masy.
    Po prostu przycisk po wcisnięciu zwiera pin do masy a nie do plusa.
    Zwykle dla pewności stosuję się tak zwane podciągnięcie do plusa.
    Po prostu należy dołożyć rezystor 10K od pinb.0 do plusa zasilania
    i tak samo drugi rezystor od pinb.1 do plusa.

    Wtedy jak przycisk jest nie wciśnięty to PINB.0 i PINB1. na pewno
    ma poziom wyskoki a po wciśnięcie łączy pin do masy.
    Wtedy zadziała na 100%
  • #3
    piotrek_nn
    Level 10  
    dzięki ,

    tylko czy nie powinno być "config portd.0=output ' pin sterujący diodą LED'' ?
    i wg tego co napisałeś pwenie muszę zmienić warunki tak jak poniżej :
    if pinb.0=0 then 'jeżeli przycisk 1 wciśnięty
    portd.0=1 'zapal diode
    elseif pinb.1=0 then 'jeżeli przycisk 2 wciśnięty
    portd.0=0 'zgaś diodę
    endif 'koniec bloku warunkowego

    Teraz by mi pasowało , tak jak pisałem dopiero się uczę także proszę o sprawdzenie.
  • Helpful post
    #4
    alien_audio
    Level 21  
    Witam.
    Tak, masz racje powinno być tak jak opisałeś
    "config portd.0=output ' pin sterujący diodą LED''
    Tak samo jak zapis warunków o których piszesz i jest prawidłowy.
    Przetestuj te zmiany i zobaczymy.
  • Computer Controls
  • #5
    piotrek_nn
    Level 10  
    Jeszcze jedno mnie martwi , czy potrzebne jest ustalanie portów tzn stanów początkowych tak jak jest to opisane na przykładzie portd=&B0000000 i czy muszę zmienić stan spoczynkowy portów wejściowych na logiczne 1 portb=&B11111111 ?
  • Helpful post
    #6
    Wojtek001
    Level 15  
    1) Nie potrzebne jest ustawianie stanów spoczynkowych. Jeśli tego nie zrobisz będą miały domyślną wartość czyli chyba 0. Tak samo domyślnie wszystkie piny są ustawione jako wyjścia czyli w (DDRX.Y = 1 <- nazwa rejestru kierunkowego w BASCOMIE nie musisz się tym martwić).

    2)Co do drugiej części pytania powiem tak: najbardziej naturalnym rozwiązaniem jest ustawienie stanów spoczynkowych wejść na 1 (w ten sposób uruchamiasz wewnętrzne rezystory odciągające do plusa -tzw pull-up'y) i jednocześnie dawanie sygnału przez przyciski od masy. Poza tym nie wdze sensu używania elseif. ja bym napisał prosto:
    Code:

    if pinb.0 = 0 then portd.0 = 1
    if pinb.1 = 0 then portd.0 = 0


    Jeśli byś się uparł to mógłbyś dać stan spoczynkowy 0 ale po co? Wtedy musiał byś na zewnątrz poprowadzić rezystory podciągające bo inaczej kiedy przycisk byłby otwarty miał byś na wejściu tzw. trzeci stan logiczny.

    Teraz zastanówmy się nad drugim nieszczęśliwym scenariuszem, który jest teoretycznie możliwy. Mógłbyś chcieć inicjować zdarzenie zwieraniem przycisku do plusa. Wtedy musisz pwyłączyć wewnętrzne pull-upy do plusa czyli wpisać stan spoczynkowy 0 . Producenci AVR nie przewidzieli wewnętrznego podciągnięcia do masy więc musisz każde wejście podciągać do masy przez rezystor na zewnątrz.

    Generalnie zapamiętaj że w AVR i w ogóle w elektronice cyfrowej z reguły stosuje się sterowanie od masy. Tyczy się to zarówno wejść jak i wyjść tzn inicjacja jakiegoś zdarzenia powinna być wywoływana masą ale także gdy np. chcesz strować jakimś obciążeniem (np. diodą) to też powinieneś uruchamiać ją masą. Nie będę wgłębiał się w techniczne zagadnienia ale powiem ogólnie: AVRy dają możliwość wybrania funkcji danego pinu(wejscie/wyjście) i okupione jest to tym że właśnie stan 0 ma większą wydajność prądową.
    Dlatego zmień program na:
    Code:

    if pinb.0 = 0 then portd.0 = 0 'zapal
    if pinb.1 = 0 then portd.0 = 1 'zgaś

    i odwróć diodę.
  • Helpful post
    #7
    slx
    Level 19  
    Quote:
    Tak samo domyślnie wszystkie piny są ustawione jako wyjścia czyli w (DDRX.Y = 1

    Nie prawda - po resecie, domyślnie piny ustawione są jako wejścia - rejestry DDR = 0

    Quote:
    AVRy dają możliwość wybrania funkcji danego pinu(wejscie/wyjście) i okupione jest to tym że właśnie stan 0 ma większą wydajność prądową
    Znowu, nie prawda. Wyjścia w AVR są całkowicie symetryczne i mają taką samą wydajność prądową dla 0 jaki dla 1.
  • Helpful post
    #8
    Wojtek001
    Level 15  
    slx wrote:
    Quote:
    Tak samo domyślnie wszystkie piny są ustawione jako wyjścia czyli w (DDRX.Y = 1

    Nie prawda - po resecie, domyślnie piny ustawione są jako wejścia - rejestry DDR = 0

    Quote:
    AVRy dają możliwość wybrania funkcji danego pinu(wejscie/wyjście) i okupione jest to tym że właśnie stan 0 ma większą wydajność prądową
    Znowu, nie prawda. Wyjścia w AVR są całkowicie symetryczne i mają taką samą wydajność prądową dla 0 jaki dla 1.


    Co do domyślnych ustawień to tak jak napisałem na początku postu - nie byłem pewny. W każdym razie dziwnym jest że producent ustawia piny domyślnie jako wejścia żeby działały niepotrzebnie jako anteny - pewnie miał taki kaprys.

    Co do asymetryczności wyjść moje stanowisko jest nieugięte. Kolega chcąc podważyć moje zdanie powinien zapoznać się z odpowiednimi informacja a nie wytykać "nieprawde" nie zadawszy sobie nawet trudu aby zajrzeć do noty. Pan ma chyba jakieś przestarzałe informacje rodem z rodziny '51...
    ...bo w AVR w odróżnieniu od '51 jest możliwość zmiany funkcji pinu! Zagadnienie jest trochę bardziej skomplikowane i nie wytłumaczę w kilku słowach bez rysunków (tak jak już mówiłem - odsyłam do noty).
  • Helpful post
    #9
    piotrva
    VIP Meritorious for electroda.pl
    Wojtek001 wrote:
    W każdym razie dziwnym jest że producent ustawia piny domyślnie jako wejścia żeby działały niepotrzebnie jako anteny - pewnie miał taki kaprys.

    No akurat kaprys to nie jest.
    Pomyśl sobie co by było w sytuacji, gdyby piny były skonfigurowane jako jakiekolwiek wyjścia, a podczas startu procesora pod te WYJŚCIA podpięte były inne układy wymuszające jakiś stan (nie wiem, np. impulsatory, przyciski, kontaktrony, jakieś urządzenia będące masterami dla danego procesora) - podczas każdego startu aplikacji byłaby szansa na zwarcie (co prawda na ułamek sekundy, ale i tak to zwarcie) i w konsekwencji na uszkodzenie procesora lub innych układów.
    Na prawdę inżynierowie Atmela są nieco bardziej wykształceni niż my, a ustawienie wszystkich pinów w tryb wyjścia ze stanem niskim to w najgorszym przypadku AVR'a 13 instrukcji asemblera czyli 13 taktów procesora (mówię o ATMega2560, który ma 12 portów).
  • Helpful post
    #10
    slx
    Level 19  
    Wojtek001 wrote:
    W każdym razie dziwnym jest że producent ustawia piny domyślnie jako wejścia żeby działały niepotrzebnie jako anteny - pewnie miał taki kaprys.
    Co w tym dziwnego. Chyba w większości współczesnych mikrokontrolerów tak jest.

    Wojtek001 wrote:
    Co do asymetryczności wyjść moje stanowisko jest nieugięte. Kolega chcąc podważyć moje zdanie powinien zapoznać się z odpowiednimi informacja a nie wytykać "nieprawde" nie zadawszy sobie nawet trudu aby zajrzeć do noty.
    Może samemu warto do noty...
    Źródło: http://www.atmel.com/Images/Atmel-2486-8-bit-AVR-microcontroller-ATmega8_L_datasheet.pdf
    Rozdział I/O Ports Introduction strona 51
    Quote:
    Each output buffer has symmetrical drive characteristics with both high sink and source capability.

    Mało - no to jeszcze do obejrzenia wykresy - rozdział ATmega8 Typical Characteristics podpunkt Pin Driver Strength, strony 259,260 z podanego datasheeta.

    Wojtek001 wrote:
    Pan ma chyba jakieś przestarzałe informacje rodem z rodziny '51...
    To właściwie było by podsumowanie wcześniejszych informacji, na temat asymetryczności wyjść. Bo to właśnie w 51 były wyjscia typu otwarty dren, zwierające do masy.
  • Helpful post
    #11
    Wojtek001
    Level 15  
    Racja. Przepraszam jeśli kogoś uraziłem powyższymi informacjami, ale radził bym nie wiązać się z możliwościami wysysania gigantycznych prądów jakie dają nam AVRy. Powinniśmy pozostawać wierni tradycyjnej konwencji która mówi że sterujemy od strony masy - daje nam to zresztą możliwość wykorzystania starszych układów takich jak AT89C2051 w przypadku którego na pierwszej stronie noty można przeczytać że jest kompatybilny pod względem budowy z '51 i ma asymetryczne wyjścia.
  • Helpful post
    #12
    piotrva
    VIP Meritorious for electroda.pl
    Sterujemy od strony masy? Co to za dziwna filozofia. Wiadomo, że żarówki za pomocą AVR'a nie zasilimy, ale tu stan wysoki to stan wysoki, a nie jak w starodawnych 89C* zapewniany przez iluśtam omowy wewnętrzny pull-up...
  • #13
    piotrek_nn
    Level 10  
    Witam ,

    Dziękuje za odpowiedzi i dyskusję udało się wykonać układ i kilka innych na bazie tego programu. Teraz znowu proszę was o pomoc zacząłem bawić się z ADC czytałem help i nic mi z tego nie wychodzi chcę zmierzyć napięcie i wysłać je na wyświetlacz na symulacji pokazuje mi liczbę która się zmienia ale ma dużo cyfr po przecinku , jak zaprogramuję atmegę to już cuda mi na wyświetlaczu latają i od dwóch dni nie mam pomysłu jak to ogarnąć.

    wklejam kod jaki udało mi się wypocić. Miało być tak pięknie a wyszło jak zawsze :-(

    Code: basic4gl
    Log in, to see the code

    {code}=>{syntax} LordBlick
  • Helpful post
    #14
    alien_audio
    Level 21  
    Witam.
    Wybrałeś dość trudny temat na początek nauki
    1./ przed wysłaniem danej na wyświetlacz skasuj go instrukcją CLS.
    2./ pomiary z przetwornika różnią się, należałoby wykonać np. 10 pomiarów
    co 25ms i wyciągnąć średnią.
    3./ wynik aby był czytelny należy zaokrąglić do np. dwóch miejsc po przecinku
    można zastosować funkcję Fusing
  • Helpful post
    #15
    landy13
    Level 30  
    alien_audio wrote:
    1./ przed wysłaniem danej na wyświetlacz skasuj go instrukcją CLS.
    Błąd. Spowoduje to migotanie wyświetlacza. Należy użyć raczej "Locate".
  • #16
    piotrek_nn
    Level 10  
    ok dzięki odpowiedziom udało się ruszyć pomiar ADC, działa poprawnie i wymyśliłem sobie zrobić monitor stanu akumulatora .

    Nie mam pojęcia jak zrobić cos takiego aby wykonał warunek :

    If 13< nap < 14 then
    portb.1=1
    if nap<12,5 then `samo to działa
    portb.2=1

    jak dać przedział jako warunek próbowałem z or , and. Ręce opadają .

    Code: basic4gl
    Log in, to see the code
  • Helpful post
    #17
    landy13
    Level 30  
    piotrek_nn w listingu wrote:
    If 20 < We Or We < 23 Then

    Przecież We jest zawsze większe od 20 albo mniejsze od 23. Warunek więc zawsze jest spełniony. Gdy chcesz sprawdzić trafienie w okienko napisz:
    Code:
    If 20 < We And We < 23
    czyli We jest większe od 20 i jednocześnie mniejsze od 23.

    Na przyszłość zajrzyj do słownika co znaczy "or" a co "and".
  • Helpful post
    #18
    emarcus
    Level 38  
    piotrek_nn wrote:
    Witam ,

    wklejam kod jaki udało mi się wypocić. Miało być tak pięknie a wyszło jak zawsze :-(

    Code: basic4gl
    Log in, to see the code



    Ten twój kod jest oczywiście błędny.
    Po pierwsze, jeżeli stosujesz napięcie referencyjne wewnętrzne, to dla AtMega 8 wynosi ono 2.56V. Zatem poziom napięcia mierzonego podanego na dowolny pin ADC nie może przekroczyc tej wartości.
    Jeżeli jednak ten warunek masz spełniony, to sposób obliczenia tego napięcia masz błędny - winno byc:

    W = V * 0.0025
    (2.56/1024 = 0.0025) a nie 0.025
    Jest to jednak dośc duża różnica w pomiarze.

    Powiedzmy, zechcesz mierzyc napięcia wyższe niż referencyjne, wtedy wymagane jest stosowanie dzielnika napięcia (voltage divider), tak jak poniżej

    [ATmega8][Bascom] - Sprawdzenie programu - nie działa poprawnie

    I znów, rezystory R1 i R2 winny byc tak obliczone/'dobrane' aby napięcie U2 (do ADC) nie przekraczało napięcia referencyjnego przy założonym maxymalnym mierzonym napięciu U1. Dla poprawnego interpretowania wyniku pomiaru będzie koniecznośc określenia współczynnika: X = U1/U2 (dla wybranego dzielnika napięcia) i wtedy mierzone napięcie (U1) reprezentowane w twoim wzorze jako 'W' wyniesie:

    W = V * 0.0025 * X

    Quote:


    Nie mam pojęcia jak zrobić cos takiego aby wykonał warunek :

    If 13< nap < 14 then
    portb.1=1


    If Nap > 13 and Nap < 14 then
    set PORTB.1
    end if
    Powyższy twój zapis reprezentuje więcej niż jedno działanie arytmetyczne w jednej linii. Bascom ma zasadę:jedno działanie /1 linię

    Tu możesz pominąc process obliczania napięcia, w zamian możesz w instrukcjach warunkowych wstawic tylko wartości ADC odpowiadające tym przedziałom napięc.


    e marcus
  • #19
    piotrek_nn
    Level 10  
    Witam ,

    Temat rozwiązany dzięki uwagom poskładałem wszystko i działa jak należy, dodam iż część błędów i zmarnowanego czasu były symulacje i dodanie $sim, na symulacji wszystko titało a na procku już nie .