I'm trying to print on Olivetti PR 4 SL. In of out .NET application ("Print Test Page", Word, ...) it works. But in my .NET application, it doesn't.
This is my simplified code:
using (var serialPort = new SerialPort())
{
serialPort.PortName = "COM1"; // Where the printer is installed.
serialPort.Open();
serialPort.Write("Hello world!");
}
The error message is:
The given port name does not start with COM/com or does not resolve to
a valid serial port. Parameter name: portName
Would anyone help me to solve this problem?
You need to finalize the character stream which are sent to the printer by NEW_LINE (ASCII code is 10).
You can use the following line of code in order to print;
serialPort.Write(new byte[] { 10 });
Related
I am trying to send the bytes (b'\x03\r') to a device on COM5. The result will be the micropython board on the other end crashing. The python code results in the board freezing (As intended). The C# code results in no changes on the device's end, and the serial port not working until it is replugged. How can I get the C# code to do the same thing that the python code does?
This python code works:
import serial # this is installed with 'pip install pyserial'
ser = serial.Serial(
port='COM5',
baudrate=115200,
)
ser.write(b'\x03\r')
I tried to make this C# code to do the same thing but it does not work
using System.IO.Ports;
public static class tester {
public static void main(/* String[] args */) {
SerialPort sport = new SerialPort("COM5", 115200);
sport.Open();
sport.Write(new byte[]{0x03, 0xD}, 0, 2);
sport.Close();
}
}
Thanks for trying to help me :)
The solution as #kunif and #Hans Passant said was that I needed to set certain parameters as their defaults are not the same on different implementations of serial port libraries. To use a serial device that works fine with the default settings of PySerial use the following code. You will likely have to change the baud rate based on your specific device.
SerialPort sport = new SerialPort("COM5", 115200);
// I love StackOverflow
sport.Handshake = Handshake.None;
sport.DtrEnable = true;
sport.RtsEnable = true;
sport.StopBits = StopBits.One;
sport.DataBits = 8;
sport.Parity = Parity.None;
sport.Open();
I'm using Zebra printer model ZQ520 and connecting to it through application in C#.
string zpl = "^XA^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ";
try
{
connection.Open();
string setLang = "! U1 setvar \"device.languages\" \"zpl\"\r\n";
string calibrate = "~jc^xa^jus^xz\r\n";
connection.Write(Encoding.UTF8.GetBytes(setLang));
connection.Write(Encoding.UTF8.GetBytes(calibrate));
connection.Write(Encoding.UTF8.GetBytes(zpl));
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Exception:" + e.Message);
}
The issue is the printer is printing out an excessive amount of paper. It doesn't print "This is a ZPL test." until I press the line feed button on the printer, and then it printer more excess paper after the desired message.
Any idea what issue might be?
Have you checked the ^LL (Label Length) command. Look it up in your Zebra Programming Language guide.
I also know when I was doing Zebra (and also Intermec), the device itself had machine settings / display using buttons and arrows to change such default settings as page sizes, if thermal, what burn strength 0-30, etc., so you did not have to invoke those on every label submit.
I was also communicating directly with serial port using USB to RS232 connector cable, but it has been a while.
You may try to use the following code to communicate with the printer:
using (var tcpClient = new TcpClient())
{
try
{
var ipAddress = "127.0.0.1";
var printerPort = 9001;
tcpClient.Connect(ipAddress, printerPort);
using (var tcpClientStream = new StreamWriter(tcpClient.GetStream()))
{
var deviceLang = "! U1 setvar \"device.languages\" \"zpl\"\r\n");
tcpClientStream.Write(deviceLang );
tcpClientStream.Flush();
var calibrate = "~jc^xa^jus^xz";
tcpClientStream.Write(calibrate);
tcpClientStream.Flush();
Thread.Sleep(500);
string zpl = "^XA^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ";
// with ^LL: string zpl = "^XA^LL400^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ";
tcpClientStream.Write(zpl);
tcpClientStream.Flush();
tcpClientStream.Close();
}
tcpClient.Close();
}
catch (Exception ex)
{
Logger.Error(ex); // replace with your own logger or console
}
}
This should print the expected text immediately. Other than that, for continuous media (i.e. no gaps). I'm not familiar with this particular model but according to this:
https://supportcommunity.zebra.com/s/article/Calibrating-Zebra-QLn-Series-Mobile-Printers?language=en_US
You need to send the following command: ! U1 setvar "media.type" "journal" then set the label length somehow, for example ^LL400.
Also you may try to comment the deviceLang and calibrate commands, not 100% sure those are really required (on the ZT610 they're definitely not, as you can calibrate the printer using buttons).
I developed an in-browser Silverlight application that consist in a button. When it pressed it open a Socket to send ZPL commands to a Zebra Printer (model RZ400).
I made all the required actions to allow in-browser app to open connection to other hosts.
The printer works well except that it print only a limited number of labels (27) even if the socket send right all the data to the printer (that consist in 48 labels, about 440 bytes each).
To be sure, I check the buffer size of the socket that is 65536 bytes. The amount of data that I send to the printer through the socket is only 21282 bytes.
foreach (Label l in args.Labels)
{
saea = new SocketAsyncEventArgs();
printCommand = GetPrintCommandFromLabelAndPRN(l, args.SelectedPrinter.prn);
buffer = Encoding.UTF8.GetBytes(printCommand);
saea.SetBuffer(buffer, 0, buffer.Length);
willRaiseEvent = args.ConnectionSocket.SendAsync(saea);
totBytes += buffer.Length;
Log("Pack " + l.data + " inviato al socket di stampa");
}
The method GetPrintCommandFromLabelAndPRN build the PRN command for a single label:
private string GetPrintCommandFromLabelAndPRN(Label l, string prn)
{
// Codice e RFID
string aux = prn.Replace("{code}", l.code).Replace("{epc}", l.data);
// Meta
foreach (labelMeta meta in l.meta)
{
if (meta.key != null && !meta.key.Equals(String.Empty))
{
aux = aux.Replace("{" + meta.key + "}", meta.value);
}
}
return aux;
}
And this is the PRN template:
^XA
~SD25
^FO10,70^XGE:LOGO.GRF,1,1^FS
^FT275,65^A0N,29,28^FH\^FDArticolo:^FS
^FT375,65^A0N,29,28^FH\^FD{code}^FS
^FT509,65^A0N,25,24^FH\^FD{description1}^FS
^FT275,99^A0N,25,24^FH\^FD{description2}^FS
^BY2,3,57^FT275,166^BCN,50,Y,N,N^FD>:{code}^FS
^FT50,225^A0N,29,28^FH\^FDLotto:^FS
^BY2,3,35^FT130,225^BCN,30,Y,N,N^FD>:{lotCode}^FS
^PQ1,0,1,Y
^RR2
^RS8,300,50,2,N
^RW20,20
^RFW,H
^FD{epc}^FS
~RVE
^XZ
I try to do the same in Java, with the same PRN, using PrintWriter and it works correctly. So I exclude that is a printer issue.
I would bet that the printer is queuing up your labels and that is what causes it to stop at 27. Have you tried sending one at a time just to test to see if you might need to let the printer 'catch up' with the print jobs you are sending? We used to have an issue similar to this - when we slowed down the loop to the printer it allowed the printer to work at it's own rate just fine, but labels came out at a slower rate.
I am trying to run a treadmill using the serial port, I was able to do it using matlab however I am having a few probelms when I ported the same code to C#. I am sure that the port is open there is probably something wrong with the message format. Would be great if someone can tell me what mistake I am making.The matlab code (which works) and the C# code (which doesn't work) are given below.
MATLAB CODE :
ctr = char(12); %control character
rel = char(169); %release
set_speed = char(163);
set_dir = char (184);
%initializing the ports
R = serial('COM4');
set(R, 'BaudRate', 4800, 'Parity', 'none', 'DataBits', 8, 'StopBits', 1, 'Terminator', 'CR');
set(R, 'InputBufferSize', 128, 'OutputBufferSize', 128);
fopen(R);
if R.status == 'open'
fprintf(R, [rel ctr]);
disp('port for R belt open and released');
else
disp('error with R port-- COM3');
end;
%initial direction to FORWARD
fprintf(R, [set_dir '0' char(12)]);
%set speed to
fprintf(R, [set_speed '0005' ctr]);
My C# version of the matlab code above
char ctr = (char)12;
char rel = (char)169; //release
char set_speed = (char)163;
char set_dir = (char)184;
void Start () {
try{
SerialPort R = new SerialPort();
R.BaudRate = 4800;
R.Parity = Parity.None;
R.DataBits = 8;
R.StopBits = StopBits.One;
R.ReadBufferSize = 128;
R.WriteBufferSize = 128;
R.Open();
if(R.IsOpen){
//Release
R.Write(rel+""+ctr);
print ("Serial port is open");
}
else print ("Serial port is close");
R.Write(set_dir+""+"0"+""+ctr);
R.Write(set_speed+""+"0005"+""+ctr);
}
catch(UnityException e){
print ("Exception");
print (e);
}
}
I'm not really familiar with C#, but I'll try to guess that you should also send terminator character in your C# code.
Check the fprintf (serial) documentation in MatLab:
fprintf(obj,'cmd') writes the string cmd to the device connected to the serial port object, obj. The default format is %s\n. The write operation is synchronous and blocks the command-line until execution completes.
fprintf(obj,'format','cmd') writes the string using the format specified by format.
In your calls you are using 1st syntax so your call
fprintf(R, [rel ctr]);
is actually
fprintf(R, '%s\n', [rel ctr]);
Usually, serial devices read input data until the terminator character is found. This means that transmission of the command string or data is completed and the device now can execute the command. This is much like hitting ENTER in MatLab command window: command is executed only after you do this.
Which terminator character to use should be specified in your device programming manual.
Seems that CR is OK since your MatLab code works.
In your MatLAb code you set the terminator to be CR character (ASCII code 13). I do not see this in your C# code so your device waits for CR which is not sent so there should be no reaction from your device.
I do not think that C# will send the terminator character for you, you should take care of it by yourself.
My guess is that
R.Write(rel+""+ctr + "\r");
should solve the problem (thanks dodald for reminding me that I missed the proper conclusion).
See also Terminator property of SERIAL object and Rules for Writing the Terminator.
I'm attempting to write a C# library which looks at all available USB serial ports on a Raspberry Pi so that I can enumerate, identify and communicate with a set of Arduinos connected to the Pi via a USB hub.
I am able to make this work on my windows machine (several Arduinos connected to my desktop computer) and have even been able to make it work on my Pi however, I am struggling to understand how to generalize the fix.
If I attempt to run the program by itself on the Pi, I am able to open the serial port and send data however, I cannot receive anything from the Arduinos: I get timeout exceptions. I understand that Mono's implementation of SerialPort is limited and I must use SerialPort.ReadByte() instead of Readline() and the data received events (my solution is based on code from HowToSystemIOPorts). My Serial port enumeration is using a method outlined in another stack exchange response here.
My timeout is currently set to 4 seconds, which is several orders of magnitude longer than I expect to receive the message.
After a lot of googling, I came across mention of using minicom to initialize the serial port here, which to my surprise allowed me to receive data from the Arduino. The biggest drawback is that I need to initialize the port using minicom and leave the process opening each time I boot the Pi. I also can't seem to figure out how to make this work with multiple Arduinos.
Here is what I have tried so far:
Updated the Pi firmware and software to their latest versions
Attempted to use both an Arduino MEGA 2560 R3 and Arduino UNO
Changed the owner of the tty* ports (ttyACM0 and ttyUSB0 in this case) to both my user and group
Successfully configured the port via minicom, left the process running and start the program and read/wrote data. A manual process which only seems to work for one Arduino at a time
Successfully run the program in Windows without fault
Verified the Arduinos are recognized by the Pi running "dmesg | grep tty"
Here is what I hope to solve:
Automatic setup/initialization of the Arduino serial ports. Whether through a shell script run before the main program or within Mono code so that the code below can run as intended.
Here is my connection code:
public bool StartArduinoComms()
{
string[] ports = GetPortNames();
foreach (string port in ports)
{
mLogger.LogMessage(ProsthesisCore.Utility.Logger.LoggerChannels.Arduino, string.Format("Found serial port {0}", port));
}
bool foundCorrectArduino = false;
var idPacket = new ArduinoMessageBase();
idPacket.ID = ArduinoMessageValues.kIdentifyValue;
string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(idPacket);
foreach (string port in ports)
{
SerialPort serialPort = new SerialPort(port, kArduinoCommsBaudRate);
serialPort.Parity = Parity.None;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
//Only check unopened ports
if (!serialPort.IsOpen)
{
serialPort.Open();
//Disable telemtry just incase
var toggle = new { ID = ArduinoMessageValues.kTelemetryEnableValue, EN = false };
string disableTelem = Newtonsoft.Json.JsonConvert.SerializeObject(toggle);
serialPort.Write(disableTelem);
//Discard any built up data
serialPort.DiscardInBuffer();
serialPort.Write(jsonOutput);
serialPort.ReadTimeout = kIDTimeoutMilliseconds;
string response = string.Empty;
for (int i = 0; i < kNumRetries; ++i)
{
try
{
//This is guaranteed to timeout if not configured through minicom
response = ReadLine(serialPort);
break;
}
//Catch case where the serial port is unavailable. MOve to next port
catch (TimeoutException)
{
continue;
}
}
if (!string.IsNullOrEmpty(response))
{
//Perform response validation
}
else
{
//Got no response
}
if (!foundCorrectArduino)
{
serialPort.Close();
}
}
}
return foundCorrectArduino;
}
/// <summary>
/// From https://stackoverflow.com/questions/434494/serial-port-rs232-in-mono-for-multiple-platforms
/// </summary>
/// <returns></returns>
private static string[] GetPortNames()
{
int p = (int)Environment.OSVersion.Platform;
List<string> serial_ports = new List<string>();
// Are we on Unix?
if (p == 4 || p == 128 || p == 6)
{
string[] ttys = System.IO.Directory.GetFiles("/dev/", "tty*");
foreach (string dev in ttys)
{
//Arduino MEGAs show up as ttyACM due to their different USB<->RS232 chips
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
{
serial_ports.Add(dev);
}
}
}
else
{
serial_ports.AddRange(SerialPort.GetPortNames());
}
return serial_ports.ToArray();
}
Have a look at stty command. It will let you set/read teminal settings
http://linux.about.com/od/lna_guide/a/gdelna38t01.htm will give a rundown on it's use.
It would be easier to call out to than minicom, and the settings stay on the device.
I have done something like the same as you before.
I had to read and write data through USB Serial adapter, and didnt use minicom.
It may not be god code but i found that inorder to read the data I could create a new thread and have that check for data, my code include a lot of stuff but basicly i did this:
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(this.check_get_data);
and the check_get_data method
public void check_get_data ()
{
byte tmpByte = 0;
while (m_objSerialPort.BytesToRead != 0) {
tmpByte = (byte)m_objSerialPort.ReadByte ();
DoSomethingWithByte(tmpByte);
Thread.Sleep(20);
}
}
this is currently running with two usbserials. dont know if it helps but hope you find your solution