VB.Net program freezing!

Hi Everyone

I have a circuit with a one-wire sensor and one button. The aim of the program is to collect the temperature of an external camera rig in real-time (and print it over serial) and when the button is pushed it should send the word "capture" over serial.

I have a VB.net program that listens to the COM port and will collect the serial data and do stuff with it. The problem is the VB program keeps freezing but pressing the reset button on the Arduino allows it to carry on! I think it is due to the Arduino. Code attached below, can anyone see a problem with this or suggest a better way to achieve my goal?

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 6

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

float Celcius=0;
float lastTemp = 0;
int tempOffset = 3;
 
const int BUTTON_PIN = 2;       // Pin number of the rig switch
const int FAIL_PIN = 3;         // Pin number of the PLC output for a failed image
const int PASS_PIN = 4;         // Pin number of the PLC output for a passed image
const int LED_PIN = 5;          // Pin number of the status LED
String data = "";               // For incoming serial string data
volatile byte state = LOW;



void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(BUTTON_PIN,INPUT_PULLUP);
  pinMode(ONE_WIRE_BUS,INPUT_PULLUP);
  Serial.begin(9600);
  while (!Serial) ;                       //Wait for Arduino serial monitor to open
  sensors.requestTemperatures(); 
  Celcius=sensors.getTempCByIndex(0);
  lastTemp = round(Celcius);              //Store the current temp 
  Serial.println("                                Arduino_Interface_Connected"); //DO NOT DELETE WHITE SPACE FROM FRONT OF THIS STRING!!!!
  Serial.print(" TEMP="); 
  Serial.println(round(Celcius));         //Write the temp at start as the program needs it at startup
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonPressed, FALLING ); //Attach interupt to BUTTON_PIN so it interupts the TEMP reading loop
}

void loop() {
  GetSerialData();
  GetTemp();
  FlashLED();
}



void buttonPressed() {
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 500ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 500)
 {
      state = HIGH;
      Serial.println ("capture");
 }
 last_interrupt_time = interrupt_time;
}

void(* resetFunc) (void) = 0;

void GetTemp() {
  sensors.requestTemperatures(); 
  Celcius=sensors.getTempCByIndex(0);
  if (round(Celcius) == -127) {
    //If the temp is -127 (known error) then don't write it out 
  }

  //If the temp is greater or less than the offset then write the value to the serial port
  if (round(Celcius) == lastTemp + tempOffset || round(Celcius) == lastTemp - tempOffset) {
    Serial.print(" TEMP=");
    Serial.println(round(Celcius));
    delay(1000);
    lastTemp = round(Celcius);
    }
  }

void GetSerialData() {
  if (Serial.available()) {
    // read the incoming string:
    String data;
    data = Serial.readString();
    data.trim();
    if (data == "thermal?") {
      Serial.println("Thermal_Interface_Connected");
      return;
    }
    if (data == "temp?") {
      Serial.print(" TEMP=");
      Serial.println(round(Celcius));
      return;
    }
    if (data == "on") {
      digitalWrite(LED_PIN, HIGH);
    }
    if (data == "off") {
      digitalWrite(LED_PIN, LOW);
    }
    if (data == "reset") {
          resetFunc();
    }
    Serial.println(data);
  }
}
void FlashLED() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on 
  delay(500);                       // wait for half a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off 
  delay(500);                       // wait for half a second
}

Hi Everyone

I have a circuit with a one-wire sensor and one button. The aim of the program is to collect the temperature of an external camera rig in real-time (and print it over serial) and when the button is pushed it should send the word "capture" over serial.

I have a VB.net program that listens to the COM port and will collect the serial data and do stuff with it. The problem is the VB program keeps freezing but pressing the reset button on the Arduino allows it to carry on! I think it is due to the Arduino. Code attached below, can anyone see a problem with this or suggest a better way to achieve my goal?

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 6

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

float Celcius=0;
float lastTemp = 0;
int tempOffset = 3;
 
const int BUTTON_PIN = 2;       // Pin number of the rig switch
const int FAIL_PIN = 3;         // Pin number of the PLC output for a failed image
const int PASS_PIN = 4;         // Pin number of the PLC output for a passed image
const int LED_PIN = 5;          // Pin number of the status LED
String data = "";               // For incoming serial string data
volatile byte state = LOW;



void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(BUTTON_PIN,INPUT_PULLUP);
  pinMode(ONE_WIRE_BUS,INPUT_PULLUP);
  Serial.begin(9600);
  while (!Serial) ;                       //Wait for Arduino serial monitor to open
  sensors.requestTemperatures();
  Celcius=sensors.getTempCByIndex(0);
  lastTemp = round(Celcius);              //Store the current temp
  Serial.println("                                Arduino_Interface_Connected"); //DO NOT DELETE WHITE SPACE FROM FRONT OF THIS STRING!!!!
  Serial.print(" TEMP=");
  Serial.println(round(Celcius));         //Write the temp at start as the program needs it at startup
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonPressed, FALLING ); //Attach interupt to BUTTON_PIN so it interupts the TEMP reading loop
}

void loop() {
  GetSerialData();
  GetTemp();
  FlashLED();
}



void buttonPressed() {
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 500ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 500)
 {
      state = HIGH;
      Serial.println ("capture");
 }
 last_interrupt_time = interrupt_time;
}

void(* resetFunc) (void) = 0;

void GetTemp() {
  sensors.requestTemperatures();
  Celcius=sensors.getTempCByIndex(0);
  if (round(Celcius) == -127) {
    //If the temp is -127 (known error) then don't write it out
  }

  //If the temp is greater or less than the offset then write the value to the serial port
  if (round(Celcius) == lastTemp + tempOffset || round(Celcius) == lastTemp - tempOffset) {
    Serial.print(" TEMP=");
    Serial.println(round(Celcius));
    delay(1000);
    lastTemp = round(Celcius);
    }
  }

void GetSerialData() {
  if (Serial.available()) {
    // read the incoming string:
    String data;
    data = Serial.readString();
    data.trim();
    if (data == "thermal?") {
      Serial.println("Thermal_Interface_Connected");
      return;
    }
    if (data == "temp?") {
      Serial.print(" TEMP=");
      Serial.println(round(Celcius));
      return;
    }
    if (data == "on") {
      digitalWrite(LED_PIN, HIGH);
    }
    if (data == "off") {
      digitalWrite(LED_PIN, LOW);
    }
    if (data == "reset") {
          resetFunc();
    }
    Serial.println(data);
  }
}
void FlashLED() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on
  delay(500);                       // wait for half a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off
  delay(500);                       // wait for half a second
}

Close the VB.net program and use the Arduino IDE serial monitor window to capture the output from the Arduino.
Post the data here.

What does Ardunio Serial Console show you?

Console shows all OK, I can leave it running for hours and it all works fine.
The problem seems to be with the serial port locking up?

Think you need to post your VB program.

(deleted)

Why are you doing Serial.readString( ) ? Is the VB.NET sending something?

I cannot post my VB program as it is huge and I agree there is no need.
I'm more interested in how other people have done this and if there is anything I need to look out for which "could" be causing the program to freeze. I might be barking up the wrong tree but I have written loads of other programs which don't use Ardunio and serial ports with no issue.

reported to moderator as duplicate of : VB.Net program freezing! - #2 by darrenash99 - Interfacing w/ Software on the Computer - Arduino Forum

.

@darrenash99, please do not cross-post. Threads merged.

@ieee488, yes the VB program can send strings as well.

I worked on a project in 2019 where a Mega was sending 30 bytes every 100 ms to a VB.NET program.
Used DataReceived event handler. Worked perfectly.

I still can't make this work without freezing :frowning:

Can anyone provide "working" code that will allow me to write a string to the Arduino and have it send a string back? It just doesn't seem to work yet I am getting status from buttons and temp sensor from Ardunio no problem.

In my vb.net program, I connect to the port ...

SerialPort1.PortName = Port
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.RequestToSend
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 10000
AddHandler SerialPort1.DataReceived, AddressOf serialport_DataReceived
SerialPort1.Open()

When I press a button on the Arduino it is captured by the serialport_DataReceived handler and I get the desired string back from the Arduino.

void GetSerialData() {
if (Serial.available()) {
// read the incoming string:
String data;
data = Serial.readString();
data.trim();
if (data == "thermal?") {
Serial.println("Thermal_Interface_Connected");
return;
}
if (data == "temp?") {
Serial.print(" TEMP=");
Serial.println(round(Celcius));
return;
}
if (data == "reset") {
resetFunc();
}
Serial.println(data);
}
}

If I use serial monitor it all works just fine though it does seem to take around a second to repsond, is this the problem perhaps?

Just as in the Arduino code, I use byte arrays not Strings in my VB.NET code.

In case anyone is interested I found the issue and it was in the .net program!

There is a windows event, namely "SystemEvents.UserPreferenceChanged", this event fires when any user preferences such as font, screen saver etc are changed. This event was "firing" and causing handlers in my program to freeze waiting for the event to respond.

More info on "UserPreferenceChanged" can be found at:

The SystemEvents class is the troublemaker here, it makes an attempt to raise it events on the UI thread of a program. Which is very important, UI isn't thread-safe. Trouble is, you've got two threads that created UI. SystemEvents is incapable of guessing which one is right, it only has 50% odds at it so is doomed to get it wrong. If it initially guessed wrong at which thread in your program is the UI thread, and that thread exited, then it will be 100% wrong.

This makes creating UI on a worker thread exceedingly hazardous of course. It is technically possible, you'll however have to avoid using several controls from the toolbox. They don't handle the UserPreferenceChanged event well when it is raised on the wrong thread. The ones that definitely cause deadlock are DataGridView, NumericUpDown, DomainUpDown, ToolStrip+MenuStrip and the ToolStripItem derived classes. The ones that are iffy (can't analyze the code deep enough) are RichTextBox and ProgressBar. Looks like I ought to put ProgressBar in the first set, judging from your callstacks.

The true cure is to not create UI on a worker thread. It is never necessary, the UI thread of your program is already capable of handling any number of windows.

I didn't use UserPreferenceChanged event handler. Have never encounter a need for it yet.

.

Funny, neither was I! :slight_smile:

I am using handlers to detect files changing in a folder ... it appears that this one was being picked up (even though it was not subscribed too) and causing the issues.

darrenash99:
Funny, neither was I! :slight_smile:

I am using handlers to detect files changing in a folder ... it appears that this one was being picked up (even though it was not subscribed too) and causing the issues.

Not sure what you mean by subscribed to.

If the event handler is there, it is going to run if the event occurs.

Perhaps you mean you did not realize that the event handler did what you were not expecting.

.

I was adding handlers as below but they were being added to form2, not form1, for some reason when "UserPreferenceChanged" fired it was hanging to UI thread.

Private Sub Load()
watchfolder.Path = My.Settings.ImageSaveFolder
watchfolder.EnableRaisingEvents = True
AddHandler watchfolder.Created, AddressOf watchfolderchanged
AddHandler watchfolder.Deleted, AddressOf watchfolderchanged
End Sub

Sub watchfolderchanged(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)
Do Stuff!
End Sub

I added the following code to form1 and it now doesn't hang, if you know a better way I'm all ears as I'm new to handlers and only know what Google has told me.

Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
MyBase.OnHandleCreated(e)
AddHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf Me.UserPreferenceChangedHandler)
End Sub

Protected Overrides Sub OnHandleDestroyed(ByVal e As System.EventArgs)
RemoveHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf Me.UserPreferenceChangedHandler)
MyBase.OnHandleDestroyed(e)
End Sub

Private Sub UserPreferenceChangedHandler(ByVal sender As Object, ByVal e As UserPreferenceChangedEventArgs)
Debug.Print("UserPreferenceChangedHandler Fired!")
End Sub