News:

;) This forum is the property of Proton software developers

Main Menu

Looking for a Programming Language for pc to display serial data

Started by TimB, Jul 16, 2023, 02:39 PM

Previous topic - Next topic

TimB


Hi all


I'm looking for a way to display serial data on a PC. Is there a PC programming language or even an app that will let me parse serial data and display it.

I do not need fancy graphics but I need to do raw data conversion eg Mchip float format to display it on the screen.

I really need to be able to make changes myself as the data I send out changes with my requirements.

Thanks

Tim

trastikata

I used in the past MS Visual Studio with Visual Basic for some GPS serial data processing. Reception, parsing, conversion and visualization is all quite straightforward with many on-line examples.

JonW

I use xojo for serial terminals.  Similar to VB

okmn

i was using Profilab expert  of Abacom
you have to check it , if you need only  windows OS supporting



RGV250

Hi Tim,
I use xojo (it started out as Real Basic) and found it very simple to get serial comms going. I found it much easier than Visual studio. I haven't used it in a while but if you go that route I should be able to find a simple demo for you to get started.
The other good thing is it is free to try and you only need a licence when you deploy it.

Bob

okmn

i just remembered a free software
it is  name Processing
a my friend had used it and his app was great.

https://processing.org/download

Class for sending and receiving data using the serial communication protocol.
https://processing.org/reference/libraries/serial/Serial.html


TimB

Many thanks all.

xojo looks interesting and I may take you up Bob, on any code you can offer to get me started

I was also looking at Pure Basic.

I'm also going to check out the other suggestions.

Tim

JonW

Xojo also has a lot of very powerful addons written by Monkeybread.  I tend to use these for Comms as they can get down another layer and get access to the RTS lines etc

What is the repetition rate you are wanting to receive at Tim?  Also are you wanting to receive binary data or ASCII encoded floating point data?

 

TimB

Thanks JonW

I have been watching some videos on Xojo. I really like it and think I can do stuff with it. My mission is to learn it now.

The data is sent every 1hz (every second) it is normally 55 bytes long. It starts with $55 then the number of bytes then the data.

In my current implementation I'm sending the data out on both USARTS. Usart1 is talking to the display handler pic and the interrupt driven RX on that device works like modbus in that on every RX it loads a software timer. After x ms it flags that there is data. The RX decoding routine then checks for the $55 and compares the packet size to that actually received. Is its ok it just loads the bytes into it duplicate variables/types and uses the data,

So to answer your question the data is sent every 1hz and is binary data.

'*******************************************************************************
'* Title  :  SendTX1Data
'* Input  :  None
'* Notes  :  Sends the data out to the front end via the USART
'*******************************************************************************

    Dim cGeneralDataPacketSize as 55                                            ' This is the number of bytes in the data being sent

    Dim cSettingsDataPacketSize as 17

    Proc SendTX1Data()


        If bTXMode = cNormalComsMode then




        ' Pack the current status Info

            bTemp1 = bMainStateSubState << 4
            bTemp1 = bTemp1 ^ bMainState





            HRSOUT $55                                                              ' Send the sync byte  1
            Hrsout cGeneralDataPacketSize                                           ' 2

            Hrsout fLastDrynessResult                                               '
            Hrsout fLastNCResult                                                    '
            HRSOUT fLastSuperHeat                                                   '

            Hrsout fCurrentNC                                                       '
            HRSOUT fSuperHeat                                                       '

            Hrsout fCurrentNCTotal_ml                                               '
            HRSout fTotal_Flow_ml                                                   '

            Hrsout wMainSteamPress                                                  '     ;<<<<<<<<<<<<<
            Hrsout wPostOrificePress                                                '
            hrsout fT1_TempC                                                        '

            HRSOUT fFlowMls                                                         '
            Hrsout fNCFlowMls                                                       '

            Hrsout fHz1NCVolume_ml                                                  '

            Hrsout bCondenceTemp                                                    '

            HRSOut bTemp1                                                           '

            HRSOUT wErrors                                                          '

            Hrsout bI_OStatus

        Endif

        If bTXMode = cSettingsComsMode then


            HRSOUT $55                                                          ' Send the sync byte  1
            Hrsout cSettingsDataPacketSize                                      ' 2

            ' Send the data required to calibrate

            hrsout fT1_TempC                                                    ' 6
            Hrsout wMainSteamPress                                              ' 10
            Hrsout wPostOrificePress                                            ' 14

            ' Send the DAC channel info

            Hrsout bDACChannel1                                                 ' 15
            Hrsout bDACChannel2                                                 ' 16
            Hrsout bDACChannel3                                                 ' 17
            Hrsout bDACChannel4                                                 ' 18

            ' Send the Input channel info

            Hrsout bInputChannel1                                               ' 19
            Hrsout bInputChannel1                                               ' 20

            ' Send hardware related info eg valve status alarms etc
            Hrsout bI_OStatus

        Endif



    EndProc






trastikata

TimB, are you using the actual COM port on your PC or some Serial-USB-COM emulator?

If you are using Serial-to USB-to COM, not all languages have the correct drivers for handling the COM emulation.

TimB


JonW

To make the parsing of the data easier in Xojo its probably best to send it as ascii with a seperator character with a start and end character, for example >1122:-3344:12:11<.  You can then easily search the string and convert each segment rather than have to convert the raw binary data.  Its also easier to read.

Stephen Moss

I have used Visual Basic to send/recive data to an Arduino which essentialy acts as a serial device for its PC interface, Arduino sends data every 200mS.  I was not using it as a way of displaying the raw serial data but to do so you would just have to place a TextBox on your form and add the code to append the received serial data to it.
 
The form in my application does have a Connect/Disconnect button for the com port, a Dropdown Combo box to select the Com port to connect to, and a Serial Port added to it. My code for setting up the comms side of the program is below, obviously some of it will be appliacable to my specific appliaction but it should be enough to get someone wanting to use VB to create a serial interface started.
    '==================================================================================
    '=== Commumications:                                                            ===
    '=== Handles...                                                                ===
    '=== Connection/Disconnection to Drive Board (Connect_Disconnet_Button)        ===
    '=== Opening the Serial Port (Open_Serial_Port)                                ===
    '=== Closing the Serial Port (Close_Serial_Port)                                === OK --/--/2018
    '=== Select Drive Board Com Port (Select_ComPort)                              ===
    '=== Refresh Active Comport Listbox (Refresh_Com_Ports)                        ===
    '=== Display waring message of coms failure (No_Comms_MsgBox)                  ===
    '==================================================================================

    'Must define "WithEvents" hooks to Form1 controls so that they can be handeled by code located withing the module rather than the form
    'Call Configure_ComPort() required in Form Load event to call module otherwise does not work!

    'Define Hooks to Form1 Buttons so that Click events can be handled within the module rather than in the form
    Public WithEvents Connect_Disconnect_Button As Button = Form1.Connect_Button
    Public WithEvents Select_Comport1 As ComboBox = Form1.ComPort_ComboBox
    Public WithEvents Refresh_Comports_Button As Button = Form1.Refresh_Button
    Public SerialPort2 As New IO.Ports.SerialPort
    'Public Get_Data As New IO.Ports.SerialDataReceivedEventHandler(AddressOf Get_Serial_Data)



    '===== Configure Com Port ===== OK 15/03/20 (Called from From1 Load event)
    Public Sub Configure_ComPorts()

        Try
            'Clear ComPort Listbox
            Form1.ComPort_ComboBox.Items.Clear()  'Belt & Braces as should be clear anyway

            'Populate Comport Combobox with active comports
            For Each sp As String In My.Computer.Ports.SerialPortNames
                Form1.ComPort_ComboBox.Items.Add(sp)
            Next

            'Set Defualt comport - NOTE COM1 is usually PC internal so default is to last Comport found
            If Form1.ComPort_ComboBox.Items.Count > 1 Then
                Form1.ComPort_ComboBox.SelectedIndex = (Form1.ComPort_ComboBox.Items.Count - 1)    'Display Name of Last Comport Found
            Else
                Form1.ComPort_ComboBox.Text = Form1.ComPort_ComboBox.Items.Item(0)                  'Display Name of only Comport Found
            End If

            'Configure Comport with Arduino compatible settings
            If Alt = True Then
                'Configure Comport with Arduino compatible settings
                SerialPort2.PortName = Form1.ComPort_ComboBox.SelectedItem    'Set Comport to Open - Default last Active ComPort in list
                SerialPort2.BaudRate = 19200                                  'Set Baud Rate
                SerialPort2.DataBits = 8                                      'Set Number of Fata Bits
                SerialPort2.Parity = IO.Ports.Parity.None                    'Set Parity used
                SerialPort2.StopBits = IO.Ports.StopBits.One                  'Set Stop bits used
                SerialPort2.Handshake = IO.Ports.Handshake.None              'Set Handshaking used
                SerialPort2.Encoding = Text.Encoding.Default                  'Set text encoding used
                SerialPort2.ReadTimeout = 10000                              'Set Timeout in Milliseconds - 10 seconds recommended           
                SerialPort2.NewLine = vbCr                                    'Set Newline identifier - Arduino specified
                SerialPort2.ReceivedBytesThreshold = 38                      'Set minimum number of Bytes to recieve before Recieved Event is Triggered - 38 in minimum that should be sent
                AddHandler SerialPort2.DataReceived, AddressOf Get_Serial_Data
                Tx_Data = "e"                                                'Set default Tx data value to the stop value in case sent before full control established
            Else
                'Configure Comport with Arduino compatible settings
                Form1.SerialPort1.PortName = Form1.ComPort_ComboBox.SelectedItem    'Set Comport to Open - Default last Active ComPort in list
                Form1.SerialPort1.BaudRate = 19200                                  'Set Baud Rate
                Form1.SerialPort1.DataBits = 8                                      'Set Number of Fata Bits
                Form1.SerialPort1.Parity = IO.Ports.Parity.None                    'Set Parity used
                Form1.SerialPort1.StopBits = IO.Ports.StopBits.One                  'Set Stop bits used
                Form1.SerialPort1.Handshake = IO.Ports.Handshake.None              'Set Handshaking used
                Form1.SerialPort1.Encoding = Text.Encoding.Default                  'Set text encoding used
                Form1.SerialPort1.ReadTimeout = 10000                              'Set Timeout in Milliseconds - 10 seconds recommended           
                Form1.SerialPort1.NewLine = vbCr                                    'Set Newline identifier - Arduino specified
                Form1.SerialPort1.ReceivedBytesThreshold = 38                      'Set minimum number of Bytes to recieve before Recieved Event is Triggered - 38 in minimum that should be sent
                Tx_Data = "e"                                                      'Set default Tx data value to the stop value in case sent before full control established
            End If

        Catch ex As Exception
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, Title:="Configure Com Ports Error")    'Display error Message
                Serial_Errors = Serial_Errors + 1
            End If

        End Try

    End Sub

    '===== Connect/Disconnect Button ===== OK 06/06/2018
    Public Sub Connect_Disconnect(sender As Object, e As EventArgs) Handles Connect_Disconnect_Button.Click
        Try
            '--- Connect to Arduino ---
            If Form1.Connect_Button.Text = "Connect Drive Board" And Form1.SerialPort1.PortName <> "" Then
                'Ensure Serial Port is Closed before attempting to open it (Belt & Braces)
                If Form1.SerialPort1.IsOpen = True Then
                    Form1.SerialPort1.Close()
                End If
                If SerialPort2.IsOpen = True Then
                    SerialPort2.Close()
                End If

                'Update Connect button status to "Connecting"
                Form1.Connect_Button.Text = "Connecting..."
                Form1.Connect_Button.BackColor = Color.Orange
                'Open the serial port
                Call Open_Serial_Port()
            Else
                '--- Disconnect From Arduino ---
                'MsgBox("Close the ComPort", Title:="Connect/disconnect Button - Close ComPort") 'Display message --- Debugging ONLY ---
                Call Close_Serial_Port()    'Close the Serial Port & changes Button Colour back to Red
            End If

        Catch ex As Exception  'Report Errors
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, +vbCr + "Closing the Serial Port", Title:="Connect/Disconnect Button Error")    'Display error Message
                Call Close_Serial_Port()    'Close the Serial Port (create known stable port state) & changes Button Colour back to Red
                Serial_Errors = Serial_Errors + 1
            End If

        End Try

    End Sub

    '===== Open the Serial Port ===== OK 23/03/2018
    Public Sub Open_Serial_Port()
        'Open the Comport & Establish a connection with the Arduino

        Try
            'MsgBox(SerialPort1.PortName, Title:="ComPort Being Communicated with")  'Display ComPort being communicated with --- Debugging ONLY ---

            '--- Open the selected Comport & wait for a line of data to be recieved ---
            If Alt = True Then
                SerialPort2.Open()
                While SerialPort2.ReadLine.Contains("OK") = False
                    SerialPort2.DiscardInBuffer()
                    'request & respond version
                    'i_Flag = True
                    'Send_Serial_BW.RunWorkerAsync()
                End While
            Else
                Form1.SerialPort1.Open()  'Open the Serial Port
                While Form1.SerialPort1.ReadLine.Contains("OK") = False
                    Form1.SerialPort1.DiscardInBuffer()
                    'request & respond version
                    'i_Flag = True
                    'Send_Serial_BW.RunWorkerAsync()
                End While
            End If

            'TimerReference.Change(200, 200)

            '--- Update Connect button status to "Connected", Enable the Lab Topic, Run/Run Stop buttons & start the serial data Parsing thread
            If Form1.Connect_Button.BackColor = Color.Orange Then 'Check button is in connecting mode
                'Update Connect Button
                Form1.Connect_Button.BackColor = Color.Red
                Form1.Connect_Button.Text = "Disconnect Drive Board"

                'Enable Lab Topic Menu & Run/Run Stop buttons
                Form1.Run_Stop_Button.Enabled = True
                Form1.ToolStripMenuItem2.Enabled = True

                'Start the asynchronous Parse Data operation. --- No longer required as now started my Data recieved event
                'If Form1.Parse_Rx_Data_BW.IsBusy <> True Then    'Check thread not alread running before starting
                'Form1.Parse_Rx_Data_BW.RunWorkerAsync()      'Start Serial Data BackgroundWorker Thread
                'End If
            End If



        Catch tx As TimeoutException    'Catch serial Read timeout
            Call No_Comms_MsgBox()              'Display user Serial timeout Message - MessageBox calls Close Serial Port

        Catch ex As Exception  'Report other Errors
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, Title:="Open Serial Port Error")    'Display Error Message
                Call Close_Serial_Port()    'Close the Serial Port (create known stable port state)
                Serial_Errors = Serial_Errors + 1
            End If

        End Try

    End Sub

    '===== Close the Serial Port ===== OK --/--/2018
    Public Sub Close_Serial_Port()

        Try
            'If Form1.InvokeRequired Then
            'If the Close Serial Port method is called on the Main UI thread the InvokeRequired property of the form retuns False.
            'If the Close Serial Port method is called from another thread the InvokeRequired property returns True...
            'then From1's Me.Invoke method is used to call the Display method again in its own thread
            'Form1.Invoke(New EventHandler(AddressOf Close_Serial_Port))  'Rec all Close Serial Port on Form1 UI Thread
            'End If

            If Form1.SerialPort1.IsOpen = True Or SerialPort2.IsOpen = True Then  'Check Serial Port is open before closing it
                '--- Send Stop Command to Arduino to shut down motor drive ---
                Tx_Data = "e"  'Stop command
                If Alt = True Then
                    SerialPort2.Write(Tx_Data)
                Else
                    Form1.SerialPort1.Write(Tx_Data)
                End If



                '--- Stop the asynchronous Parse Data operation ---
                If Form1.Parse_Rx_Data_BW.IsBusy = True Then 'Check thread is running before canceling it
                    Form1.Parse_Rx_Data_BW.CancelAsync()    'Cancel  Aysnchronous Backgound working

                    If Form1.Parse_Rx_Data_BW.CancellationPending = True Then
                        'MsgBox("Background Worker closed")            'Display Message --- Debugging ONLY ---
                        Form1.Parse_Rx_Data_BW.Dispose() 'Free up Background Worker thread resources of non running thread
                    End If

                ElseIf Form1.Parse_Rx_Data_BW.CancellationPending = True
                    Form1.Parse_Rx_Data_BW.Dispose() 'Free up Background worker thread resources of non runing thread (Belt & Braces)
                Else
                    'TimerReference.Dispose()    'Dispose of Timer Serial Data Thread -- DOES NOT LIKE IT
                End If

                '--- Close the Serial port ---
                If Form1.SerialPort1.IsOpen = True Then
                    Form1.SerialPort1.DiscardInBuffer()  'Clear Serial Rx data Buffer
                    Form1.SerialPort1.DiscardOutBuffer()  'Clear Serial Tx data Buffer
                    Form1.SerialPort1.Close()            'Close the Serial Port
                ElseIf SerialPort2.IsOpen = True Then
                    SerialPort2.DiscardInBuffer()
                    SerialPort2.DiscardOutBuffer()
                    SerialPort2.Close()
                End If
            End If



            '--- Update Connect button status back to "Connect" ---
            Form1.Connect_Button.Text = "Connect Drive Board"
            Form1.Connect_Button.BackColor = Color.MediumSeaGreen

            '--- Reset Displays & Values to default ---
            Form1.Bat_Volt_Textbox.Text = "0.00"
            Form1.BLDCM_Current_Textbox.Text = "0.00"
            Form1.DC_Load_Current_Textbox.Text = "0.00"
            Form1.BLDCM_RPM_Textbox.Text = "0"

            Rx_Data = ""
            Rx_RPM = "0"
            Rx_Vbat = "0.00"
            Rx_VDCM = "0.00"
            Rx_I_BLDCM = "0.00"
            Rx_I_DCM = "0.00"

            Rx_BLDCM_PWM = "0"
            'Tx_BLDCM_PWM = "0"
            Rx_State = ""
            Tx_State = ""
            Rx_Currsetpoint = "0"
            Rx_DCM_PWM = "0"
            'Tx_DCM_PWM = "0"

            '--- Disable Run/run Stop buttons & Lab Topic Menu ---
            Form1.Run_Stop_Button.Enabled = False
            Form1.ToolStripMenuItem2.Enabled = False

        Catch ex As Exception  'Report errors
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, Title:="Close Serial Port Error")
                Serial_Errors = Serial_Errors + 1
            End If

        End Try

    End Sub

    '===== Change Selected Com port ===== OK 06/06/2018
    Public Sub Select_ComPort(sender As Object, e As EventArgs) Handles Select_Comport1.SelectedIndexChanged

        Try
            If Form1.ComPort_ComboBox.SelectedItem <> "" Then
                Form1.SerialPort1.PortName = Form1.ComPort_ComboBox.SelectedItem 'Assign currently selected ComPort as the one to Open
            End If
        Catch ex As Exception
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, Title:="Select Com Port Error")
                Serial_Errors = Serial_Errors + 1
            End If
        End Try

    End Sub

    '===== Refresh Comm Ports ===== OK 06/06/2018
    Public Sub Refresh_Com_Ports(sender As Object, e As EventArgs) Handles Refresh_Comports_Button.Click
        Try
            'Clear existing ComboBox Items
            Form1.ComPort_ComboBox.Items.Clear()

            'Populate ComPort Combobox with list of active ComPort - ComPort 1 Always seems to be PC internal use.
            For Each sp As String In My.Computer.Ports.SerialPortNames
                Form1.ComPort_ComboBox.Items.Add(sp)
            Next

            'Set Selected comport to last item in list
            If Form1.ComPort_ComboBox.Items.Count > 1 Then
                Form1.ComPort_ComboBox.SelectedIndex = (Form1.ComPort_ComboBox.Items.Count - 1) 'Display Last Comport found
            Else
                Form1.ComPort_ComboBox.Text = Form1.ComPort_ComboBox.Items.Item(0)              'Display First Comport found
            End If

            'Set Selected ComPort to Displayed comPort
            If Alt = True Then
                SerialPort2.PortName = Form1.ComPort_ComboBox.SelectedItem
            Else
                Form1.SerialPort1.PortName = Form1.ComPort_ComboBox.SelectedItem
            End If

        Catch ex As Exception
            If Serial_Errors < 3 Then
                MsgBox(ex.Message, Title:="Refresh Com Ports Error")
                Serial_Errors = Serial_Errors + 1
            End If
        End Try

    End Sub

    '===== No Comms Message Box ===== OK 23/03/2018
    Public Sub No_Comms_MsgBox()
        Try
            MsgBox("If you have lost communication try resetting the Drive Board, otherwise..." + vbCr +
              "1) Check that the Drive board is connected to the PC." + vbCr +
              "2) Ensure the charger is switched off and unplugged from" + vbCr + "    the Drive board." + vbCr +
              "3) You may have the wrong com port selected, try another.", MsgBoxStyle.Exclamation, Title:="Unable to communitcate with the Drive Board")
            If MsgBoxResult.Ok Or MsgBoxResult.Cancel Then
                Call Close_Serial_Port() 'Close the serial port
            End If
        Catch ex As Exception
            MsgBox(ex.Message, Title:="No comms MsgBox Error")
            Call Close_Serial_Port()    'Close the Serial Port (create known stable port state)
        End Try

    End Sub

To send data to the serial port I used
            '--- Send Data ---
            If SerialPort1.IsOpen = True And Tx_Data <> Old_Tx_Data Then  'Compare current to previous Tx_Data - Only Tramsmit data if there is new data available
                Tx_Data = Replace(Tx_Data, " ", "") + "\n" 'Remove leading space created when converting numbers to strings and + line termination charcter
                SerialPort1.Write(Tx_Data)
                Old_Tx_Data = Tx_Data
            ElseIf SerialPort2.IsOpen = True And Tx_Data <> Old_Tx_Data Then  'Compare current to previous Tx_Data - Only Tramsmit data if there is new data available
                Tx_Data = Replace(Tx_Data, " ", "") + "\n" 'Remove leading space created when converting numbers to strings and + line termination charcter
                SerialPort2.Write(Tx_Data)
                Old_Tx_Data = Tx_Data
            End If

For recieved data I used
    '=== Serial Port Data Recieved Interrupt Handler === OK 25/06/2018
    Private Sub Serial_Data_Recieved() Handles SerialPort1.DataReceived
        Try
            If Parse_Rx_Data_BW.IsBusy = False Then
                Parse_Rx_Data_BW.RunWorkerAsync()   'Start Data Parsing Background Worker (thread)
            End If

            'Display Error Message
        Catch ex As Exception
            If Serial_Errors < 3 Then 'Added 10/01/2019 - recuce the number of onscreen messages toa managable amount
                MsgBox(ex.Message + vbCrLf + Rx_Data, Title:="Serial Data Recieved Error") 'Display error
                Serial_Errors = Serial_Errors + 1 '--- new 07/01/2019
                'Parsing_Errors = Parsing_Errors + 1
            End If

        End Try

    End Sub
As you can see I used a Background worker to Recieve and Parce the incomming data, you do not have to and the preferred method now is to use Asynchronous Subs/Functions instead of a background workers, but the primary code within the Background worker that would be of use is...
            '--- Read Serial Data ---
            If SerialPort1.IsOpen Then              'Check Serial port is open before trying to read data
                Thread.Sleep(4)                    'Wait to ensure all data is recieved (Change value as appliable for length & speed of data)
                Rx_Data = SerialPort1.ReadLine
                'ElseIf SerialPort2.IsOpen Then          'Check Serial port is open before trying to read data
                '  Thread.Sleep(4)                    'Wait to ensure all data is recieved
                '  Rx_Data = SerialPort2.ReadLine
            End If
You can then process the Rx_Data string as applicable, it is possible I have ommitted something but the above should cover most of it.

TimB

Quote from: JonW on Jul 18, 2023, 08:56 AMTo make the parsing of the data easier in Xojo its probably best to send it as ascii with a seperator character with a start and end character, for example >1122:-3344:12:11<.  You can then easily search the string and convert each segment rather than have to convert the raw binary data.  Its also easier to read.


Thanks
One of the reasons I went for raw binary was the time it saved. Doing a Bin to Dec conversion takes time and I need to service routines every 10ms. 15+ vars converted to ASCII will take more than that.
I have an interrupt driven TX buffer so my current system of just stuffing the raw bytes into the buffer is very quick

What I do have is another PIC doing the user interface via buttons and the GLCD. That device is pushing pixels around but is not time sensitive like the main pic so it could use its spare USART to do the conversions.