I'm working on writing a simple program to move a stepper motor in C#. I have some past experience in C++, but have decided to transition over, as I'd have to reteach myself a bit of C++.
Previously, I've controlled the motor (using an Applied Motion ST5 Stepper Controller) with serial commands via PuTTY. My thought is that I could just send the same commands using C# by opening the correct COM Port (which works fine, as it crashes when I feed in a nonworking port number), and sending a string over. However, when I send a string of the same command that I had been using via serial terminal (FL1000, followed by a carriage return, it tells the motor to move 1000 steps clockwise), the motor does nothing. WriteLine should be the correct thing to use here, as it sends the string then a return, correct?
Does anybody see any glaring mistakes that would make my string not make it to the controller?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
namespace ConsoleApp3
{
class Program
{
static SerialPort comPort;
static void Main()
{
//These values in the declared serial port match what my device manager says.
comPort = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One);
comPort.ReadTimeout = 5000;
comPort.WriteTimeout = 5000;
comPort.Open();
//Pauses for a moment so that I can see the console otuput.
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
string command = "FL1000";
Console.WriteLine("Moving Motor...");
//Tells the controller to move the motor 1000 steps clockwise
comPort.WriteLine(command);
//confirms that the code made it past the comPort writeline
Console.Write("Command Sent");
//Pauses for a moment so that I can see the console output.
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
}
}
}
I expect that this would move the motor 1000 steps. The only results I see are that my "markers" appear on the console. The program exits without error.
Thank you in advance!
Your command does not contain a carriage return or newline. The motor is looking for one of these to know that the command is complete.
I haven't worked with their ST5 line of motors, but other products they carry require the command to be terminated with a carriage return. Try changing your message to:
string command = "FL1000\r";
Related
I recently got a sas expander card.
The one who gave card to me said:
It has a firmware on the chip and it can show sensor's temperature.
He wants me to develop a C# Console app to execute the firmware.
I didn't know the firmware source code looks like.
But it could be executed by PuTTy and it's connection was via RS232 Serial Port.
PuTTy connection setting:
After I click Open,press Enter and type command sys:
What I try in my C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Threading;
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
[STAThread]
static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DtrEnable = true;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 1000;
mySerialPort.Open();
if(mySerialPort.IsOpen)
{
string str= "Enter";
mySerialPort.Write(str);
}
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
Console.ReadLine();
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
}
}
What my code execute:
What is the problem with my code?
How can I execute firmware via RS232 and interact like PuTTy have done?
My Console app is using .Net Framework 4.7.2.
You are sending the string Enter (like typing ⇧E, N, T, E, R). You should probably send the ⏎ Enter key, which is represented on a terminal with the ASCII code 13, i.e. \r in a C# string.
Also you don't yet send any actual command. Try something like counters\r or sys\r.
(You currently receive the Enter back as response because that's what you sent out, and the card echoes any incoming characters so it can be used like a shell without blind typing. There is no other response yet because from the card's perspective you basically started typing the (invalid) command Enter but haven't yet submitted it with the ⏎ Enter key.)
Also I'd suggest adding the event listener for received data before sending any data, otherwise there would be a race condition in which the card could be responding before you even set up your listener and you would lose part of the data.
Additional note: Using the DataRecieved event may not even be desirable in your case.
According to docs:
The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.
This means that your DataReceived event may not even fire at all if there wasn't enough data sent in total yet (it may fire some time later with all the data at once) - but if you quit your program before that, you will never see.
As suggested here (emphasis mine):
Here is my general approach:
Use event-driven (DataReceived) code for streaming data. That is, where data is delivered at regular intervals, without specific associated commands that originate from your application.
Use polling for Command/Response protocols. These might involve a thread the you create to poll, but more frequently would be simple loops that may or may not block other operations until they complete.
So, it would be recommended to use one of the Read methods instead (see docs). There is also ReadTo and ReadLine which you may find useful. You may choose to use ReadTo(" bp1 >") for instance.
I have a programmable electro-pneumatic regulator and i need to communicate with it through serial port, i have never done things like that befire. The operation manual shows some instructions to communicate with it. These are the following:
Specification
==============
Comm. type
Master/slave type
Synchronous type
Asynchronous type
Comm. speed
9,600[bps]
Start bit
1[bit]
Data length
8[bit]
Stop bit
1[bit]
Parity bit
N/A
Flow control
N/A
Command end code
CR・LF
Character-code
ASCII
I have successfully connect it with the pc, but when im trying to control it and send the command the communication LED lights but it does not set the pressure. I think the problem will be with the command end code or the character code. The command sample is: send "SET 614"(its working range is 0-1023). I use the recommended specifications(comm speed,start bit etc.) in variables(just to be multifunctional). The program closes the port when you close the UI form.
private void ComunicateComport()
{
comtimer.Stop();
Global.Refreshtime = Global.Refreshrate;
comtimer.Start();
SerialPort ComPort = new SerialPort(Global.COMPort,Global.Baudrate,Parity.None,Global.Databits,StopBits.One);
if (ComPort.IsOpen == false)
{
ComPort.Open();
}
Global.Error = 0;
ComPort.DiscardOutBuffer();
ComPort.WriteLine("SET 100");
}
Don't use WriteLine replace it with use ComPort.Write(String) and then send explicitly < CR > < LF > as end of your command string with byte array using ComPort.Write({0x0D, 0x0A}, 0, 2).
I'm using a API called WindAPI which provided the financial data from China markets. This API provides a method call wsq() which will provide the RealTime price data to user's program through a callback function!
I write some simple codes in c#,trying to use this wsq() method, but get no results. I wonder there must be some error in codes, but just can't find it!
I'm new to both C# and programming, so if it's a rookie mistake, don't laugh at me:)
Here's the codes, I'll give as much comments as possible, so you can find the misunderstanding in it quickly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//-----------------------------
using WAPIWrapperCSharp; //the namespace in API dll(official provided)
using WindCommon; //the namespace to process the data formats (official provided)
namespace WSQ2String
{
class WSQ2StringSample
{
static void Main()
{
Console.Write("Begin......");
Console.ReadLine();
//--------------------creat the new API object and log on
WindAPI w = new WindAPI();
Console.WriteLine("New API created!");
w.start();
Console.WriteLine("API log on!");
//--------------------request for the realtime data through w.wsq() method
int errorId = 0;
ulong reqId = w.wsq(ref errorId, "150195.sz", "rt_date, rt_time, rt_lastest", "", myCallback);
Console.WriteLine("errorId = {0}", errorId);
//----adding a control line which will stop the main program and wait for myCallback function to be called
Console.ReadLine(); //after the data arrived, the test is over, and we press a key to let the main program continue
w.cancelRequest(reqId);
w.stop();
Console.Write("End......");
Console.ReadLine();
}
//----
static void myCallback(ulong reqId, WindData wd)
{
Console.WriteLine("wsq data gotback......");
//----transfer the official WindData format to String, and output to the screen
string s = WindDataMethod.WindDataToString(wd, "wsq"); //the method is in WindCommon namespace
Console.Write(s);
}
}
}
My understanding is that, when I request the data service by using w.wsq(), when the prices change(that's the event), myCallback() will be called and export the data on screen!
The reason I add a readline() is to prevent the main program runs too fast, and end before the event(price changing). In that situation, the myCallback() would have no chance to be called!
But when I run the codes, after "errorId = 0" shows, I wait several minutes and still get no results! I confirmed that the price has changed(it usually changed within seconds).
Here is the result I get, and I can't find the reason....(I just type the lines in screen)
>>Begin......
>>New API created!
>>API log on!
>>errorId = 0
and then the prgram just paused there and nothing more happened!
So I'd be very thankful if someone could explain that to me....
Thank you in advanced!
Updated:
According to the comments below, I give the zip files of my solutions.
Also with the API dll and it's source codes.
My solution files and dll
so, anyone help?
I am starting from the ground up and trying to write a simple console to interface with a serial port on a windows 7 computer.
I am using:
Visual Studio 2010 Ultimate
C# console project
Code: http://pastebin.com/0ADaEiSY
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
mySerialPort.Write("This is a test");
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
mySerialPort.Close();
}
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.Write(indata);
}
}
}
So far i have ran this code and interfaced with a xbee module connected to my computer. That xbee module sent the serial data to another xbee connected to a msp430. The msp430 is programmed to take whatever it receives and echo it back. This works with the code I have. In my console I will get "This is a test" echoed back onto the console window.
The problem I am having is when I use a virtual serial connection to a putty window. I am using this to try to ease development and not have to use hardware all of the time. I will use HHD Free Virtual Serial Ports to create a bridged connection between two serial ports. I will connect one to the putty terminal and the other will be for my console program. When running the program I recieve the error.
"A first chance exception of type 'System.TimeoutException' occurred in System.dll"
on the line
mySerialPort.Write("This is a test");
But the "This is a test" will appear on the Putty terminal.
If I remove the "mySerialPort.Write("This is a test");" line and attempt to send data from the Putty window to the console window, nothing appears.
Again this works with my hardware solution just fine.
Please help and i will try to clarify any questions. Thank you again.
I guess the problem is in virtual utility you are using. It seems it sets pin states incorrect. If I use 2 putty instances and connect to bridged ports I see infinite sending of symbol I entered. So I think your code is fine.
When I was working on such tasks I used a special cable for connecting 2 hardware com ports (com1 and com2, if you don't have them you can try usb-to-com converters) and it worked fine.
I'm has the very same problem with HHD Free Virtual Serial Ports, but this work great with asynchronous write operation.
Also you can replace
mySerialPort.Write("This is a test");
with (for example)
var buffer = Encoding.ASCII.GetBytes("This is a test");
mySerialPort.BaseStream.BeginWrite(buffer, 0, buffer.Length, ar => mySerialPort.BaseStream.EndWrite(ar), new object());
Thanks in advance for your help. I'm writing a lightweight C# program to write lines to a serial port (sending commands to a PLC) for work, and I'm not a programmer. My problem is that my button won't send the line to the serial port. Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
string command = "Turn Motor";
SerialPort COM1 = new SerialPort("COM1");
public Form1() {
InitializeComponent();
COM1.Open();
}
private void button1_MouseClick(object sender, MouseEventArgs e) {
COM1.WriteLine(command);
}
}
What can I do to make the button1 click send the text line to the serial port? The code must be as simple as possible as this is only run on one workstation. I've looked at all the examples, but have been unable to adapt them to my code. I also don't want to blatantly rip off others' code to get it working. Any advice would be appreciated.
EDIT: The code above is not everything, for example I'm initializing the port properly. I have another section of code that properly receives and processes strings, it's just the sender I'm having problems with. I also created the button method using the form designer, so there should be no disconnect there.
It looks like you are not initializing your Com Port. You need to set your BaudRate, Parity, DataBits, StopBits and Handshake property's. Look at the above MSDN examples for guidence. You can set the property's individualy or set them in the constructor.
According to MSDN the Default values for the above propertys are:
BuadRate = 9600
Parity = Parity.None
DataBits = 8
StopBits = StopBits.One
HandShake = HandShake.None
I would suggest:
Use the Click event instead of the MouseClick event.
If you just copied your button1_MouseClick method from an example somewhere that method probably isn't subscribed to the click event properly. If you double click the button in Visual Studio designer it will set up a method subscribed to the click event correctly for you automatically. That's where you would put your COM1.WriteLine(command);
If both of those suggestions are incorrect, you should probably be getting an Exception thrown somewhere (unless you're opening an incorrect port). In that case, you should describe that error in your question here.