PWM vezérlés RS485 buszon át
Hát ma kicsit ollózgattam és az eredmény a sikeres kommunikáció lett.
CRC16 ot kellene számoljak valahogy a master oldalon de ott VisualBasic6 van még ebben szeretnék segítséget kérni mert gugli most épp nem a barátom legalábbis amiket találtam mintákat azok nem nagyon állnak közel a várt értékekhez. Illetve lenne még 1 dolog, PC ventillátor fordulatszámát szeretném szabályozni(hőfok fügvényében), és lekérdezni(rs485).
Szabad lábak még az int0 , adc0,1,7 , oca1a , icp1a
A kódom ami sikeres lett eddig:
CRC16 ot kellene számoljak valahogy a master oldalon de ott VisualBasic6 van még ebben szeretnék segítséget kérni mert gugli most épp nem a barátom legalábbis amiket találtam mintákat azok nem nagyon állnak közel a várt értékekhez. Illetve lenne még 1 dolog, PC ventillátor fordulatszámát szeretném szabályozni(hőfok fügvényében), és lekérdezni(rs485).
Szabad lábak még az int0 , adc0,1,7 , oca1a , icp1a
A kódom ami sikeres lett eddig:
Kód: Egész kijelölése
$regfile = "m8def.dat"
$crystal = 11059200
$baud = 19200
Config Sda = Portc.4
Config Scl = Portc.5
Config Serialin = Buffered , Size = 64 , Bytematch = 10
Enable Interrupts
Echo Off
Const Master = "00"
Dim Slave As String * 2
Slave = "01"
Const Namee = "ARA600"
Const Sep = "#"
Dim Rpmmsb As Byte
Dim Tempmsb As Byte
Dim Templsb As Byte
Dim S_cmd As String * 20
Dim S_val As String * 20
Dim S_slave As String * 2
Dim Tmp_line As String * 255
Dim Chk As String * 4
Dim Chk_a As Integer
Dim Chk_c As Byte
Dim Chk_line As String * 255
Dim Homero As String * 7
Dim Speed As String * 8
Dim Olvas As Byte
Dim Chkstart As String * 1
Dim Dd As String * 2
Dim Ddh As String * 2
Dim Error As Byte
Dim Flag As Byte
Dim Tel As Integer
Dim Teltmp As Integer
Dim Tmp As String * 1
Dim Ss As String * 2
Dim G_cmd As String * 20
Dim S_chk As String * 4
Dim G_val As String * 20
Dim Ge_val As String * 20
Dim Tmp_cmd As String * 20
Dim Cik As Byte
Dim Tmp_cik As Byte
Dim Tmp_cikk As Byte
Declare Sub Send_line(byval Slave As String , Byval S_cmd As String , Byval S_val As String)
Declare Sub Checksumm(chk_line As String)
Declare Sub Readtemp(tempmsb As Byte)
Declare Sub Readrpm(rpmmsb As Byte)
Declare Sub Startconvert()
Declare Sub Get_line(tmp_line As String , Flag As Byte , Error As Byte)
Declare Sub Getval(g_cmd As String)
Olvas = 0
'******** Main program **************************
Call Startconvert
Reset Portd.3
Do
If Olvas > 0 Then 'Ha érkezett $10 az UARTra akkor ugrás a rutinra
Gosub Rs485cmd
End If
Loop
'******** end main program **********************
End
Rs485cmd: 'Ez már a BenBus része
'Print "getline"
Call Get_line(tmp_line , Flag , Error)
'Reset Watchdog 'töröljük az UART IN buffert
'Clear Serialin
'Csak hibakeresésre
'Print "Get_line :" ; Tmp_line ; " F:" ; Flag ; " E:" ; Error
'Print "Chk :" ; Chk
' Flag = 1, ha a csomag hibátlan, elválasztó jelek a helyükön vannak és az ellenőrző összeg OK
' G_cmd változóba kerül be a master által küldött parancs
' G_val változóba kerül be a master által küldött érték
' 3 = ellenőrző összeg hiba
' 4 = slave nem válaszol
' 5 = nyitó karakter hibás
' 6 = elválasztó karakter 1 nem jó
' 7 = elválasztó karakter 2 nem jó
' 8 = elválasztó karakter 3 nem jó
' 9 = zárókarakter hibás
If Flag = 1 Then
Select Case G_cmd
Case "[PING]" : Call Send_line(slave , Namee , "PONG" )
Case "[GET]" :
Select Case G_val
Case "TEMP" :
Call Readtemp(tempmsb)
Call Send_line(slave , "[Temp]" , Homero)
Case "FANS" :
Call Readrpm(rpmmsb)
Call Send_line(slave , "[Fans]" , Speed)
Case Else : 'Ismeretlen, vagy nem feldolgozott a g_val értéke
Call Send_line(slave , "unknow value" , G_val) 'ezért unknow választ küldünk masternak
End Select
Case Else:
Call Send_line(slave , G_cmd , "unknow cmd") 'ismeretlen parancsra válasz a masternak
End Select
End If
Clear Serialin 'UART IN buffer törlése
Olvas = 0
Return
'******** start convert *************************
Sub Startconvert()
I2cstart
I2cwbyte &H90
I2cwbyte &HEE
I2cstop
End Sub
'************************************************
'******** read temperature **********************
Sub Readtemp(tempmsb As Byte)
'-------------
I2cstart
I2cwbyte &H90 'send adress byte
I2cwbyte &HAA 'send register byte
I2cstop
I2cstart
I2cwbyte &H91 'read register
I2crbyte Tempmsb , Ack
I2crbyte Templsb , Nack
I2cstop
Tempmsb = Tempmsb - 3
Homero = Str(tempmsb) 'homero változóba összeállítjuk a visszakapott adatokat
Homero = Homero + ","
Homero = Homero + Str(templsb)
Homero = Homero + "C"
End Sub Readtemp
'************************************************
'******** read rpm ******************************
Sub Readrpm(rpmmsb As Byte)
'-------------ide kellene a ford. szám mérés
Speed = "1260"
Speed = Speed + "Rpm"
End Sub Readrpm
'************************************************
'************************************************
Serial0charmatch:
Olvas = 1
Return
'************************************************
'************************************************
Sub Send_line(byval Slave As String , Byval S_cmd As String , Byval S_val As String)
Portd.3 = 1
Tmp_line = "{" + Master + Sep + Slave + Sep + S_cmd + "[" + S_val + "]" + Sep
Call Checksumm(tmp_line)
Tmp_line = Tmp_line + Chk + "}" : Print Tmp_line : Tmp_line = " "
Waitms 100
Portd.3 = 0
End Sub Send_line
'************************************************
'************************************************
Sub Checksumm(chk_line As String)
Chk_c = Len(chk_line)
Chk_a = Crc16(chk_line , Chk_c)
Chk = Hex(chk_a)
End Sub
'************************************************
'************************************************
Sub Get_line(tmp_line As String)
Error = 0
Flag = 1
'slave
Input Tmp_line ' no timeout
Chkstart = Left(tmp_line , 1)
If Chkstart = "{" Then
Dd = Mid(tmp_line , 2 , 2)
If Dd = Slave Or Dd = "99" Then
If Tmp_line = "" Then
Error = 4 : Flag = 0
Else
Tel = Len(tmp_line) : Tmp = Left(tmp_line , 1)
If Tmp = "{" Then
Tmp = Mid(tmp_line , 4 , 1)
If Tmp = Sep Then
Tmp = Mid(tmp_line , 7 , 1)
If Tmp = Sep Then
Teltmp = Tel - 5 : Tmp = Mid(tmp_line , Teltmp , 1)
If Tmp = Sep Then
Tmp = Right(tmp_line , 1)
If Tmp = "}" Then
Dd = Mid(tmp_line , 2 , 2)
If Dd <> Slave And Dd <> "99" Then Flag = 0
Ss = Mid(tmp_line , 5 , 2) : Teltmp = Tel - 13 : G_cmd = Mid(tmp_line , 8 , Teltmp)
Teltmp = Tel - 4 : S_chk = Mid(tmp_line , Teltmp , 4)
G_val = ""
Ge_val = ""
Call Getval(g_cmd)
If Len(g_val) > 0 Then
G_cmd = Tmp_cmd
Ge_val = "[" + G_val + "]"
End If
If Dd = "99" Then
Ddh = "99"
Else
Ddh = Slave
End If
Tmp_line = "{" + Ddh + Sep + Master + Sep + G_cmd + Ge_val + Sep
Call Checksumm(tmp_line)
Tmp_line = Tmp_line + Chk + "}"
If Chk <> S_chk Then
Error = 3 : Flag = 0
End If
Else
Error = 9 : Flag = 0
End If
Else
Error = 8 : Flag = 0
End If
Else
Error = 7 : Flag = 0
End If
Else
Error = 6 : Flag = 0
End If
Else
Error = 5 : Flag = 0
End If
End If
If Flag = 0 Then G_cmd = ""
Else
Flag = 0
End If
Else
Flag = 0
End If
End Sub
'
'*********************************************************************************
'*********************************************************************************
Sub Getval(g_cmd As String)
Tmp_cik = Len(g_cmd) - 1 ' g_cmd hossza-1
Tmp_cikk = Tmp_cik + 1 ' g_cmd hossza
For Cik = 2 To Tmp_cik Step 1 ' végégmegyünk g_cmd-n
Tmp_cmd = Mid(g_cmd , Cik , 1) 'kivágunk egy karaktert
If Tmp_cmd = "[" Then Tmp_cikk = Cik 'ha "[" akkor megjegyezzük a pozicióját
Next Cik
Cik = Tmp_cikk 'cik egyenlő a "["pozíciójával
Incr Cik 'cik +1 átugorjuk a "[" zárójelet
If Cik < Tmp_cik Then 'ha cik még kiebb mint a g_cmd hossza akkor
Tmp_cikk = Tmp_cik - Cik 'vége - eleje = hossz
Incr Tmp_cikk
If Tmp_cikk >= 1 Then
G_val = Mid(g_cmd , Cik , Tmp_cikk)
Decr Cik
Decr Cik
Tmp_cmd = Mid(g_cmd , 1 , Cik)
End If
End If
End Sub
'*********************************************************************************
Kipróbáltam, így most működik, de csak ledet tettem rá.
Milyen megoldást lehetne kitalálni hogy a pc ventit tudja szabályozni?
Szerintem a + ágba kellene valamit beiktatni, mert a gndnek fixnek kellene lennie a benne lévő fordulatszám mérő miatt.
Vagy annak a + kell hogy fix legyen(valahol ilyet is olvastam)?
Hogy működhet ez?
Arra milyen csatolást lehetne csinálni? Gondoltam 1k val felhuzom + ra az int0 lábat teszek rá egy 5,1v -os zenert és a venti jeladó lábát. Ez így jó lehet?
Pwm kimenetre pedig egy npn és egy pnp fet ?
Kód: Egész kijelölése
'PWM
Config Timer1 = Pwm , Prescale = 256 , Compare A Pwm = Clear Down
Enable Timer1
Start Timer1
Config Portb.1 = Output
Dim Pwm_a As Byte
Kód: Egész kijelölése
Pwm1a = 0
Do
For Pwm_a = 1 To 255
Pwm1a = Pwm_a
Pwm_a = Pwm_a + 1
Waitms 10
Next Pwm_a
Loop
Szerintem a + ágba kellene valamit beiktatni, mert a gndnek fixnek kellene lennie a benne lévő fordulatszám mérő miatt.
Vagy annak a + kell hogy fix legyen(valahol ilyet is olvastam)?
Hogy működhet ez?
Arra milyen csatolást lehetne csinálni? Gondoltam 1k val felhuzom + ra az int0 lábat teszek rá egy 5,1v -os zenert és a venti jeladó lábát. Ez így jó lehet?
Pwm kimenetre pedig egy npn és egy pnp fet ?
Hülye tipp:
- tranzisztor, akár a gnd fele is, és innentől a ventillátor megy a kollektorkörbe. Itt kondival simítani a lüktetést.
- Optocsatolóval jelfordítást végezni. Vagy simán hajts meg egy tranzisztoros forídtóval egy P-FET-et (+ ág szaggatás).
- műveleti erősítővel PWM-> analóg jel -> erősítés
- kapcsolóüzemű táp, szabályzott visszacsatoló körrel...
Megyek pihenni ...
Mintha Sirleslie valamelyik évi versenyre küldött volna be ilyen szabályozást Tiny13 alapúal...
Az INT az jó. Amire vigáyzz: GND-ne szaggass a ventillátornál, mert az azonnal INTet generál . A venti kimeneti láb ra soros ellenállás (1k...3k3), és a AVRláb-GND közé 5V1 zener.
- tranzisztor, akár a gnd fele is, és innentől a ventillátor megy a kollektorkörbe. Itt kondival simítani a lüktetést.
- Optocsatolóval jelfordítást végezni. Vagy simán hajts meg egy tranzisztoros forídtóval egy P-FET-et (+ ág szaggatás).
- műveleti erősítővel PWM-> analóg jel -> erősítés
- kapcsolóüzemű táp, szabályzott visszacsatoló körrel...
Megyek pihenni ...
Mintha Sirleslie valamelyik évi versenyre küldött volna be ilyen szabályozást Tiny13 alapúal...
Az INT az jó. Amire vigáyzz: GND-ne szaggass a ventillátornál, mert az azonnal INTet generál . A venti kimeneti láb ra soros ellenállás (1k...3k3), és a AVRláb-GND közé 5V1 zener.
Ez a kapcsolás jó lehet nekem?(7805 háttal )
A hozzászólást 1 alkalommal szerkesztették, utoljára tetye 2012. október 1. hétfő, 16:03-kor.
Amit én néztem az csak 3 vezetékes, 8x8cm elég nagy fordulatú, ezért gondoltam a bd138 ra mert nagyon nem tudom hűteni így talán nem is melegedne. A diódát csak azért raktam oda hogy védje a tranyót a ventitől. De igen oda szerintem teszek egy soros diódát is a + ágba hogy csak arra folyjon a feszültség. Rajzon változtattam, de ha gnd re is 10kval húzom és az avr is 10k val húzza 5 v-ra lesz ott elég áram neki a nyitáshoz? Ill ezt a pwm sebességével tudja majd produkálni? Ezekhez a számolásokhoz nem vagyok elég képzett....(Villanyszerelőim van).
Az NPN-nek biztosan elég a nyitáshoz, a felső PNP tranyó bétáját kellene tudni as pontosításhoz, de ha van szkópod, akkor megnézed, hogy kerekedik-e a kapcsoláskor a PNP-n a fesz. Akkor csökkenteni kell a 4.7k és a 10k-t is (nagyobb bázisáram kell). De ránézésre jónak kell lennie, ha nagyon melegszik a PNP, akkor beállt analógba, akkor mondjuk megfelezed az ellenállásokat.
JAni
JAni
Újra itt!
Siker, működik a pwm már tekeri a ventit a fenti kapcsolással bár a bc547 helyett 337-et tettem. Nem melegszik semmi.
Szintet lépnék fordulatszám mérésre.
A kapcsolás a rajzon van ahogy bekötöttem a jeladót.
Programban kérnék segítséget.
Ha INT0-ban kezelem le mint megszakítást és számolom hogy 2 megszakítás közt mennyi idő telik el, megkapom ,hogy mennyit forog, eddig tiszta. De ha én INT0 ban számolgatom akkor mikor fog futni a program többi része? pl a hő mérés, pwm szabályzás, RS485 kommunikáció?
Arra gondoltam, berakom INT0 ba a mérést, RS bytematch-al generál egy megszakítást ha bejön kérés, ekkor kikapcsolná az INT0 amíg lefut, majd vissza. Ez így nem lenne rossz, de a pwm-et nem tudja még ettől szabályozni közben hőmérséklet függvényében. Tudnátok még ebben segíteni hogy hogy oldjam meg?
Siker, működik a pwm már tekeri a ventit a fenti kapcsolással bár a bc547 helyett 337-et tettem. Nem melegszik semmi.
Szintet lépnék fordulatszám mérésre.
A kapcsolás a rajzon van ahogy bekötöttem a jeladót.
Programban kérnék segítséget.
Ha INT0-ban kezelem le mint megszakítást és számolom hogy 2 megszakítás közt mennyi idő telik el, megkapom ,hogy mennyit forog, eddig tiszta. De ha én INT0 ban számolgatom akkor mikor fog futni a program többi része? pl a hő mérés, pwm szabályzás, RS485 kommunikáció?
Arra gondoltam, berakom INT0 ba a mérést, RS bytematch-al generál egy megszakítást ha bejön kérés, ekkor kikapcsolná az INT0 amíg lefut, majd vissza. Ez így nem lenne rossz, de a pwm-et nem tudja még ettől szabályozni közben hőmérséklet függvényében. Tudnátok még ebben segíteni hogy hogy oldjam meg?
ITben csak tedd el az időmérő értékét, a többit majd intézi a főprogram:
Int:
idovaltozo=timer
timer=0
return
A főprogramba meg csak az időváltozóval foglalkozol és szabályozod, ami kell. Elvileg az INT-ed "láthatatlan" lesz, többet nem is kell vele foglalkozni. Ha nagyon pipeckedni kell, akkor duplán pufferelheted a változód, de itt szerintem nem okoz nagy hibát.
JAni
Int:
idovaltozo=timer
timer=0
return
A főprogramba meg csak az időváltozóval foglalkozol és szabályozod, ami kell. Elvileg az INT-ed "láthatatlan" lesz, többet nem is kell vele foglalkozni. Ha nagyon pipeckedni kell, akkor duplán pufferelheted a változód, de itt szerintem nem okoz nagy hibát.
JAni