Programowy PWM


10
Ocena: None Średnia: 10 (2 głosujących)

PWM (Pulse - Width Modulation) modulacja szerokości impulsu jest powszechnie stosowana do regulacji mocy odbiorników prądu stałego (i nie tylko). Polega ona na sterowaniu wypełnieniem przebiegu prostokątnego o stałej amplitudzie. Mimo że większość mikrokontrolerów posiada własne, przeważnie wielokanałowe, układy PWM, czasem zachodzi potrzeba wekonania czegoś podobnego programowo. W przedstawionym dalej przykładzie pokazana jest zasada sterowania diodami trójkolorowymi (RGB), poprzez zmianę wypełnienia przebiegu prostokątnego sterującego każdy z kolorów.

Język BASCOM AVR:

Przykładowy program do sterowania diodą RGB przedstawiony jest poniżej:

'************* Konfiguracja uC *****************
'***********************************************
$regfile = "attiny2313.dat"
$crystal = 16000000
 
Config Portb = &B11111111 : Portb = &B11111111
Config Portd = &B11111111 : Portd = &B11111111
 
Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
'********** Konfiguracja uC Koniec  ************
 
'******************  Nazwy *******************
'***********************************************
Rd Alias Portb.0
Gd Alias Portb.1
Bd Alias Portb.2
'*************  Nazwy Koniec  ****************
 
'******************  Zmienne *******************
'***********************************************
Dim Licznik As Byte
Dim Rled As Byte , Bled As Byte , Gled As Byte
'*************  Zmienne Koniec  ****************
 
'************ Warunki Poczatkowe ***************
'***********************************************
Rled = 80
Gled = 0
Bled = 90
'*******  Warunki Poczatkowe Koniec  ***********
 
'**************  Petla glowna ******************
'***********************************************
Do
 
Loop
End
'************ Petla glowna Koniec **************
 
'************ Przerwanie timer 0 ***************
'***********************************************
Prztimer0:
 Incr Licznik
 If Licznik = 100 Then Licznik = 0
 
 If Licznik < Rled Then Set Rd Else Reset Rd
 If Licznik < Gled Then Set Gd Else Reset Gd
 If Licznik < Bled Then Set Bd Else Reset Bd
Return
'******** Przerwanie timer 0 Koniec ************

Program był testowany na mikrokontrolerze ATTiny2313 o czym świadczy pierwsza linijka w konfiguracji. Timer został ustawiony na podział częstotliwości przez 8. Ponieważ jest on ośmiobitowy (liczy do 256) to przerwanie będzie występowało z częstotliwością ok. 7,8kHz.

W przerwaniu Timera (Prztimer0) zostaje zwiększany cyklicznie Licznik od wartosci 0 do 99, co odpowiada regulacji wypełnienia co 1%. Działanie PWM jest zrealizowane w banalny sposób za pomocą instrukcji warunkowej if Licznik.... Porównuje ona aktualną wartość Licznika ze zmienną określającą natężenie (Rled, Gled lub Bled, 3 kanały) i wystawia stan wysoki na pinie wyjściowym jeśli Licznik ma mniejszą wartość od zmiennej, a stan niski jeśli warunek ten nie jest spełniony. W efekcie dla zmiennej (Rled, Gled lub Bled) równej 100 Licznik jest mniejszy od niej cały czas (liczy od 0 do 99) i na wyjściu jest cały czas stan wysoki (wypełnienie 100%). Jeśli natomiast zmienna jest równa 0 to licznik nigdy nie jest od niej mniejszy i wypełnienie będzie równe 0%.




Portret użytkownika rafliczek22

Witam. Mam 3 pytania

Witam.

Mam 3 pytania odnośnie PWM:

1.Dlaczego nie mogę tego zrobić na Attiny13, zamieszczam kod, co jest w nim nie tak???

$regfile = "attiny13.dat"
$crystal = 9600000
 
Config Portb = &B000011 : Portb = &B111111
 
Config Timer1 = Pwm , Prescale = 1 , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Disconnect
 
Dim F As Byte         'w tej linijce pokazuje error brak pam. sram
 
S1 Alias Pinb.2       '1 przycisk
S2 Alias Pinb.3       '2 przycisk
Pwm1a = 0
 
Do
 
F = Pwm1a   'zeby nie pisac ciagle pwm1a tylko F
 
If S1 = 0 Then
Waitms 15      'zamiast polecenie debounce
If S1 = 0 Then
Incr F        'zmniejsza wypelnienie
If F = 0 Then
F = 255
End If
End If
 
 
If S2 = 0 Then
Waitms 15      'zamiast polecenie debounce    
If S2 = 0 Then
Decr F        'zwieksza wypelnienie
If F = 255 Then
F = 0
End If
End If
 
 
Loop
End

Kiedy zamienie porty na np. Attiny2313 wszystko działa, jednym z error-ów jest brak pamięci SRAM
2.Prosiłbym o kawałek kodu żeby na wyświetlaczu lcd przy np. Atmega8 u góry pokazywał sie pasek a pod spodem procent (chodzi o to aby ustawiać w 100 krokach a nie jak zwykły PWM w 255)
3.Jaki układ trzeba zastosować aby sterować triakiem (chcę z pilota do telewizora gdy już leże w łóżku zmieniać jasność żarówek halogenowych)

Przepraszam za tak obszerne pytania ale chciałem żeby każdy wiedział o co chodzi.

Portret użytkownika mirley

Re: Tiny13 i PWM

Po pierwsze tiny13 jest procesorem który mało nadaje się do takiego celu. Przynajmniej zaprogramowanie go w bascomie jest dużym problemem. Spróbuj dodać do swojego programu na początku takie wpisy:

$hwstack = 20
$swstack = 10
$framesize = 40


W starszej wersji bascoma kosztem stosu można było uzyskać trochę ramu. W nowej wersji cos skopali i jest to niemozliwe. Basmom tyle niepotrzebnych zmiennych sam sobie w ramie tworzy że nie ma miejsca na nic innego i temu jest błąd.

2. Dodaj linijkę z wyświetlaczem LCD w procesdurze obsługi klawiatury aby wyświetlał wartość wypełnienia po kliknięciu w przycisk.

3. Sterowanie PWM nie nadaje się do żarówek prądu zmiennego. Jeśli żarówki są na 12V to możesz wykorzystać PWM zasilając żarówki prądem stałym i sterując tranzystorem mosfet. W programie który widzisz wyżej masz napisany programowy PWM o zakresie 0-100%

Ps. Twoje pytania praktycznie nie mają związku z tematem opisu wyżej... takie pytania pisze się na forum http://mirley.firlej.org/forum

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika rafliczek22

Witam. 1. Zrobiłem tak jak

Witam.

1. Zrobiłem tak jak powiedziałeś brak sram-u już mu nie dokucza ale pokazały się inne błędy, screen zamieszczam [url=][/url]http://www.fotosik.pl/pokaz_obrazek/pelny/dd77a11e8a76db34.html
O co teraz chodzi to kompletnie nie wiem kod nie zmieniony tylko dodane te 3 linijki???

2. Mi chodziło o to aby na wyśw. nie wyświetlać wartości 0-255 tylko aby to ładnie i przyjemnie wyglądało, że u góry kolejno wyświetlają się matryce wyśw. a w dolnej linijce wartość ale od 0-100%.

3. A czy nie dało rady by jakoś wykorzystać tego układziku??? [url=]http://mirley.firlej.org/regulator_obrotow_silnika_230v[/url]

Portret użytkownika mirley

Re; PWM

1. Dodaj End if na końcu bo brakuje.... zobacz jaki będzie efekt bo czasem bascom dziwne rzeczy pokazuje. Czy ten sam program działa na ATTiny2313?

3. nie.. układ który podałeś to regulator fazowy mocy a nie pwm. Może jakby zrobić jakis izolowany optycznie układ DAC żeby zamiast potencjometru działał ale to tylko luźny domysł, zabardzo sam nie wiem czy działało by w ten sposób

Ps. Załóż watek na forum bo mówiłem że piszesz nie na temat...

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika Marek

Quote:Timer został ustawiony

Quote:
Timer został ustawiony na podział częstotliwości przez 8. Ponieważ jest on ośmiobitowy (liczy do 256) to przerwanie będzie występowało z częstotliwością ok. 7,8kHz.

Hej,
Moglbys napisac jaki jest wzor na wyliczenie sobie tego?
Rozumiem ze 1Hz to 1 sekunda, czyli 1kHz to 1ms, tak?

Dzieki

Portret użytkownika mirley

Re: Timer

Quote:
Rozumiem ze 1Hz to 1 sekunda, czyli 1kHz to 1ms, tak?

jeśli chodzi o ścisłość to 1kHz to częstotliwość która odpowiada okresowi 1ms :)

Poprostu należy wziąść częstotliwość jaką jest taktowany mikrokontroler, w tym przypadku 16000000Hz (16MHz), timer ma ustawiony podział przez 8:

Config Timer0 = Timer , Prescale = 8

więc dzielimy 16Mhz/8 = 2Mhz, z taką częstotliwością będzie zwiększany licznik timera0 a ponieważ jest on 8-bitowy (liczy do 256) to dzielimy to jeszcze przez 256 uzyskując 0,0078125Mhz. Z taką częstotliwościa będzie wywoływane przerwanie timera. Jeśli w pierwszej linijce przerwania damy np wpis timer0 = 5 to timer zacznie liczyc od 5 czyli zliczy 250 impulsów do następnego przerwania i częstotliwość wyniesie wtedy 8khz

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika Kaka

PWM

Witam! A czy jest możliwość regulacji częstotliwości działania PWM w Twoim programie? Np tak żeby mozna regulować szerokość impulsu oraz częstotliwość również płynnie , powiedzmy od 1Hz do 20Hz?

Portret użytkownika mirley

Re: PWM

Częstotliwość można regulować poprzez podzielnik timera i preskaler (płynnie to się raczej nie da jest krok wynikający z podzielnika). Ale po co ci PWM na częstotliwości rzędu Hz, może chodziło Ci o kHz?

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika Kaka

Np do stroboskopu z regulacją

Np do stroboskopu z regulacją jasności;p Chodzi tu o czas ładowania kondensatora, impuls musi mieć częstotliwość impulsu wyzwalania iskry, ale mieć różną szerokość. Ale już sobie z tym poradziłem. Tylko że liniowość jest kiepska, ale sie dopracuje.

Portret użytkownika matrix

Re: Programowy PWM

ja mam małe pytanko. zmodyfikowałem lekko Twój soft żeby diody zapalały się pod wpływem napięcia (a raczej wartości już pobranej z adc, bo napięcie nie ma znaczenia) na wejściu ADC, ale nie wszystkie na raz a kolejno płynnie czyli w skrajnym położeniu potencjometru zapala się na max jedna, w środkowym ta pierwsza powoli gaśnie a na max świeci się druga i w drugim skrajnym położeniu zapala się trzecia a ta druga powoli gaśnie.

i mam drobny zgryz, otóż jedna z diod nie gaśnie mi do zera.
na filmie (kiepskiej jakości) widać o co chodzi.
-> FILM <-

jest drobna odchyłka rzędu 4 bo po podzieleniu 1023/5 nie wyjdzie idealnie 200. później się tym zajmę.
bodajże nie gaśnie do zera bled
nie zmieniłem nic poza dodaniem tego co poniżej:

x = x / 5  'pobrane ADC podzieliłem przez 5
           'żeby mieć rozpiętość od skrajnych płożeń
           'do środka równą 100.

a tu Twój program wywoływany co przerwanie i mój mały mod:

Prztimer0:
 
rled = 200 - x
if rled > 100 then
   rled = 100
end if
 
bled = x
if bled > 100 then
   bled = 100
end if
 
if x > 100 then
   gled = x - 100
end if
 
if x < 100 then
   gled = 100 - x
end if
 
gled=gled *2
 
 Incr Licznik
 If Licznik = 100 Then Licznik = 0
 
 If Licznik < Rled Then Set Rd Else Reset Rd
 If Licznik < Gled Then Set Gd Else Reset Gd
 If Licznik < Bled Then Set Bd Else Reset Bd
Return

Portret użytkownika mirley

Re: LED

Wszystkie wyliczenia wywal z przerwania... ma tam zostać tylko to co miałem i ewentualnie ustawianie flagi co jakąś sensowną wartość np co 100 przerwań i dopisac If Licznik = 100 Then set flaga. Natomiast w głównej pętli if flaga = 1 then (reset flaga, przeliczenia itp.......)

Podawałeś na wyświetlacz wartści rled, gled i bled. Zobacz co przyjmują

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika matrix

Re: Programowy PWM

jako że korzystam z wewnętrznego oscylatora 8MHz na atmega8, to musiałem napisać coś takiego:

Prztimer0:
 stop timer0
 Incr Licznik
  If Licznik = 100 Then
     Licznik = 0
     toggle zmienna_pomocnicza
  end if
 
  If Licznik < Bled Then Set Bd Else Reset Bd
  If Licznik < Rled Then Set Rd Else Reset Rd
  If Licznik < Gled Then Set Gd Else Reset Gd
 
  timer0 = 120
  start timer0
Return

a w pętli głównej jest:
if zmienna_pomocnicza = 1 then
   gosub obliczenia
end if

i wiesz że działa. dzięki. tylko się dziwię troszkę, bo nigdy z czymś podobnym nie miałem kłopotu. zwykle takie obliczenia w przerwaniach bez problemu mi działały.

a jeszcze małe pytanko. czemu w takim kawałku Twojego kodu:

If Licznik < Gled Then Set Gd Else Reset Gd

nie ma end if i kompilator nie zgłasza błędu?

Portret użytkownika mirley

Re: PWM

Ja bym wywalił stop i start timer z przerwania, po co Ci to. Polecenie timer0=120 daj na sam początek przerwania, przed incr licznik

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika matrix

mirley wrote:Ja bym wywalił

mirley wrote:
Ja bym wywalił stop i start timer z przerwania, po co Ci to.

jak wywalę stop timer z przerwania to w pętli głównej programu wariuje mi wyświetlanie wartości pobranej z ADC, czyli to co poniżej, a komenda stop timer nie przeszkadza mi w niczym, a podejrzewam że wręcz pomoże jakbym zaprzągł (w innym procku) jeszcze ze dwa timery.

x = 0
x = getadc(0)
x = x / 5
if x > 200 then
   x = 200
end if
 
locate 1 , 5
lcd x ; "  "

Portret użytkownika DariuszEE

PWM na AT89Sxx AT89Sxxxx

Witaj
Mam Pytanie
Jak zrobić PWM na AT89Sxxxx w Baskomie
ponieważ one mają sprzętową implementację

AT89S2051-24SU
2kB-FL 256B-RAM 15I/O ISP 2,7÷5,5V 2xtimer UART SPI PWM -40÷85°C

AT89S4051-24SU
4kB-FL 256B-RAM 15I/O ISP 2,7÷5,5V 2xtimer UART SPI PWM -40÷85°C

Portret użytkownika RoB

Pytanie BASCOM czy C++

Witam,
Nie wiedziałem gdzie zadać to pytani więc pytam przy okazji tego programiku :D
Zacząłem się uczyć C++ z książki Symfonia C++ ...
Czy trudno taki program jak wyżej napisać w C++ i który język jest lepszy do zabawy z mikrokontrolerami ? Pozdrawiam.

Portret użytkownika mirley

Re: Programowanie

Do programowania mikrokontrolerów lepszy jest C od bascoma. Zapewnia leszą kontrolę nad tym co się dzieje ale wymaga większej wiedzy o sprzęcie i programowaniu. Mowa tutaj o C a nie o C++, ten ostatni jest do aplikacji na komputerze a nie w procku. Jakoś podobno da się napisać coś w C++ na mikrokontroler ale raczej jest to mało polecane

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika morswin

A żeby zwiększyć

A żeby zwiększyć rozdzielczość PWM wystarczy zwiększyć zakres zmiennej licznik?

Portret użytkownika mirley

Re: PWM

Tak zwiększasz zmienną Licznik aby działała np w zakresie 0-200 zamiast 0-100 ale wtedy częstotliwość generowanego przebiegu spada dwukrotnie.

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika morswin

A jak wyliczyć częstotliwość

A jak wyliczyć częstotliwość tego PWM?

Portret użytkownika mirley

Re: PWM

Częstotliwośc przebiegu PWM to częstotliwość przerwania timera / zakres licznika

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

Programowy PWM

Witam serdecznie
Chciałbym do mojego kodu niżej dołożyć programowy PWM tyle że nie wiem jak to mogę zacząć. Pomoże mi ktoś?

$regfile = "m8def.dat"
$crystal = 8000000
 
 
Ddrb = &B00111111 : Portb = &B11000000
Ddrc = &B11001111 : Portc = &B00XX0000
Ddrd = &B11111110 : Portd = &B00000001
 
 
Dim X As Byte
Dim Y As Byte
Dim W As Word
Dim E As Word
 
 
Config Adc = Single , Prescaler = Auto , Reference = Avcc
 
Start Adc
 
Do
W = Getadc(4)
E = Getadc(5) * 2
 
If Pind.0 = 0 Then
Waitms 20
If Pind.0 = 0 Then
 
   For X = 1 To 7
   Portd.x = 1
   Waitms E
   Next X
 
       For X = 0 To 5
       Portb.x = 1
       Waitms E
       Next X
 
         For X = 0 To 3
         Portc.x = 1
         Waitms E
         Next X
 
                  For Y = 0 To W
                  Waitms 150
                  Next Y
 
     For X = 1 To 7
     Portd.x = 0
     Waitms E
     Next X
 
 
       For X = 0 To 5
       Portb.x = 0
       Waitms E
       Next X
 
               For X = 0 To 3
               Portc.x = 0
               Waitms E
               Next X
 
     End If
        End If
 
 
Loop

Portret użytkownika mirley

Re: PWM

Na początku programu tam gdzie masz config od ADC wstaw:

Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts

a na samym końcu:

Prztimer0:
 Incr Licznik
 If Licznik = 100 Then Licznik = 0
 
 If Licznik < Poziom Then Set portx.y Else Reset portx.y
 
Return

Na początku programu trzeba jeszcze zadeklarować zmienne Licznik i Poziom jako byte. Portx.y zamień na taki jaki potrzebujesz.

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

PWM

Wstawiłem config, a na samym końcu to co kolega pisał

Prztimer0:
 Incr Licznik
 If Licznik = 100 Then Licznik = 0
 
 If Licznik < Poziom Then Set Portd.3 Else Reset Portd.3
  If Licznik < Poziom Then Set Portd.4 Else Reset Portd.4
   If Licznik < Poziom Then Set Portd.5 Else Reset Portd.5
    If Licznik < Poziom Then Set Portd.6 Else Reset Portd.6
     If Licznik < Poziom Then Set Portd.7 Else Reset Portd.7
      If Licznik < Poziom Then Set Portb.0 Else Reset Portb.0
Return

ale jest coś nie tak bo te porty co wyżej wypisane to tylko jest jeden błysk, a powinny się rozjaśnić, a później przyciemnić, więc nie działa ten PWM

Portret użytkownika mirley

Re: PWM

Wkleiłeś to do kodu wyżej? Z tego co widzę to ustawiasz tam stany na portach d3-d7 w pętli głównej... nie masz prawa zmieniac stanu portów nigdzie poza linijkami:

If Licznik < Poziom Then Set Portd.3 Else Reset Portd.3

Możesz jedynie modyfikowac wartość zmiennej poziom która określa jasność. W tym wypadku jasność na wszystkich portach d3-d7 i b0 będzie taka sama. Zrób sobie tablicę zmiennych poziom i w każdej linijce użyj innej zmiennej poziom aby ustawiać niezależnie wszystkie piny. W pętli głownej jedynie modyfikuj wartości tych zmiennych

Zrób prosty test.... wywal wszystko z do loop i napisz:

do
  waitms 50
  incr Poziom
  if Poziom > 100 then poziom = 0 
loop

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

$regfile =

Ten kod mi działa

$regfile = "m8def.dat"
$crystal = 8000000
 
 
Ddrb = &B11111111 : Portb = &B00000000
Ddrc = &B11110000 : Portc = &B0000XX00
Ddrd = &B11111111 : Portd = &B00000000
 
Dim Licznik As Byte
Dim X As Byte
Dim Y As Byte
Dim Poziom As Byte
 
 
 
 
Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
 
 
 
 
Do
waitms 50
  incr Poziom
  If Poziom > 100 Then Poziom = 0
 
loop
Prztimer0:
If Licznik = 100 Then Licznik = 0
 Incr Licznik
 If Licznik < Poziom Then Set Portd.3 Else Reset Portd.3
  If Licznik < Poziom Then Set Portd.4 Else Reset Portd.4
   If Licznik < Poziom Then Set Portd.5 Else Reset Portd.5
    If Licznik < Poziom Then Set Portd.6 Else Reset Portd.6
     If Licznik < Poziom Then Set Portd.7 Else Reset Portd.7
 
Return

ale ten już nie...
$regfile = "m8def.dat"
$crystal = 8000000
 
 
Ddrb = &B11111111 : Portb = &B00000000
Ddrc = &B11110000 : Portc = &B0000XX00
Ddrd = &B11111111 : Portd = &B00000000
 
Dim Licznik As Byte
Dim X As Byte
Dim Y As Byte
Dim Poziom As Byte
 
 
 
 
Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
 
 
 
 
Do
 
   For X = 3 To 7
   Portd.x = 1
   Waitms 300
   Next X
 
   loop
Prztimer0:
If Licznik = 100 Then Licznik = 0
 Incr Licznik
 If Licznik < Poziom Then Set Portd.3 Else Reset Portd.3
  If Licznik < Poziom Then Set Portd.4 Else Reset Portd.4
   If Licznik < Poziom Then Set Portd.5 Else Reset Portd.5
    If Licznik < Poziom Then Set Portd.6 Else Reset Portd.6
     If Licznik < Poziom Then Set Portd.7 Else Reset Portd.7
 
Return

Portret użytkownika maro

PWM

nikt nie potrafi mi podpowiedzieć?

Portret użytkownika matrix

Re: Nikt nie potrafi mi powiedzieć ?

Nie działa bo nie dość że masz:

For X = 3 To 7
...
...
...
Next x

To jeszcze w pętli for...next masz wait

Staraj się nie używać wait.

Portret użytkownika mirley

Re: PWM

Jasne że Ci nie działa bo ustawiasz stany na portach d3-d7 anie masz prawa nigdzie togo robić skoro chciałeś PWM mieć na tych pinach. Pisałem już post wyżej o tym i dalej to samo... co chesz uzyskać tym fragmentem kodu?:

   For X = 3 To 7
   Portd.x = 1
   Waitms 300
   Next X
 

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

Czyli powinienem zamienić

Czyli powinienem zmienić

 For X = 3 To 7
   Portd.x = x ' zadziała to?
   Waitms 300
   Next X
 

Portret użytkownika mirley

Re: PWM

Masz te linijki skasować i ustawiać zmienną Poziom.... Poczytaj o tym jak działa PWM zanim będziesz kontynuował pisanie. Ostatni raz powtarzam nie możesz ustawiać nigdzie w programie stanów na porcie a polecenie portd.x = 1 ustawia stan wysoki na porcie. Stan na portach ma ustawiac tylko jedna linjka:

If Licznik < Poziom Then Set Portd.3 Else Reset Portd.3

i nic poza tym

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

No tak nie zauważyłem, ale

No tak nie zauważyłem, ale jak zrobić żeby zapalały się kolejno i przy okazji rozjaśniały i kolejno gasły przyciemniając się

Portret użytkownika mirley

Re: PWM

Tak jak pisałem... robisz tablicę zmiennych poziom zamiast pojedynczej zmiennej bo każda musi mieć inną wartość:

Dim Poziom(5) as byte 

w przerwaniu

 If Licznik < Poziom(1) Then Set Portd.3 Else Reset Portd.3
 If Licznik < Poziom(2) Then Set Portd.4 Else Reset Portd.4
 If Licznik < Poziom(3) Then Set Portd.5 Else Reset Portd.5
 If Licznik < Poziom(4) Then Set Portd.6 Else Reset Portd.6
 If Licznik < Poziom(5) Then Set Portd.7 Else Reset Portd.7

Masz teraz 5 zmiennych poziom i każda powinna przyjmować wartości 0-100. Każda zmienna reguluje wypełnieniem na jednym wejściu.

W pętli głownej piszesz tylko modyfikacje zmiennych poziom:

Do
  waitms 100 
  If Poziom(1) < 100 Then incr Poziom(1)
  If Poziom(1) > 20 and Poziom(2) < 100 Then incr Poziom(2)
  If Poziom(2) > 20 and Poziom(3) < 100 Then incr Poziom(3)
  If Poziom(3) > 20 and Poziom(4) < 100 Then incr Poziom(4)
  If Poziom(4) > 20 and Poziom(5) < 100 Then incr Poziom(5)
loop

To taki przykład sterowania..... pomyśli jak napisać to co chcesz aby działało fajnie. Aha wypełnienie nie przekłada się wprost na jasność diod. Zależność jest funkcją kwadratową ale to szczegół do opanowania

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika matrix

Re: PWM

Łatwiej było by umieścić dane w liniach DTA i czytać to poleceniem.

Zgaduję że kolega chce napisać coś w stylu Knight rider'a?

Portret użytkownika maro

PWM

Witam
Coś w stylu Knight rider'a ? Nie raczej coś innego. Chciałem jeszcze do programu dodać 2 przyciski, naciskam przycisk 1 włącza się kolejno od zmiennej poziom(1) do poziom (5) program czeka 8 sekund i wyłącza diody zaczynając od poziom(1) do poziom(5), a drugi przycisk spróbuję sam...

Portret użytkownika mirley

Re: Przyciski

Aby napisac to porządnie trzeba zmodyfikowac trochę przerwanie timera i dodać dwie flagi. Zamiast linijki z licznikiem

If Licznik = 100 Then Licznik = 0

wstaw:

If Licznik = 100 Then 
  Licznik = 0
  set f25m
  incr dziel
  if dziel = 4 then
    dziel = 0
    set f100m
  end if
End If

Na początku programu trzeba zadeklarować f25 i f100m jako bit oraz dziel jako byte

Pętla głowna:

Do
  if f25m = 1 then
    f25m = 0
 
    'obsługa przycisku 1
    if pinx.y = 0 then
      incr sw1_licz
      if sw1_licz = 100 then
        animacja = 1 
      end if
    else
      sw1_licz = 95
    end if  
 
  end if  
 
  if f100m = 1 then
    f100m = 0
    if animacja = 1
      If Poziom(1) < 100 Then incr Poziom(1)
      If Poziom(1) > 20 and Poziom(2) < 100 Then incr Poziom(2)
      If Poziom(2) > 20 and Poziom(3) < 100 Then incr Poziom(3)
      If Poziom(3) > 20 and Poziom(4) < 100 Then incr Poziom(4)
      If Poziom(4) > 20 and Poziom(5) < 100 Then incr Poziom(5)
      'tutaj trzeba dopisać czekanie za pomocą licznika jeśli Poziom(5) = 100 i potem dalsza animacja gaszenia, na końcu animacja = 0 trzeba ustawić
    end if 
  end if
loop

zmienna animacja ma być byte, sw1_licz też byte. Pin x.y który podasz jako wejście przycisku ma być ustawiony w konfiguracji jako wejście. W linijce z config port ma być wartość 0 dla tego bitu na którym jest przycisk.

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika maro

PWm

Wyskakuje mi błąd na jeden linijce

Do
  if f25m = 1 then
    f25m = 0
 
    'obsługa przycisku 1
    if PIND.0 = 0 then
      incr sw1_licz
      if sw1_licz = 100 then
        animacja = 1 
      end if
    else
      sw1_licz = 95
    end if  
 
  end if  
 
  if f100m = 1 then
    f100m = 0
    if animacja = 1'''''''''''''''''''''TUTEJ MAM BŁĄD
      If Poziom(1) < 100 Then incr Poziom(1)
      If Poziom(1) > 20 and Poziom(2) < 100 Then incr Poziom(2)
      If Poziom(2) > 20 and Poziom(3) < 100 Then incr Poziom(3)
      If Poziom(3) > 20 and Poziom(4) < 100 Then incr Poziom(4)
      If Poziom(4) > 20 and Poziom(5) < 100 Then incr Poziom(5)
      'tutaj trzeba dopisać czekanie za pomocą licznika jeśli Poziom(5) = 100 i potem dalsza animacja gaszenia, na końcu animacja = 0 trzeba ustawić
    end if 
  end if
loop

Portret użytkownika mirley

Re: Animacja

A zmienna Animacja zadeklarowana jest jako byte na początku?

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika matrix

Re: Animacja

I czy w tej linijce:

    if animacja = 1'''''''''''TUTEJ MAM BŁĄD     czy tu masz na końcu then?

Powyższy fragment kodu powinien wyglądać tak:

 if animacja = 1 then
      If Poziom(1) < 100 Then incr Poziom(1)
      If Poziom(1) > 20 and Poziom(2) < 100 Then incr Poziom(2)
      If Poziom(2) > 20 and Poziom(3) < 100 Then incr Poziom(3)
      If Poziom(3) > 20 and Poziom(4) < 100 Then incr Poziom(4)
      If Poziom(4) > 20 and Poziom(5) < 100 Then incr Poziom(5)
      'tutaj trzeba dopisać czekanie za pomocą licznika jeśli Poziom(5) = 100 i potem dalsza animacja gaszenia, na końcu animacja = 0 trzeba ustawić
    end if 

Portret użytkownika maro

PWM

Mam coś takiego, ale nie działa przycisk

$regfile = "m8def.dat"
$crystal = 8000000
 
 
Ddrb = &B00111111 : Portb = &B11000000
Ddrc = &B11001111 : Portc = &B00XX0000
Ddrd = &B11111110 : Portd = &B00000001
 
Dim Licznik As Byte
Dim Poziom(6) As Byte
Dim X As Byte
Dim F25m As Bit
Dim F100m As Bit
Dim Dziel As Byte
Dim Sw1_licz As Byte
Dim Animacja As Bit
 
 
Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
 
 
 
Do
If F25m = 1 Then
    F25m = 0
 
    'obsługa przycisku 1
    If Pind.0 = 0 Then
      Incr Sw1_licz
      If Sw1_licz = 100 Then
        Animacja = 0
      End If
    Else
      Sw1_licz = 95
    End If
 
  End If
 
  If F100m = 1 Then
    F100m = 0
     If Animacja = 1 Then
 
      If Poziom(1) < 100 Then Incr Poziom(1)
      If Poziom(1) > 20 And Poziom(2) < 100 Then Incr Poziom(2)
      If Poziom(2) > 20 And Poziom(3) < 100 Then Incr Poziom(3)
      If Poziom(3) > 20 And Poziom(4) < 100 Then Incr Poziom(4)
      If Poziom(4) > 20 And Poziom(5) < 100 Then Incr Poziom(5)
      If Poziom(5) > 20 And Poziom(6) < 100 Then Incr Poziom(6)
 
 
 
      'tutaj trzeba dopisać czekanie za pomocą licznika jeśli Poziom(5) = 100 i potem dalsza animacja gaszenia, na końcu animacja = 0 trzeba ustawić
    End If
    End If
 
Loop
 
 
Prztimer0:
If Licznik = 100 Then
  Licznik = 0
  Set F25m
  Incr Dziel
  If Dziel = 1 Then
    Dziel = 0
    Set F100m
  End If
End If
  Incr Licznik
 If Licznik < Poziom(1) Then Set Portc.3 Else Reset Portc.3
  If Licznik < Poziom(2) Then Set Portc.2 Else Reset Portc.2
   If Licznik < Poziom(3) Then Set Portc.1 Else Reset Portc.1
    If Licznik < Poziom(4) Then Set Portc.0 Else Reset Portc.0
     If Licznik < Poziom(5) Then Set Portb.5 Else Reset Portb.5
      If Licznik < Poziom(6) Then Set Portb.4 Else Reset Portb.4
Return

Portret użytkownika matrix

Re: Animacja

Jakoś nie widzi mi się ten fragment:

If Pind.0 = 0 Then
      Incr Sw1_licz
      If Sw1_licz = 100 Then
        Animacja = 0
      End If
    Else
      Sw1_licz = 95
    End If

Co on w ogóle robi poza czytaniem stanu przycisku? Wnioskuję że ma Ci liczyć od 95 do 100?

Tylko jak ma to właściwie działać skoro nie dopuszczasz do zwiększenia zmiennej każąc za każdym razem ustawiać zmienną Sw1_licz na 95.

Napisz tak:

If Pind.0 = 0 Then
    Incr Sw1_licz
      If Sw1_licz = 100 Then
        Sw1_licz = 95
        Animacja = 0
      End If
End If

Portret użytkownika maro

pwm

Również to nie działa

If Pind.0 = 0 Then
    Incr Sw1_licz
      If Sw1_licz = 100 Then
        Sw1_licz = 95
        Animacja = 0
      End If
End If

Portret użytkownika matrix

Re: Animacja

Przed pętlą główną wpisz do zmiennej Sw1_licz wartość początkową. Po co zliczasz od 95 do 100? Nie można od 0 do 5? Wpisz wartość 0.

Zaraz za tym wpisz wartość 0 do zmiennej:

Config Timer0 = Timer , Prescale = 8
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
 
Sw1_licz = 0

I dalej w odpowiednim miejscu wpisz to z tym sterowaniem przyciskiem:

If Pind.0 = 0 Then
   waitms 25
    Incr Sw1_licz
      If Sw1_licz = 5 Then
        Sw1_licz = 0
        Animacja = 0
      End If
End If

Jeśli to nie pomoże to trzeba się doszukiwać błędów w podłączeniu mechanicznym.

Portret użytkownika maro

PWM

Przycisk nie działał dopóki nie zmieniłem Animacja = 1
i teraz przycisk działa

If Pind.0 = 0 Then
   waitms 25
    Incr Sw1_licz
      If Sw1_licz = 5 Then
        Sw1_licz = 0
        Animacja = 0''''''''''''''''''''''Animacja = 1
      End If
End If

Mam jeszcze jedno pytanie czy gaszenie nie trzeba przypadkiem zrobić na dodatkowej zmiennej oznaczonej np kierunek?

Portret użytkownika matrix

Re: Animacja

Ja to w ogóle nie zauważyłem że obsługę przycisku masz w warunku:

If F25m = 1 Then
   If Pind.0 = 0 Then
   ...
   ...
   ...
   end if
end if

Czemu tak masz? Dziwne to jakieś.

Portret użytkownika maro

PWM

Mam jeszcze jedno pytanie czy gaszenie nie trzeba przypadkiem zrobić na dodatkowej zmiennej oznaczonej np kierunek?

Portret użytkownika mirley

Re: Przyciski

Obsługa przycisków:

If F25m = 1 Then
    F25m = 0
 
    'obsługa przycisku 1
    If Pind.0 = 0 Then
      Incr Sw1_licz
      If Sw1_licz = 100 Then
        Sw1_licz = 0
        Animacja = 0
      End If
    Else
      Sw1_licz = 95
    End If
 
End If

Jest jak najbardziej prawidłowa F25m taktuje sprawdzanie przyciku co 25ms (przecież nie wwalisz obsługi przycisków do do loopa bo to bezsens), w else zawsze Sw1_licz = 95 czyli pierwszy klik następuje po trzymaniu co najmniej 125ms przycisku. Jak trzymasz cały czas to reakcja następuje co 2,5s.

Odnosie animacji.. Chciałeś mieć zapalanie sekwencyjne a potem gaszenie sekwencyjne i stop. Czyli dodajesz kolejne linijki a całość wygląda tak:

      If Poziom(1) < 100 Then Incr Poziom(1)
      If Poziom(1) > 20 And Poziom(2) < 100 Then Incr Poziom(2)
      If Poziom(2) > 20 And Poziom(3) < 100 Then Incr Poziom(3)
      If Poziom(3) > 20 And Poziom(4) < 100 Then Incr Poziom(4)
      If Poziom(4) > 20 And Poziom(5) < 100 Then Incr Poziom(5)
      If Poziom(5) > 20 And Poziom(6) < 100 Then Incr Poziom(6)
 
      If Poziom(6) = 100 and Licz_anim < 100 Then Incr Licz_anim
 
      If Licz_anim = 100 And Poziom(1) > 0 Then Decr Poziom(1)
      If Poziom(1) < 80 And Poziom(2) > 0 Then Decr Poziom(2)
      If Poziom(2) < 80 And Poziom(3) > 0 Then Decr Poziom(3)
      If Poziom(3) < 80 And Poziom(4) > 0 Then Decr Poziom(4)
      If Poziom(4) < 80 And Poziom(5) > 0 Then Decr Poziom(5)
      If Poziom(5) < 80 And Poziom(6) > 0 Then Decr Poziom(6)
 
      If Poziom(6) = 0 Then Animacja = 0

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika morswin

Częstotliwość PWM

Witam

Jeżeli dobrze rozumiem to aby zmienić częstotliwość generowanego sygnału PWM w przerwaniu od timera należy wpisać jakąś wartość do licznik, zmieniając tą wartość zmieniać będzie się częstotliwość PWM?

Portret użytkownika mirley

Re: PwM

Programowy pwm można tak zrobić wpisując wartość Timer0 = X, dodajesz dzielnik = 256-X. Jesli chodzi o sprzętowy PWM to jest parametr w konfiguracji pozwalający uzyskać różne częstotliwości PWM

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika tevo

Witam Próbuję zastosować

Witam

Próbuję zastosować programowe pwm, ale coś mi nie wychodzi. Dostosowałem kod źródłowy z tej strony pod mój procesor ale mam problem. Otóż według tego programu powinna się zmieniać jasność świecenia leda a świeci się cały czas tak samo. Zmiana wartości preskalera powoduje tylko zmianę częstotliwości migania diody a chyba nie o to chodzi.

$regfile = "attiny26.dat"
$crystal = 1000000
 
Config Portb = &B11111111 : Portb = &B11111111
Config Porta = &B11111111 : Porta = &B00000010
 
Config Timer0 = 100 , Prescale = 1
Enable Timer0 : On Timer0 Prztimer0
Enable Interrupts
 
 
Gd Alias Porta.1
 
 
Dim Licznik As Byte
Dim  Gled As Byte
 
 
Gled = 10
 
Do
 
Loop
End
 
Prztimer0:
 Incr Licznik
 
 If Licznik = 100 Then Licznik = 0
 
 If Licznik < Gled Then Set Gd Else Reset Gd
 
Return