Play Real Time from Byte array - c#

Im sending audio from micro to PC using dma(LAN-TCP):
while (1) {
U32 max;
int r,i;
main_TcpNet ();
if(tcpSend & sendBuffer)
{
if(selectBuffer)
{
send_datalog(ADC_RegularConvertedValueTab2,sizeof(ADC_RegularConvertedValueTab2));
sendBuffer = 0;
}
else
{
send_datalog(ADC_RegularConvertedValueTab,sizeof(ADC_RegularConvertedValueTab));
sendBuffer = 0;
}
main_TcpNet ();
}
}
}
I need to play it in real time .this is what Ive done so far using NAudio:
byte[] recBuff = new byte[1400];
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
recBuff [count]= theSockId.dataBuffer[0];
count++;
if (count >= 1400)
{
//--------------------------------------------------------------------
for (int i = 0; i < 1400; i += 2)
recieveSound[i / 2] = recBuff[i] + (recBuff[i + 1] * 256); //turn back to 16bit
//--------------------------------------------------------------------
foreach(int data in recieveSound)
sound.Add(data);
//----------------------------------
if (playStauts)
{
if (firstplay)
{
IWaveProvider provider = new RawSourceWaveStream(
new MemoryStream(recBuff), new WaveFormat());
_waveOut.Init(provider);
_waveOut.Play();
//playThread.Start();
//firstplay = false;
}
}
else
{
player.Stop();
}
count = 0; //RESET THE RecBuff
}
//---------------------------------------------------------------
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
if (m_clientSocket != null)
{
m_clientSocket.Close();
m_clientSocket = null;
}
Close();
}
private void frmMain_Load(object sender, EventArgs e)
{
playThread = new Thread(new ThreadStart(play));
player = new SoundPlayer(filePath);
toolStriplbIP.Text = "Your IP: " + GetIP();
btnDisconnect.Enabled = false;
}
#region Palying Sound
private void btnPlay_Click(object sender, EventArgs e)
{
try
{
//Array.Clear(sound, 0, sound.Count);
buffCount = 0;
offsetSound = 0;
sound.Clear();
Object objData = "7";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
if (m_clientSocket != null)
m_clientSocket.Send(byData);
playStauts = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnPause_Click(object sender, EventArgs e)
{
playStauts = false;
}
#endregion
public void play()
{
while(true){
using (SoundPlayer player = new SoundPlayer(filePath))
{
//????????
}
}
}
I just hear like a bijilion Buzzes in sec. But When I save it and then play it I hear the song very clear and loud.
What is wrong? How can I play my byte array when its growing?
does this even work for me?
byte[] bytes = new byte[1400];
IWaveProvider provider = new RawSourceWaveStream(
new MemoryStream(bytes), new WaveFormat());
_waveOut.Init(provider);
_waveOut.Play();

For one thing, you're using the default WaveFormat, which may or may not be correct. Disagreement between source and destination formats will definitely cause you problems.
Once you're sure the WaveFormat is correct, I would suggest using a BufferedWaveProvider as the input to your wave player rather than the MemoryStream, something like this:
WaveFormat Format = new WaveFormat(/* fill in the right parameters here */);
BufferedWaveProvider Provider = new BufferedWaveProvider(Foramt);
Then, whenever you're happy with your recBuff, you just call Provider.AddSamples to drop the data into the BufferedWaveProvider, which will then be picked up by your WaveOut player.
There's some other strangeness going on. Are you receiving only one byte at a time? It looks like that's what your asynchronous handler is doing. This might not be the best thing, since that will result in lots and lots of context switching. If you're receiving more than one byte at a time, then you're only grabbing the first one and ignoring the rest. That will undoubtedly result in "unexpected" sounds during playback.

Related

WasapiLoopbackCapture.DataAvailable reading silence bytes

I am trying to record the speaker sound to a wave file using NAudio's WasapiLoopbackCapture by writing the stream of bytes available. The WasapiLoopbackCapture.DataAvailable BytesRecorded will be 0 is there is no sound. however in my case i am getting bytecount in BytesRecorded even though the speakers are silent. could you please let me know whats wrong here.
class CallResponse
{
private WaveFileWriter _writer;
private WasapiLoopbackCapture _waveIn;
private string _inFile;
private string _inFileCompressed;
private int _duration;
public bool _isRecording;
public bool _speechDetected;
public CallResponse()
{
_inFile = #"C:\Naresh\test.wav";
_inFileCompressed = #"C:\Naresh\test16Hz.wav";
_waveIn = new WasapiLoopbackCapture();
_waveIn.DataAvailable += (s, e) =>
{
Console.WriteLine(e.BytesRecorded);
_writer.Write(e.Buffer, 0, e.BytesRecorded);
if (_writer.Position > _waveIn.WaveFormat.AverageBytesPerSecond * _duration)
{
Console.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bRecording stopped...");
_waveIn.StopRecording();
}
};
_waveIn.RecordingStopped += (s, e) =>
{
if (_writer != null)
{
_writer.Close();
_writer.Dispose();
_writer = null;
}
Console.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bCompressing Audio...");
using (var reader = new AudioFileReader(_inFile))
{
var resampler = new WdlResamplingSampleProvider(reader, 16000);
WaveFileWriter.CreateWaveFile16(_inFileCompressed, resampler);
}
_isRecording = false;
};
}
public void DisposeObjects()
{
if (_waveIn != null)
{
_waveIn.Dispose();
_waveIn = null;
}
}
public void StartRecording(int duration = 5)
{
_writer = new WaveFileWriter(_inFile, _waveIn.WaveFormat);
this._duration = duration;
_speechDetected = false;
_isRecording = true;
Console.WriteLine("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bRecording....");
_waveIn.StartRecording();
}
}
if something is playing audio, then WasapiLoopbackCapture will capture that audio, even if it contains silence. So there's nothing particularly wrong or surprising that you are getting non-zero BytesRecorded values. In fact, if no applications are sending audio to the device being captured, then what typically happens is that you won't get any DataAvailable callbacks at all.

Plotting serial port data using zedgraph (data Vs time)

I'm trying to plot the data read from a serial port using zedgraph. I'm still learing to code so I couldn't deduce why the plot does not work. Please have a look at the code and advice;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
string t;
SerialPort sp;
Thread m_thread;
bool m_running = false;
ManualResetEvent m_event = new ManualResetEvent(true);
bool m_pause = false;
private GraphPane myPane;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
// User can already search for ports when the constructor of the FORM1 is calling
// And let the user search ports again with a click
// Searching for ports function
SearchPorts();
CreateZedGraph(); //error : Severity Code Description Project File Line Suppression State
//Error CS7036 There is no argument given that corresponds to the required formal parameter
//'w' of 'Form1.DrawPoint(ZedGraphControl, int, PointPair)'
}
// start button
private void btnStart_Click(object sender, EventArgs e)
{
if (m_thread == null || m_thread.IsAlive == false)
{
ClearGraph();
m_thread = new Thread(Process);
m_thread.Start();
}
}
void Process()
{
PointPair point = new PointPair();
btnStart.Enabled = false;
btnStop.Enabled = true;
m_running = true;
while (m_running == true)
{
m_event.WaitOne();
point.Y = Convert.ToDouble(serialPort1);
point.X++; //time instance of measurement??
DrawPoint(zed1, point);
ssData.Value = point.Y.ToString();
RefresheZedGraphs(zed1);
Thread.Sleep(700);
}
btnStart.Enabled = true;
}
private void CreateZedGraph(object sender, SerialDataReceivedEventArgs e, ZedGraphControl zgc)
{
myPane = zgc.GraphPane;
// axes stuff
myPane.Title.Text = "FRDM-KW40z serial Test";
myPane.XAxis.Title.Text = "Time";
myPane.YAxis.Title.Text = "Voltage";
myPane.XAxis.MajorGrid.IsVisible = true;
myPane.YAxis.MajorGrid.IsVisible = true;
myPane.XAxis.MinorGrid.IsVisible = true;
myPane.YAxis.MinorGrid.IsVisible = true;
// data from serial port
PointPairList list = new PointPairList();
zed1.GraphPane.AddCurve("Test", list, Color.Red);
}
To open and read from a serial port, I use a combox and a couple of buttons (and then later I try to save it to a text file);
private void button2_Click(object sender, EventArgs e)
{
comboBox1.Items.Clear();
SearchPorts();
}
void SearchPorts()
{
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
comboBox1.Items.Add(port);
}
}
private void button3_Click(object sender, EventArgs e)
{
// Catch exception if it will be thrown so the user will see it in a message box
OpenCloseSerial();
}
void OpenCloseSerial()
{
try
{
if (sp == null || sp.IsOpen == false)
{
t = comboBox1.Text.ToString();
sErial(t);
button3.Text = "Close Serial port"; // button text
}
else
{
sp.Close();
button3.Text = "Connect and wait for inputs"; // button text
}
}
catch (Exception err) // catching error message
{
MessageBox.Show(err.Message); // displaying error message
}
}
void sErial(string Port_name)
{
try
{
sp = new SerialPort(Port_name, 115200, Parity.None, 8, StopBits.One); // serial port parameters
sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
sp.Open();
}
catch (Exception err)
{
throw (new SystemException(err.Message));
}
}
private void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
// This below line is not need , sp is global (belongs to the class!!)
//SerialPort sp = (SerialPort)sender;
if (e.EventType == SerialData.Chars)
{
if (sp.IsOpen)
{
string w = sp.ReadExisting();
if (w != String.Empty)
{
Invoke(new Action(() => Control.Update(w)));
}
}
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (sp == null || sp.IsOpen == false)
{
OpenCloseSerial();
}
}
The plot does not update! I can't quite guess why. Please tell me if there's mistakes in my approach or the code.
I get an error at : Invoke(new Action(() => Control.Update(w))); when trying to update the graph so that I can save after that.
I again have an error at: DrawPoint(zed1, point);
Thank you all for your time. Good day.
Cheers,
Ram.
To update the chart, you need to call the Invalidate method.
When you receive data from serial port, you need to convert it to double[] and add those points to your PointPairList.
PointPairList list = new PointPairList();
zed1.GraphPane.AddCurve("Test", list, Color.Red);
//Convert the received data to double array
double[] serialPortData = ....
//You may want to clear list first, by list.Clear();
list.Add(serialPortData);
//Invalidate the ZedGraphControl to update
zed1.Invalidate();

C# Received data from SerialPort is wrong after writing

I have a communication device which sends requests every two seconds through COM. Between the requests, the device waits for response. I'm building software in C# with SerialPort. I call an event handler for data receiving and I run a method in new thread with while loop which checks that the request is as expected and calls method responsible for response. The thing is, after response next received data is wrong. Here is the code:
The SerialPortManager:
class SerialPortManager : IDisposable
{
...
public void connect()
{
if (mSerialPort.IsOpen)
return;
mSerialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
try
{
mSerialPort.Open();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
mStatus = Status.DISCONNECTED;
return;
}
if (mSerialPort.IsOpen)
{
mStatus = Status.CONNECTED;
Thread tryToResponseThread = new Thread(tryToResponse);
tryToResponseThread.Start();
}
}
private void tryToResponse()
{
while (mStatus == Status.CONNECTED)
{
if (mRequest.Length >= 56)
{
string checksum = "555555555555555580808080";
if (mRequest.Length > 56)
{
mRequest.Remove(55, mRequest.Length - 56);
Debug.Print("cutting");
}
if (mRequest.ToString().StartsWith(checksum))
{
StringBuilder strToCMD = new StringBuilder();
for (int i = 0; i < mRequest.Length; i += 2)
{
strToCMD.Append(mRequest[i]);
strToCMD.Append(mRequest[i + 1]);
strToCMD.Append(" ");
}
StringBuilder address = new StringBuilder();
StringBuilder group = new StringBuilder();
address.Append(mRequest.ToString(24, 8));
group.Append(mRequest.ToString(24 + 8, 2));
mMainForm.appendCMDTextboxText(Environment.NewLine);
mMainForm.appendCMDTextboxText(DateTime.Now.ToLongTimeString() + " [RX] " + address.ToString() + " " + group.ToString() + "\t");
mMainForm.appendCMDTextboxText(strToCMD.ToString());
byte[] request = ByteArrayConverter.fromString16(mRequest.ToString());
mRequest.Clear();
response(request);
Array.Clear(request, 0, request.Length);
Debug.Print("starts with checksum");
}
else if (mRequest.ToString().Contains(checksum))
{
int indexOfChecksum = mRequest.ToString().IndexOf(checksum);
mRequest.Remove(0, indexOfChecksum);
Debug.Print("contains");
}
else
{
int index = 0;
bool found = false;
for (int i = 0; i < checksum.Length; i++)
{
StringBuilder s = new StringBuilder();
int sub = mRequest.Length - checksum.Length + i + 2;
if (sub == mRequest.Length)
break;
s.Append(mRequest.ToString().Substring((Math.Max(0, mRequest.Length - checksum.Length + i + 2))));
s.Append(mRequest.ToString(0, i + 2));
if (s.ToString().Equals(checksum))
{
index = sub;
found = true;
break;
}
}
if (found)
{
mRequest.Remove(0, index);
}
else
{
mRequest.Clear();
}
Debug.Print("on start and end");
}
}
}
}
private void response(byte[] request)
{
Luminaire lumToResponse = mLuminaireManager.getLuminaire(request);
if (lumToResponse == null)
{
return;
}
else
{
if (lumToResponse.isNotResponding())
return;
}
byte[] responseMsg = lumToResponse.getWholeFrame(request);
mMainForm.setCommandLabelForResponsingLuminaire(lumToResponse);
mMainForm.appendCMDTextboxText(Environment.NewLine + DateTime.Now.ToLongTimeString() + " [TX]\t");
string responseMsgAsString = ByteArrayConverter.toString(responseMsg).Replace("-", " ");
mMainForm.appendCMDTextboxText(responseMsgAsString);
write(responseMsg, 0, responseMsg.Length);
mSerialDataEventArgs.clearData();
}
public void write(byte[] buffer, int offset, int count)
{
if (mStatus == Status.DISCONNECTED || mSerialPort.IsOpen == false)
{
mStatus = Status.DISCONNECTED;
return;
}
mSerialPort.Write(buffer, offset, count);
}
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (mStatus == Status.DISCONNECTED)
return;
int dataLength = mSerialPort.BytesToRead;
if (dataLength == 0)
return;
byte[] data = new byte[dataLength];
mSerialPort.Read(data, 0, dataLength);
mSerialDataEventArgs.setData(data);
mDataReceived?.Invoke(this, mSerialDataEventArgs);
}
...
}
The helpser class for passing the received data:
public class SerialDataEventArgs : EventArgs
{
public SerialDataEventArgs()
{
}
public void setData(byte[] data)
{
clearData();
mData = data;
}
public SerialDataEventArgs(byte[] dataInByteArray)
{
mData = dataInByteArray;
}
public void clearData()
{
if (mData == null)
return;
Array.Clear(mData, 0, mData.Length);
}
public byte[] mData;
}
And the main class:
public partial class MainForm : Form
{
...
private void MainForm_Load(object sender, EventArgs e)
{
mSerialPortManager = new SerialPortManager();
mSerialPortManager.setPortBoudRate((int)numUpDown_SerialPortSpeed.Value);
mLuminaireManager = new LuminaireManager();
mSerialPortManager.mMainForm = this;
mSerialPortManager.mLuminaireManager = mLuminaireManager;
fixTableLayoutColumnSize(ref tl_SingleLuminaire);
fillTheRestOfSingleLuminaireGroupBoxes();
fillSerialPortComboBoxWithNamesOfAvailablePorts();
mSerialPortManager.mDataReceived += new EventHandler<SerialDataEventArgs>(serialPortManager_DataReceived);
mIsPaused = false;
}
private void serialPortManager_DataReceived(object sender, SerialDataEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(serialPortManager_DataReceived), new object[] { sender, e });
return;
}
if (mIsPaused)
return;
mSerialPortManager.mRequest.Append(ByteArrayConverter.toString(e.mData).Replace("-", ""));
}
...
}
The communication should be like below:
request: 5555555555555555808080800100000001001A0006070001060031B1
response: 55555555555555558080808001000000010000808076
request: 5555555555555555808080800200000001001A0006070001060034B2
response: 555555555555555580808080020000000100008041BA
request: 5555555555555555808080800300000001001A000607000106003473
response: 55555555555555558080808003000000010000804049
And so on. It is just example, what the request frame should look like. As you can see, the device asks for 1,2,3,4, etc. It always asks in this order. The last four values are just checksum. What I receive after response is like:
request: 5555555555555555808080800200000001001A0006070001060034B2
response: 555555555555555580808080020000000100008041BA
request: 55555555555555558080808002000000000A0100000000000000BCAE
After response for 2, there should be an ask for 3. If I set the software to not responding, every request looks fine.
What I am doing wrong?
Ok, so everything is okay. My COM interface is broken :( Everything is fine with both ways - DataReceived event handler and read() right after write() (no matter which solution is better in programming way). Thank you all for trying help with my case anyway!

H7 Heart Rate Sensor in C# for Windows Desktop

Specifically, I need to develop a Desktop app that pulls data from H7 Heart Rate Sensor in C# code.
I have searched everywhere and i cant find nothing to help me.
The closest i cam is with this video (https://www.youtube.com/watch?v=Jn05CU3mxzo&list=UUizfLH6Q2igGUyTWO1bH3YA) tutorial but still it didn't find my H7 Heart Rate Sensor.
namespace _123
{
public partial class Form1 : Form
{
List<string> items;
public Form1()
{
InitializeComponent();
items = new List<string>();
}
private void bGo_Click(object sender, EventArgs e)//button
{
if (serverStarted)
{
updateUI("server aleredy started");
return;
}
if (rbClient.Checked) {
startScan();
}
else{
connectAsServer();
}
}
private void startScan() {
listBox1.DataSource = null;
listBox1.Items.Clear();
items.Clear();
Thread bluetoothScanThread = new Thread(new ThreadStart(scan));
bluetoothScanThread.Start();
}
BluetoothDeviceInfo[] devices;
private void scan ()
{
updateUI("Starting scan...");
BluetoothClient client = new BluetoothClient();
devices = client.DiscoverDevicesInRange();
updateUI("Scan complet");
updateUI(devices.Length.ToString() + "devices discovered");
foreach (BluetoothDeviceInfo d in devices)
{
items.Add(d.DeviceName);
}
updateDeviceList();
}
private void connectAsServer()
{
Thread bluetoothServerTherad = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerTherad.Start();
}
private void connectAsClient()
{
}
Guid mUUID = new Guid("ECC037FD-72AE-AFC5-9213-CA785B3B5C63");
bool serverStarted = false;
private void ServerConnectThread()
{
//throw new NotImplementedException();
serverStarted = true;
updateUI("Server started, waiting for clients");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
BluetoothClient conn = blueListener.AcceptBluetoothClient();
updateUI("Client has connected");
Stream mStream = conn.GetStream();
while (true)
{
try
{
byte[] received = new byte[1024];
mStream.Read(received, 0, received.Length);
updateUI("Received: " + Encoding.ASCII.GetString(received));
byte[] sent = Encoding.ASCII.GetBytes("hello world");
mStream.Write(sent, 0, sent.Length);
}
catch (IOException exeption)
{
updateUI("Client has disconected!");
}
}
}
private void updateUI(string message)
{
Func<int> del = delegate()
{
tbOutput.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateDeviceList()
{
Func<int> del = delegate()
{
listBox1.DataSource = items;
return 0;
};
Invoke(del);
}
BluetoothDeviceInfo deviceInfo;
private void listBox1_DoubleClick(object sender, EventArgs e)
{
deviceInfo = devices.ElementAt(listBox1.SelectedIndex);
updateUI(deviceInfo.DeviceName + " was selected, attemting connect");
if (pairDevice())
{
updateUI("device paired..");
updateUI("starting conected thread");
Thread bluetoothClientThread = new Thread(new ThreadStart(ClientConnectThread));
bluetoothClientThread.Start();
}
else
{
updateUI("pair failed");
}
}
private void ClientConnectThread()
{
BluetoothClient client = new BluetoothClient();
updateUI("attepting connnection");
client.BeginConnect(deviceInfo.DeviceAddress, mUUID, this.BluetoothClientConnectCallback, client);
}
void BluetoothClientConnectCallback(IAsyncResult result)
{
BluetoothClient client = (BluetoothClient)result.AsyncState;
client.EndConnect(result);
Stream stream = client.GetStream();
stream.ReadTimeout = 1000;
while (true)
{
while (!ready) ;
stream.Write(message, 0, message.Length);
}
}
string myPin = "1234";
private bool pairDevice()
{
if (!deviceInfo.Authenticated)
{
if (!BluetoothSecurity.PairRequest(deviceInfo.DeviceAddress, myPin))
{
return false;
}
}
return true;
}
bool ready = false;
byte[] message;
private void tbText_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
message = Encoding.ASCII.GetBytes(tbText.Text);
ready = true;
tbText.Clear();
}
}
}
}
This question is old now but here is my answer. So if you have Polar H7 and you are trying to get the Heart rate then I would recommend follow this Bluetooth Low Energy sample and just run the code it should work fine.
After you run this sample click on start enumerating and it will give you list of all the Bluetooth device .
Then find Polar H7 and click on it.
Go to step 2 and hit Connect and choose characteristic and service and you are done.

Why does C# thread die?

This is my 1st C# project so I may be doing something obviously improper in the code below.
I am using .NET, WinForms (I think), and this is a desktop application until I get the bugs out.
UpdateGui() uses Invoke((MethodInvoker)delegate to update various GUI controls based on received serial data and
sends a GetStatus() command out the serial port 4 times a second.
Thread Read() reads the response from serial port whenever it arrives which should be near immediate.
SerialPortFixer is a SerialPort IOException Workaround in C# I found at
http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.html.
After one or both threads die I'll see something like
The thread 0x1288 has exited with code 0 (0x0).
in the debug code output.
Why do UpdateGui() and/or Read() eventually die?
public partial class UpdateStatus : Form
{
private readonly byte[] Command = new byte[32];
private readonly byte[] Status = new byte[32];
readonly Thread readThread;
private static readonly Mutex commandMutex = new Mutex();
private static readonly Mutex statusMutex = new Mutex();
...
public UpdateStatus()
{
InitializeComponent();
SerialPortFixer.Execute("COM2");
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
try
{
serialPort1.Open();
}
catch (Exception e)
{
labelWarning.Text = LOST_COMMUNICATIONS + e;
labelStatus.Text = LOST_COMMUNICATIONS + e;
labelWarning.Visible = true;
}
readThread = new Thread(Read);
readThread.Start();
new Timer(UpdateGui, null, 0, 250);
}
static void ProcessStatus(byte[] status)
{
Status.State = (State) status[4];
Status.Speed = status[6]; // MSB
Status.Speed *= 256;
Status.Speed += status[5];
var Speed = Status.Speed/GEAR_RATIO;
Status.Speed = (int) Speed;
...
}
public void Read()
{
while (serialPort1 != null)
{
try
{
serialPort1.Read(Status, 0, 1);
if (Status[0] != StartCharacter[0]) continue;
serialPort1.Read(Status, 1, 1);
if (Status[1] != StartCharacter[1]) continue;
serialPort1.Read(Status, 2, 1);
if (Status[2] != (int)Command.GetStatus) continue;
serialPort1.Read(Status, 3, 1);
...
statusMutex.WaitOne();
ProcessStatus(Status);
Status.update = true;
statusMutex.ReleaseMutex();
}
catch (Exception e)
{
Console.WriteLine(#"ERROR! Read() " + e);
}
}
}
public void GetStatus()
{
const int parameterLength = 0; // For GetStatus
statusMutex.WaitOne();
Status.update = false;
statusMutex.ReleaseMutex();
commandMutex.WaitOne();
if (!SendCommand(Command.GetStatus, parameterLength))
{
Console.WriteLine(#"ERROR! SendCommand(GetStatus)");
}
commandMutex.ReleaseMutex();
}
private void UpdateGui(object x)
{
try
{
Invoke((MethodInvoker)delegate
{
Text = DateTime.Now.ToLongTimeString();
statusMutex.WaitOne();
if (Status.update)
{
if (Status.Speed > progressBarSpeed.Maximum)
{
Status.Speed = progressBarSpeed.Maximum;
}
progressBarSpeed.Value = Status.Speed;
labelSpeed.Text = Status.Speed + RPM;
...
}
else
{
labelWarning.Text = LOST_COMMUNICATIONS;
labelStatus.Text = LOST_COMMUNICATIONS;
labelWarning.Visible = true;
}
statusMutex.ReleaseMutex();
GetStatus();
});
}
catch (Exception e)
{
Console.WriteLine(#"ERROR! UpdateGui() " + e);
}
}
}
A thread will terminate when there's no more code to execute, or more specifically when the method you specify when you create thread returns.
Maybe serialport1 becomes null?
As for the update timer, there is a special purpose windows forms timer that runs periodically that doesn't require you to use Invoke. It's the right tool for the job

Categories

Resources