Wysyłanie i odbieranie danych w Visual basic

Pisanie aplikacji na PC w Visual Studio
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 11 sie 2018, 21:46

Witam. Panowie mam na pewnym etapie wykonany system kontroli i sterowania małą elektrownią solarną, ale niestety tak jak wspomniałem to połowa mojej roboty.
Otóż chciałbym mieć to pod kontrolą zdalną na PC. Łącze się za pomocą modułów HC-12 i ta łączność jest super. Do obsługi tego ustrojstwa wykorzystałem visual basic.
Tak na dobry początek wyskrobałem sobie malutki program, nawet kilka opcji pozwoliłem sobie zaczerpnąć od Pana Bartka.
No i teraz tak: atxmega wyśle dane jak się o nie poprosi żądaniem. Kawałek kodu z bascoma.
  1.       B1 = Ischarwaiting(#5)
  2.       If B1 = 1 Then
  3.          Print #5 , B1
  4.          Clear Serialin4
  5.          B1 = 0
  6.          Gosub Rs232
  7.       End If
  8.  
  9. Rs232:
  10.    Clear Serialin4
  11.    B3 = 0
  12.  
  13.    Do
  14.  
  15.       Print #5 , "Nacisnij ENTER "
  16.       Print #5 , "1 - Temperatura "
  17.       Print #5 , "2 - Ustaw Zegar "
  18.       Print #5 , "3 - Ustaw Date "
  19.       Print #5 , "4 - Pomiar VCC  "
  20.       Print #5 , "9 - EXIT SETUP  "
  21.       Input #5 , "Cakam na wybor ?" , B3
  22.       If B3 = Esc Then Gosub Podprogram
  23.       'B3 = Id
  24.       Print #5 , B3
  25.       If B3 = 1 Then
  26.          Clear Serialin4
  27.          Call Temperatura
  28.       End If
  29.       If B3 = 4 Then
  30.          Clear Serialin4
  31.          Call Read_mcp3421ch1
  32.       End If
  33.       If B3 = 2 Then
  34.          Clear Serialin4
  35.          Print #5 , "Wprowadz godzine : "
  36.          Info = 0
  37.          Input #5 , Info
  38.          Godziny = Info
  39.          Print #5 , "Wprowadz minuty : "
  40.          Info = 0
  41.          Input #5 , Info
  42.          Minuty = Info
  43.          Print #5 , "Wprowadz sekundy : "
  44.          Info = 0
  45.          Input #5 , Info
  46.          Sekundy = Info
  47.          Print #5 , "Status OK !"
  48.          Clear Serialin4
  49.          Call Settime
  50.       End If
  51.       If B3 = 3 Then
  52.          Clear Serialin4
  53.  
  54.          Print #5 , "Wprowadz dzien tygodnia 1-7 : "
  55.          Info = 0
  56.          Input #5 , Info
  57.          Dzien_tygodnia = Info
  58.          Print #5 , "Wprowadz dzien 1-31 : "
  59.          Info = 0
  60.          Input #5 , Info
  61.          Dzien = Info
  62.          Print #5 , "Wprowadz miesiac 1-12 : "
  63.          Info = 0
  64.          Input #5 , Info
  65.          Miesiac = Info
  66.          Print #5 , "Wprowadz rok 1-99 : "
  67.          Info = 0
  68.          Input #5 , Info
  69.          Rok = Info
  70.          Clear Serialin4
  71.          Print #5 , "Status OK !"
  72.          Call Setdate
  73.       End If
  74.       If B3 = 9 Then
  75.          Waitms 100
  76.          Gosub Podprogram
  77.       End If
  78.    Loop
Ale za groma nie mogę sobie poradzić aby te dane były wyświetlane nie w ogólnym terminalu tylko w moim programie na PC.
Przede wszystkim chodzi mi o odbieranie danych takich jak napięcia, temperatura. Format gotowy do wyświetlenia to
  1. vout=str(vin)
Byłbym bardzo wdzięczny za okazaną pomoc w tej sprawie, a poniżej główny kod.
  1. Imports System
  2. Imports System.Threading
  3. Imports System.IO.Ports
  4. Imports System.ComponentModel
  5. Public Class Form1
  6.     Dim myPort As Array              'posłuży do zebrania informacji o wszystkich dostępnych portach
  7.     Dim TestArray As String()        'zmienna Test podzielona/rozdzielona na małe stringi z indeksami
  8.     Dim pomiar_txt As String = ""          'wiadomość odebrana ze sterownika, po testach nazwa została :D
  9.     Dim tryb As Integer              'tryb w jakim pracuje sterownik ręczny/automatyczny
  10.     Dim zaczekaj As Boolean          'pomocniczy Bit by pominąć jeden odczyt
  11.     Delegate Sub TextCallback(ByVal [text] As String)
  12.     Delegate Sub SetTextCallback(ByVal [text] As String)
  13.  
  14.  
  15.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  16.         myPort = IO.Ports.SerialPort.GetPortNames()    'myPort przyjmuje informacje o dostępnych portach COM
  17.         portComboBox.Items.AddRange(myPort)            'rozwijana lista portów przyjmuje wartości z myPort
  18.         baudComboBox.Text = My.Settings.Baud_rate      'tekst przyjmuje wartość ostatnio zapamiętanego wyboru
  19.         portComboBox.Text = My.Settings.Port_numer     'tekst nazwy portu przyjmuje zapamiętaną wartość
  20.         ' CheckBox2.Text = My.Settings.Aux1              'nazwa dla dodatkowego wyjścia przyrównana do zapisanej
  21.         ' CheckBox3.Text = My.Settings.Aux2
  22.         'CheckBox1.Checked = My.Settings.Autostart      'wczytuje z pamięci czy połączyć automatycznie
  23.         Timer2.Enabled = True
  24.         Timer2.Interval = 1000
  25.         'Dialog1.Visible = False
  26.         Disconnect_Button.Enabled = False
  27.     End Sub
  28.  
  29.     Private Sub Connect_button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Connect_button.Click
  30.         ' MsgBox("Włączam Port Komunikacyjnu RS232/USB")
  31.         Try
  32.             SerialPort1.PortName = portComboBox.Text
  33.             SerialPort1.BaudRate = baudComboBox.Text
  34.             SerialPort1.Open()                           'otwieramy port
  35.             Timer1.Start()                               'uruchamiamy Timer1
  36.             zaczekaj = True                              'pomijamy jeden cykl odczytu (niekonieczne)
  37.             baudComboBox.Enabled = False                 'wyłączamy możliwość zmiany na otwartym porcie
  38.             portComboBox.Enabled = False                 'możliwość wyboru portu nieaktywna
  39.             Connect_button.Enabled = False               'połączony więc przycisk "Połącz" nieaktywny
  40.             Button_exit.Enabled = False
  41.             Disconnect_Button.Enabled = True             ' przycisk "Rozłącz"
  42.         Catch
  43.             MessageBox.Show("Wybierz numer portu COM", "Ostrzeżenie")
  44.             Connect_button.Enabled = False
  45.         End Try
  46.     End Sub
  47.  
  48.  
  49.     Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
  50.         ' My.Settings.Autostart = CheckBox1.Checked  'zmienna Autostart w My.Settings przyjmuje wartość CheckBoxa
  51.     End Sub
  52.  
  53.     Private Sub Disconnect_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Disconnect_Button.Click
  54.         Timer1.Stop()                           'zatrzymaj Timer1
  55.         Connect_button.Enabled = True           'aktywuj i dezaktywuj przyciski
  56.         Disconnect_Button.Enabled = False
  57.         Button_exit.Enabled = True
  58.         baudComboBox.Enabled = True
  59.         portComboBox.Enabled = True
  60.         SerialPort1.Close()                     'zamknij port
  61.     End Sub
  62.  
  63.     Private Sub portComboBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles portComboBox.SelectedIndexChanged
  64.         My.Settings.Port_numer = portComboBox.Text
  65.     End Sub
  66.  
  67.     Private Sub baudComboBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles baudComboBox.SelectedIndexChanged
  68.         My.Settings.Baud_rate = baudComboBox.Text
  69.     End Sub
  70.  
  71.     Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
  72.         ReceivedText(SerialPort1.ReadExisting())
  73.     End Sub
  74.  
  75.     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
  76.  
  77.     End Sub
  78.     ' Włączenie lub wyłączenie przekaźników systemu
  79.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
  80.  
  81.     End Sub
  82.  
  83.     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Enter
  84.  
  85.     End Sub
  86.  
  87.     Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
  88.         Label3.Text = TimeOfDay
  89.     End Sub
  90.     Private Sub ReceivedText(ByVal [text] As String) 'input from ReadExisting
  91.         If Me.RichTextBox1.InvokeRequired Then
  92.             Dim x As New SetTextCallback(AddressOf ReceivedText)
  93.             Me.Invoke(x, New Object() {(text)})
  94.  
  95.         Else
  96.             Me.RichTextBox1.Text &= [text] 'append text
  97.         End If
  98.     End Sub
  99.  
  100.     Private Sub GroupBox5_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBox5.Enter
  101.  
  102.     End Sub
  103.  
  104.     Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  105.         '  Dialog1.Visible = True
  106.  
  107.     End Sub
  108.  
  109.     Private Sub Button_exit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_exit.Click
  110.         Me.Close()
  111.     End Sub
  112.  
  113.     Private Sub Button2_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
  114.         SerialPort1.Write(RichTextBox1.Text & vbCr) 'concatenate with \n
  115.         RichTextBox1.Clear()
  116.     End Sub
  117.  
  118.     Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
  119.         SerialPort1.Write(RichTextBox1.Text & vbCr) 'concatenate with \n
  120.         ' RichTextBox1.Clear()
  121.     End Sub
  122.  
  123.     Private Sub PictureBox11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
  124.  
  125.     End Sub
  126.  
  127.     Private Sub PictureBox8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox8.Click
  128.  
  129.     End Sub
  130. End Class
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: niveasoft » 11 sie 2018, 22:43

Problemem w tym wszystkim jest tylko to że odbiór danych jest w innym wątku i nie możesz tak bezpośrednio w nim zmieniać coś w innych obiektach.
Po to tam były te Delegate i Callbacki, ale to wprowadza niepotrzebny galimatias.
Sprawa jest bardzo prosta i robi się to niemal tak samo jak w Bascom. Można sobie szukać różnych rzeczy funkcją "Instr".
Oczywiście reszta operacji na stringach też jest możliwa.

Wywalamy te Delegate a zamiast nich powołujemy dwie zmienne globalne "Received" i "Mystring"
Czyścimy ten sub który odbiera dane i wpisujemy prostą formułkę.
  1.     Dim received As String       'dwie globalne zmienne zamiast tych Delegate
  2.     Dim mystring As String
  3.  
  4. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
  5.  
  6.         received = received & SerialPort1.ReadExisting() 'dodawaj paczki danych aż znajdziemy Enter
  7.  
  8.         'szukamy Entera
  9.         If InStr(1, received, vbcr) > 0 Then 'czy w Received jest Enter?
  10.  
  11.             mystring = received 'przepisz dane
  12.             received = ""       'wyczyść string
  13.             Me.Invoke(New MethodInvoker(AddressOf ReceivedText))  'skocz do innego wątku
  14.  
  15.         End If
  16.  
  17.     End Sub
  18.  
Ta ostatnia linijka da znać innemu Subowi w programie że mamy nowe dane, ale oczywiście dopiero wtedy jak znajdziemy Enter ;)
  1.  
  2.     Private Sub ReceivedText() 'input from ReadExisting
  3.  
  4.         'w tym Subie już możesz bez problemu uaktualniać Labele czy Textboxy
  5.         'tu operujemy na globalnej zmiennej Mystring
  6.         'np dostaliśmy wiadomość "NAP=100,7"
  7.  
  8.         'szukamy..
  9.         If instr(1, mystring, "NAP=") > 0 Then 'jesli w stringu znaleźliśmy NAP=
  10.             'dzielimy sobie string od wystapienia znaku równości
  11.             Dim myarr() As String = mystring.Split("=") '
  12.             'teraz mamy dwa stringi
  13.             'w Myarr(0) mamy "NAP=" i to sobie odrzucamy
  14.             'wykorzystujemy drugi Myarr(1) w którym mamy "100.7"
  15.             'możesz teraz z tym zrobić co chcesz
  16.             MyLabel.Text = myarr(1) 'załadowanie do Labela
  17.             MyTextbox.Text = myarr(1) 'załadowanie do okienka tekstowego
  18.             'itd...
  19.  
  20.         End If
  21.  
  22.  
  23.     End Sub
Warto czasem sprawdzać If Myarr.Lenght > 0 ;)
Nie sposób wszystko opisać od razu a roboty tyle że nie wiadomo w co ręce włożyć :D
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 12 sie 2018, 18:29

No to pięknie, twoja regułka sprawiła że ożył mój panel kontrolny. Wielkie dzięki Bartku. Jedna sprawa już załatwiona.
A teraz kolejna może i łatwa, ale. Mam taką regułkę i jak nacisnę guzik pobierz dane to najpierw wysyła powiedzmy "id pomiaru" i to o co tak bardzo proszę odbiera tyle że jeden pomiar,
a ja chciałbym aby pomiary były odbierane wszystkie w odstępach czasowych 100ms.
  1.     Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
  2.         SerialPort1.Write("PN1" + Chr(13) + Chr(13))                      ' Temperatura 1
  3.         SerialPort1.Write("PN2" + Chr(13) + Chr(13))                      ' Temperatura 2
  4.         SerialPort1.Write("PN3" + Chr(13) + Chr(13))                      ' Napięcie 1
  5.       ' itd......
  6.     End Sub
Co robię nie tak ?
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: niveasoft » 12 sie 2018, 18:43

Do kolorowania wybieram u góry VB.NET

Robię to tak że używam do tego Timera co jest chyba oczywiste.
Więc pakujesz do aplikacji Timer i ustawiasz interwał na 100ms.
Potem dodajesz jedną zmienną globalną "DIm Sequence As Integer" żeby tak po amerykańsku ;)

W subie od zapytania dajesz tylko :
  1.  Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
  2.  
  3. Sequence = 4
  4. Timer1.Start()
  5.  
  6. End Sub
W subie od Timera czyli Tick:
  1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
  2.  
  3. If Sequence > 0 Then
  4.  Select Case Sequence
  5.    Case 4
  6.       SerialPort1.Write("PN1" + Chr(13) + Chr(13))                      ' Temperatura 1
  7.   Case 3
  8.       SerialPort1.Write("PN2" + Chr(13) + Chr(13))                      ' Temperatura 2
  9.   Case 2
  10.      SerialPort1.Write("PN3" + Chr(13) + Chr(13))                      ' Napięcie 1
  11.  
  12.   Case 1
  13.     Timer1.Stop()  'przykład
  14. End Select
  15.  
  16.  Sequence -= 1      'odejmuj jeden co 100ms
  17.  
  18. End If   ''Timer może sobie chodzić, ten kod się wykonuje tylko gdy Sequence > 0
  19.  
  20.  'możesz zatrzymać Timer kiedy zero itd..
  21.  
  22. End Sub
  23.  
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 12 sie 2018, 20:16

No i cacy! Teraz Pobiera dane każde do swojego miejsca tylko musiałem ustawić timer1 na 300ms bo te 100 to trochę za szybko. :o
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 15 sie 2018, 10:37

Bartku, a jak rozwiązać problem z otwieraniem pliku zewnętrznego typu exe. Chodzi o to że jak nacisnę przycisk "SET HC-12" to powinien otworzyć się podprogram zmieniający parapetry
modułu komunikacyjnego, i tak mam np.
  1.    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
  2.         System.Diagnostics.Process.Start("HC-12 config", "C:\Users\Karlos\Documents\Visual Studio 2010\Projects\System Kontroli MPPT\System Kontroli MPPT\bin\Release\HC-12 config.exe")
  3.  
  4.     End Sub
Jest to sposób niezbyt ciekawy. Na pewno jest inna możliwość. Dlatego że zawsze będę musiał się odwoływać do pełnej ścieżki, a wystarczyło by do samego katalogu projektu.
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: niveasoft » 15 sie 2018, 12:08

Myślę, że trzeba odczytać ścieżkę folderu z którego uruchamiasz program i dopisać do niej nazwę programu który chcesz uruchomić. Coś w ten deseń:
  1.  
  2.         Try
  3.             System.Diagnostics.Process.Start(My.Application.Info.DirectoryPath & "\moj_program.exe")
  4.  
  5.         Catch ex As Exception
  6.             MessageBox.Show("Brak programu moj_program.exe")
  7.         End Try
Poniżej masz kilka metod na określenie ścieżki programu:
  1. My.Application.Info.DirectoryPath
  2.  
  3. Environment.CurrentDirectory
  4.  
  5. System.Windows.Forms.Application.StartupPath
  6.  
  7. AppDomain.CurrentDomain.BaseDirectory
Pewnie jest tego więcej.
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 15 sie 2018, 23:27

Dzięki za podpowiedzi i jakoś się z tym uporałem. Co prawda wybrałem jednak sposób na otwarcie pliku poprzez dialog.
  1.     Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
  2.         OpenFileDialog1.Filter = "All Files |*.*"
  3.         If OpenFileDialog1.ShowDialog = DialogResult.OK Then
  4.             System.Diagnostics.Process.Start(OpenFileDialog1.FileName)
  5.         End If
  6.     End Sub
Jak by kto miał kłopoty z tym czymś.
Awatar użytkownika
Karlos128@nos
Posty: 54
Rejestracja: 18 sie 2015, 13:32

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: Karlos128@nos » 25 lis 2020, 10:37

Witam ponownie, moje pytanko jest takie :?:
W jaki sposób przepisać z MaskedTextBox1 w którym jest np. 25.35 do RichTextBox1, w którym to powinno wyświetlić się tak samo, a tu wyświetla 25,35.
Chodzi o to aby po 25 nie wstawiał przecinka tylko kropkę. Inaczej mówiąc chodzi mi o liczby dziesiętne.
Jest to dla mnie istotne bo chciałbym wysłać taką postać do xmegi .
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Wysyłanie i odbieranie danych w Visual basic

Post autor: niveasoft » 25 lis 2020, 13:00

replacechar
ODPOWIEDZ