none
[Solved] SerialPort.Write() fail/bug to Arduino RRS feed

  • Question

  • Hello community!

    As a lot of the questions usually start - I'm a programming newbie. :) You'll notice that from my code bellow. Yet I'm developing a model of a parking and a smart barrier which is controlled by an Arduino. I did the VB application which connects to the Arduino and a MySQL server as well. All good, although my coding is pretty not-optimized - it works. All of it. Except for just one part which it totally looks like a bug to me - SerialPort.Write(). And it's not like it doesn't work at all - it does. Just not all the time. I use the serial port to communicate with the Arduino in two way - both write and read. I read just one 'command' and write 9 others. I always use .Write in the following order:

            spArduino.Close()
            spArduino.Open()
            spArduino.Write("openAuto")

    There is no error or exception to show you. Those 3 lines in several subs works perfectly, in one particular they don't. During my hundreds of tries, a simple MsgBox("*") as line 4 made it work. Then it stopped as well. I really can't explain it. I'll post few of my subs to see what I mean:

    Private Sub btnOpenBarrierManually_Click(sender As Object, e As EventArgs) Handles btnOpenBarrierManually.Click
            spArduino.Close()
            spArduino.Open()
            spArduino.Write("openMan")
            pbxBarrier.Image = My.Resources.barrier_opened
            btnCloseBarrierManually.Enabled = True
            btnCloseBarrierManually.Visible = True
            btnOpenBarrierManually.Enabled = False
            btnOpenBarrierManually.Visible = False
        End Sub
    
        Private Sub btnNCloseBarrierManually_Click(sender As Object, e As EventArgs) Handles btnCloseBarrierManually.Click
            spArduino.Close()
            spArduino.Open()
            spArduino.Write("closeMan")
            pbxBarrier.Image = My.Resources.barrier_closed
            btnCloseBarrierManually.Enabled = False
            btnCloseBarrierManually.Visible = False
            btnOpenBarrierManually.Enabled = True
            btnOpenBarrierManually.Visible = True
        End Sub

    Those 2 subs above for example work perfectly.

    I had this hunch where a SerialPort.Write and a MySQL command under one Sub causes the bug. But then this sub:

    Private Sub InsOuts()
            Dim connStr As String = "Server=localhost;Database=smart_barrier;Uid=VBasic;Pwd=VBasic;"
            Dim conn As New MySqlConnection(connStr)
            Dim SDA As New MySqlDataAdapter
            Dim dbDataSet As New DataTable
            Dim bSource As New BindingSource
            Dim COMMANDGetIns As New MySqlCommand
            Dim COMMANDGetOuts As New MySqlCommand
            Try
                Try
                    conn.Open()
                Catch ex2 As Exception
                    MsgBox("Cannot connect to MySQL. Check if server is available.", vbCritical, "Connection Error")
                End Try
                Dim QueryGetIns As String
                Dim QueryGetOuts As String
    
                QueryGetIns = "SELECT COUNT(*) FROM smart_barrier.vehicle_movement WHERE Direction = 'In';"
                COMMANDGetIns = New MySqlCommand(QueryGetIns, conn)
                Ins = CInt(COMMANDGetIns.ExecuteScalar())
    
                QueryGetOuts = "SELECT COUNT(*) FROM smart_barrier.vehicle_movement WHERE Direction = 'Out';"
                COMMANDGetOuts = New MySqlCommand(QueryGetOuts, conn)
                Outs = CInt(COMMANDGetOuts.ExecuteScalar())
    
                SDA.SelectCommand = COMMANDGetIns
                SDA.SelectCommand = COMMANDGetOuts
                SDA.Fill(dbDataSet)
                bSource.DataSource = dbDataSet
                dgvLive.DataSource = bSource
                SDA.Update(dbDataSet)
            Catch ex As Exception
                Console.WriteLine(ex.ToString())
            End Try
            conn.Close()
    
            AvailableSlots = 7 - (Ins - Outs)
            tbAvailableSlots.Text = AvailableSlots
    
            If AvailableSlots = 0 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("zero")
            ElseIf AvailableSlots = 1 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("one")
            ElseIf AvailableSlots = 2 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("two")
            ElseIf AvailableSlots = 3 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("three")
            ElseIf AvailableSlots = 4 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("four")
            ElseIf AvailableSlots = 5 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("five")
            ElseIf AvailableSlots = 6 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("six")
            ElseIf AvailableSlots = 7 Then
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("seven")
            Else
                spArduino.Close()
                spArduino.Open()
                spArduino.Write("none")
            End If
        End Sub

    ...it works perfectly as well.

    And now what it does not work:

        Private Sub tmrOpenAuto_Tick(sender As Object, e As EventArgs) Handles tmrOpenAuto.Tick
            spArduino.Close()
            spArduino.Open()
            spArduino.Write("openAuto")
            'MsgBox("wtfff")
    
            Dim lastID As String = tbLastInsertedID.Text
            Dim connStr As String = "Server=localhost;Database=smart_barrier;Uid=VBasic;Pwd=VBasic;"
            Dim conn As New MySqlConnection(connStr)
            Dim SDA As New MySqlDataAdapter
            Dim dbDataSet As New DataTable
            Dim bSource As New BindingSource
            Dim COMMAND As New MySqlCommand
            Dim Query As String
            Try
                Try
                    conn.Open()
                Catch ex2 As Exception
                    MsgBox("Cannot connect to MySQL. Check if server is available.", vbCritical, "Connection Error")
                End Try
                Query = "UPDATE `smart_barrier`.`vehicle_movement` SET `Executed` = 'Yes' WHERE (`Row_ID` = '" & lastID & "');"
                COMMAND = New MySqlCommand(Query, conn)
                SDA.SelectCommand = COMMAND
                SDA.Fill(dbDataSet)
                bSource.DataSource = dbDataSet
                SDA.Update(dbDataSet)
            Catch ex As Exception
                Console.WriteLine(ex.ToString())
            End Try
            conn.Close()
    
            InsOuts()
    
            tmrOpenAuto.Enabled = False
        End Sub

    The only part of the above sub which doesn't work is:

            spArduino.Close()
            spArduino.Open()
            spArduino.Write("openAuto")

    For like few hours, it worked only if I un-comment the 'MsgBox at which point I was pretty sure it's a bug.

    And I must assure you the problem is not in the Arduino code. I switched the .Write commands tens of times on both platforms, this sub is the only thing that doesn't work.

    The other weird part is that in this long sub, the first 3 lines don't work, then the MySQL query works and then InsOuts() at the end which I posted above doesn't work as well.

    I'd really really really appreciate any help as this is my very last 'bug' to complete my project.

    Thank you in advance!


    • Edited by bongo_bg Monday, April 15, 2019 6:08 AM Solved
    Monday, April 8, 2019 6:01 AM

Answers

  • Hi Alex,

    I tried to explain it although I'm not very good in explanations. The problem was using the String format in Arduino. Code-wise it looks like that:

    Arduino part - from...

    void serialMonitor() {
      if (Serial.available() > 0) {
        String val = Serial.readString();
        if (val == "openMan") {
          manual = true;
          delay(20);
          open(); }
        else if (val == "closeMan") {
          manual = false; 
          delay(20); }
        else if (val == "openAuto") {
          delay(20);
          open();
          greenOn();
          redOff();
          delay(5000);
          manual = false; }

    ...to...

    void serialMonitor() {
      if (Serial.available() > 0) {
        char val = Serial.read();
        if (val == 'O') {
          manual = true;
          delay(20);
          open(); }
        else if (val == 'C') {
          manual = false; 
          delay(20); }
        else if (val == 'A') {
          delay(20);
          open();
          greenOn();
          redOff();
          delay(5000);
          manual = false; }

    VB.NET part - from...

    spArduino.Close()
    spArduino.Open()
    spArduino.Write("openAuto")

    ...to...

    spArduino.Close()
    spArduino.Open()
    spArduino.WriteLine("A")

    • Marked as answer by bongo_bg Wednesday, April 17, 2019 7:38 AM
    Wednesday, April 17, 2019 7:38 AM

All replies

  • Hi,

    What you mean is that you only add MsgBox(" ") after the code beolw,does it work fine?

     spArduino.Close()
            spArduino.Open()
            spArduino.Write("openAuto")

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, April 8, 2019 9:21 AM
  • Hello Alex and thank you for you interest.

    I mean that as part of the whole sub,

    spArduino.Close()
    spArduino.Open()
    spArduino.Write("openAuto")


    does not work.

    But this one:

    spArduino.Close()
    spArduino.Open()
    spArduino.Write("openAuto")
    MsgBox("wtfff")

    works. And not just the 'MsgBox' part but the .Write as well. With the MsgBox the Arduino responds. Without - it doesn't.

    I know it sounds unbelievable but it's true. Although now, after N changes and tries, it doesn't again with or without the MsgBox.

    Edit: It feels like the application doesn't have enough time to do all of this and pausing with the MsgBox gives it time. I know it makes no sense what so ever. That's why I tried to extract that part into a timer with 100ms delay but still no resulsts...

    • Edited by bongo_bg Monday, April 8, 2019 10:33 AM Addition
    Monday, April 8, 2019 10:30 AM
  • Ok, if anyone gets here via Google for example, I just want to point out that the problem was not in the VB but in the Arduino. Trying to read "String"s was really not a good idea and switching to 'char' + spArduino.WriteLine("O") sealed the deal for me.

    Anyhow, thank you.

    Monday, April 15, 2019 6:06 AM
  • Ok, if anyone gets here via Google for example, I just want to point out that the problem was not in the VB but in the Arduino. Trying to read "String"s was really not a good idea and switching to 'char' + spArduino.WriteLine("O") sealed the deal for me.

    Anyhow, thank you.

    Hi,

    I am glad you have got your solution. It would be appreciated if you could share us your solution and then mark it as an answer.

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, April 17, 2019 7:18 AM
  • Hi Alex,

    I tried to explain it although I'm not very good in explanations. The problem was using the String format in Arduino. Code-wise it looks like that:

    Arduino part - from...

    void serialMonitor() {
      if (Serial.available() > 0) {
        String val = Serial.readString();
        if (val == "openMan") {
          manual = true;
          delay(20);
          open(); }
        else if (val == "closeMan") {
          manual = false; 
          delay(20); }
        else if (val == "openAuto") {
          delay(20);
          open();
          greenOn();
          redOff();
          delay(5000);
          manual = false; }

    ...to...

    void serialMonitor() {
      if (Serial.available() > 0) {
        char val = Serial.read();
        if (val == 'O') {
          manual = true;
          delay(20);
          open(); }
        else if (val == 'C') {
          manual = false; 
          delay(20); }
        else if (val == 'A') {
          delay(20);
          open();
          greenOn();
          redOff();
          delay(5000);
          manual = false; }

    VB.NET part - from...

    spArduino.Close()
    spArduino.Open()
    spArduino.Write("openAuto")

    ...to...

    spArduino.Close()
    spArduino.Open()
    spArduino.WriteLine("A")

    • Marked as answer by bongo_bg Wednesday, April 17, 2019 7:38 AM
    Wednesday, April 17, 2019 7:38 AM