I am a starter who is stuck very badly on this initially my main aim is to control robots using speech. Initially I started with making grammar for my speech with this code I was even successful my code is this I made this in windows form application:
using System.Speech.Recognition;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create a new SpeechRecognizer instance.
sr = new SpeechRecognizer();
// Create a simple grammar that recognizes "red", "green", or "blue".
Choices colors = new Choices();
colors.Add("red");
colors.Add("green");
colors.Add("blue");
colors.Add("white");
GrammarBuilder gb = new GrammarBuilder();
gb.Append(colors);
// Create the actual Grammar instance, and then load it into the speech recognizer.
Grammar g = new Grammar(gb);
sr.LoadGrammar(g);
// Register a handler for the SpeechRecognized event.
sr.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(sr_SpeechRecognized);
}
// Simple handler for the SpeechRecognized event.
private void sr_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
MessageBox.Show(e.Result.Text);
}
private SpeechRecognizer sr;
}
Now from this code when I speak red , I get red in message box now I want to control motors therefore i need to communicate with my robots therefore i MADE ONE CONSOLE APPLICATION from help from internet FOR SENDING DATA TO MY SERVO CONTROLLER -SSC 32 THE CODE FOR ABOVE IS:
using System.IO.Ports;
using System.Threading;
namespace cConsoleAppMonitorServoCompletion
{
class Program
{
static SerialPort _serialPort;
static void Main(string[] args)
{
try
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM3";
_serialPort.Open();
_serialPort.Write("#27 P1600 S750\r");
Console.WriteLine("#27 P1500 S750\r");
string output;
output = "";
//Example: "Q <cr>"
//This will return a "." if the previous move is complete, or a "+" if it is still in progress.
while (!(output == ".")) //loop until you get back a period
{
_serialPort.Write("Q \r");
output = _serialPort.ReadExisting();
Console.WriteLine(output);
Thread.Sleep(10);
}
_serialPort.Close();
}
catch (TimeoutException) { }
}
}
}
Now I want like when I speak red instead of giving a text box I want get serial command like _serialPort.Write("#27 P1600 S750\r");
Please help I have tried but I was not successful , it is my humble request please answer in more detailed manner , I am a just starter so it will be easy for me thanks in advance.
Controlling a robot using voice recognition... an ambitious project for a starter! There could be a million things going wrong here.
Just as important as the ability to write code is the ability to debug it. What can you tell us further - which parts work, which parts don't? Have you single-stepped through the code to see what happens and when, to diagnose where things start to go wrong?
You could also try some debugging output - Console.WriteLine for example - so we you can see the state of variables and flow of the code as it's running.
It looks like you need to use System.Diagnostics.Process.Start
This page has an example - how to execute console application from windows form?
// Simple handler for the SpeechRecognized event.
private void sr_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
System.Diagnostics.Process.Start( #"cmd.exe", #"/k c:\path\my.exe" );
}
An ambitious starter project indeed!
Update
private bool LaunchApp(String sAppPath, String sArg)
{
bool bSuccess = false;
try
{
//create a new process
Process myApp = new Process();
myApp.StartInfo.FileName = sAppPath;
myApp.StartInfo.Arguments = sArg;
bSuccess = myApp.Start();
}
catch (Win32Exception e)
{
MessageBox.Show("Error Details: {0}", e.Message);
}
return bSuccess;
}
if Now I want like when I speak red instead of giving a text box I want get serial command means - just to _serialPort.Write("#27 P1600 S750\r"); instead of showing messagebox (i.e. MessageBox.Show(e.Result.Text);) then task is really simple. just copy-paste that code. and add using System.IO.Ports; so that u can work with ports.
so prolly ur code will look like this:
private void sr_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
//MessageBox.Show(e.Result.Text);
try
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM3";
_serialPort.Open();
_serialPort.Write("#27 P1600 S750\r");
Console.WriteLine("#27 P1500 S750\r");
string output;
output = "";
//Example: "Q <cr>"
//This will return a "." if the previous move is complete, or a "+" if it is still in progress.
while (!(output == ".")) //loop until you get back a period
{
_serialPort.Write("Q \r");
output = _serialPort.ReadExisting();
Console.WriteLine(output);
Thread.Sleep(10);
}
_serialPort.Close();
}
catch (TimeoutException) { }
}
p.s.
if you don't understand how SerialPort Class works go to MSDN
Related
I tried to follow this tutorial in building voice recognition C# app, the only difference is I wanted to have a Console app, not a Win Form app, so I wrote this this code:
using System;
using System.Speech.Recognition;
//using System.Speech.Synthesis;
namespace Voice_Recognation
{
class Program
{
static void Main(string[] args)
{
SpeechRecognitionEngine recEngine = new SpeechRecognitionEngine();
recEngine.SetInputToDefaultAudioDevice();
Choices commands = new Choices();
commands.Add(new string[] { "say Hi", "say Hello"});
GrammarBuilder gb = new GrammarBuilder();
gb.Append(commands);
Grammar g = new Grammar(gb);
recEngine.LoadGrammarAsync(g);
recEngine.RecognizeAsync(RecognizeMode.Multiple);
recEngine.SpeechRecognized += recEngine_SpeechRecognized;
}
// Create a simple handler for the SpeechRecognized event
static void recEngine_SpeechRecognized (object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("Speech recognized: {0}", e.Result.Text);
switch(e.Result.Text){
case "Red":
Console.WriteLine("you said hi");
break;
default:
break;
}
}
}
}
and compiled it using mono project as below:
c:\mcs /reference:System.Speech.dll Program.cs
after adding the System.Speech.dll to the folder project, and got the Program.exe file generated.
Once I run the program at the terminal, it ends up directly, without giving me any chance to say anything!!
I've 2 questions:
What I'm missing here, and what the wrong thing I did?
and
How Is there a way to add the '.dll' file in a better way, I tried adding it to the Project.json file as below, but did not work, though I did not get any error at running dotnet restore:
"frameworks": {
"netcoreapp1.0": {
"bin": {
"assembly": "D:/2016/Speech/CORE/System.Speech.dll"
},
}
}
I solved the first part by adding Thread.Sleep so it give enough time for the thread to keep listening, another option is to make it endless loop using while(true);
I still could'not solve the second part which is how to make the VS code recognize the existing of the assembly file.
The new full code, if any is interested is below, and a more comprehensive code can be found here:
using System;
using System.Speech.Recognition;
using System.Threading;
//using System.Speech.Synthesis;
namespace Voice_Recognation
{
class Program
{
static void Main(string[] args)
{
SpeechRecognitionEngine recEngine = new SpeechRecognitionEngine();
recEngine.SetInputToDefaultAudioDevice();
Choices commands = new Choices();
commands.Add(new string[] { "say Hi", "say Hello"});
GrammarBuilder gb = new GrammarBuilder();
gb.Append(commands);
Grammar g = new Grammar(gb);
recEngine.LoadGrammarAsync(g);
recEngine.SpeechRecognized += recEngine_SpeechRecognized;
Console.WriteLine("Starting asynchronous recognition...");
recEngine.RecognizeAsync(RecognizeMode.Multiple);
// Wait 30 seconds, and then cancel asynchronous recognition.
Thread.Sleep(TimeSpan.FromSeconds(30));
// or
// while(true);
}
// Create a simple handler for the SpeechRecognized event
static void recEngine_SpeechRecognized (object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("Speech recognized: {0}", e.Result.Text);
switch(e.Result.Text){
case "say Hello":
Console.WriteLine("you said hi");
break;
default:
break;
}
}
}
}
I am building a program in C# to be used in one of my course at a college to demonstrate how Asynchronous connections work using RS-232 and two computers connected together. My course is not about programming, but data networks, so the connectivity is what I am looking for.
picture 1 - sample layout of GUI using Visual Studio 2015
One of the features I want to implement in my program is to show how a Master-slave, simplex connection works (i.e. the program can choose between been a master to send input from the keyboard; or slave to only receive information and print it on a textbox).
What I have already is the capability of initializing the serial port with specific characteristics (baud rate, data bits, stop bits, etc). This features are selected using combo boxes from the GUI, and assigned to the port when the user clicks a button to "open the port".
What I don't know is how to create the "slave" part of the program. My idea of what I could do is, after you choose the program to be "slave", you open the port waiting for some sort of flag or event to trigger when the input buffer has data stored.
I've been reading several forums and I can't find anything similar to what I need. I have, however, tested multiple alternatives that I believed would bring me closer to what I need with little to no result. I come to ask for an idea of what I could be doing wrong, or suggestions on how to tackle this problem. The problematic lines are bolded (or 2 stars ( * ) ):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialCommTester
{
public partial class frmSerialComm : Form
{
static SerialPort _PuertoSerial;
public frmSerialComm()
{
InitializeComponent();
getAvailablePorts();
}
//---------------------------------my functions--------------------------------------
void getAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
cmbPortList.Items.AddRange(ports);
}
void activatePort()
{
//Note that all the combo boxes are named somewhat accordingly to what the information they are meant to display.
if (cmbPortList.Text != "" && cmbBaudRate.Text != "" && cmbParity.Text != "" && cmbStopBits.Text != "")
{
_PuertoSerial.PortName = cmbPortList.Text;
_PuertoSerial.BaudRate = Convert.ToInt32(cmbBaudRate.Text);
_PuertoSerial.RtsEnable = true;
_PuertoSerial.DtrEnable = true;
_PuertoSerial.DataBits = Convert.ToInt32(cmbDataBits.Text);
if (cmbParity.Text == "Even") { _PuertoSerial.Parity = Parity.Even; }
else if (cmbParity.Text == "Odd") { _PuertoSerial.Parity = Parity.Odd; }
else if (cmbParity.Text == "Space") { _PuertoSerial.Parity = Parity.Space; }
else if (cmbParity.Text == "Mark") { _PuertoSerial.Parity = Parity.Mark; }
else { _PuertoSerial.Parity = Parity.None; }
if (cmbStopBits.Text =="2") { _PuertoSerial.StopBits = StopBits.Two; }
else if (cmbStopBits.Text == "1.5") { _PuertoSerial.StopBits = StopBits.OnePointFive; }
else { _PuertoSerial.StopBits = StopBits.One; }
if (cmbHandShake.Text == "Software Flow Control") { _PuertoSerial.Handshake = Handshake.XOnXOff; }
else if (cmbHandShake.Text == "Hardware Flow Control") { _PuertoSerial.Handshake = Handshake.RequestToSend; }
else { _PuertoSerial.Handshake = Handshake.None; }
_PuertoSerial.ReadTimeout = 500;
_PuertoSerial.WriteTimeout = 500;
_PuertoSerial.Open();
//in my understanding, this line of code is needed to handle data being received. Does it trigger a flag or something?
**_PuertoSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);**
}
else
{
txtRecieve.Text = "Input selection missing 1 or more characteristics";
}
}
**
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort testing = (SerialPort)sender;
txtRecieve.AppendText(testing.ReadExisting()); //txtRecieve cannot be reached within this function. It indicates the following error: "An object reference is required for the non-static field, method, or property 'frmSerialComm.txtRecieve'
}
**
void enableDisableGUI(bool[] input)
{
grpConnection.Enabled = input[0];
grpCharacteristics.Enabled = input[1];
btnOpenPort.Enabled = input[2];
btnClosePort.Enabled = input[3];
txtSend.Enabled = ((cmbControlMasterSlave.Text == "Slave") ? false : true);
}
//----------------------------C# objects / functions--------------------------------------
private void btnOpenPort_Click(object sender, EventArgs e)
{
try
{
_PuertoSerial = new SerialPort();
activatePort();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Message ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
bool[] format = { false, false, false, true};
enableDisableGUI(format);
}
private void btnClosePort_Click(object sender, EventArgs e)
{
_PuertoSerial.Close();
bool[] format = { true, true, true, false};
enableDisableGUI(format);
}
private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
{
_PuertoSerial.Write(e.KeyChar.ToString()); //this is how I send data through the serial port.
}
private void btnClearTxts_Click(object sender, EventArgs e)
{
txtRecieve.Clear();
txtSend.Clear();
}
} //class closes
} //program closes
I am not an experienced programmer, I just want to create something useful for my students. Any constructive criticism will be highly appreciated.
I don't have any definitive answers for you. You code looks like it should provide what you need once you get past the two possible glitches.
I think you should attach your SerialDataReceivedEventHandler BEFORE
you call _PuertoSerial.Open().
It may have no effect since event handlers can normally be enabled/disabled dynamically, but I base the advice on the following comment taken from the .Net source code for SerialPort on MSDN.
// all the magic happens in the call to the instance's .Open() method.
// Internally, the SerialStream constructor opens the file handle, sets the device control block and associated Win32 structures, and begins the event-watching cycle.
The "object reference" error might be resolved by removing the
static modifier from your DataReceivedHandler. If not, or if that
static modifier is necessary for some reason, then perhaps the
txtRecieve control has a private modifier which needs to be changed
to internal or public. You should be able to use Visual Studio in
debug mode to step into the InitializeComponent() method and see
where txtRecieve is being instantiated.
Well, I believe that I needed to read more. This is how I solved the problem (if this is not the real solution, at least is working for now):
I moved the "SerialDataReceivedEventHandler" line before the _PuertoSerial.open();
I followed the suggestions from this article:
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
So my funtions (one existings + a new one) look like this:
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
printReceivedText(_PuertoSerial.ReadExisting());
}
private void printReceivedText(string text)
{
if (this.txtSend.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(printReceivedText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtRecieve.AppendText(text);
_PuertoSerial.DiscardInBuffer();
}
}
For now seems to be working fine. The final testing will come when I connect another terminal and see the program interacting with each other.
Hi I'm trying to program a simple C# WPF that displays time information on a virtual scoreboard in real time from a timing system. I'm fairly new to programming so in depth explanation would be appreciated.
I have created a new thread to handle the incoming data from the COM port and as the app is developed this data will be interpreted. For now I just wanted to display the raw information (in hex) that is coming from the timer into a textbox. This works but not as intended. I am receiving tons of duplicate information, my only explanation is I am reading the data too slowly or its reading the same byte over and over. What I would like to happen is to take out each byte and display them, all controlled by one start/stop button.
Possible solutions include storing the entire buffer in a list or array which I'm not quite sure of yet, I don't want to add so many threads that the program freezes everything up.
Here is my code so far (I'm new to pretty much all the code I have written here, so if anything is bad practice please let me know):
public partial class MainWindow : Window
{
SerialPort comms;
Thread commThread;
bool flag;
string message;
public MainWindow()
{
InitializeComponent();
comms = new SerialPort();
}
private void PortControl_Click(object sender, RoutedEventArgs e)
{
if (!comms.IsOpen)
{
PortControl.Content = "Stop";
comms.PortName = "COM1";
comms.BaudRate = 9600;
comms.DataBits = 8;
comms.StopBits = StopBits.One;
comms.Parity = Parity.Even;
comms.ReadTimeout = 500;
comms.ReceivedBytesThreshold = 1;
commThread = new Thread(new ThreadStart(Handle));
comms.Open();
comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
}
else
{
PortControl.Content = "Start";
flag = false;
comms.DataReceived -= ReadIn;
commThread.Join();
comms.Close();
}
}
private void ReadIn(object sender, SerialDataReceivedEventArgs e)
{
if (!commThread.IsAlive)
{
flag = true;
commThread.Start();
}
}
private void Handle()
{
while (flag)
{
if (comms.IsOpen)
{
try
{
message = comms.ReadByte().ToString("X2");
Dispatcher.BeginInvoke((Action)(() =>
{
ConsoleBox.Text += message + " ";
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
Here is one solution.
The serial port is receiving the data in its own thread, and you should read the incoming bytes in the data received handler.
I propose to read the data and add it to a thread-safe FIFO list in the data received handler and read the data from the list in the main thread.
See my solution in post Serial port reading + Threads or something better?
I have been trying to record and play the audio simultaneously with out using a temporary wav file. And later I would like to create a VOIP chat program.
I have used the Naudio library to capture and play audio in C# and it seems to work quite well.
below is the c # code that i have written:
using System.IO.Ports;
using NAudio.Wave;
using System.IO;
namespace VOIP
{
public partial class Form1 : Form
{
WaveIn wab = new WaveIn();
MemoryStream s;
int k;
public Form1()
{
InitializeComponent();
wab.BufferMilliseconds = 100;
wab.NumberOfBuffers=5;
wab.DataAvailable += new EventHandler<WaveInEventArgs>(wa_DataAvailable);
}
void wa_DataAvailable(object sender, WaveInEventArgs e)
{
Play(e.Buffer);
}
private void Play(byte[] p)
{
WaveOut ou = new WaveOut();
s = new MemoryStream(p);
RawSourceWaveStream r = new RawSourceWaveStream(s, wab.WaveFormat);
ou.Init(r);
ou.Play();
ou.Stop();
ou.Dispose();
s.Dispose();
r.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "Stop")
{
wab.StopRecording();
button1.Text = "Record";
}
else if (button1.Text == "Record")
{
wab.StartRecording();
button1.Text = "Stop";
}
}
}
}
The Problem is at the "Play" method .Since the waveout object is created and disposed every time the data is available : i can hear some clicking sound. Is there a way to avoid this way of creating and disposing object and instead just create one object and then initialize with the new data. I also observed that the memory consumed by this program keeps increasing.
Thanks in advance.
sanatan
Use a BufferedWaveProvider, and as audio arrives, decompress it and add it to the BufferedWaveProvider. Then have a single instance of WaveOut that is playing constantly from the BufferedWaveProvider.
The source code for NAudioDemo shows how to do this in the chat example.
I'm making a program that uses the system.speech namespace (it's a simple program that will launch movies). I load all of the filenames from a folder and add them to the grammars I want to use. It's working remarkably well, however there is a hitch: I DON'T want the windows speech recognition to interact with windows at all (ie. when I say start, I don't want the start menu to open... I don't want anything to happen).
Likewise, I have a listbox for the moment that lists all of the movies found in the directory. When I say the show/movie that I want to open, the program isn't recognizing that the name was said because windows speech recognition is selecting the listboxitem from the list instead of passing that to my program.
The recognition is working otherwise, because I have words like "stop", "play", "rewind" in the grammar, and when I catch listener_SpeechRecognized, it will correctly know the word(s)/phrase that I'm saying (and currently just type it in a textbox).
Any idea how I might be able to do this?
I'd use the SpeechRecognitionEngine class rather than the SpeechRecognizer class. This creates a speech recognizer that is completely disconnected from Windows Speech Recognition.
private bool Status = false;
SpeechRecognitionEngine sre = new SpeechRecognitionEngine();
Choices dic = new Choices(new String[] {
"word1",
"word2",
});
public Form1()
{
InitializeComponent();
Grammar gmr = new Grammar(new GrammarBuilder(dic));
gmr.Name = "myGMR";
// My Dic
sre.LoadGrammar(gmr);
sre.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs>(sre_SpeechRecognized);
sre.SetInputToDefaultAudioDevice();
sre.RecognizeAsync(RecognizeMode.Multiple);
}
private void button1_Click(object sender, EventArgs e)
{
if (Status)
{
button1.Text = "START";
Status = false;
stslable.Text = "Stopped";
}
else {
button1.Text = "STOP";
Status = true;
stslable.Text = "Started";
}
}
public void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs ev)
{
String theText = ev.Result.Text;
MessageBox.Show(theText);
}