Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Attiny 2313 (BASCOM) obrotomierz 4 wentylatorów.

25 Aug 2009 20:06 7403 53
  • Level 27  
    Witam .
    Przeszukując ELEKTRODĘ natknąłem się na kilka obrotomierzy wentylatorów komputerowych.
    Jest tylko jeden problem .
    Chciał bym żeby Uc mierzył obroty 4 wentylatorów na raz i wyświetlał to na LCD.
    Wszystkie projekty obsługują tylko max 2, a ja potrzebuję 4.
    Zna ktoś jakieś rozwiązanie w BASCOM tego problemu??
  • Level 38  
    A jakie zastosujesz czujniki do pomiaru tych prędkości?
    Podejrzewam że te obrotomierze wykorzystywały przerwania tylko na INT0 i INT1 a nie na PCINT7...0.
    str.62 dokumentacji.
  • Level 27  
    Masz rację ,kod wyglądał tak :
    Code:

    Dim Wynik As Long
    Dim Wynik1 As Long


    Config Timer0 = Counter , Edge = Rising
    Config Timer1 = Counter , Edge = Rising
    Config Portb.1 = Input
    Config Portb.0 = Input
    Portb.0 = 1
    Portb.1 = 1

    Cursor Off
    Cls

    Do
    Timer0 = 0
    Timer1 = 0
    Start Timer0
    Start Timer1
    Waitms 500
    Stop Timer0
    Stop Timer1


    Wynik = Timer0 * 30
    Wynik1 = Timer1 * 30

    Jeśli można to napisać inaczej to bardzo proszę o pomoc.
    I 62 strona jakiej dokumentacji??
    A może w BASCOMie coś jest?
  • Level 43  
    arktik1 wrote:
    Masz rację


    No właśnie nie, bo po tym kodzie widać że to wykorzystuje wejścia T0 i T1.

    W ten sposób nie da się tego zrobić.
    2313 ma tylko 2 Timery i możesz zmierzyć obroty maxymalnie 2 wentylatorów.
    No chyba że pomiar będziesz robił programowo, albo przełączał sygnały z 4 wentylatorów na jeden Timer i mierzył po kolei każdy z wentylatorów (można też mierzyć po dwa dwoma Timerami).
  • Level 27  
    Więc potrzebuje rozwiązania na tym PCINT7...0, ponieważ chciał bym wyświetlić wszystkie wentyle na raz.
  • Level 43  
    Szczerze mówiąc to jest niekoniecznie najlepsze rozwiązanie, bo będziesz musiał mieć 4 przerwania równolegle.
    Ja bym zrobił zliczanie impulsów programowo, i bramkował to jednym z Timerów a przy odrobinie szczęścia nawet też programowo.
  • Level 27  
    Wszystko dobrze tylko że dopiero zaczynam z Uc i nie bardzo wiem jak to napisać .
    Jestem na razie na etapie przerabiania programów źródłowych.
    Więc jak bym miał jakiś przykład to mógł bym pokombinować.
  • Level 43  
    Będzie trochę ciężko w BASCOMie, ale może takie coś:
    Code:

    Dim W1 as Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim W1_previous as Byte
    Dim W2_previous as Byte
    Dim W2_previous as Byte
    Dim W3_previous as Byte

    Dim Koncz_liczenie as Byte

    Config Timer0 = Timer, Prescale = 16
    Enable Timer0
    Enable Interrupts
    On Timer0 Timer0_int

    Do
      Timer0 = 0

      W1 = 0
      W2 = 0
      W3 = 0
      W4 = 0

      Koncz_liczenie = 0

      Start Timer0



      Do
        If PinD.0 = 1 Then
          If W1_Previous = 0 Then
            Incr W1
          End If

          W1_Previous = 1
        Else
          W1_Previous = 0
        End If

        ... Podobne dla W2
        ... Podobne dla W3
        ... Podobne dla W4

        If Koncz_liczenie = 1 Then
          Exit Do
        End If
      Loop

      Stop Timer0

      Locate 1, 1
      LCD W1 ; "  "; W2 ; "  "; W3 ; "  "; W4 ; "      "
    Loop

    Timer0:
      Koncz_liczenie = 1
    Return
  • Level 27  
    Zrobiłem to tak ale BASCOM pokazuje jakieś głupoty.
    Code:

    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim W1_previous As Byte
    Dim W2_previous As Byte
    Dim W2_previous As Byte
    Dim W3_previous As Byte

    Dim Koncz_liczenie As Byte

    Config Timer0 = Timer , Prescale = 64
    Enable Timer0
    Enable Interrupts
    On Timer0 Timer0_int

    Do
      Timer0 = 0

      W1 = 0
      W2 = 0
      W3 = 0
      W4 = 0

      Koncz_liczenie = 0

      Start Timer0

      Do
    If Pind.0 = 1 Then
          If W1_previous = 0 Then
            Incr W1
          End If

          W1_previous = 1
        Else
          W1_previous = 0
        End If

    If Pind.1 = 1 Then
          If W2_previous = 0 Then
            Incr W2
          End If

          W2_previous = 1
        Else
          W2_previous = 0
        End If

    If Pind.2 = 1 Then
          If W3_previous = 0 Then
            Incr W3
          End If

          W3_previous = 1
        Else
          W3_previous = 0
        End If

    If Pind.3 = 1 Then
          If W4_previous = 0 Then
            Incr W4
          End If

          W4_previous = 1
        Else
          W4_previous = 0
        End If


    If Koncz_liczenie = 1 Then
          Exit Do
        End If
      Loop

      Stop Timer0

      Locate 1 , 1
      Lcd W1 ; "  " ; W2 ; "  " ; W3 ; "  " ; W4 ; "      "
    Loop

    Timer0:
      Koncz_liczenie = 1
    Return


    Dodano po 3 [minuty]:

    Sorki nie zauważyłem wszystkiego.
    Code:


    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim W1_previous As Byte
    Dim W2_previous As Byte
    Dim W3_previous As Byte
    Dim W4_previous As Byte

    Dim Koncz_liczenie As Byte

    Config Timer0 = Timer , Prescale = 64
    Enable Timer0
    Enable Interrupts
    On Timer0 Timer0_int

    Do
      Timer0 = 0

      W1 = 0
      W2 = 0
      W3 = 0
      W4 = 0

      Koncz_liczenie = 0

      Start Timer0

      Do
    If Pind.0 = 1 Then
          If W1_previous = 0 Then
            Incr W1
          End If

          W1_previous = 1
        Else
          W1_previous = 0
        End If

    If Pind.1 = 1 Then
          If W2_previous = 0 Then
            Incr W2
          End If

          W2_previous = 1
        Else
          W2_previous = 0
        End If

    If Pind.2 = 1 Then
          If W3_previous = 0 Then
            Incr W3
          End If

          W3_previous = 1
        Else
          W3_previous = 0
        End If

    If Pind.3 = 1 Then
          If W4_previous = 0 Then
            Incr W4
          End If

          W4_previous = 1
        Else
          W4_previous = 0
        End If


    If Koncz_liczenie = 1 Then
          Exit Do
        End If
      Loop

      Stop Timer0

      Locate 1 , 1
      Lcd W1 ; "  " ; W2 ; "  " ; W3 ; "  " ; W4 ; "      "
    Loop

    Timer0_int:
      Koncz_liczenie = 1
    Return

    Czy tak to ma wyglądać??
  • Level 27  
    Niestety to nie działa :cry:
    Ma ktoś jeszcze jakiś pomysł??.
    Może da się to poprawić??
  • Level 27  
    Już nie pokazuje, źle skopiowałem kod.
    Poprawiłem parę rzeczy i jest ok.
    Nie działa ponieważ nie pokazuje obrotów ,na wyświetlaczu widać w 4 miejscach tylko 0,1,1,0,0,1 itd...
  • Level 27  
    Próbuje go an m16.
    Kod wygląda tak i nadal nie działa:
    Code:

    $regfile = "m16def.dat"
    $crystal = 16000000
    Config Portc = Input
     Portc = &B11111111
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portb.6 , Rs = Portb.7


    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim W1_previous As Byte
    Dim W2_previous As Byte
    Dim W3_previous As Byte
    Dim W4_previous As Byte

    Dim Koncz_liczenie As Byte

    Config Timer0 = Timer , Prescale = 8
    Enable Timer0
    Enable Interrupts
    On Timer0 Timer0_int
    Cls
    Do
      Timer0 = 0

      W1 = 0
      W2 = 0
      W3 = 0
      W4 = 0

      Koncz_liczenie = 0

      Start Timer0

      Do

    If Pinc.1 = 1 Then
          If W1_previous = 0 Then
            Incr W1
          End If
              W1_previous = 1
        Else
          W1_previous = 0

        End If


    If Pinc.2 = 1 Then
          If W2_previous = 0 Then
            Incr W2
          End If

          W2_previous = 1
        Else
          W2_previous = 0
        End If

    If Pinc.3 = 1 Then
          If W3_previous = 0 Then
            Incr W3
          End If

          W3_previous = 1
        Else
          W3_previous = 0
        End If

    If Pinc.4 = 1 Then
          If W4_previous = 0 Then
            Incr W4
          End If

          W4_previous = 1
        Else
          W4_previous = 0
        End If

    If Koncz_liczenie = 1 Then
          Exit Do
        End If
      Loop
      Stop Timer0

      Locate 1 , 1
      Lcd W1 ; "rpm"
      Locate 1 , 7
      Lcd W2 ; "rpm"
      Locate 2 , 1
      Lcd W3 ; "rpm"
      Locate 2 , 7
      Lcd W4 ; "rpm"
    Loop

    Timer0_int:
      Koncz_liczenie = 1
    Return
  • Level 27  
    Nie liczy obrotów ,jeśli podłączy się wentylator to na wyświetlaczu podaje stan pinu.
    Czyli 1 lub 0
    Po dopisaniu np. W1 = Timer0 * 25 ,coś zaczyna wyświetlać ale kompletnie nie zgadza się z obrotami.
  • Level 27  
    Włączamy Uc ,na wyświetlaczu świeca 4 zera.
    Podłączamy PINC.1 lub 2 lub 3 lub 4 do żółtego przewodu wentylatora i w tedy zamiast obrotów pojawia się tylko 0 ,1 i na odwrót.
    Jaki schemat??

    Dodano po 57 [sekundy]:

    jest to montowane na płycie testowej.
  • Level 43  
    Schemat podłączenia.
    A ten żółty przewód to zwiera do masy?
    Kręcisz wentylatorami ręka czy normalnie podłączasz je do zasilania?

    Dodano po 5 [minuty]:

    Acha.
    Przerwanie jest wywoływane za często.
    U mnie to działa. Ale wymaga wielu kHz na wejściach.
    Zmień Prescale na 1024 a jeszcze lepiej Timer na Timer1.
  • Level 27  
    Wentylator podłączony jest do zasilania 12v ,jedyny schemat to taki że podłączam żółty przewód do któregoś z portów, reszta jest na płycie z kontrolerem która działa.
    Wyprowadzenie wentylatora działa jak port Uc 1,0,1,0.
    Załóżmy że wentylator zwiera do masy ,zmieniłem IF PORTC.1 = 1 THEN... na PORTC.1=0 i to samo.
  • Level 27  
    Zmieniłem PRESCALE na 1024 i dochodzi do 3 ale strasznie szybko zmieniają się liczby.

    Dodano po 57 [sekundy]:

    Masa jest podłączona bo wentylator jest zasilany z płytki.
  • Level 27  
    Mało ,dochodzi do 35 rpm a went. ma 4000

    Dodano po 1 [minuty]:

    przy 1024 dochodzi do 550

    Dodano po 1 [minuty]:

    Więc co zrobić żeby to działało prawidłowo?.

    Dodano po 3 [minuty]:

    może przemnożyć ten wynik jakoś??
  • Level 43  
    No tak. Zeby dojść do 4000 czas pomiaru musiał by trwać minutę.
    Pomnóż przez 7,27. Tylko że to na zmiennych typu Single by trzeba.

    Dodano po 8 [sekundy]:

    No tak. Żeby dojść do 4000 czas pomiaru musiał by trwać minutę. W końcu chesz rpm a to sa obroty na minutę.
    Pomnóż przez 7,15256. Tylko że to na zmiennych typu Single by trzeba.
    Twój wentylator ma 3934rpm :D
  • Level 27  
    Niby działa ,tylko że to odświeżanie jest do kitu.
    Chyba zastosuje jednak pierwszy sposób i dam na przełączanie wentylatorów tranzystory.
  • Helpful post
    Level 43  
    Ten sposób też będzie powolny a do tego niedokładny.
    W sumie doszedłem do wniosku że programowe zliczanie impulsów nie będzie gorsze. Zliczanie 4 impulsów trwa 10us w symulacji programowej.

    Zauważ że w tym pierwszym rozwiązaniu mnoży się przez 28 a więc dokładność pomiaru jest do kitu.
    Przy 4000rpm układ zlicza tylko 160 impulsów.

    Możesz dać Prescale na 256 i mnożyć przez 28,61. Będziesz miał odświeżanie co sekundę.

    Dodano po 2 [minuty]:

    Możesz mierzyć okres. Obejdzie się bez tranzystorów do przełączania źródeł sygnału i dokładność będzie większa. A czas pomiaru będzie rewelacyjnie mały (kilkanaście ms). Nie licząc oczywiście obsługi LCD która trwa z 50ms a więc spowolni odświeżanie.
  • Level 27  
    Jak mierzyć OKRES??

    Dodano po 10 [minuty]:



    Dodano po 3 [minuty]:

    Napisałem coś takiego :
    Code:

    $crystal = 16000000



    Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portb.6 , Rs = Portb.7

    Config Lcd = 16 * 2

    Dim Wynik As Long
    Dim Wynik1 As Long


    Config Timer0 = Counter , Edge = Rising
    Config Timer1 = Counter , Edge = Rising
    Config Portb.0 = Input
     Portb.0 = 1
    Config Portb.1 = Input
     Portb.1 = 1
     Config Portc = Output

     Portc = &B00111111

     Cursor Off
    Cls
    Locate 1 , 4
    Lcd "CHLODNICA"
    Locate 2 , 4
    Lcd "WLACZONA"

    Wait 4
    Cls
    Do
    Timer0 = 0
    Timer1 = 0
    Start Timer0
    Start Timer1
    Waitms 600
    Stop Timer0
    Stop Timer1


    Wynik = Timer0 * 50
    Wynik1 = Timer1 * 50
    If Pinc.7 = 0 Then Gosub W1
    If Pinc.7 = 1 Then Gosub W2
    Toggle Portc.7
    If Portc.7 = 0 Then
     Portc.6 = 0
    Else
    Portc.6 = 1
    End If
    If Portc.7 = 0 Then
    Portc.5 = 1
    Else
    Portc.5 = 0
    End If



    Loop
    End

    W1:
    Locate 1 , 1
    Lcd Wynik
    Locate 1 , 5
    Lcd "rpm"
    Locate 1 , 10
    Lcd Wynik1
    Locate 1 , 14
    Lcd "rpm"
    If Wynik <= 999 Then
    Locate 1 , 4
    Lcd " "
    End If
    If Wynik1 <= 999 Then
    Locate 1 , 13
    Lcd " "
    End If
    If Wynik <= 500 Or Wynik1 <= 500 Then
    Portc.4 = 0
    End If
    Return

    W2:
    Locate 2 , 1
    Lcd Wynik
    Locate 2 , 5
    Lcd "rpm"
    Locate 2 , 10
    Lcd Wynik1
    Locate 2 , 14
    Lcd "rpm"
    If Wynik <= 999 Then
    Locate 2 , 4
    Lcd " "
    End If
    If Wynik1 <= 999 Then
    Locate 2 , 13
    Lcd " "
    End If
    If Wynik <= 500 Or Wynik1 <= 500 Then
    Portc.4 = 0
    End If
    Return

    tylko że tutaj trzeba przełączać źródła sygnału i dokładność wynosi 50 rpm. przy odświeżaniu ok 600ms.
  • Level 43  
    Na moje oko odświeżanie wynosi 1200ms skoro trzeba przełączać źródła sygnału.
    Żeby zmierzyć okres czekasz aż stan pinu zmieni się powiedzmy na 0. Wtedy uruchamiasz Timer z przeskalerem równym 1 pracujący jaki licznik zliczajcy takty zegara i czekasz aż stan pinu zmieni się na 1.
    Wtedy odczytujesz licznik Timera i masz okres.
    Można by też czekać na kilka zmian stanów. Na pewno dokładność wzrośnie.
    Sprawdzenie stanu pinu jest programowe więc nic nie trzeba przełączać tylko po prostu co raz sprawdzać inny pin.

    Dodano po 6 [minuty]:

    Chm. Przy tak małej częstotliwości (wentylatorów) chyba nawet Timer musiał by chodzić z preskalerem równym 8 albo nawet więcej.

    Code:

    $regfile = "m16def.dat"
    $crystal = 16000000
    Config Portc = Input
     Portc = &B11111111
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portb.6 , Rs = Portb.7


    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim Text1 As String * 16
    Dim Text2 As String * 16
    Dim Text3 As String * 16
    Dim Text4 As String * 16


    Dim S As Single



    Dim Overfolw As Byte

    Config Timer1 = Timer , Prescale = 64
    Enable Timer1
    Enable Interrupts
    On Timer1 Timer1_int

    Cls




    Do
      '================================
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.1 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.1 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.1 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.1 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1

      W1 = Timer1
      '================================

      '================================
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.2 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.2 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.2 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.2 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1

      W2 = Timer1
      '================================

      '================================
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.3 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.3 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.3 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.3 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1

      W3 = Timer1
      '================================

      '================================
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.4 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.4 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1
      Timer1 = 0
      Overfolw = 0
      Start Timer1

      While Pinc.4 = 0
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Overfolw = 0

      While Pinc.4 = 1
        If Overfolw = 1 Then
          Exit While
        End If
      Wend

      Stop Timer1

      W4 = Timer1
      '================================



      S = W1
      S = 15000000 / S
      W1 = Round(s)

      S = W2
      S = 15000000 / S
      W2 = Round(s)

      S = W3
      S = 15000000 / S
      W3 = Round(s)

      S = W4
      S = 15000000 / S
      W4 = Round(s)


      Text1 = Str(w1)
      Text1 = Format(text1 , "   0")

      Text2 = Str(w2)
      Text2 = Format(text2 , "   0")

      Text3 = Str(w3)
      Text3 = Format(text3 , "   0")

      Text4 = Str(w4)
      Text4 = Format(text4 , "   0")


      Locate 1 , 1
      Lcd Text1 ; "rpm"
      Locate 1 , 9
      Lcd Text2 ; "rpm"
      Locate 2 , 1
      Lcd Text3 ; "rpm"
      Locate 2 , 9
      Lcd Text4 ; "rpm"
    Loop

    Timer1_int:
      Overfolw = 1
    Return



    Jak to zadziała to to będzie cud ;p
  • Level 27  
    Niestety nie działa ,nawet nie widać 0