Komunikace po sériovém portu   zodpovězená otázka

VB.NET, Hardware

Ahoj,

viděl jsem již několikrát omýlané články jak je komunikace na sériovém portu jednoduchá a že se pro ni nemusí zakládat žádný článek, ale to je tak na každém serveru a kakoce žádný článek založený není (nebo jsem jenom špatně hledal).

Zkrátka jde mi o to že potřebuji nejak zpracovat data přenášená do počítače přes sérivý port z mé stavebnice arduina.

Většinou se neco naučím pouze ze zdrojáku, tak bych chtěl poprosit, zda tu není nějaký dobrodinec, který by mi ukázal kus kódu pro komunikaci po sériové lince, klidně i bez popisu, já už to nějak přechroustám.

Nejsem žádný odborník na VB, začal jsem se jej uči jen kvůli přítelkyni abych jí pomohl se školou. Když už ale mám základy tak bych toho chtěl využít.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Dobrý den.

Komunikace přes sér. port je vážně jednoduchá.

Stačí, když si z ToolBoxu vezmete komponentu SerialPort (je to v kategorii Components) a nebo objekt IO.Ports.SerialPort který si nadeklarujete jako WithEvents

 SerialPort1.PortName = "COM1" 'nastaví port na COM1
 SerialPort1.Bitrate = 9600 'nastaví rychlost
 SerialPort1.Open() 'otevře port
 SerialPort1.Close() 'zavře port
 SerialPort1.IsOpen() 'Boolean. Zjistí jestli je port Otevřen
 SerialPort1.Write("text") 'něco napíše
 SerialPort1.DtrEnabled = True/False 'aktivuje/deaktivuje DTR
 SerialPort1.DsrHolding 'Boolean. Zjistí jestli je DSR aktivní
 SerialPort1.Encoding = System.Text.Encoding.UTF8 'UTF8-kódování
 'odchytávání dat
 Private Sub SerialPort1_DataReceived(sender As Object, e As SerialPortDataReceivedEventArgs) Handles SerialPort1.DataReceived
 MsgBox(SerialPort1.ReadExist) 'ukaž přijaté data
 End Sub

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Díky moc za návod na ten sériový port, jak přijedu domů z práce tak to hned vyzkouším. Dodatečně se omlouvám za tón se kterým jsem to napsal, ale byl jsem rozčílen z příspěvku jednoho nepříjemného vývojáře z tohoto serveru.

Ještě jednou Díky moc i za to okomentování.

Petr Dunaj

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ahoj,

potom co napíšu ten program asi tak, jak je níže uvedeno ve zdrojáku, mi to vypíše pro řádek Label1.Location...:

Operace mezi podprocesy není platná: Přístup k ovládacímu prvku Form1 proběhl z jiného podprocesu než z podprocesu, v rámci kterého byl vytvořen.

Private Sub SerialPort1_DataRecieved(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim data As String = SerialPort1.ReadLine
        Dim osax As Integer = 0
        Dim osay As Integer = 0

        If data.StartsWith("X") And data.Length < 6 Then
            osax = CInt(data.Substring(2, data.Length - 2))
        End If

        If data.StartsWith("Y") And data.Length < 6 Then
            osay = CInt(data.Substring(2, data.Length - 2))
        End If

        Label1.Location = New Point(Label1.Location.X + osax, Label1.Location.Y + osay)
End Sub

Zkoušel jsem to různě přepisovat, ale pořád stejný výsledek.

Petr

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den.

Také mi to dělalo problémy. Je to myslím vlákny (viz.

http://vbnet.cz/forum-tema--389-opet_rs_... )

Pro váš případ je to nějak takhle:


    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        If Me.InvokeRequired() Then
            Dim dr As New DataRecievedDelegate(AddressOf DataRecieved)
            Me.Invoke(dr, e, serialport1.ReadLine)
        Else
            DataRecieved(e, SerialPort1.ReadLine)
        End If
    End Sub

    Delegate Sub DataRecievedDelegate(ByVal e As System.IO.Ports.SerialDataReceivedEventArgs,ByVal linka as string)

    Sub DataRecieved(ByVal e As System.IO.Ports.SerialDataReceivedEventArgs, ByVal linka As String)
        Dim data As String = linka
        Dim osax As Integer = 0
        Dim osay As Integer = 0

        If data.StartsWith("X") And data.Length < 6 Then
            osax = CInt(data.Substring(2, data.Length - 2))
        End If

        If data.StartsWith("Y") And data.Length < 6 Then
            osay = CInt(data.Substring(2, data.Length - 2))
        End If

        Label1.Location = New Point(Label1.Location.X + osax, Label1.Location.Y + osay)

    End Sub

Musíte si udělat proceduru (zde DataRecieved) ve které budete mít parametr toho eventargs a své další. Poté jí v DataRecieved SerialPortu jen zavoláte.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den, jak ošetřit, že program spustí automaticky další událost, jakmile je operace v DataReceived dokončena?

(Napadá mě např. zadání příkazu uspat vlákno Thread.Sleep(xx) na nějakou dobu po zadání příkazu po sériovém portu, abych ho nepřehltil, ale nevím, jestli je to vhodný postup.)

- s tím souvisí: zajistí mi garbage collector odpojení od sériového portu automaticky, či musím nějak zajistit odpojení po skončení přenosu?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ad 1) Ono já bych to řešil tak že bych si tu "další událost" dal do procedury a do DataReceived bych dal jen něco jako Procedura("parametr")

Ad 2) Ten sériový port se odpojí po ukončení aplikace, pokud ho tedy předčasně neukončíte pomocí port.Close(). Pokud máte port jako komponentu tak ji odeberete pomocí

Me.Controls("portName").Remove 

nebo nějak tak. Pokud jej máte vytvořený jako proměnnou (IO.něco.SerialPort) tak jej odstraníte pomocí Dispose() (myslím) nebo vynulujete pomocí proměnná = Nothing

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jak uz tu padlo, je to problem s krizenim vlaken.

Komponenty, domnivam se, ze zejmena deklarovane s WithEvents, jsou vytvoreny "v ramci" nejakeho vlakna a mohou v ramci tohoto vlakna vykonavat nejakou cinost (interni funkcionalita a vyhazovani udalosti musi zrat cas nejakeho vlakna). Jakmile zacnu po komponente neco chtit a pohybuju se v jinem vlakne (treba obsluha timeru, volani z nejake jine casti programu s vlastnim vlaknem a podobne), muzu zpusobit problem - bude se treba zapisovat do mista, ze ktereho se prave cte, a zpusobit nejakou nekoznistenci atd atd atd ....

Problem se komponentou SerialPort je, ze pokud si ji naklikate do formulare, bude vytvarena v ramci formulare pomoci GUI vlakna.

Reseni (teoreticky) ... vice se zabejvat vlaknama a mit prehled o tom co se kde vytvari a rozdelit program na oddelene casti (gui, data, io). Pak se bude hodit i prace s delegatama a tady uz zminovanym "invoke" - umoznuje vyvolat udalost/volani v ramci jineho vlakna. A pro operace, ktere mohou probihat nekde na pozadi, se hodi Background Worker (bezi si potichu ve vlastnim vlakne...takze by mohl treba samostatne zpracovat i veci kolem serioveho portu, atd atd).

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Pro komunikaci přes port potřebujete vědět jak komunikuje vaše stavebnice arduina. Myslím protokol nebo v asci.Je potřeba vědět, na jaké příkazy bude stavebnice reagovat.

nahlásit spamnahlásit spam -2 / 2 odpovědětodpovědět

Ohledně příkazů je to v pohodě, já jsem jenom potřeboval vědě jak navázat komunikaci.

Petr Dunaj

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback