Printing to an O’Neil Route Printer RP2000-8000 Line Mode (COM) Printer using embedded Visual Basic (eVB) on Windows CE and Windows Mobile

System Requirements:

  • Microsoft embedded Visual Basic
  • Windows CE 2.11, 3.0, 4.0, 4.1, 4.2, 5.0
  • Pocket PC 2000, 2002
  • Windows Mobile 2003, 2003SE, 5.0

The Problem:

Although this article specifically addresses a problem that I had between a Symbol PDT8046 and the O’Neil Route Printer RP2000-8000, the issue and resolution should be applicable to any serial (COM) port based line printer.

If you have a raw ascii line printer, you can check to see if the printer works by echoing directly from the stdout into the COM port. Under DOS or the Windows command shell on the PC or Pocket DOS on Windows CE/Windows Mobile issue the following commands

mode com1: 9600,n,8,1,r
mode lpt1:=com1:echo I am a fish > lpt1

This will send I am a fish and a line feed to COM1 at 9600bps with no parity. Note that Pocket DOS doesn’t support the “,r” parameter.

So now that you have ascertained that the printer actually works, when you use the Microsoft Communications Control (Microsoft Comm Control) for embedded Visual Basic (eVB) to send the same data, why is it that nothing happens what so ever.

More Info

Let us look at the VB

‘ Set to COM1, 9600bps, no Parity.
‘ Enable DTR Flow Control, disable RTS Flow Control, disable handshaking
msComm.CommPort = 1
msComm.Settings = “9600,n,8,1,r”
msComm.DTREnable = truemsComm.RTSEnable = false
msComm.Handshaking = 0

‘ Attempt to get control of the COM port if it isn’t available
On Error Resume Next
if (msComm.PortOpen) then
msComm.PortOpen = false
end if
On Error Goto 0

‘ Open the port, Send the message, shutdown the port
msComm.PortOpen = true
msComm.Output = “I am a fish” & Chr(13) & Chr(10)
msComm.PortOpen = false

This is a logical flow of execution and basically what on the surface the DOS version is doing. Yet the message I am a fish will never arrive at the printer. In fact, the printer will not even acknowledge the presence of the message.

The Fix

This code is in fact completely logical, and is right (for the O’Neil RP2000-8000 anyway). However after some frustration and experimentation I discovered that there are two important pieces of the puzzle missing, one of them strongly recommended and the other very much mandatory.

Issue 1: Sleeping Printer

The O’Neil printer will go into standby mode after a couple of minutes of idle time so as to conserve power. If the printer is in sleep mode and you send data to it, it probably will not be awake to receive information and send it to the print head fast enough; best case nothing happens and worst case less than half of your message gets printed.

The O’Neil hardware manual has a very short section on this. In order to wake the printer up (or ensure that it is awake) you need to send a string of ASCII NULL characters (0x00) at the printer. For ONeil line mode printers operating at 9600bps you need to send this string 6+ times. For 38,400bps printers you should send this 24+ times. In our VB world that means:

msComm.Output = Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0)

7 times is a charm, however the manual also states that you should wait 150ms before sending data to the printer. See the next section on implementing Sleep().

If you repeat your test now, your printer should at least wake up even if nothing else happens

Issue 2: Speed = Distance / Time

I could wax lyrical on this, but Ill keep it brief.

There are a couple of buffers at play in the form of the OS and the printer, the embedded operating system and the eVB runtime processor. All of which cause delays. It follows something similar to this

  1. User Sends Print Request
  2. eVB Runtime Parses the command and sends it to the native code of the machine
  3. Operating System queues it in RAM as it gets processed through and send on its merry way
  4. Operating System queues it in the COM port transmit (TX) buffer
  5. Printer receives the message and queues it in the print buffer (512 bytes I *think* on the RP2000-8000)
  6. Printer processes it forward to the print head and the line at the front of the queue is printed

eVB does not care about steps 3 – 6, neither is it aware of them. As far as eVB is concerned, it has finished with the msComm.Output() command as soon as it has received an OK from the operating system that the requests has been through the processor and the data is in a queue.

Referring back to our original code

‘ Set to COM1, 9600bps, no Parity.
‘ Enable DTR Flow Control, disable RTS Flow Control, disable handshaking
msComm.CommPort = 1
msComm.Settings = “9600,n,8,1,r”
msComm.DTREnable = truemsComm.RTSEnable = false
msComm.Handshaking = 0

‘ Attempt to get control of the COM port if it isn’t available
On Error Resume Next
if (msComm.PortOpen) then
msComm.PortOpen = false
end if
On Error Goto 0

‘ Open the port, Send the message, shutdown the port
msComm.PortOpen = true
msComm.Output = “I am a fish” & Chr(13) & Chr(10)      <—— My work as VB is now over
msComm.PortOpen = false                                    <—— Shutdown the COM port

What is happening? eVB thinks that everything has been delivered and shuts down the COM port before the data has left the sending device and is safely received into the printers hardware buffer.

What is the solution? Well, you can be as eloquent or in-eloquent as you like. You can do a byte by byte check of data into the VB transmit buffer, ensuring that this has gone before you progress through the output stream. Alternatively if you are feeling lazy you could use the threading model and implement a fixed length sleep action. If however you are feeling somewhere between the two extremes you can try and weight the sleep timer based upon message length. Something along the lines of

delay (ms) = Absolute(((Length(Message) / ((Printer Bit Rate * 0.50) / 8 )) * 1000))

A weighting of 0.66 is assumed so that the link speed and buffer writing can be running at only 1/2 of line speed. Division by 8 is used to convert from Bits Per Second to Bytes Per Second. Multiplication by 1000 converts the value to milliseconds.

or for the RP2000-8000 with message “I am a fish <cr><lf>” [13 characters]

delay (ms) = Abs(13 / ((9600 * 0.66) / 8) * 1000)

or 21 ms

Onto this you may want to add a standard value that reflects the time the message takes to leave the operating system onto the wire. 50 – 100ms should do.

In order to use the thread sleep function in eVB you have to import the export from the C++ corelib as follows

Declare Sub Sleep Lib “Coredll.dll” (ByVal dwMilliseconds As Integer)

Dim strMessage
strMessage = “I am a fish” & Chr(13) & Chr(10)

‘ Set to COM1, 9600bps, no Parity.
‘ Enable DTR Flow Control, disable RTS Flow Control, disable handshaking
msComm.CommPort = 1
msComm.Settings = “9600,n,8,1,r”
msComm.DTREnable = true

msComm.RTSEnable = false
msComm.Handshaking = 0

‘ Attempt to get control of the COM port if it isn’t available
On Error Resume Next
if (msComm.PortOpen) then
msComm.PortOpen = false
end if
On Error Goto 0

‘ Open the port, Send the message, shutdown the port
msComm.PortOpen = true
msComm.Output = strMessage
call Sleep((Abs(((Len(strMessage) / ((9600 * 0.50) / 8)) * 1000)) + 50))
msComm.PortOpen = false

Note: This code is highly summarised it will not work directly as a copy/paste, you need to modularise it and create the msComm object.

With the sleep function in place and the correct tuning you should now find that the data gets to the printer before eVB closes the COM port.

Remember that you need to implement the function of Sleep(150) after sending the wake-up NULL string to the printer.

Uninstalled WD SES Device USB Device appears in device manager with Western Digital Passport ‘Smartware’ enabled device

System Requirements:

  • Western Digital Smartware enabled USB device

The Problem:

When you install a Western Digital USB hard drive an uninstalled device appears in “other devices” in the Windows device manager.

More Info

The WD SES Device USB Device is a enclosure communication and feedback device which, when enabled allows the USB enclosure to communicate additional metrics about the state of the equipment. In this case, the USB enclosure is the USB Caddy containing the 2.5″ drive.

SES stands for SCSI Enclosure Services, which provide extensions to the SCSI command set to allow for reporting and querying of data such as power consumption and state and cooling performance and thermal state within the caddy. The commands are used for diagnostic purposes and are not required in the functionality of the drive or data I/O itself.

You can continue to use the drive without this driver installed. In the case of Western Digital, its main purpose is to facilitate value added features in the Smartware management software.

The Fix

You can find the driver on the 614MB UDF partition that appears with the data storage volume in My Computer. Point the driver installation Wizard at the UDF partition, or more specifically to X:\Extras\WD SES Device Driver where X: is the mounted driver letter for the UDF partition labeled “WD SmartWare”.

The WD SES Driver version shipping with drives containing WD Smartware 1.2.0.8 and with the update (3.1.0.13) available from wdc.com is version 1.0.7.2. It is available for both x86 and x64 systems.

Warning: Asus P4C800-E Deluxe and using modern Power Supply Units (PSU) with a motherboard earlier than 2005/2006 (Intel Socket 478)

System Requirements:

  • Old motherboard (specifically in my case a Intel Socket 478 motherboard)
  • Asus P4C800-E

The Problem:

So you have a trusty old 478 system that you cant bare to part with, but the PSU has just blow out on it and you need a new one. You know that a good PSU is worth the investment, you get a brand name, a high wattage value and something with a high efficiency value.

You get home, you wire it up and… nothing.

The machine turns on, it may post, it may just hold up on a black screen before the POST. The latter is what happened with my Asus P4C800-E Deluxe when I came to replace the PSU with a £70 Antec TruePower PT-550. It would not start, however if I swapped back a cheap PSU that I borrowed as a stop gap, it would POST fine.

More Information:

Another 15 mile one way trip back to the store with the Antec and we stood around scratching our heads over this one for a few minutes.

It turns out that all (decent) modern PSU’s have a design change which makes them incompatible with boards that require -5v – and probably quite a few others.

The Asus P4C800-E Deluxe requires a -5v rail on the ATX in order to get going. In every brand name PSU box we opened in the store – including the one I was returning – the -5v rain pin was missing from the 20-pin ATX connector.

Net result: the system cannot boot.

Why are PSU’s shipping without this?

Some post-event research leads me to understand that with the release of the ATX12V specification version 1.2 in January 2002, the -5v rail became optional on the ATX specification. With revision 1.3 in April 2003 and the 2.x revision the -5v rail was banned altogether. Look at any modern PSU and you’ll find that pin 20 in the ATX connector is blanked out.

So if you are looking for a decent PSU for a Intel 478 system, you may have a problem. In the end I was forced to get one of those cheap PSU’s that case manufacturers supply with cases – which conveniently has a -5v rail but is unremarkable in every other way aside from probably its inefficiency.

Cannot install the integrated audio AC97′ hardware from a Asus P4S333 or P4S533 under Windows Vista

System Requirements:

  • Windows Vista SP1
  • Windows Server 2008

The Problem:

So, you get fed-up of trying to get PCI sound cards working under Vista and opted for the integrated sound CPU clogging solution?! I don’t blame you.

The P4S333 may be old kit, but it’s a solid motherboard, very much Vista capable with the right upper end P4 and enough RAM, particularly if you flashed the P4S333 with the P4S533’s BIOS to make use of the 533 MHz FSB. The difficulty we have is however in that the C-Media CMI8738 AC97′ chip that the board uses cannot be matched to any of Windows Updates hardware ID’s and Asus, naturally, do not offer a Vista driver.

More Information:

Thankfully, C-Media do provide generic drivers, and there is a January 2009 driver release for the CMI8738 as of writing. The driver does work once you get it out of the RAR file, however:

  1. The driver does not have the necessary hardware ID to install automatically against the customised chip on the P4S333 / P4S533
  2. The driver is not digitally signed

Despite that, I’ve not seen any problems with it, and despite the CPU connotations, it got rid of irritating buzzing that the Creative Labs Sound Blaster Live! 5.1 was causing with the useless Vista driver set.

The Fix

Very simply, you need to manually install the driver.

  1. Download the latest CMI8738 driver from C-Media (http://www.cmedia.com.tw/). As of writing the driver version was 8.17.33 and it worked a treat
  2. Deflate the RAR into the file system
  3. Open the Control Panel
  4. Open the Device Manager
  5. Find the uninstalled multimedia device in the Other Devices section, right click, Update Driver Software
  6. Click Browse my computer for driver software
  7. Click let me pick from a list of device drivers on my computer
  8. Hit the have disk button
  9. Browse to the path that you inflated the RAR file to, for example if you inflated the RAR file to c:\temp\ you want to browse to the following location:
    c:\temp\PCI-8738-090109-8.17.33(Vista3264-RC-01)\SoftwareDriver\driverNote that if the driver version you are using is newer, then the version in the file name will clearly be different. Ultimately however you are looking to point to the SoftwareDriver\driver folder (there are several INF’s and some CAT files in here)
  10. In the manufacturer list from the available select:
    C-Media
  11. From the Model list select:
    C-Media PCI Audio Device
  12. Click Next
  13. Windows will notify you that the driver has not been digitally signed. You’re going to have to tough this one out I’m afraid and install it.
  14. At that point the audio should just start working.