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

Problemik w banalnym programiku (Bascom AVR)

Roko 17 Paź 2008 23:02 2571 15
  • #1 5642450
    Roko
    Poziom 11  
    Mam oto taki problemik.
    Programik jest banalnie prosty i działa mniej więcej tak:
    Gdy zmienna (Wart) nie osiągnie 30 zostaje załączone wyjście Portc.0 .
    Po osiągnięciu tej wartości wyjście zostaje wyłączone i załącza się kolejne czyli Portc.1 .
    Podprogram kończy się na wyłączeniu wyjścia Portc.3 .
    To wszystko jest proste.
    Problemem dla mnie jest natomiast zrobienie opóźniena np. 1 sek. przed załączeniem poszcze-
    gólnych wyjść.

    np:
    wart < 30 załącz wyjście Portc.0 po około 1sek.
    wart > 30 i wart < 60 wyłącz wyjście Portc.0 po około 1sek. załącz Portc.1
    wart > 60 i wart < 90 wyłącz wyjście Portc.1 po około 1sek. załącz Portc.2
    wart > 60 i wart < 90 wyłącz wyjście Portc.2 po około 1sek. załącz Portc.3

    Wartość zmiennej (Wart) zwiększa się dopiero po załączeniu jednego z wyjść Portc.0 ..Portc.3 .

    Wstawienie instrukcji Wait 1 jest prostym rozwizaniem, ale zależy mi na płynności głównej
    pętli programu Do-Loop w której jest odczyt zmiennej (Wart), obsługa klawiatury, wyświetlanie
    wyniku i inne. Instrukcja Wait zatrzymuje wykonywanie pętli i ją dyskwalifikuje w tym przypadku.
    Próbowałem do opóźnień użyć procedury przerwania od Timer0, która ładnie dziala tylko nie potrafię
    załączać (Start Timer0) i zatrzymywać Timera0 w odpowiednich miejscach podprogramu Doza.

    Może Ktoś z Kolegów bardziej biegłych w Bascom mi coś podpowie. Może muszę przebudować podprogram
    Doza na procedury i je po kolei wywoływać z wcześniejszym opóżnieniem, ale nie bardzo wiem jak.
    Za podpowiedzi z góry dziękuję.

    Poniżej moje wypociny:


    $regfile = "m8def.dat"
    $crystal = 16000000
    
    Config Lcdbus = 4
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Przerwanie_timer
    Enable Timer0
    Timer0 = 6                                                'wartość początkowa timera
    'Stop Timer0
    
    Config Portc = Output
    Config Pinb.0 = Output                                    'linia pb.0 jako wyjscie 
    Dim Licznik As Integer
    Dim Wart As Single
    Dim Flaga As Bit
    Led Alias Portb.0                                         'alias dla wyjscia b.0
    
    Licznik = 0                                               'wyzerowanie zmiennej licznikowej
    Flaga = 0
    Portc = 0
    
    Enable Interrupts
    
    '******************* Główna pętla wyświetlania *********************
    Do
    'obsługa klawiatury
    'odczyt zmiennej (Wart)
    .
    .
    Gosub Doza
    Loop
    
    
    Doza:
    If Wart < 30 Then
    'If Flaga = 1 Then
       Set Portc.0                                                 'zał. wyjśćie
       Portc = Portc And &B00000001                                'wył. pozostałe wyjścia (zab.)
       'Flaga = 0
    Elseif Wart > 30 Then
       Reset Portc.0                                               'wył. wyjście
       'Flaga = 1
       'Start Timer0
     End If
    'End If
    
    If Wart > 30 And Wart < 60 Then
    'If Flaga = 1 Then
       Set Portc.1
       Portc = Portc And &B00000010
       'Flaga = 0
    Elseif Wart > 60 Then
       Reset Portc.1
       'Flaga = 1
       'Start Timer0
     End If
    'End If
    
    If Wart > 60 And Wart < 90 Then
    'If Flaga = 1 Then
       Set Portc.2
       Portc = Portc And &B00000100
       'Flaga = 0
    Elseif Wart > 90 Then
       Reset Portc.2
       'Flaga = 1
       'Start Timer0
     End If
    'End If
    
    If Wart > 90 And Wart < 120 Then
    'If Flaga = 1 Then
       Set Portc.3
       Portc = Portc And &B00001000
       'Flaga = 0
    Elseif Wart > 120 Then
       Reset Portc.3
       'Flaga = 1
     End If
    'End If
    
    Return
    
    
    '********************* Przerwanie od Timer0 ******************
    
    Przerwanie_timer:                                           
      Counter0 = Counter0 + 6                                  'ustawienie początkowej wartości timera0 
      Incr Licznik                                             'zwiększenie licznika
      If Licznik = 1000 Then                                   'jeśli zmienna licznik równa 1000 (około 1sek.)
        Toggle Led                                             'sygnalizacja czy upłynął czas
        Licznik = 0                                            'wyzeruj zmienną licznik
        Flaga = 1                                              'ustaw flagę
        Stop Timer0                                            'wył. timer0
      End If                                                    
    Return                                                     'powrót z przerwania
    
    End                                                        'end program


    Sory za przejżystość kodu.
    ROKO
  • #2 5642949
    ZbeeGin
    Poziom 39  
    Skup się na znaczniku FLAGA. Jeśli dany warunek z WART się spełnił to najpierw sprawdzaj czy FLAGA=0 i wtedy START TIMER co oznaczać będzie: "warunek spełniony -> licznik ma zacząć liczyć". Jeśli zaś FLAGA = 1 to STOP TIMER i dopiero teraz ustaw wyjścia bo licznik wykonał swoje zadanie.
    Możesz dodać kolejną flage LICZY (lub sprawdzać czy LICZNIK = 0), która będzie dokładnie precyzować kiedy licznik liczy i nie podejmować akcji ciągłego wznawiania licznika przez START TIMER.

    Czy może dojść do sytuacji, gdy z poprzedniego warunku licznik został wystartowany, a pojawił się w międzyczasie spełniony kolejny warunek? Co wtedy masz zamiar zrobić?
  • #3 5643166
    Roko
    Poziom 11  
    Cześć.
    Dzięki ZbeeGin za odzew.

    Co do Twojego pytania:
    Czy może dojść do sytuacji, gdy z poprzedniego warunku licznik został wystartowany, a pojawił się w międzyczasie spełniony kolejny warunek? Co wtedy masz zamiar zrobić?

    Jeszcze się nie zastanawiałem. Prawdopodobnie do takiej sytuacji nie dojdzie ponieważ, zmienna Wart jest przyrostowa (zawsze się zwiększa po załączeniu któregoś z wyjść i kiedy dojdzie do załączenia ostatnigo składnika Timer zostanie zatrzymany na stałe.

    Woli wyjaśnienia to 'coś' steruje układem dozowania materiałami sypkimi.
    Po kolei otwierają się spusty pneumatyczne sterowane elektrozaworami. Składników jest 8 i wszystkie trafiają na wagę, która wysyła wartość do zmiennej WART. Układ działa fajnie, ale jest niedoskonały. Uwzględnia co prawda przesypy (to co zostaje w locie po zamknięciu spustu), ale odbywa się to zbyt szybko między kolejnymi naważeniami i przy lekko zmiennych warunkach (wilgotność materiału) są lekkie odchyłki. Najgorsze jest to, że ciężko jest zaobserwować czy jest wszystko ok. Z tego względu potrzebne jest opóźnienie między poszczególnymi dozami. W tej chwili jest to rozwiązane w dość drogi sposób, a mianowicie użyłem aż 8 układów przekaźników czasowych (~100zł 1szt.) z których chcę zrezygnować.
    W pierwszej wersji układy czasowe zrobiłem na NE556 + przekaźnik, ale układ był bardzo rozbudowany i doszedłem do wniosku po co budować dodatkowe układy jak można to wszystko załatwić programowo.
    Z tego wziął się ten post z prośbą o pomoc.
    Odnośnie Twojej podpowiedzi to już kombinowałem ze sprawdzaniem Flaga=0 i Flaga=1 i nic z tego nie wyszło. W pewnym momencie przyszła mi taka myśl czy na jednej zmiennej Flaga jest to możliwe.
    Pokombinuje jeszcze trochę i dam znać co i jak. Przebuduję podprogram.
    Dzięki serdeczne za podpowiedź.
    ROKO.

    Dodano po 5 [godziny] 12 [minuty]:

    Doszedłem do czegoś takiego:

    Doza:
    If Wart < 30 Then
       Portc = Portc And &B00000001                              'wył. wszystkie oprócz pierwszego
    If Cykl = 0 Then
       Start Timer0
    End If
    If Flaga = 1 Then
       Set Portc.0
       Flaga = 0
    End If
    End If
    
    If Wart > 30 And Wart < 60 Then
       Portc = Portc And &B00000010                              'wył. wszystkie oprócz drugiego
    If Cykl = 1 Then
       Start Timer0
       End If
    If Flaga = 1 Then
       Set Portc.1
       Flaga = 0
    End If
    End If
    
    If Wart > 60 And Wart < 90 Then
       Portc = Portc And &B00000100                              'wył. wszystkie oprócz trzeciego
    If Cykl = 2 Then
       Start Timer0
       End If
    If Flaga = 1 Then
       Set Portc.2
       Flaga = 0
    End If
    End If
    
    If Wart > 90 And Wart < 120 Then
       Portc = Portc And &B00001000                               'wył. wszystkie oprócz czwartego
    If Cykl = 3 Then
       Start Timer0
       End If
    If Flaga = 1 Then
       Set Portc.3
       Flaga = 0
    End If
    End If
    
    If Wart > 120 Then
       Portc = Portc And &B00000000                               'wył. wszystkie
       Flaga = 0
       Cykl = 0
    End If
    
    Return
    
    
    '********************* Przerwanie od Timer0 ******************
    
    Przerwanie_timer:                                           
      Counter0 = Counter0 + 6                             'ustawienie początkowej wartości timera0 
      Incr Licznik                                        'zwiększenie licznika
      If Licznik = 1000 Then                              'jeśli zmienna licznik równa 1000 (około 1sek.)
        Toggle Led                                        'sygnalizacja czy upłynął czas
        Licznik = 0                                       'wyzeruj zmienną licznik
        incr cykl                                         'ilość cykli 1sekundowych
        Flaga = 1                                         'ustaw flagę
        Stop Timer0                                       'wył. timer0
      End If                                                    
    Return                                                'powrot z przerwania
    
    End                                                   'end program



    Wszystko działa ale......
    Podprogram działa tylko do przodu to znaczy:
    - jeżeli jest przy kolejnym naważeniu i przekroczy 'próg' wartości zmiennej WART np. 60 i wartość tą zmniejszymy np. na 58 to nie wyłączy aktualnego Portc.2 i nie załączy poprzedniego Portc.1 chociaż jest mniej niż 60 . Czyli wyszedł taki układ progowy tylko wartość większa.

    W moim wypadku może to zda egzamin chociaż dobrze by było żeby 'podprogram potrafił się cofnąć'. W moim urządzeniu materiał nie sypie się z jednakową prędkością i może się zdarzyć, że po uwzględnieniu przesypu (wyprzedzenie zamknięcia spustu) podczas spustu materiał uderzy z większą siłą w platformę wagi i będzie wskazanie np. 62, a po uspokojeniu platformy okaże się, że jest 58 i wówczas należałoby dosypać do wartości nie mniej niż 60.

    Może jest jakiś inny, może bardziej skąplikowany sposób na rozwiązanie mojego problemu. Z doświadczenia wiem, że jak temat prosty tym bardziej się komplikuje.

    Za podpowiedzi dzięki nawet te teoretyczne.
    Roko.
  • #4 5655381
    szun
    Poziom 19  
    Temat zainteresował mnie kiedyś podobny problem rozgryzałem
    mam pytanie ile czasu trwa zasyp jednego komponentu i czy to wszystko spada na jedną wagę czyli jeśli dobrze zrozumiałem waga wzrasta po każdym zsypie ?
  • #5 5655827
    Roko
    Poziom 11  
    Cześć.
    Jak się cieszę, że oprócz ZbeeGin jest jeszcze Ktoś kogo interesują trochę poważniejsze rzeczy niż budowa 'Zegarków' sory jeżeli kogoś uraziłem.
    Dzięki szun za zaiteresowanie i myślę, że ważnym tematem jest dozowanie różnych środków.
    Jest to moim zdaniem podstawa w produkcji (mieszalnie) jak też w innych gałęziach np. w domu (dozowanie środków spożywczych dla swoich pupili podczas np. nieobecności właściciela) przykładów by można mnożyć.

    krótki opis mojego urządzenia:

    - dozowanie do 12 składników (może być więcej w zależności od potrzeb)
    - przechowanie do 100 receptur w pamięci.
    - wpisy do receptury dowalnych wartości naważek dla dowolnych składników np. Program 1 , składnik A - 40kg, przesyp A - 3kg , składnik - D - 25kg, przesyp B - 1.6kg .. itd.
    - czasy opóźnień niędzy naważkami poszczególnych składników 1- 255 sek.

    Na Twoje pytanie odpowiem tak.
    1. zasyp jednego składnika trwa różnie 20-40 sek.(im wolniej tym dokładniej)
    2. wszystko trafia do jednego zbiornika, który jest wagą(stoi na platformie).

    Wszystko działa wyśmienicie czyli :
    -komunikacja z wagą po rs.
    -zapis i odczyt receptur (programów) na ukończeniu pisanie procedur.
    -sterowanie poszczególnymi spustami.

    Brak jest jeszcze programowego układu opóźnień czasowych między poszczególnymi naważkami. I z tym mam największy problem.
    Jak podałem w ostatnim poście procedura ta działa, ale jest niedoskonała chociaż trochę ją poprawiłem i jest całkiem, całkiem. Brak jak dla mnie 100% satysfakcji.
    Dlatego mam pytanie czy można inaczej rozwiązać ten problem (programowo) bo sprzętowo to wiadomo na wyjściach poszczególnych składników układy czasowe. Ja zastosowałem KOL 311 (szwajcarskie), ale ich cena trochę odstrasza 12x100zł = 1200zł+trochę miejsca to zajmuje i ma co nawalać oraz jest czym kręcić. W życiu różnie bywa, a ciekawość Ludzka jest jaka jest i kończy się zazwyczaj telefonem ("coś pracownik pokręcił i przestało działać czy może Pan przyjechać") Pół biedy jak jest to parę km. Z tego też względu warto to wszystko załatwić prockiem, który i tak już jest, a kosztuje 8zł. Dodatkowo można jeszcze zabezpieczyć receptury hasłem dla osób postronnych.

    Dzięki za zainteresowanie i czekam na dyskusję.
    Roko.
  • #6 5656196
    crazy_phisic
    VIP Zasłużony dla elektroda
    :arrow: Roko, próbowałeś dodać pewną histerezę do pomiarów wagi? W tym momencie masz na sztywno podane granice po przekroczeniu których - jak sam zaznaczyłeś - program nie potrafi skorygować wagi przesypanego materiału. Dobrze byłoby dodać mu "kilku punktów swobody" i rozbić pomiar na przedziały (coś a'la pomiar zgrubny i dokładny). Dodatkowo, z uwagi na powtarzalność fragmentów programu warto przekształcić je w funkcję pobierającą tylko określone parametry - a stąd już bardzo niedaleko do pełnego sukcesu ;) Ujednolicona funkcja dozowania pozwala bardzo łatwo zarządzać zwłoką czasową pomiędzy dosypywaniem/korekcją wagi i przejściem do następnego składnika.
  • #7 5656307
    Roko
    Poziom 11  
    Witam ponownie i dzięki crazy_phisic za zainteresowanie.

    Problemik jest troszeczkę innej natury, a mianowicie, żeby zaobserwować przesyp (to ile za dużo wpadnie na wagę) trzeba zrobić opóźnienie przed następnym dozowaniem składnika 1-5 sekund również po to, żeby szalka wagi (platforma) się ustabilizowała.
    Wydaje mi się, że histerezę można by pominąć i napisać procedurę obliczającą odchyłkę procentową od ilości zadanej do ilości otrzymanej.
    Z doświadczenia wiem, że każda receptura (kleje, spożywcza czy inna) mają zachowaną dość dużą tolerancję odchyłki.
    Przykład 1:
    Marka betonu np. b-15
    piasek - 200kg
    żwir - 1450kg
    cement - 280kg
    woda - 100 do 130 litrów

    Według tej przykładowej receptury odchyłka 10% poszczególnych składników jest dość znaczna.
    piasek - 20kg
    żwir - 145kg
    cement - 28kg
    z wodą to różnie w zależności od zastosowania.
    Przykład 2:
    Klej do płytek ceramiczych:
    piasek - 650kg
    cement - 330kg
    chemia - 20kg

    Wegług powyższych chemia powinna być naważona ze znaczną dokładnością +/- 1kg i tą dozujemy nie grawitacyjnie lecz przenośnikami ślimakowymi, które mają teoretycznie zawsze ten sam niewielki przesyp.
    Dla chemii odchyłka +/- 1kg to 5% , 5% dla piasku to 37.5kg, a cementu 16.5kg czyli wartości dość znacznie odbiegające od ustalonych, a jednak nie wpływające jeszcze na jakość wyrobu.
    W praktyce uzyskuję odchyłki rzędu 1-5kg na piachu (650kg w czasie 40 sekund) cement 0.2- 0.6kg (350kg w czasie 1-1.5 minuty) chemia 0.1-0.3kg (w czasie 40 sekund).

    To wszystko co podałem jest trochę nie na temat i służyć może wyłącznie do zapoznania z systemem dozowania jako takim. Metod dozowania jest sporo jest nawet taki inteligentny coś ala PID.

    Generalnie chodzi mi o to jak napisać procedurę opóźniającą dozowaniem poszczególnych składników. Jest to potrzebne oprócz tego że podglądamy jakie są odchyłki poszczególnych składników na wadze to jeszcze oszczędzamy spusty od uszkodzeń, a mianowicie gdy wyłączy się dany składnik i jest on niedoważony powinno nastąpić jego ponowne załączenie po upływie zadanego czasu i szybkim zamknięciu po uzyskaniu wartości na wadze. Bez opóźnienia spust potrafi otwierać się i zamykać co sekundę kilka razy i doprowadzić to może do uszkodzeń po pewnym czasie.

    Problem w moim podprogramie sterującym wyjściami jest taki, że jest on odwiedzany za każdym razem czy trzeba czy nie. Muszę chyba napisać podprogram zał./wył. dla każdego wyjścia. Natomiast z programu głównego wywoływać je po kolei z odpowiednim opóźnieniem. Łatwiej będzie wówczas sterować załączaniem Timera. Tak kombinuję.
    Dla logiki człowieka to proste gorzej przełożyć to na bity.

    Ok. Dzięki serdeczne idę spać. Może jutro coś do głowy przyjdzie.
    Do zobaczenia i dzięki.
    Roko.
  • #8 5658179
    szun
    Poziom 19  
    Odnoszę wrażenie iż chcesz napisać program uniwersalny
    Dozownik ślimakowy sam napisałeś jest precyzyjny a jak to się ma do zasuwy hydraulicznej dzięki której spada na wagę setki kilogramów

    Dodano po 12 [minuty]:

    Dlaczego chcesz wykorzystać do opóżnienia liczniki przecież w trakcie rozbudowy programu mogą okazać się bardzo potrzebne a wręcz niezbędne

    Dodano po 21 [minuty]:

    crazy_phisic
    napisał i
    oczywiście ma racje dozowanie może być podzielone na etapy
    dodam od siebie iż pomiar wagi można zapisać w pamięci i analizować czego dosypać aby utrzymać proporcje bo raczej nie przewidujesz odbioru nadmiaru z wagi
  • #9 5658938
    Roko
    Poziom 11  
    Cześć.

    Tak podajnik ślimakowy jest w miarę precyzyjny.
    Nie chodzi mi o zasadę działania dozownika i jego rozbudowę chodzi mi o sedno tematu. Mam mianowicie problem z przerwami czasowymi między załączeniami poszczególnych składników. Nie ma różnicy czy jest to spust czy też podajnik ślimakowy. W przypadku spustu zasuwa otwiera się i zamyka niekiedy parę razy, a w przypadku ślimaka silnik załącza się i wyłącza co objawia się szarpaniem. Te objawy na pewno nie wpływają korzystnie na te urządzenia i powodują po pewnym czasie ich usterki.

    Dajmy może spokój co by gdyby i czy będą potrzebne liczniki. Więcej liczników nie potrzeba choć się nie zarzekam.
    Jak pisałem w pierwszym poście nie mogę użyć instrukcji Wait i dlatego korzystam z Timer
    Mam problem z procedurą :?
    np.
    - otwierta A
    - zamyka A (jeżeli za mało)
    - opóźnienie
    - otwiera A (jeżeli dobrze lub więcej)
    - zamyka A
    - opóźnienie
    - otwiera B
    - zamyka B (jeżeli dobrze lub więcej)
    - opóźnienie
    .
    .
    itd.
    Z tym pogrubionym jest problem, a zasadniczo z Start Timer0 i Stop Timer0, a pozostałe to pikuś(bynajmniej dla mnie).
    Dzięki za uwagi do całości zagadnienia. Jak uda się coś skrobnąć (procedura opóźnienia) to napewno załorzymy nowy temat ogólny o dozowaniu, ale na razie chodzi mi o tę procedurę.
    Dzięki za zainteresowanie i do usłyszenia, a raczej widzenia.
    Roko
  • #10 5659002
    dawid512
    Poziom 32  
    Osobiście mam taki pomysł:
    Ustawiamy sobie timer w tryb licznika i oczywiście zlicza sobie impulsy i generuje przerwanie podczas przepełnienia. Teraz resetuje nam(lub ustawia wedle uznania) zmienną "flaga", oczywiście po jakimś czasie. Następnie prosty waruneczek:
    Set Flaga : While Flaga = 1 : Wend  
    I co robi procek? Grzecznie czeka aż flaga zostanie zresetowana i przejdzie dalej.

    Co wy na to?
  • #11 5659153
    Roko
    Poziom 11  
    Hej.
    Pomysł fajny i na temat.
    Jest tylko jeden problemik a mianowicie procesor nie może czekać ponieważ musi obsługiwać główną pętlę Do-Loop, ( bierzący odczyt wskazań wagi, odczyt klawiatury i parę innych rzeczy) gdyby nie to użyłbym w podprogramie instrukcji Wait co było by proste i adekwatne do Twojego pomysłu.

    Dzięki za zainteresowanie.
    Roko
  • #12 5659287
    dawid512
    Poziom 32  
    To zrób inaczej: dokladnie to co wczesniej tylko ze bez warunku zeby czekal. Poprostu wlacz timer kiedy ci potrzeba i niech odmierzy jakis tam czas. Potem daj warunek że jesli minelo iles tam czasu(np.flaga ustawiona) to albo wykonaj instrukcje albo nie.
  • #13 5659376
    Roko
    Poziom 11  
    Hej.

    Nie wiem czy Prześledziłeś poprzednie kody.
    W tej chwili stanęło na tym kodzie.


    
    Dim Licznik As Integer
    Dim Wart As Single
    Dim Flaga As Bit
    Dim A As Bit , B As Bit , C As Bit , D As Bit
    Led Alias Portb.0                                           'alias dla wyjścia Portb.0
     
    
    Licznik = 0                                                 'wyzerowanie zmiennej licznikowej
    Portc = 0                                                   'wyłącz wyjścia
    Flaga = 0
    Wart = 0
    
    '*********************** Główna pętla *********************
    Do
    'odczyt bieżących wskazań wagi -> 'wart'
    'obsługa wyświetlacza
    'obsługa klawiatury                                         'start dozowania -> 'Gosub Doza'  
    '.....                                                      'ze wskaźnikiem ilości dozowań (cykli) 
    '.....
    '.....
    Gosub Doza                                                  'tylko na próbę  
    Loop
    
    '************************ DOZOWANIE ***************
    Doza:
    
    If Wart < 30 Then                                           'jeżeli < 30 (dla próby wartość przykł.)
       Portc = Portc And 1                                      'wyłącz wszystkie wyjścia oprócz A
       If Flaga = 0 Then                                        'jeżeli flaga wyzerowana (na początku TAK)
          Start Timer0                                          'załącz timer0 (opóźnienie)
       End If
           If Flaga = 1 And Licznik = 0 Then                    'jeżeli przerwanie Timer0 (odliczona 1sek)
              Set Portc.0                                       'załącz A
              A = 1                                             'ustaw wskaźnik,że włączony A
           End If
    End If
    
    If Wart > 30 And Wart < 60 Then                             'na próbę wartości przykładowe
       Portc = Portc And 2                                      'wyłącz wszystkie wyjścia oprócz B
       If A = 1 Then                                            'jeżeli był dozowany A
          Flaga = 0                                             'zeruj flagę (zezwolenie na Start Timer0)
          A = 0                                                 'kasuj wskaźnik,że był włączony A
       End If
           If Flaga = 0 Then
              Start Timer0                                      'startuj Timer0
           End If
                  If Flaga = 1 And Licznik = 0 Then             'jeżeli przerwanie Timer0
                     Set Portc.1                                'włącz B
                     B = 1                                      'ustaw wskaźnik,że włączony B
                  End If
    End If
    
    If Wart > 60 And Wart < 90 Then
       Portc = Portc And 4                                      'wyłącz wszystkie wyjścia oprócz C
       If B = 1 Then                                            'jeżeli był dozowany B
          Flaga = 0                                             'zeruj flagę (zezwolenie na Start Timer0)
          B = 0                                                 'kasuj wskaźnik,że był włączony B
       End If
           If Flaga = 0 Then
              Start Timer0                                      'startuj Timer0
           End If
               If Flaga = 1 And Licznik = 0 Then                'jeżeli przerwanie Timer0
                  Set Portc.2                                   'włącz C
                  C = 1                                         'ustaw wskaźnik,że włączony C
               End If
    End If
    
    If Wart > 90 And Wart < 120 Then
       Portc = Portc And 8                                      'wyłącz wszystkie wyjścia oprócz D
       If C = 1 Then                                            'jeżeli był dozowany C
          Flaga = 0                                             'zeruj flagę (zezwolenie na Start Timer0)
          C = 0                                                 'kasuj wskaźnik,że był włączony C
       End If
           If Flaga = 0 Then                                    'startuj Timer0
              Start Timer0
           End If
               If Flaga = 1 And Licznik = 0 Then                'jeżeli przerwanie Timer0
               Set Portc.3                                      'włącz D
               D = 1                                            'ustaw wskaźnik,że włączony D
               End If
    End If
    
    If Wart > 120 Then
       Portc = Portc And 0
       Flaga = 1
    End If
    
    Return
    
    '********************* Czas do załączenia składnika ******************
    
    Przerwanie_timer:                                           'przerwanie wywolywane co 1 ms
      Counter0 = Counter0 + 6                                   'wart. pocz. timera0 (250 impulsow do przepełnienia)
      Incr Licznik                                              'zwiększenie licznika o 1
      If Licznik = 1000 Then                                    'jesli licznik równy 1000 (czyli 1000*1ms=1sek) to
        Toggle Led                                              'kontrolka czy liczy (świeci/gaśnie led)
        Licznik = 0                                             'wyzeruj zmienną licznik
        Flaga = 1                                               'ustaw flagę
        Stop Timer0                                             'zatrzymaj Timer
      End If                                                    'powrót z przerwania
    Return
    


    I jest wszystko ok. Musiałem dodać jeszcze wskaźniki (A,B,C,D) do uwarunkowania ponownego załączania Timera. Teraz Timer jest tylko raz załączany po kolejnym ustawieniu wyjścia. I tu właśnie był 'pies pogrzebany'. Takie proste, a siedziałem przy tym trochę. Śmiechu warte, ale kiedyś zawsze można sobie zęby połamać. Można by ten kawałek zoptymalizować albo napisać zgodnie z sugestią kolegi crazy_phisic jakąś funkcję.
    Jakieś inne sugestie, może sposoby, jakaś optymalizacja lub zupełnie inne podejście do tematu (programowe) ?
    Bym bardzo prosił.
    Roko.
  • #14 5661334
    szun
    Poziom 19  
    roko
    musisz zmienić tok rozumowania
    według mojej wiedzy liczniki działają niezależnie czyli liczą a procesor robi swoje
    ale przerwanie zmusza procesor do wykonania czynności innych czyli obsługi przerwania czyli obliczenia tej jednej sekundy

    Dodano po 7 [minuty]:

    czyli procesorek liczy i liczy aż minie sekundka

    Dodano po 16 [minuty]:

    czyli
    Przerwanie_timer:
    zajmnie czas procesora i nic nie można wykonać w tym czasie
    nie jestem specem od programowania ale tak to rozumię ale się uczę i mogę się mylić
  • #15 5662286
    Roko
    Poziom 11  
    Cześć sory, że tak późno, ale nie miałem neta bo w router'ku zmieniałem firmware.

    odnośnie:

    "musisz zmienić tok rozumowania
    według mojej wiedzy liczniki działają niezależnie czyli liczą a procesor robi swoje
    ale przerwanie zmusza procesor do wykonania czynności innych czyli obsługi przerwania czyli obliczenia tej jednej sekundy"


    Prawie, ale nie do końca. Gdy następuje przerwanie, które wyłącza z innych zadań procesor trwa parę cykli zegara i to nie we wszystkich mikroprocesorach. Przerwanie trwa = samo przerwanie + to co jest w procedurze przerwania czyli u mnie niewiele. Nie chce mi się liczyć tego opóźniena, ale będzie ono rzędu paru milisekund, co jest nawet nie zauważalne przy obsłudze klawiatury czy wyświetlaniu jakichś danych na wyświetlaczu nie mówiąc już o załączaniu poszczególnych składników.
    Gdybyś prześledził dokładnie pierwszy i drugi mój kod oraz Porównał je z ostatnim to Byś lepiej zrozumiał dlaczego miałem z tym podprogramem tyle kłopotu (fragment Kod: ...... Return z procedurą przerwania od timera).
    Według tego co Napisałeś w cytacie przerwanie od timera odrywa tylko mikroprocesor w tym przypadku AVR od pozostałwych czynności na jego obsługę czyli te parę milisekund jak u mnie, a nie jak piszesz obliczenia tej 1 sekundy. On tylko zwiększa zmienną licznik sprawdza warunek stan flaga i wyłącza timer czyli niewiele.
    To instrukcja Wait w zależności od swojej wartości zatrzymuje mikroprocesor na zrobienie czegoś w rodzju pętli Forx=0 to np. 2000000.

    "czyli procesorek liczy i liczy aż minie sekundka"

    niema co liczyć. Liczy to co wyżej napisałem.

    "Przerwanie_timer:
    zajmnie czas procesora i nic nie można wykonać w tym czasie"


    Ależ wykonuje właśnie to co jest w przerwaniu, aż dojdzie do RETURN i ją wtedy opóści.

    Z tego też względu wiele programów jest napisane w ten sposób, żeby w przerwaniu było dużo rzeczy do zrobienia, porównania, skomplikowane wyliczenia i inne. Każdy chce wykorzystać przerwania i robi ich dużo, żeby uzyskać efekt coś w rodzaju wielozadaniowości, ale jak wiadomo jest to raczej wielowątkowość z wywłaszczaniem no może nie do końca.

    Dzięki szun za zainteresowanie i myślę, że rozwiałem twoje obawy odnośnie przerwania. Prześledź kody, a zrozumiesz to co ja załapałem po 3 dniach no może nie dobach bo tyle przy tym nie siedziałem, ale trochę kombinowałem.
    Do usłyszenia.
    Roko
  • #16 5664000
    szun
    Poziom 19  
    Roko analizowałem i dzięki masz racje z przerwaniami
    jakoś błędnie sobie to zinterpretowałem i wiele spraw staje sie dla mnie jaśniejsze
    i oczywiście kod będę analizował pozdrawiam
REKLAMA