Hello, I am building an app where an Arduino Nano will communitate via i2c to a peripheral and usb-serial to a Windows 11 PC.
Using a VB app, I can send strings to the Nano which gets them : Starting small, I sent an On or Off via the Windows virtual Serial Port, and my sketch dutifully turns the on board Led on or off. So far so good
The issue is when I use Serial.println("abcd"): I have a Timer control in my VB app that should capture the data received (I am not using an event handler, not experienced enough yet).
If I use the Arduino IDE's serial monitor: no problem, I can serial.println all day and see the output on the serial monitor
In the VB app: nothing shows up. Even more perplexing, the Tx led on the Nano never flashes (it does that well with the IDE Serial Monitor).
So the COM port is somehow not available but I cannot figure out where the issue is except at the VB side of things (since the IDE monitor works fine, I am assuming the Nano sketch is fine).
Has anyone had this kind of behavior? I am running out of options for something that every bit of code I have seen on the web should be easy.
I have added delays pretty much everywhere without any impact. The sketch turns the led on then delays 2 sec, then does a serial.println, then another delay. And loops, and the Nano does not hang up, it just sends data to its output buffer and moves on.
Thanks in advance
Here is the sketch code I am using
#include <Wire.h>
#define LED_PIN (13)
#define SERIAL_BAUD (9600)
char incoming_byte = 0;
void setup() {
// put your setup code here, to run once:
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.begin(9600);
while(!Serial); //Wait for the serial port connection to open
Serial.println("Setup Complete"); //Nothing shows up on the VB SerialPort1
delay(2000);
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
// Try to see if Arduino responds to a serial input, whatever it is
if (Serial.available()>0) {
incoming_byte = Serial.read();
if (incoming_byte=='1') {
digitalWrite(LED_PIN, HIGH); //That works, the Led turn on
delay(2000);
Serial.println("LED is On"); //No Tx flash when COM is run by VB and no data, flashes when using IDE Serial Monitor and text displays
Serial.flush();
delay(1000);
}
else if (incoming_byte =='2') {
digitalWrite(LED_PIN, LOW); //That works, the Led turns off
delay(2000);
}
}
}
My guess is that the problem is in the VB app.
To debug serial data transmission, I recommend to use a simple terminal app on Windows, like PuTTY or TeraTerm (my favorite).
They all support continuous logging, so you can debug long sessions or save data to a disk file.
can you upload the Form1.vb code?
to capture the received serial data I would recommend using the SerialPort DataReceived event
you then use a method such as
' character received from serial port
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
TextBox1.AppendText(SerialPort1.ReadExisting())
End Sub
to read the characters (in this case displaying it on a TextBox)
Hi, VB code below
I will try your suggestion and let you know, Thank you
Imports System.IO
Imports System.IO.Ports
Imports System.Threading
Public Class Form1
Dim StrSerialIn As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.CenterToScreen()
SerialPort1.Close() 'Make sure the port Is closed When starting
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnW255.Click
If SerialPort1.IsOpen() = False Then
SerialPort1.Open()
End If
SerialPort1.Write("1")
SerialPort1.Close()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnR255.Click
If SerialPort1.IsOpen() = False Then
SerialPort1.Open()
End If
SerialPort1.Write("2")
SerialPort1.Close()
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnG255.Click
If SerialPort1.IsOpen() = False Then
SerialPort1.Open()
End If
SerialPort1.Write("3")
SerialPort1.Close()
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnB255.Click
If SerialPort1.IsOpen() = False Then
SerialPort1.Open()
End If
SerialPort1.Write("4")
' SerialPort1.Close()
End Sub
Private Sub TimerSerial_Tick(sender As Object, e As EventArgs) Handles TimerSerial.Tick
Try
If SerialPort1.IsOpen() = False Then
SerialPort1.Open()
End If
StrSerialIn = SerialPort1.ReadExisting '--> Read incoming serial data
TB_Msg.Text = StrSerialIn '--> Enter serial data into the textbox
SerialPort1.Close()
Catch ex As Exception
TimerSerial.Stop()
SerialPort1.Close()
lblConStat.Text = "Status : Disconnect"
btnDisconnect.SendToBack()
btnConnect.BringToFront()
MsgBox(Err.Description)
'MsgBox("Please check the Hardware and Please connect again." & ex.Message, MsgBoxStyle.Critical, "Connection failed !!!")
Return
End Try
End Sub
Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
Try
SerialPort1.BaudRate = cmbBaud.SelectedItem
SerialPort1.PortName = cmbPorts.SelectedItem
SerialPort1.Open()
TimerSerial.Start()
lblConStat.Text = "Status : Connected"
btnDisconnect.BringToFront()
Catch ex As Exception
MsgBox(Err.Description)
'MsgBox("Please check the Hardware, COM, Baud Rate and try again.", MsgBoxStyle.Critical, "Connection failed !!!")
End Try
End Sub
Private Sub btnDisconnect_Click(sender As Object, e As EventArgs) Handles btnDisconnect.Click
TimerSerial.Stop()
SerialPort1.Close()
btnDisconnect.SendToBack()
btnConnect.BringToFront()
lblConStat.Text = "Disconnected"
End Sub
Private Sub btnScanPort_Click(sender As Object, e As EventArgs) Handles btnScanPort.Click
If lblConStat.Text = "Connected" Then
MsgBox("Conncetion in progress, please Disconnect to scan the new port.", MsgBoxStyle.Critical, "Warning !!!")
Return
End If
cmbPorts.Items.Clear()
Dim myPort As Array
Dim i As Integer
myPort = IO.Ports.SerialPort.GetPortNames()
cmbPorts.Items.AddRange(myPort)
i = cmbPorts.Items.Count
i = i - i
Try
cmbPorts.SelectedIndex = i
btnConnect.Enabled = True
Catch ex As Exception
MsgBox("Com port not detected", MsgBoxStyle.Critical, "Warning !!!")
cmbPorts.Text = ""
cmbPorts.Items.Clear()
Return
End Try
cmbPorts.DroppedDown = True
End Sub
Private Sub btnRegRead_Click(sender As Object, e As EventArgs) Handles btnRegRead.Click
'Sends a Read register command to the Arduino, passing register address (2 bytes) and value (1 byte)
End Sub
Private Sub btnRegWr_Click(sender As Object, e As EventArgs) Handles btnRegWr.Click
'Reads a Janus register from Arduino passing the register address (2 bytes)
'Displays value in Hex in tbRegVal textbox
End Sub
End Class
I tried to use the DataReceived event (see below). No text in the text box. I did comment out the TimerSerial.Start()
I put a breakpoint in the handler at the TB_Msg.AppendText, but it never triggered
It is as if the Arduino cannot send through the usb serial port. Since that works using the Serial Monitor, it must be because my VB app is doing something weird to the Com port.
I checked with Device Manager and the settings are the same whether I use the VB code or the Arduino Serial Monitor.
But I cannot see what I am missing.
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
TB_Msg.AppendText(SerialPort1.ReadExisting())
End Sub
this is the simplest VB terminal emulator I have
' terminal emulator - in Visual Studio VB
' remember to set the COM port
' note that this version is not thread safe - the serial event handler communicates directly with the GUI
Public Class Form1
' key pressed on terminal textbox
Private Sub TextBox1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
SerialPort1.Write(e.KeyChar)
End Sub
' character received from serial port
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
TextBox1.AppendText(SerialPort1.ReadExisting())
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
SerialPort1.Open()
End Sub
End Class
the design looks like (note the SerialPort properties)
and a run displays (communicating with a ESP32 on COM27)
Thank you. I just tried it and got an exception:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'TextBox1' accessed from a thread other than the thread it was created on.'
I read somewhere that in this case, an Invoke command was needed to make things right.
I will research.
I assume you are running using DEBUG
If I hit CTRL/F5 or click "Start without debugging" the code of post 7 runs OK
here is a version using a delegate
' terminal emulator - in Visual Studio VB
Public Class Form1
' set up delegate to display data received from serial port
Private Delegate Sub SerialDelegate(ByVal Buffer As String)
Private adre As New SerialDelegate(AddressOf DisplayData)
' key pressed on terminal textbox
Private Sub TextBox1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
SerialPort1.Write(e.KeyChar)
End Sub
' character received from serial port
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim ReceivedData As String = SerialPort1.ReadExisting()
Me.Invoke(adre, ReceivedData)
End Sub
' delegate to display string received
Private Sub DisplayData(ByVal sdata As String)
TextBox1.AppendText(sdata)
End Sub
' on form load open serial port
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
SerialPort1.Open()
End Sub
Private Sub Form1_FormClosed(sender As System.Object, e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
SerialPort1.Close()
End Sub
End Class
Start without Debug worked! Thank you so much!
I will insert this in my main VB code to validate.
Got it to work in my VB App!
Very happy, thank you very much.
One key setting that made the difference is setting DtrEnable to True in the Serial Port