Baud rates for stable Bluetooth serial communication - c#

I have an Arduino mega communicating over Bluetooth (bluesmirf gold device) to a C# application that I wrote. The Arduino is constantly sending a serial signal of 32 characters, the first always being an "S" and the last an "E". Using putty I can confirm that this signal is being sent correctly 99% of the time.
Now I want to read this signal with my C# application, which I am doing with the following code:
public string receiveCommandHC()
{
string messageHC = "";
if (serialHC.IsOpen)
{
while (serialHC.ReadChar() != 'S')
{
}
messageHC = serialHC.ReadTo("E");
serialHC.DiscardInBuffer();
}
return messageHC;
}
serialHC is of the serial class.
Sometimes this works perfectly but other times I'm having problems, I cannot find out why it works sometimes but others not.
The problem that I seem to be having is that sometimes I get a rather large Lag in the data that I am reading from the arduino. I notice this because I am sending button states and they only change a few seconds after I actually press or release the button on the Arduino. I used the standard baud rate of the Bluetooth device, which is 115200, and was wondering if changing that to a much lower rate could yield better results? What if any advantage would that have? I do not need hight communication rates, even updating the state 4-5 times a second would be acceptable for my application.
Is it possible the lag is coming from my code? I think it may be from the while loop that is waiting for the incoming "S" but then I don't see why it should hang there since there are new signals always coming in at a high rate.
I'm using the DiscardInBuffer() because I do not care about outdated data and just want to skip over that. It is much more important that I am reading current up to date data and acting on that fresh data.
Thank you for your help!
Best regards,
Bender
Update:
Just found out a bit more information while debugging. The problem only seems to appear:
When connected over Bluetooth (over USB cable there is absolutely NO Lag)
When a second Bluetooth connection is established from the PC to another device (different COM port and different baud rate)
Does anybody have any experience running two different devices off the same Bluetooth dongle on the PC? I can manage to connect to both no problem but still having the lag issue mentioned before.
Thanks for any help

You are not really using a physical serial port here. The BlueTooth driver merely emulates one. This is common, the Windows API has a well defined set of api functions to talk to a serial port. Emulating one makes the interface to the driver simple, the vendor doesn't have to supply an interface DLL or document a complicated DeviceIoControl() protocol.
Which means for one thing that the actual communication settings don't matter. Baudrate is meaningless in this scenario, it is the BlueTooth radio signaling that sets the transfer rate. The driver will accept whatever you select but will otherwise ignore it. Handshake signals might be interpreted, it's up to the driver to implement them. Communication error reporting is very rarely implemented, BlueTooth has an error correcting protocol, unlike a real serial port.
No, the loss of data here is entirely self induced. Clearly the driver does implement DiscardInBuffer(). Which accomplishes nothing but throw away any data that the driver received. This goes wrong if your code runs a bit late or gets interrupted by a thread context switch.
Delete the DiscardInBuffer() call.

Related

UWP BLE stops notifications when using internal Bluetooth

I have a BLE sensor that sends data at a frequency of 100Hz and I've developed an UWP application to receive this data. I'm having a weird issue where after a couple of seconds of everything working fine, I stop receiving notifications for new data.
Now, I say it's weird because this happens when I'm using the laptop's internal Bluetooth but not when using a Bluetooth dongle. When using the dongle it works fine and never stops. Both internal Bluetooth and dongle drivers are updated to the latest version Windows can find.
As soon as the notification stops the sensor disconnects.
The sensor is based on the Nordic nRF52832 SoC.
Now a bit of information about my code:
I have a Sensor.cs class in which I handle the connection and the streaming of the data.
I'm using BluetoothLEAdvertisementWatcher in order to find the sensor.
The GattCharacteristic's are private members of the Sensor class.
I subscribe to notifications by calling:
await _gattDataSensorsCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
The application doesn't do anything fancy. Just connects to the sensor, starts the streaming and prints the data.
I've done quite a research and couldn't find anything similar. I've found posts about notifications stopping because the object was taken away by the GC, the characteristics were local variables instead of class members or calls weren't awaited.
Why does this happen?
1st edit
#Emil I'm sorry, my fault for not mentioning that as soon as the notifications stop, the sensor disconnects. I'm editing the question to mention that as well as it's something relevant. Anyway I'm trying what you mention asap.
#GrooverFromHolland That option was checked. I've tried unchecking that option on a couple of computers but sadly, unchecking it only makes the code last a few seconds longer.
#Nico Zhu - MSFT I've followed the link you posted and read the doc also went to my sensor's manual to double check if the characteristic allows Notify and it does, it does allow Read and Notify. I also do the same thing characteristic.ValueChanged += Characteristic_ValueChanged; as it's mentioned in the doc.
About the sensor disconnecting when the notifications stop/the valuechanged stops firing. I have to add that on my MainWindow, the sensor object is a member class and it isn't disposed at any moment. So it doesn't make sense that the GC takes the object away, right?
2nd edit
I've tried the code I'm using with both the laptop plugged and unplugged to a power source and it's always set to max performance. The code I'm using can be found here: link
3rd edit
Following #Emil 's recommendations I was finally able to scan the traffic. Tried to understand what the pcap file generated by USBPcap, but I simply don't understand. I've tried the issue with 2 sensors and the disconnect/notification stop pattern looks different for each sensor.
I've made a Dropbox folder containing the two pcap files: link
From what I understood, in the file "ble-FE592382586F.pcap" the interesting line No are: 12647 and 12681. It says the source is the controller and the destination is host. Is the controller the laptop's bluetooth driver?
Controller means the bluetooth chip (inside or outside the computer) and host is the main cpu. They talk with each other over usb. At packet 12681 in the first file, the disconnect reason is Connection Timeout (0x08). This means the connection was dropped unexpectedly (radio interference/bad signal?). At packet 613 in the other file, we have the same situation. A difference is that in only in the second file, there was a new attempt to reconnect the device.
Since you do not use bonding, you must make sure to re-write the client characteristic configuration descriptor upon every new connection. It doesn't seem like you do this.
I ran into similar - what I discovered was that the GattCharacteristic (the object you call WriteClientCharacteristicConfigurationDescriptorAsync on) was getting GCed - as soon as I added that to a class-wide variable (I made a Dictionary of all the characteristics I was tracking), my notifications kept coming

Serial port: read a byte as soon as it arrives

I need to write an application that can seat in the middle of a serial port communication between an application (3rd party, no source) running on my pc and a serial device connected to it (say on COM1).
The application normally communicates with the device as soon as you plug the cable. What I need to do is break this communication by "installing" my app in the middle so I can control what data goes through.
The only way I can think of solving this is creating a a pair of virtual serial ports (COM5<->COM6) using com0com. Then I would redirect the app to use COM5 instead of COM1 (I can set this in the app options) and then write a program that will copy every byte received in COM6 (sent by the application) into COM1 (sent to the device) and viceversa.
The problem is that I need to do this without introducing any delays into the communication, otherwise the application and the device will go out of sync.
I tried creating a C# console app to do this, but it seems to wait for a pause in the stream before raising the datareceived event, effectively introducing several ms of delay (speed is 9600).
What I would like to try now is to rewrite the program (maybe using the win32 api?) in such a way that it relays each rx byte as soon as it arrives, so the device would not notice any delay.
Can I do this using win32? Is there a simpler solution you can recommend?
Thanks
Maybe not much of a complete answer for your question but I think this might be worth a try.
Depending on your needs (you did not explain them) you can try to use Termite together with com0com. You can see a quick example here.
There is also an open source clone but I think the very feature you need (forwarding) was never implemented.
In any case, Termite allows scripting, so it is quite likely to be able to meet your needs.

Communication through USB to an STM32F4 microcontroller delay

I am working on a C# development project which aims at controlling a flying robot thanks to a set of Optitrack cameras (infrared Motion capture system). The concept works really well, you get a position from the camera system, our application can access to these data and we can control the robot.
The problem comes, I believe, from the communication chain. We have a USB cable linking our PC to an STM32F4 based board, which acts as a bridge and simply sends everything received on USB to radio thanks to an embedded NRF module (nRF24L01+ chip). This mechanic goes both way (NRF -> USB -> PC). The board is running under C using FreeRTOS. The PC runs Windows 10.
On the PC side we use the official STM32 VCP driver 1.4 from ST. On the board firmware, we have this user-made library for VCP on STM32F4: https://stm32f4-discovery.net/2014/08/library-24-virtual-com-port-vcp-stm32f4xx/
There are no queues on the bridge board except the ones from the radio module itself and potentially the STM32 VCP driver itself. I checked, there is a circular buffer in this driver used for in and out messages. Using JSCOPE I can visualize in real time how this circular buffer behaves and I've never seen an overflow happening.
My problem comes from the fact that a delay suddenly appears.
The system works perfectly for tens of minutes (between 10 to 20 minutes) and then a delay is clearly perceptible, which makes the controller oscillate. This happens when I do a second flight.
The following have been tried:
- Restart the C# application
- Run the C# application in debug mode and stand alone mode
- Change USB cable (shorter)
- Change USB port
- Change of computer
- Reinstall the ST VCP drivers
- Lower drastically the communication frequency (the control loop)
When the problem appears, the above solutions didn't work, the delay remains completely and none of the above proved to make it more reliable.
On the C# application, I reset all communication Lists before each flight. The SerialPort port object (from System.IO) has its buffers reset as well (DiscardOutBuffer, DiscardInBuffer, BaseStream.Flush methods)
I found a "hack" to make it work, but it is not what we want as a final solution. The "hack" is to simply physically disconnect / reconnect the USB connecting the board acting as a bridge. After this manipulation, the delay disappears.
So my questions are:
What could possibly bring this delay, knowing it doesn't look to be application dependant, nor frequency related (bandwidth).
What could explain why this disappear when unplugging/plugging the bridge board ?
I know this question is about a big project and could be hard to understand from outside. Feel free to ask me for more details if needed.
Cheers,
Marc

COM / SERIAL to USB unplugged. Memory leak [duplicate]

I got a little problem with a USB Barcode Scanner.
I am using the Scanner with the "SerialPort" class:
this._barcodeScanner = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One) { Handshake = Handshake.None, ReadTimeout = 500, WriteTimeout = 500 };
this._barcodeScanner.Open();
this._barcodeScanner.DataReceived += BarcodeScannerCallback;
If I unplug the USB Device while it´s opened via the "SerialPort" class, I can´t close the software properly and the virtual port stays open for all eternity or till I reboot the whole computer.
So my question is, is there any way to close the virtual port after I unplugged the device via C# code?
Greetings
[edit #1]
Alrighty, some more code:
This way I am checking every 10 seconds if the device is plugged in:
private bool CheckUsbDeviceAvailability()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI",
"SELECT * FROM MSSerial_PortName WHERE PortName = '" + this.PortName + "'");
if (searcher.Get().Count > 0)
return true;
return false;
}
Thats the Callback-Event of the Serial Port:
void BarcodeScannerCallback(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = this._barcodeScanner.ReadExisting().Replace(Convert.ToChar(2), Convert.ToChar(32)).Trim();
if (data.StartsWith("AX"))
{
string[] arrData = data.Split('\n');
this._barcodeScanner.StopAvailabilityThread();
Barcode code = new Barcode(arrData[0].Replace("\r", ""));
if (CheckIfBarcodeExists(code))
this.UpdateBarcodeNode(code);
else
this.CreateBarcodeNode(code);
BarcodeScannerCallbackEvent(sender, e, code);
this._barcodeScanner.StartAvailabilityThread();
}
this._barcodeScanner.ComDevicePluggedIn = ScannerDevice.ComAvailabilityState.Available;
}
if it doesnt answer anymore it will fire the "DeviceNotAvailableEvent()":
void BarcodeScannerDeviceNotAvailableEvent()
{
this._barcodeScanner.Close();
this._barcodeScanner.Dispose();
}
I have overriden the Dispose Event of the "SerialPort" class so that it´s going to abort the Thread:
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
this._deviceAvailableThread.Abort();
}
base.Dispose(isDisposing);
}
Serial ports date from the stone age of computing. That's where you plugged in your ASR-33 teletype to start typing in your Fortran program. The electrical interface is very simple. So is the Windows API to use a serial port from your own code. Practically any runtime environment supports them.
USB has replaced serial port hardware completely. It has a much more advanced logical interface to the machine, supporting many different type of devices. And it supports Plug and Play, allowing the operating system to detect when a device is attached or removed as well as automatically installing the device driver, etcetera.
This flexibility comes at a price however, a USB device always needs a device driver to become usable. Device drivers are not created equal. Different drivers require different ways to talk to the device. Usually done through DeviceIoControl() or Read/WriteFile() but those are very opaque API functions. In the early days of USB, device manufacturers would supply a DLL that provided a rich API to hide the implementation details.
That did not work so well, manufacturers are not very good at writing good APIs and they sure don't like to support them. So a good solution would be to support a standard API, one that's available on any machine, supported by any runtime, documented and maintained by somebody else. Like the serial port API.
That did not work so well, manufacturers are not very good at writing device drivers that emulate serial ports. The biggest hang-up with the API is that it doesn't have any support for Plug and Play. The core support for it is missing, after all serial port hardware doesn't have the logical interface to support it. There is some support for detecting that a device is attached through the DTR hardware handshake line, but no support whatsoever for detecting that the port is no longer there.
Detaching the USB device is the problem. In an ideal world, the emulator built into the device driver would simply pretend that the serial port is still there until the last handle on the device is closed. That would be the logical implementation, given that there's no way to trigger a Plug and Play event. For some strange reason that seems to be difficult to implement. Most USB drivers take the crummy shortcut, they simply make the device disappear even while it is in use.
This plays havoc on any user mode code that uses the device. Which is typically written to assume it is a real serial port and real serial ports don't suddenly disappear. At least not without drawing a bright blue spark. What goes wrong is pretty unpredictable because it depends on how the driver responds to requests on a device that's no longer there. An uncatchable exception in a worker thread started by SerialPort was a common mishap. Sounds like your driver really gets it wrong, it generates an error return code on the MJ_CLOSE driver request. Which is kind of a logical thing to do for a driver, after all the device isn't there anymore, but quite unsolvable from your end. You have a handle and you can't close it. That's up a creek with no paddle.
Every major release of .NET had a small patch to the SerialPort classes to try to minimize the misery a bit. But there's a limited amount that Microsoft can do, catching all errors and pretending they didn't happen ultimately leads to class that provides no good diagnostic anymore, even with a good driver.
So practical approaches are:
always use the Remove Hardware Safely tray icon in Windows
use the latest version of .NET
contact the vendor and ask for a driver update
ditch vendors that supply lousy drivers
tell your users that, just because it is the only thing you can do with a USB device, that unplugging it doesn't solve any problems
make closing the port easy and accessible in your UI
glue the USB connector to the port so it can't be removed
The 5th bullet is also what gets programmers in trouble. Writing serial port code isn't easy, it is heavily asynchronous and the threadpool thread that runs the DataReceived event is difficult to deal with. When you can't diagnose the software problem you tend to blame the hardware. There's very little you can do with the hardware but unplug it. Bad Idea. Now you have two problems.
This Problem Exists in .Net 2 , 3 , 3.5 you can use framework 4 (problem does not exist in .net 4)

Serial Communication

I have a Program that uses serial port communication to talk to some hardware. No problem.
Then I added two GSM Modens to the picture. In VB I opened the COM port to the modem with one protocol (8 data, none, 1) and when the communication between modems was open and running I closed the port and reopened it with a new protocol (7 data, even parity, 2 stop) to my hardware. The hardware is standardized to this speed several years ago so I can not change this and most modems do not support 7, e , 2 protocol.
I want to expand the support of modems and many of them break contact when the port is closed. I'm not using hardware handshaking.
So here is my question.
How can I best change between protocols with out closing the serial port?
Does anybody have another idea how this can be done without changing any hardware settings?
Make a virtual serial port? (how?)
Ideas?
To truly set all options of your serial connection you should use the Win32 API communication functions. As far as i know you don't need to close and re-open a port to get these settings active. The will work right after setting them (like in this example).
You just have to take care, if you want to change just one or two settings, that you have to prefill you structure with the corresponding GetX function, make your changes and call the SetX function.
Maybe in contrast to the sentence before, but don't rely on default settings on your first SetX call. I've seen a lot of programs just altering the popular settings (e.g baudrate, stopp bits, etc.) but not the rare ones (like XoffChar, etc). If you just do that and another program will change these settings you start wondering why your program is suddenly not able to communicate anymore with your serial device, because you use the settings which another program set to the serial port.
And before i forget, if you like to use Win32 API functions in C# take a look at PInvoke.net

Categories

Resources