B4R Tutorial OLED displaying data from a USB to Serial com port using AsyncStreams - B4R, B4J and VB.Net

Peter Simpson

Expert
Licensed User
Here is a really simple tutorial with source code on how to send data through a computer com port or laptop USB to Serial com port to receive data on your Arduino based microcontroller board. I decided to put together this short tutorial on how to send/receive data using AsyncStreams, but in this case the data comes directly from a computer or laptop.

In this particular tutorial I quickly developed 2 desktop programs using B4J and VB.Net to monitor my laptop's CPU utilisation, the programs send the CPU utilisation data directly to the Arduino based microcontroller via the computer or laptop com ports, the CPU utilisation data is then displayed on an OLED display connected to the Arduino based microcontroller. As you can see from the B4J and VB.Net source codes below, sending the CPU utilisation data through the com port is relatively simple to do. On the Arduino using B4R to read the data is so simple that it only takes one line of code to read the new data buffer.

The .jar and .exe files for sending the CPU utilisation data to an Arduino via the com ports can be DOWNLOADED HERE.

In your Arduino code, you need to use AsyncStreams to receive new data and you use ByteConverter to convert the new data from a byte array to a string thus allowing a human to read the received new data more easily. All new data that is received is done so in the following sub.
B4X:
Sub AStream_NewData (Buffer() As Byte)
     'Receive data routine goes here...
End Sub
Receive data and send to a display - B4R source code for Arduino.
Libraries:
rRandomAccessFile, rAdafruitGFX, rAdafruitSSD1306
B4X:
'WIRE LEGEND for 7 pin OLED display
'VCC (VDD)= 3.3V/5.0V
'GND = GND
'D0 (SCK) = D13
'D1 (SDA) = D11
'RST (RES) = D8
'DC = D9
'CS (SS) = D10

'WIRE LEGEND for 4 pin OLED display
'VCC (VDD)= 3.3V/5.0V
'GND = GND
'D0 (SCL) = A5
'D1 (SDA) = A4

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial

    Private SSD As AdafruitSSD1306
    Private AStream As AsyncStreams
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")

    'SSD.InitializeHSPI(9, 8, 10)    '7 pin display
    SSD.InitializeI2C(4, 0x3c)         '4 pin display
    SSD.GFX.ConfigureText(2, SSD.WHITE, False)

    AStream.Initialize(Serial1.Stream, "AStream_NewData", "AStream_Error")
End Sub

Sub AStream_NewData (Buffer() As Byte)
    Dim BC As ByteConverter

    SSD.ClearDisplay
    SSD.GFX.SetCursor(54, 9)
    SSD.GFX.DrawText(JoinStrings(Array As String(BC.StringFromBytes(Buffer), "%")))
    SSD.Display
End Sub

Sub AStream_Error
    Log("Oops...")
End Sub

B4J program sending data every second to my Arduino based microcontroller board, with memory usage.
B4J.jpg


You need to use ByteConverter to convert the string to a byte array and you use AsyncStreams to send the data through the com port to the Arduino.

Send data - B4J source code for Windows (might also work on Mac or Linux, but I would not bet on it)
.
Libraries:
ByteConverter, jAWTRobot, jCustomToast, jRandomAccessFile, jSerial
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private TmrSendData As Timer
    Private ComPort As Serial
    Private AWTRobot As AWTRobot
    Private Toast As ToastMessageShow
    Private AStream As AsyncStreams
    Private PBarCPU, PBarRAM As ProgressBar
    Private LblCPU, LblRAM As Label
    Private CmbBoxComPort As ComboBox
    Private BtnRefresh, BtnConnect, BtnDisconnect As Button
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetWindowSizeLimits(445, 258, 445, 258)
    MainForm.RootPane.LoadLayout("Main")
    MainForm.Show

    Toast.Initialize(Null)
    Toast.ToastDuration = Toast.TOAST_SHORT_DELAY
    Toast.ToastTextLocation = Toast.TEXT_CENTER
    Toast.ToastLocation = Toast.TOAST_CENTER
    Toast.ToastTitleColor = fx.Colors.White
    Toast.ToastNotificationOwner = MainForm

    ComPort.Initialize(Null)
    TmrSendData.Initialize("TmrSendData", 1000)
    AStream.Initialize(ComPort.GetInputStream, ComPort.GetOutputStream, "AStream_NewData")

    LoadComPorts
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub AStream_NewData (Buffer() As Byte)
End Sub

Sub TmrSendData_Tick
    Dim CPU As Int = Ceil(AWTRobot.SystemCPULoad * 100)

    Dim PhysicalTotal As Double = NumberFormat((AWTRobot.SystemMemoryPhysicalTotal / 1073741824), 2, 1)
    Log($"Total memory = ${PhysicalTotal}GB"$)
    Dim PhysicalFree As Double = NumberFormat((AWTRobot.SystemMemoryPhysicalFree / 1073741824), 2, 1)
    Log($"Free memory = ${PhysicalFree}GB"$)

    'Calculate percentage of used memory and flip the result
    Dim Percent As Double = 1 - (PhysicalFree / PhysicalTotal)

    PBarCPU.Progress = CPU / 100
    LblCPU.Text = CPU & "%"
    PBarRAM.Progress = NumberFormat(Percent, 1, 1)
    LblRAM.Text = Ceil(Percent * 100) & "%"

    'Send the CPU utilisation data through the com port to the Arduino.
    Dim BC As ByteConverter
    AStream.Write(BC.StringToBytes(CPU, "UTF8"))
End Sub

Sub LoadComPorts
    CmbBoxComPort.Value = ""
    CmbBoxComPort.Items.Clear
    CmbBoxComPort.Items.AddAll(ComPort.ListPorts)
    If ComPort.ListPorts.Size > 0 Then CmbBoxComPort.SelectedIndex = 0
End Sub

Sub BtnConnect_MouseClicked (EventData As MouseEvent)
    If CmbBoxComPort.SelectedIndex >= 0 Then
        Try
            ComPort.Open(CmbBoxComPort.Value)
            ComPort.SetParams(115200, 8, 1, 0)
            BtnDisconnect.Enabled = True
            BtnConnect.Enabled = False
            TmrSendData.Enabled = True
        Catch
            Log(LastException)
        End Try
    Else
        Toast.ToastShow5("Error opening port", Toast.TOAST_ERROR_ICON)
    End If
End Sub

Sub BtnDisconnect_MouseClicked (EventData As MouseEvent)
    TmrSendData.Enabled = False
    ComPort.Close()
    PBarCPU.Progress = 0
    LblCPU.Text = 0 & "%"
    PBarRAM.Progress = 0
    LblRAM.Text = 0 & "%"
    BtnDisconnect.Enabled = False
    BtnConnect.Enabled = True
End Sub

Sub BtnRefresh_MouseClicked (EventData As MouseEvent)
    LoadComPorts
End Sub

VB.Net program sending data every second to my Arduino based microcontroller board, with memory usage.
VB.Net.jpg


In VB.Net you just drag and drop a SerialPort control from the ToolBox on the left hand side of the screen onto your form, you then configure the port using the control name and use ComPort.Write(...) to send the string as a byte array (you can also just send it as a string).

Send data - VB.Net source code for Windows.
B4X:
Public Class FrmMain
    Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
        LoadComPorts()
    End Sub

    Private Sub BtnConnect_Click(sender As Object, e As EventArgs) Handles BtnConnect.Click
        If CmbBoxComPort.SelectedIndex >= 0 Then
            Try
                ComPort.PortName = CmbBoxComPort.SelectedItem
                ComPort.BaudRate = 115200
                ComPort.ReadTimeout = 3000
                ComPort.Open()

                TmrSendData.Start()
                BtnDisconnect.Enabled = True
                BtnConnect.Enabled = False
            Catch ex As Exception
                MsgBox(ex.Message)
            Finally
                'Not really needed
            End Try
        Else
            MessageBox.Show("Please select a COM port")
        End If
    End Sub

    Private Sub BtnDisconnect_Click(sender As Object, e As EventArgs) Handles BtnDisconnect.Click
        TmrSendData.Stop()
        ComPort.Close()
        PBarCPU.Value = 0
        LblCPU.Text = 0 & "%"
        PBarRAM.Value = 0
        LblRAM.Text = 0 & "%"
        BtnDisconnect.Enabled = False
        BtnConnect.Enabled = True
    End Sub

    Private Sub TmrSendData_Tick(sender As Object, e As EventArgs) Handles TmrSendData.Tick
        PBarCPU.Value = PConCPU.NextValue
        LblCPU.Text = PBarCPU.Value & "%"
        'Send the CPU utilisation data through the com port to the Arduino.
        'COMPort.Write(PBarCPU.Value)
        ComPort.Write(System.Text.Encoding.ASCII.GetBytes(PBarCPU.Value), 0, PBarCPU.Value.ToString.Length)
        'Console.WriteLine(PBarCPU.Value)
        PBarRAM.Value = PConRAM.NextValue
        LblRAM.Text = PBarRAM.Value & "%"
    End Sub

    Private Sub BtnRefresh_Click(sender As Object, e As EventArgs) Handles BtnRefresh.Click
        LoadComPorts()
    End Sub

    Public Sub LoadComPorts()
        CmbBoxComPort.Items.Clear()
        CmbBoxComPort.Text = ""

        For Each ComPort As String In My.Computer.Ports.SerialPortNames
            CmbBoxComPort.Items.Add(ComPort)
        Next

        If CmbBoxComPort.Items.Count > 0 Then CmbBoxComPort.SelectedIndex = 0
    End Sub
End Class
How to connect your OLED display to your Arduino, with memory usage.
Diagram.jpg


Displaying my laptop CPU utilisation percentage on the OLED display.
photo.jpg


OLED display in front of my laptop screen, top left B4R program, bottom right VB.Net program.
all.jpg


Enjoy...
 
Last edited:
Top