Reputation: 1557
Humbling expierence here and I think this one will make a fool of me, but...I'm trying to convert an ancient cash register program to .net. Conquered everything else, but I can't pop open the cash register. Its connected to COM1, you are supposed to send a "trigger" text down COM1 that will cause the register to open.
Here is the .net code.
MsgBox("Opening Drawer")
Dim port As System.IO.Ports.SerialPort
port = New System.IO.Ports.SerialPort("Com1")
port.PortName = "COM1"
port.BaudRate = 9600
port.Parity = IO.Ports.Parity.None
port.DataBits = 8
port.StopBits = IO.Ports.StopBits.One
'port.Handshake = IO.Ports.Handshake.RequestToSend
port.RtsEnable = True
'port.DtrEnable = True
port.Open()
If port.IsOpen Then
'MsgBox("Attempt 1")
port.Write("@@@@@@@@@@@@@@@@@@@@")
MsgBox("Signal Sent: " & Chr(65))
Else
MsgBox("Port is not open")
End If
port.Close()
MsgBox("Pop, durn it!")
I get msgboxes "Signal Sent", "Done Pop Drawer"
Dang thing, just won't pop. It's an MS-Cash Drawer (EP125KC). Definitely connected to COM1, definitely has power. Chr(65) is the old code used to pop drawer and it works:
Open drawerComPort For Output Access Write As #1
Print #1, Chr$(65); "A";
Close #1
NOTE: The above code worked successfully. The root problem was caused by a reveresed power cord (negative was on the wrong side).
Thanks for all the help guys!
Upvotes: 1
Views: 2858
Reputation: 34592
Are you sure you're supposed to send out this code? I would have always thought that the code is prefixed by ESC i.e. 0x1b hexadecimal...for cash drawers...
"\x1bA"
Interesting that double 'A' is used...oh well... :)
Edit: After thinking about this I realized there is another way of doing it, read on...
I have modified your original BASIC code with a bit of bullet-proofing...save it to opendrawer.bas
Sub OpenDrawer() drawerComPort = "COM1" Open drawerComPort For Output Access Write As #1 REM ADDED ERROR HANDLING ON ERROR GOTO ErrHandler Print #1, Chr$(65); "A"; Close #1 print "Drawer Ok" OpenDrawer_Exit: On Error Goto 0 Exit Sub ErrHandler: print "Oops, Write Failed" Goto OpenDrawer_Exit End Sub REM The Main.... OpenDrawer
Download the old QB4.5 MS-Quick Basic compiler, and compile that to an executable, into opendrawer.exe
, the QB4.5 can be found here. Now, the onus is on you to make this bulletproof, i.e. what happens if writing to COM1 fails, issue a message like in the example BASIC code I modified
Then you can use the System.Diagnostics.Process
to shell out using a hidden window
public class TestDrawer { private StringBuilder sbRedirectedOutput = new StringBuilder(); public string OutputData { get { return this.sbRedirectedOutput.ToString(); } } public void Run() { System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo(); ps.FileName = "opendrawer"; ps.ErrorDialog = false; ps.CreateNoWindow = true; ps.UseShellExecute = false; ps.RedirectStandardOutput = true; ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; using (System.Diagnostics.Process proc = new System.Diagnostics.Process()) { proc.StartInfo = ps; proc.Exited += new EventHandler(proc_Exited); proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived); proc.Start(); proc.WaitForExit(); proc.BeginOutputReadLine(); while (!proc.HasExited) ; } } void proc_Exited(object sender, EventArgs e) { System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended"); if (this.sbRedirectedOutput.ToString().IndexOf("Oops, write failed") > -1){ MessageBox.Show(this, "Error in opening Cash Drawer"); } if (this.sbRedirectedOutput.ToString().IndexOf("Drawer Ok") > -1){ MessageBox.Show(this, "Drawer Ok"); } } void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) { if (e.Data != null) this.sbRedirectedOutput.Append(e.Data + Environment.NewLine); //System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data); }
The process shells out to a hidden window and all output is redirected and handled in the event handler...that should do the trick. Notice, how the redirected output goes into the sbRedirectedOutput
(a StringBuilder instance). In the proc_ProcExited
event handler, it checks the sbRedirectedOutput
for the message 'Oops Write failed' which would be issued from the QB4.5 program.
Be aware, that you may need to include the QB4.5's run-time library in the same directory...not 100% sure...it's being years...
What do you think?
Hope this helps, Best regards, Tom.
Upvotes: 0
Reputation: 1562
I dont use .net, but is the port buffered? do you need to send a flush/fflush()?
Upvotes: 0
Reputation: 19223
It might be sending Unicode 65, which would be 0065, which would not end well.
Just a thought, can you try sending a raw int?
Upvotes: 0
Reputation: 942109
You've set your handshake to None but the cash drawer probably has its own idea. Also set DtrEnable to True. Chr(65) is the ASCII code for an "A", your VB code suggests the real command is "AA".
The manual documents that the cash drawer auto-tunes its baudrate. It recommends sending at least 20 @ characters. And that the real command is Ctrl+G (Chr(7)). The "AA" command might have worked previously due to a baudrate mismatch. Perhaps.
Upvotes: 1
Reputation: 34178
If I remember my very rusty BASIC.
Print #1, Chr$(65); "A";
means print to port1 the character 65 followed by the string "A", Now the character 65 is 'A', so this looks to me like you should be sending "AA" to port1
port.Write("AA");
or alternately,
port.Write(new byte[]{65,'A'}, 0, 2);
Upvotes: 0