We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Writing too fast to COM port?

Medium Priority
772 Views
Last Modified: 2013-11-25
I have an application developed in Turbo C++ targeted for Win16 environment. There are some problems arised when running it :-

1. It will truncate some printing if I run the program (without debugging mode) but if I run the program by putting several breakpoints in debugging mode, it will print all the output successfully.
It seems like if I put 'PAUSE' in some places, it prints good. I suspect the problem lies at WriteComm API that I used. It seems that the process of writing data to com port is to fast to handle by the printer and that makes the printer unable to catch the data and print correctly.
Well, I do need experts opinion on this matter.
Comment
Watch Question

You may update your SendMsg function to that

    void SendMsg(const char* msg, int lenMsg)
    {
           for (int i = 0; i < lenMsg; i++)
           {
                 WriteComm(hComm, msg[i], 1);
                 Sleep(1);     // wait one millisecond
           }
    }

You may increase Sleep argument if it is still too fast.

Note, the second argument of SendMsg. In case you have to send binary data also, you shouldn't use strlen() within SendMsg as strlen() stops at the first zero character.

Regards, Alex
If you actually have to write Windows 3.1x programs - very strange as i wrote my last 16-bit application 1994... - you should consider to take MS Visual Studio 1.52c. There, you have MFC (Microsoft Foundation Classes) where you don't need to write directly to printer devices but may use Win GDI functions to print to any printer defined in the Windows print settings. Also consider, that even in a Win311 environment there is a Win32s subsystem available to write 32-bit applications and not to have to care about 16 bit pointers and segmentation...

Regards, Alex
CERTIFIED EXPERT

Commented:
Can you post some of the code?

Regards, Cayce

Author

Commented:
Hi Alex.
I never used the Sleep() function before but I've tried with SetTimer(hWnd, TIMER_ID, 1000, NULL) function. SetTimer() function doesn't help to solve the problem. I will try to use Sleep() afterwards.
Is there any significant differences between Sleep() and SetTimer()?

Author

Commented:
Hi Cayce.
This is the code.
------------------------------------------------------------------------------------------------------
void SendMsg(char *pMsg)
{
      char *input;
      char sMsg[80]={0};
      int i=0;
      for(i=0;i<2000;i++)
      {
            ;
      }

      WriteComm(hComm, pMsg, strlen(pMsg));
      input = ReadCOMMInput();

}

char *ReadCOMMInput()
{
      char sMsg[80]={0};
      int ret;

      ret = ReadComm(hComm, sMsg, 1024);


      return sMsg;

}

------------------------------------------------------------------------------------------------------

Commented:
I beleive WriteComm buffers data it gets, so it isn't a matter of sending too fast for the port but overrunning the buffer.  Check the return value and make sure all the data was written, if not all data was written, wait a few milliseconds and then resend the missed stuff.

Hope this helps.

Author

Commented:
Hi Alex.
Is there any means to contact you by email or IM?
Does this allowed in EE?
CERTIFIED EXPERT

Commented:
void SendMsg(char *pMsg)
{
     char *input;
/*     char sMsg[80]={0};
     int i=0;
     for(i=0;i<2000;i++)
     {
          ;
     }
*/
     short length = strlen(pMsg);
     short pending = length;
     while(pending) {
        pending -= WriteComm(hComm, &pMsg[length - pending], pending);
        Sleep(250);
      }
     input = ReadCOMMInput();
}


// BTW You ReadCOMMInput()  is really screaming for trouble. You're reading into an auto variable then returning it.
// Plus the read buffer is just 80 bytes long, and you're reading up to 1KB.
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Commented:
Adding Sleep()'s in random places is a very bad way of trying to fix this problem!

The printer, being mechanical, may take considerably different amounts of time to print different data.

For instance, a bunch of short lines take much longer to print than one long line, as feeding the paper takes
much longer than printing a line of characters.

Also, Sleep()'s effect is somewhat overriden by the OS's buffers and any buffers in the printer.
So some Sleeps() may effectively do nothing, while others may actually speed up the output by giving the OS more time.

The way to fix this is to find out where the characters are getting lost... you may be ignoring any "I AM FULL" messages coming back from the printer.   These are often handled by the printer driver or OS, but maybe you have the wrong print driver, or it has the backchannel handshaking turned off, or it may even be a bad printer cable or one without the backchannel wires in it.

Please look at these other issues before ever thinging of using Sleep() to "fix" the problem.

Regards,



grg99

>> Adding Sleep()'s in random places is a very bad way of trying to fix this problem!

Using Sleep() to slow the output isn't worse than writting directly to a printer device. And it will most likely solve the problem if too much speed and buffer overflow had been the reason. If slowing down works you may look for a better solution like checking error codes and reading printer drivers manuals. Maybe you have to call Sleep() only after an overflow error had occurred and have to rewrite the last buffer after wait.

However, the most simple solution is to use Windows GDI not having to care about printer settings, escape sequences and hand-shakes.

BTW, i have had a device where output had to been slowed to get the final solution. It was a card reader for a big hospital over a 25 milliampere connection. The card reader's price was about 50,000 $, the computer was a VAX 650 double processor using 64 MB RAM. It's price was about 400,000 $ in .... 1984.

Regards, Alex
If you're writing to a com port that is actually going out a serial RS-232 port, your problem might more easily be solved by using either software (XON/XOFF) or hardware (RTS/CTS) flow control. It might also be solved by lowering the baud rate.

Software flow control only works if your data stream is printable characters that don't normally contain the XON or XOFF (control-S and control-Q) characters. Hardware flow control requires a cable that connects the RTS and CTS lines.

Commented:

Using Sleep() to slow the output isn't worse than writting directly to a printer device. And it will most likely solve the problem if too much speed and buffer overflow had been the reason.

"solve the problem", no.  Perhaps cover up the problem, for a certain set of data, in one particular font, maybe.
But if the operator changes  the printer font, or changes it to "higher quality" multipass priting, or opens the printer cover to straighten the paper, or undo a paper jam, or if the printer slows down for any other reason, Sleep(1000) isnt going to help.


>If slowing down works you may look for a better solution like checking error codes

YES!       Funny how we usually check for errors only if we get burnt.


However, the most simple solution is to use Windows GDI not having to care about printer settings, escape sequences and hand->shakes.

If the low-level driver is bollixed, or misconfigured, or miswired cable, then all the Windows GDI glop isnt going to help.
You'll just get bitmapped garbage instead of text garbage.


>BTW, i have had a device where output had to been slowed to get the final solution. It was a card reader for a big hospital over a 25 milliampere connection. The card reader's price was about 50,000 $, the computer was a VAX 650 double processor using 64 MB RAM. It's price was about 400,000 $ in .... 1984.

Yes, VAXes were really poor at handling lots of interrupts.  Our local guru had to patch the line-printer driver so the line-printer wouldnt interrupt so much and tie up the $300,000 VAX.

Sometimes you have to slow INPUT devices down so the computer can keep up.  

But that has little to do with this case, where the computer is too fast for the printer.


(How about we just pass a law outlawing anything using RS-232--- I've wasted weeks of my life and forests of paper  getting RS-232 connections to work between PC X and Printer Y, or worse yet, PC X and plotter Y. A $22,000 plotter and it's very picky about what it accepts.


Regards,

grg99

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.