I am trying to use the WasapiLoopbackCapture class (NAudio 1.7.1.17) and ending up with the COMException (0x88890003). The recording format is WaveFormat(44100, 16, 2). I have multiple playback devices on my system and have tried setting each one as the default device with the same results. I have also verified that each of those devices has (44100, 16, 2) listed as a supported format.
Console Output:
WasapiCapture_RecordingStopped.
Exception: System.Runtime.InteropServices.COMException (0x88890003): Exception from HRESULT: 0x88890003
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at NAudio.CoreAudioApi.AudioClient.get_AudioCaptureClient()
at NAudio.CoreAudioApi.WasapiCapture.DoRecording(AudioClient client)
at NAudio.CoreAudioApi.WasapiCapture.CaptureThread(AudioClient client)
Code:
public static class Program
{
private static int Index = 0;
private static int TotalBytesRecorded = 0;
private static bool RecordingStopped = false;
private static void Main (string [] args)
{
var device = NAudio.Wave.WasapiLoopbackCapture.GetDefaultLoopbackCaptureDevice();
using (var capture = new NAudio.CoreAudioApi.WasapiCapture(device))
{
capture.WaveFormat = new NAudio.Wave.WaveFormat(44100, 16, 2);
capture.ShareMode = NAudio.CoreAudioApi.AudioClientShareMode.Shared;
capture.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(Program.WasapiCapture_DataAvailable);
capture.RecordingStopped += new EventHandler<NAudio.Wave.StoppedEventArgs>(Program.WasapiCapture_RecordingStopped);
Program.Index = 0;
Program.TotalBytesRecorded = 0;
Program.RecordingStopped = false;
capture.StartRecording();
Thread.Sleep(TimeSpan.FromSeconds(10));
capture.StopRecording();
while (!Program.RecordingStopped)
{
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}
}
Console.WriteLine();
Console.WriteLine();
Console.Write("TotalBytesRecorded: {0}.", Program.TotalBytesRecorded.ToString("N0"));
}
private static void WasapiCapture_DataAvailable (object sender, NAudio.Wave.WaveInEventArgs e)
{
Program.Index++;
Program.TotalBytesRecorded += e.BytesRecorded;
Console.WriteLine();
Console.Write
(
"Index: {0}, BytesRecorded: {1}, Buffer Length: {2}, TotalBytesRecorded: {3}.",
Program.Index.ToString("N0").PadLeft(10, ' '),
e.BytesRecorded.ToString("N0").PadLeft(10, ' '),
e.Buffer.Length.ToString("N0").PadLeft(10, ' '),
Program.TotalBytesRecorded.ToString("N0").PadLeft(10, ' ')
);
}
private static void WasapiCapture_RecordingStopped (object sender, NAudio.Wave.StoppedEventArgs e)
{
Program.RecordingStopped = true;
Console.WriteLine();
Console.WriteLine();
Console.Write("WasapiCapture_RecordingStopped.");
if (e.Exception != null)
{
Console.WriteLine();
Console.WriteLine();
Console.Write("Exception: {0}", e.Exception);
}
}
}
Any tips would be appreciated.
You can't set the capture for WASAPI loopback capture - you have to use the system mix format, which will use 32 bit floating point samples. Just use the WasapiLoopbackCapture class directly and it will work.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I Have the string :
Humidity: 33 %
Temperature: 25.7 deg C
Visible light: 112 lx
Infrared radiation: 1802.5 mW/m2
UV index: 0.12
CO2: 404 ppm CO2
Pressure: 102126 Pa
I have to extract all the numbers coming after 'Humidity:' , ..
I was thinking to use the Regex class but i dont know exactly how to do it
My code for getting the serial data :
namespace Demo1Arduino
{
public partial class MainWindow : Window
{
private SerialPort port;
DispatcherTimer timer = new DispatcherTimer();
private string buff;
public MainWindow()
{
InitializeComponent();
}
private void btnOpenPort_Click(object sender, RoutedEventArgs e)
{
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Start();
try
{
port = new SerialPort(); // Create a new SerialPort object with default settings.
port.PortName="COM4";
port.BaudRate = 115200; // Opent de seriele poort, zet data snelheid op 9600 bps.
port.StopBits = StopBits.One; // One Stop bit is used. Stop bits separate each unit of data on an asynchronous serial connection. They are also sent continuously when no data is available for transmission.
port.Parity = Parity.None; // No parity check occurs.
port.DataReceived += Port_DataReceived;
port.Open(); // Opens a new serial port connection.
buff = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer_Tick(object sender, EventArgs e)
{
try
{
if(buff != "")
{
textBox.Text += buff;
buff = "";
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer = new byte[128];
int len = port.Read(buffer, 0, buffer.Length); // .Read --> Reads a number of characters from the SerialPort input buffer and writes them into an array of characters at a given offset.
if(len>0)
{
string str = "";
for (int i=0; i<len; i++)
{
if (buffer[i] != 0)
{
str = str + ((char)buffer[i]).ToString();
}
}
buff += str;
}
// throw new NotImplementedException();
}
}
Thank you
Try regular expression, the only trick is CO2 and m2 - we don't want 2 that's why I've added \b:
string source =
#"Humidity: 33 %
Temperature: 25.7 deg C
Visible light: 112 lx
Infrared radiation: 1802.5 mW/m2
UV index: 0.12
CO2: 404 ppm CO2
Pressure: 102126 Pa";
string[] numbers = Regex
.Matches(source, #"\b[0-9]+(?:\.[0-9]+)?\b")
.OfType<Match>()
.Select(match => match.Value)
.ToArray();
Test
Console.Write(string.Join("; ", numbers));
Outcome
33; 25.7; 112; 1802.5; 0.12; 404; 102126
It makes no sense to get multiple number without know the type. I put values into a dictionary to make it easy to use the number later in the code. See code below and https://msdn.microsoft.com/en-us/library/az24scfc(v=vs.110).aspx:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication55
{
class Program
{
static void Main(string[] args)
{
string[] inputs = {
"Humidity: 33 %",
"Temperature: 25.7 deg C",
"Visible light: 112 lx",
"Infrared radiation: 1802.5 mW/m2",
"UV index: 0.12",
"CO2: 404 ppm CO2",
"Pressure: 102126 Pa"
};
string pattern = #"^(?'name'[^:]+):\s(?'value'[\d.]+)";
Dictionary<string, decimal> dict = new Dictionary<string,decimal>();
foreach(string input in inputs)
{
Match match = Regex.Match(input,pattern);
string name = match.Groups["name"].Value;
decimal value = decimal.Parse(match.Groups["value"].Value);
Console.WriteLine("name = '{0}', value = '{1}'", name, value);
dict.Add(name, value);
}
Console.ReadLine();
}
}
}
public partial class Form1 : Form
{
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
string[] Tags;
public Form1()
{
InitializeComponent();
SerialPort RFID = new SerialPort();
RFID.PortName = "COM5";
RFID.BaudRate = 9600;
RFID.DataBits = 8;
RFID.Parity = Parity.None;
RFID.StopBits = StopBits.One;
RFID.Open();
RFID.DataReceived += new SerialDataReceivedEventHandler(RFID_DataReceived);
this.myDelegate = new AddDataDelegate(AddDataMethod);
}
public void AddDataMethod(String myString)
{
textBox1.AppendText(myString);
}
public void RFID_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort RFID = (SerialPort)sender;
int buffer = RFID.ReadBufferSize;
byte[] data = new byte[buffer];
RFID.Read(data, 0, buffer);
string s;
for (int i = 0; i < 18; i++)
{
s = Convert.ToString(data[i], 16);
//Console.WriteLine(Convert.ToString(data[i], 16));
textBox1.Invoke(this.myDelegate, new Object[] { s });
}
//Console.WriteLine(Convert.ToString(i,16));
//textBox1.Invoke(this.myDelegate, new Object[] { s });
}
The above prints the data to a text box. How can I create a space every two characters and leave a line between the data from each scan.
Current output after three scans:
00e203027313032180000000605641acff00000000000000e20302731301716606c200001b5ff00000000000000000e203027313000000000001716606c21b5ff000000000
You may append a space after each converted byte and append a new line (Environment.NewLine) after you've converted the entire buffer.
Please also note that myDelegate should be called after the loop:
public void RFID_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort RFID = (SerialPort)sender;
int buffer = RFID.ReadBufferSize;
byte[] data = new byte[buffer];
RFID.Read(data, 0, buffer);
string s = "";
for (int i = 0; i < 18; i++)
{
s += Convert.ToString(data[i], 16) + " ";
}
s += Environment.NewLine;
textBox1.Invoke(this.myDelegate, new Object[] { s });
}
Alternative solution:
With a little help of LINQ you may format your output string in one go:
public void RFID_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort RFID = (SerialPort)sender;
int buffer = RFID.ReadBufferSize;
byte[] data = new byte[buffer];
RFID.Read(data, 0, buffer);
string s = string.Join(" ", data.Select(b => b.ToString("x2"))) + Environment.NewLine;
textBox1.Invoke(this.myDelegate, new Object[] { s });
}
Where
data.Select(b => b.ToString("x2")) converts an array of bytes to an array of the bytes' string representations using x2 format.
string.Join(" ", ...) concatenates this array of strings onto one string with the elements delimited by a space
+ Environment.NewLine finally ensures the next data portion will go to a new line.
Working on my last assignment of the year trying to get into C# and kinda stuck on how to pull the array in and parse it. Any help is appreciated.
Here is the actual assignment:
Write a program to calculate averages. Create a method named ReadData that will load a two-dimensional array, named stuGradesArray, with the following data from a file.
1324 75.8 89.3 92.3
4356 86.3 83.4 98.3
4790 90.1 77.3 76.9
8393 73.9 76.3 89.3
5563 97.3 78.4 78.9
8329 87.3 65.3 77.2
2717 67.9 89.3 79.3
The first number represents the last four digits of a student number. The last three numbers represent test grades. ReadData will have one argument, the stuGradesArray.
Create a method named DisplayAverages that will display the student number and the average of the three test grades. DisplayAverages will have one argument, the stuGradesArray. Your output should closely resemble the following.
Student # Test1 Test2 Test3 Average
1324 75.8 89.3 92.3 85.8
4356 86.3 83.4 98.3 89.3
4790 90.1 77.3 76.9 81.4
8393 73.9 76.3 89.3 79.8
5563 97.3 78.4 78.9 84.9
8329 87.3 65.3 77.2 76.6
2717 67.9 89.3 79.3 78.8
Input from the file named Program12Dat.txt, found in Blackboard. Output to a file. Round averages to one decimal place. Passing arguments is important for this program. No global variables are allowed, except for the streamReader and the streamWriter. The stuGradesArray must be declared in Main and passed as an argument to the methods ReadData and DisplayAverages.
And here is what I have so far.
using System;
using System.IO;
using System.Text.RegularExpressions;
class Program11
{
static StreamReader fileIn;
static StreamWriter fileOut;
static void Main()
{
uint[,] StudentArray = new uint[7, 4];
ReadData();
DisplayAverages();
CloseFiles();
}
private static void DisplayAverages()
{
throw new NotImplementedException();
}
static void ReadData()
{
uint[,] StudentArray = new uint[7, 4];
string OUTPUT_FILE_NAME = #"C:\Files\output1.txt";
string INPUT_FILE_NAME = #"C:\Files\output1.txt";
if (File.Exists(INPUT_FILE_NAME))
{
fileIn = File.OpenText(INPUT_FILE_NAME);
Console.WriteLine("{ 0} was opened", INPUT_FILE_NAME);
}
else
{
Console.WriteLine("Error: {0} does not exist\n", INPUT_FILE_NAME);
}
fileOut = File.CreateText(OUTPUT_FILE_NAME);
if (File.Exists(OUTPUT_FILE_NAME))
Console.WriteLine("{0} was created\n", OUTPUT_FILE_NAME);
else
{
Console.WriteLine("Error: {0} could not be created\n", OUTPUT_FILE_NAME);
}
}
static void DisplayAverages()
{
fileOut.WriteLine(" Grades Report ");
fileOut.WriteLine();
fileOut.WriteLine(" Student# Test1 Test2 Test3 Average FICA Fed Tax State Tax Net Pay ");
fileOut.WriteLine("--------------- --------------- ---- ----- ----- --------- --------- --------- --------- ---------");
}
static void CloseFiles()
{
fileIn.Close(); fileOut.Close();
}
}
Here is a sample solution to your assignments. The output file formatting is not as expected but you can play with that.
using System;
using System.IO;
using System.Linq;
public class Program
{
public const string INPUT_FILE_NAME = #"F:\Program12Dat.txt";
public const string OUTPUT_FILE_NAME = #"F:\Output.txt";
static void Main(string[] args)
{
var stuGradesArray = new double[7, 4];
ReadData(stuGradesArray);
DisplayAverages(stuGradesArray);
}
public static void ReadData(double[,] stuGradesArray)
{
try
{
StreamReader reader = new StreamReader(INPUT_FILE_NAME);
using (reader)
{
int lineNumber = 0;
// Read first line from the text file
string line = reader.ReadLine();
// Read the other lines from the text file
while (line != null)
{
double[] lineNumbers = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => double.Parse(x))
.ToArray();
for (int i = 0; i < lineNumbers.Length; i++)
{
stuGradesArray[lineNumber, i] = lineNumbers[i];
}
lineNumber++;
line = reader.ReadLine();
}
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
public static void DisplayAverages(double[,] stuGradesArray)
{
StreamWriter writer = new StreamWriter(OUTPUT_FILE_NAME);
using (writer)
{
writer.WriteLine("Student # Test1 Test2 Test3 Average");
for (int i = 0; i < stuGradesArray.GetLength(0); i++)
{
var line = string.Empty;
var average = 0d;
for (int j = 0; j < stuGradesArray.GetLength(1); j++)
{
line += stuGradesArray[i, j];
line += "\t";
if (j != 0)
{
average += stuGradesArray[i, j];
}
}
line += Math.Round(average / 3, 1);
writer.WriteLine(line);
}
}
}
}
I am using NeuronDotNet for neural networks in C#. In order to test the network (as well as train it), I wrote my own function to get the sum squared error. However, when I tested this function by running it on the training data and comparing it to the MeanSquaredError of the Backpropagation network, the results were different.
I discovered the reason for the different error is that the network is returning different outputs when I run to when its run in the learning phase. I run it for each TrainingSample using:
double[] output = xorNetwork.Run(sample.InputVector);
In the learning phase its using:
xorNetwork.Learn(trainingSet, cycles);
...with a delegate to trap the end sample event:
xorNetwork.EndSampleEvent +=
delegate(object network, TrainingSampleEventArgs args)
{
double[] test = xorNetwork.OutputLayer.GetOutput();
debug.addSampleOutput(test);
};
I tried doing this using the XOR problem, to keep it simple, and the outputs are still different. For example, at the end of the first epoch, the outputs from the EndSampleEvent delegate vs those from my function are:
Input: 01, Expected: 1, my_function: 0.703332, EndSampleEvent 0.734385
Input: 00, Expected: 0, my_function: 0.632568, EndSampleEvent 0.649198
Input: 10, Expected: 1, my_function: 0.650141, EndSampleEvent 0.710484
Input: 11, Expected: 0, my_function: 0.715175, EndSampleEvent 0.647102
Error: my_function: 0.280508, EndSampleEvent 0.291236
Its not something as simple as it being captured at a different phase in the epoch, the outputs are not identical to those in the next/previous epoch.
I've tried debugging, but I am not an expert in Visual Studio and I'm struggling a bit with this. My project references the NeuronDotNet DLL. When I put breakpoints into my code, it won't step into the code from the DLL. I've looked elsewhere for advice on this and tried several solutions and got nowhere.
I don't think its due to the 'observer effect', i.e. the Run method in my function causing the network to change. I have examined the code (in the project that makes the DLL) and I don't think Run changes any of the weights. The errors from my function tend to be lower than those from the EndSampleEvent by a factor which exceeds the decrease in error from a typical epoch, i.e. its as if the network is getting ahead of itself (in terms of training) temporarily during my code.
Neural networks are stochastic in the sense that they adjust their functions during training. However, the output should be deterministic. Why is it that the two sets of outputs are different?
EDIT: Here is the code I am using.
/***********************************************************************************************
COPYRIGHT 2008 Vijeth D
This file is part of NeuronDotNet XOR Sample.
(Project Website : http://neurondotnet.freehostia.com)
NeuronDotNet is a free software. You can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.
NeuronDotNet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with NeuronDotNet.
If not, see <http://www.gnu.org/licenses/>.
***********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using NeuronDotNet.Core;
using NeuronDotNet.Core.Backpropagation;
using ZedGraph;
namespace NeuronDotNet.Samples.XorSample
{
public partial class MainForm : Form
{
private BackpropagationNetwork xorNetwork;
private double[] errorList;
private int cycles = 5000;
private int neuronCount = 3;
private double learningRate = 0.25d;
public MainForm()
{
InitializeComponent();
}
private void Train(object sender, EventArgs e)
{
EnableControls(false);
if (!int.TryParse(txtCycles.Text.Trim(), out cycles)) { cycles = 5000; }
if (!double.TryParse(txtLearningRate.Text.Trim(), out learningRate)) { learningRate = 0.25d; }
if (!int.TryParse(txtNeuronCount.Text.Trim(), out neuronCount)) { neuronCount = 3; }
if (cycles < 1) { cycles = 1; }
if (learningRate < 0.01) { learningRate = 0.01; }
if (neuronCount < 1) { neuronCount = 1; }
txtNeuronCount.Text = neuronCount.ToString();
txtCycles.Text = cycles.ToString();
txtLearningRate.Text = learningRate.ToString();
errorList = new double[cycles];
InitGraph();
LinearLayer inputLayer = new LinearLayer(2);
SigmoidLayer hiddenLayer = new SigmoidLayer(neuronCount);
SigmoidLayer outputLayer = new SigmoidLayer(1);
new BackpropagationConnector(inputLayer, hiddenLayer);
new BackpropagationConnector(hiddenLayer, outputLayer);
xorNetwork = new BackpropagationNetwork(inputLayer, outputLayer);
xorNetwork.SetLearningRate(learningRate);
TrainingSet trainingSet = new TrainingSet(2, 1);
trainingSet.Add(new TrainingSample(new double[2] { 0d, 0d }, new double[1] { 0d }));
trainingSet.Add(new TrainingSample(new double[2] { 0d, 1d }, new double[1] { 1d }));
trainingSet.Add(new TrainingSample(new double[2] { 1d, 0d }, new double[1] { 1d }));
trainingSet.Add(new TrainingSample(new double[2] { 1d, 1d }, new double[1] { 0d }));
Console.WriteLine("mse_begin,mse_end,output,outputs,myerror");
double max = 0d;
Console.WriteLine(NNDebug.Header);
List < NNDebug > debugList = new List<NNDebug>();
NNDebug debug = null;
xorNetwork.BeginEpochEvent +=
delegate(object network, TrainingEpochEventArgs args)
{
debug = new NNDebug(trainingSet);
};
xorNetwork.EndSampleEvent +=
delegate(object network, TrainingSampleEventArgs args)
{
double[] test = xorNetwork.OutputLayer.GetOutput();
debug.addSampleOutput(args.TrainingSample, test);
};
xorNetwork.EndEpochEvent +=
delegate(object network, TrainingEpochEventArgs args)
{
errorList[args.TrainingIteration] = xorNetwork.MeanSquaredError;
debug.setMSE(xorNetwork.MeanSquaredError);
double[] test = xorNetwork.OutputLayer.GetOutput();
GetError(trainingSet, debug);
max = Math.Max(max, xorNetwork.MeanSquaredError);
progressBar.Value = (int)(args.TrainingIteration * 100d / cycles);
//Console.WriteLine(debug);
debugList.Add(debug);
};
xorNetwork.Learn(trainingSet, cycles);
double[] indices = new double[cycles];
for (int i = 0; i < cycles; i++) { indices[i] = i; }
lblTrainErrorVal.Text = xorNetwork.MeanSquaredError.ToString("0.000000");
LineItem errorCurve = new LineItem("Error Dynamics", indices, errorList, Color.Tomato, SymbolType.None, 1.5f);
errorGraph.GraphPane.YAxis.Scale.Max = max;
errorGraph.GraphPane.CurveList.Add(errorCurve);
errorGraph.Invalidate();
writeOut(debugList);
EnableControls(true);
}
private const String pathFileName = "C:\\Temp\\NDN_Debug_Output.txt";
private void writeOut(IEnumerable<NNDebug> data)
{
using (StreamWriter streamWriter = new StreamWriter(pathFileName))
{
streamWriter.WriteLine(NNDebug.Header);
//write results to a file for each load combination
foreach (NNDebug debug in data)
{
streamWriter.WriteLine(debug);
}
}
}
private void GetError(TrainingSet trainingSet, NNDebug debug)
{
double total = 0;
foreach (TrainingSample sample in trainingSet.TrainingSamples)
{
double[] output = xorNetwork.Run(sample.InputVector);
double[] expected = sample.OutputVector;
debug.addOutput(sample, output);
int len = output.Length;
for (int i = 0; i < len; i++)
{
double error = output[i] - expected[i];
total += (error * error);
}
}
total = total / trainingSet.TrainingSampleCount;
debug.setMyError(total);
}
private class NNDebug
{
public const String Header = "output(00->0),output(01->1),output(10->1),output(11->0),mse,my_output(00->0),my_output(01->1),my_output(10->1),my_output(11->0),my_error";
public double MyErrorAtEndOfEpoch;
public double MeanSquaredError;
public double[][] OutputAtEndOfEpoch;
public double[][] SampleOutput;
private readonly List<TrainingSample> samples;
public NNDebug(TrainingSet trainingSet)
{
samples =new List<TrainingSample>(trainingSet.TrainingSamples);
SampleOutput = new double[samples.Count][];
OutputAtEndOfEpoch = new double[samples.Count][];
}
public void addSampleOutput(TrainingSample mySample, double[] output)
{
int index = samples.IndexOf(mySample);
SampleOutput[index] = output;
}
public void addOutput(TrainingSample mySample, double[] output)
{
int index = samples.IndexOf(mySample);
OutputAtEndOfEpoch[index] = output;
}
public void setMyError(double error)
{
MyErrorAtEndOfEpoch = error;
}
public void setMSE(double mse)
{
this.MeanSquaredError = mse;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (double[] arr in SampleOutput)
{
writeOut(arr, sb);
sb.Append(',');
}
sb.Append(Math.Round(MeanSquaredError,6));
sb.Append(',');
foreach (double[] arr in OutputAtEndOfEpoch)
{
writeOut(arr, sb);
sb.Append(',');
}
sb.Append(Math.Round(MyErrorAtEndOfEpoch,6));
return sb.ToString();
}
}
private static void writeOut(double[] arr, StringBuilder sb)
{
bool first = true;
foreach (double d in arr)
{
if (first)
{
first = false;
}
else
{
sb.Append(',');
}
sb.Append(Math.Round(d, 6));
}
}
private void EnableControls(bool enabled)
{
btnTrain.Enabled = enabled;
txtCycles.Enabled = enabled;
txtNeuronCount.Enabled = enabled;
txtLearningRate.Enabled = enabled;
progressBar.Value = 0;
btnTest.Enabled = enabled;
txtTestInput.Enabled = enabled;
}
private void LoadForm(object sender, EventArgs e)
{
InitGraph();
txtCycles.Text = cycles.ToString();
txtLearningRate.Text = learningRate.ToString();
txtNeuronCount.Text = neuronCount.ToString();
}
private void InitGraph()
{
GraphPane pane = errorGraph.GraphPane;
pane.Chart.Fill = new Fill(Color.AntiqueWhite, Color.Honeydew, -45F);
pane.Title.Text = "Back Propagation Training - Error Graph";
pane.XAxis.Title.Text = "Training Iteration";
pane.YAxis.Title.Text = "Sum Squared Error";
pane.XAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.Color = Color.LightGray;
pane.XAxis.MajorGrid.Color = Color.LightGray;
pane.XAxis.Scale.Max = cycles;
pane.XAxis.Scale.Min = 0;
pane.YAxis.Scale.Min = 0;
pane.CurveList.Clear();
pane.Legend.IsVisible = false;
pane.AxisChange();
errorGraph.Invalidate();
}
private void Test(object sender, EventArgs e)
{
if (xorNetwork != null)
{
lblTestOutput.Text = xorNetwork.Run(
new double[] {double.Parse(txtTestInput.Text.Substring(2,4)),
double.Parse(txtTestInput.Text.Substring(8,4))})[0].ToString("0.000000");
}
}
}
}
Its not to do with normalisation, as the mapping between the two sets of outputs is not monotonic. For example, the output in {0,1} is higher in EndSampleEvent but in {1,1} it is lower. Normalisation would be a simple linear function.
Its not to do with jitter either, as I've tried turning that off, and the results are still different.
I have received an answer from my professor. The problem lies in the LearnSample method from the BackpropagationNetwork class which is called for each training sample every iteration.
The order of relevant events in this method is ….
1) Add to the MeanSquaredError which is calculated using only the output layer and desired output
2) Backpropagate errors to all earlier layer; this has no effect on the network.
3) Finally recalculate biases for each layer; this affects the network.
(3) is the last thing that occurs in the LearnSample method and happens after the calculation of the output error for each training instance. For the XOR example this means that the network is changed 4 times from the state is was in when the MSE calculation was made.
In theory, if you want to compare training and test errors then you should do a manual calculation (like my GetError function) and run it twice: once for each data set. However, in reality it might not be necessary to go to all this trouble as the values are not that different.
I have a Keyence camera which communicates through RS-232. It is configured to output three integer values when triggered. I'm having trouble reading the integer values. I try to use a char array buffer but it only reads the first + sign in the output. I tested it using putty and output is something like this
+346.0,+261.0,098
I want to know if there is anything I need to use to read integer values like these?
static void Main(string[] args)
{
char[] buffer1 = new char[200] ;
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
if (port.IsOpen) { Console.WriteLine("port is now open"); } else { Console.WriteLine("port not opened correctly"); }
port.Write("T"); //triggers the camera
port.Read(buffer1, 0, 200);
for (int i = 0; i < 200; i++)
{
Console.WriteLine(buffer1[i]);
}
Console.ReadLine();
}
I've had issues before with reading from the serial port and not reading in everything expected.
Turns out I was reading in the response from the device and it wasn't done yet writing. I figured the serial port object would continue trying to fill the buffer until the read timeout was hit, and that was not what was happening.
In my scenario I knew how many characters I was going to be reading from the serial port. So if you know that you could implement a repeat on the read until your character buffer is full. I don't know if the same would apply if you are reading from SerialPort.BaseStream.
SerialPort serialPort;
char[] buffer = new char[expectedLength];
int totalBytesRead = 0;
//continue to read until all of the expected characters have been read
while (totalBytesRead < expectedLength)
{
totalBytesRead += serialPort.Read(buffer, totalBytesRead, expectedLength - totalBytesRead);
}
This is the code I use (simplified):
public class Scanner : SerialPort
{
private string _word;
private int _globalCounter;
private readonly char[] _rxArray = new char[2047];
public Scanner()
{
DataReceived += MyDataReceivedEventHandler;
}
public event EventHandler<CodeScannedEventArgs> CodeScanned;
private void MyDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
{
do
{
var rxByte = (byte)ReadByte();
// end of word
if (rxByte == 10)
{
// first byte (02) and last two bytes (13 and 10) are ignored
_word = new string(_rxArray, 1, _globalCounter - 2);
DisplayData(_word);
_globalCounter = 0;
}
else
{
_rxArray[_globalCounter] = (char)rxByte;
_globalCounter++;
}
} while (BytesToRead > 0);
}
private void DisplayData(string receivedText)
{
OnCodeScanned(new CodeScannedEventArgs(receivedText));
}
protected void OnCodeScanned(CodeScannedEventArgs e)
{
EventHandler<CodeScannedEventArgs> handler = CodeScanned;
if (handler != null)
{
handler(this, e);
}
}
}
The scanner I use adds byte 02 as a prefix and bytes 13 and 10 as postfix to everything it scans, so it is pretty easy for me to break it up into words. You'll obviously need to change the implementation slightly so it works for you.
Edit - CodeScannedEventArgs class:
public class CodeScannedEventArgs : EventArgs
{
public CodeScannedEventArgs(string scannedCode)
{
ScannedCode = scannedCode;
}
public string ScannedCode { get; set; }
}
I used the port.ReadTo("\r") and it works, as the output ends with a carriage return.
But I want to know what is the advantage of using a data received event?