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.

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

piotrek_nn 25 Maj 2013 07:51 4077 18
  • #1 25 Maj 2013 07:51
    piotrek_nn
    Poziom 9  

    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.

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Poprawiłem tytuł na zgodny z regulaminem p. 3.1.15.
    LordBlick

    0 18
  • Pomocny post
    #2 25 Maj 2013 08:55
    alien_audio
    Poziom 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%

    0
  • #3 25 Maj 2013 09:29
    piotrek_nn
    Poziom 9  

    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.

    0
  • Pomocny post
    #4 25 Maj 2013 09:46
    alien_audio
    Poziom 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.

    0
  • #5 25 Maj 2013 11:04
    piotrek_nn
    Poziom 9  

    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 ?

    0
  • Pomocny post
    #6 25 Maj 2013 12:05
    Wojtek001
    Poziom 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ę.

    0
  • Pomocny post
    #7 25 Maj 2013 19:51
    slx
    Poziom 18  

    Cytat:
    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

    Cytat:
    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.

    0
  • Pomocny post
    #8 25 Maj 2013 20:42
    Wojtek001
    Poziom 15  

    slx napisał:
    Cytat:
    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

    Cytat:
    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).

    -1
  • Pomocny post
    #9 25 Maj 2013 21:20
    piotrva
    Moderator Mikrokontrolery

    Wojtek001 napisał:
    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).

    0
  • Pomocny post
    #10 25 Maj 2013 21:48
    slx
    Poziom 18  

    Wojtek001 napisał:
    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 napisał:
    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
    Cytat:
    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 napisał:
    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.

    0
  • Pomocny post
    #11 25 Maj 2013 22:08
    Wojtek001
    Poziom 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.

    -1
  • #13 28 Maj 2013 22:45
    piotrek_nn
    Poziom 9  

    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 :-(

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    {code}=>{syntax} LordBlick

    0
  • Pomocny post
    #14 29 Maj 2013 19:26
    alien_audio
    Poziom 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

    0
  • Pomocny post
    #15 29 Maj 2013 21:28
    landy13
    Poziom 29  

    alien_audio napisał:
    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".

    0
  • #16 29 Maj 2013 22:31
    piotrek_nn
    Poziom 9  

    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ą .

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #17 29 Maj 2013 23:03
    landy13
    Poziom 29  

    piotrek_nn w listingu napisał:
    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".

    0
  • Pomocny post
    #18 30 Maj 2013 06:26
    emarcus
    Poziom 34  

    piotrek_nn napisał:
    Witam ,

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

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod



    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

    Cytat:


    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

    0
  • #19 02 Cze 2013 22:42
    piotrek_nn
    Poziom 9  

    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 .

    0