Read data from parallel port

Hi to everybody!
I would like to read the output of a parallel port with my arduino, and translate it in text.

Es. If some send to the printer “Hello world”, I would like to find the Arduino, instead the printer, who translate me the signal in a “Hello world” text.

Is it possible?

Marco

Yes it should be possible, you will probably have to detect the STROBE signal so you know the data is valid for each character then pulse the ACK signal to indicate you've got the data.


Rob

Thank you Rob. Can you explain me better, please?

What do you mean "detect the STROBE signal"? Have I to read it with an Analog Pin?

And how can I pulse the ACK? When I send the order to print, It became from 0 to 5v....

This is going back about 20 years to the days of parallel ports on computers but IIRC the process of sending data to a print goes like this.

PC puts data on bus PC pulses STROBE Printer detects STROBE Printer reads data Printer pulses ACK PC detects ACK can now send another byte.

The above process is repeated until all the data has been transferred.

You would probably detect STROBE by running that signal to an external interrupt on the Arduino.

Having read the data you pulse ACK using a normal digital output.

That's how you would read the "Hello world" data, what do you then plan to do with it?


Rob

I have an old industrial machine who print a little paper to a dot printer, with a parallel port.
I would like to bring what the machine print and put the data in a database…

So, I can find the byte in the strobe pin? And after I can write it in the serial port. And after, how can I pulse the Ack pin? By sending a digital HIGH?

You have to find out exactly what format this "parallel port" is, but let's assume it's Centronics for the time being. Here's some information about them

http://en.wikipedia.org/wiki/Parallel_port

I can find the byte in the strobe pin?

Well you can't "find a byte in a pin" but when STROBE goes LOW the data on D0:7 is valid. You can then read it from 8 other pins.

And after I can write it in the serial port.

Yep, do with it what you will.

how can I pulse the Ack pin? By sending a digital HIGH?

Yes, HIGH then LOW to make a pulse, probably with a short delay between the two digitalWrite()s to stretch the pulse because the Ardiuno may be a bit fast for this old protocol.


Rob

Ok Rob. Thank you very much.

I have already discovered that the data go from the machine to the printer with a serial port.. with 25 pin, but a serial port. So I will try to get the data without Arduino, but directly putting a reduction 25 pin --> 9 pin cable to the serial port of a pc. I will try to read the data with Python PySerial.

25-pin connectors were common for both serial and parallel in the "old days".

If this is serial and has a DB25 connector it's probably RS-232, if that's the case you have to invert and scale the voltage because it will be +-12v. Use one of the many RS-232 transceiver chips (eg MAX232) to do that.

So test this BEFORE connecting your Arduino.

If you are running directly into another computer you should be OK in that regard, but you may have to swap pins 2 and 3 as both devices will probably be wired as DTEs and therefore have the same pinout, ie both are transmitting on pin 2.


Rob

25-pin connectors were common for both serial and parallel in the "old days".

On the computer the serial port had a male connector and the parallel port had a female connector. That's how you could tell them apart.

Don

I have solved without Arduino, By reducing the 25pin male to a 9pin male, connecting it to a pc and reading the buffer with Python Pyserial. Thank you so much to everybody.

Now I'm going to send data to Arduino with Python by Ethernet. But this is another story. Bye. Marco

Hello, I had a similar project in mind, and was directed to this thread. My job has old control units have a 25-pin parallel centronics printer output. We use this to print a systems report. I want to be able to "print" a .txt file to a USB flash drive (not a computer) instead of using an old printer.

In the past we have used this unit to do the job: http://www.ipcas.com/products/centronics-parallel-to-usb-printer.html It works great, but we need more, and each unit costs $600

There are many converters on the market that go from USB to parallel, but very few that go from parallel to USB.

Could I do this with an arduino? I would need multiple inputs, then store the data, then have the arduino convert it to serial format, then output it to a usb socket, right? How much programming (that hasn't already been figured out) be required? Any help would be greatly appreciated!

Could I do this with an arduino?

This is quite feasible, pretty much what marcofoc was doing it seems.

I would need multiple inputs, then store the data, then have the arduino convert it to serial format, then output it to a usb socket, right?

Yep.

How much programming (that hasn't already been figured out) be required?

Not a huge amount of code required, ask marcofoc for his to start with.


Rob

Well, I sent marcofoc a message a while back, but never heard from him. Another forum recommended using a raspberry pi, because of its usb capabilities. So I posted a similar message on the raspberry forum, but no luck... I'm striking out here... Anybody here have experience with the raspberry pi platform? I know its super off-topic, sorry.

I needed to do this last week, and this is what I came up with:

/********************************************************************************
 * PrinterCapturePoll.ino
 * ------------------
 * Monitor a parallel port printer output and capture each character. Output the 
 * character on the USB serial port so it can be captured in a terminal program.
 *
 * By............: Paul Jewell
 * Date..........: 29th January 2015
 * Version.......: 0.1a
 *-------------------------------------------------------------------------------
 * Wiring Layout
 * -------------
 * 
 * Parallel Port Output               Arduino Input
 * --------------------               -------------
 * Name      Dir.   Pin                Name    Pin
 * ----             ---                ----    ---
 * nSTROBE    >       1..........................2 
 * DATA BYTE  >     2-9.......................3-10    
 * nACK       <      10.........................11
 * BUSY       <      11.........................12
 * OutofPaper <      12................GND
 * Selected   <      13.................5v
 * GND        <>  18-25................GND
 *-------------------------------------------------------------------------------
 ********************************************************************************/

int nStrobe = 2;
int Data0   = 3;
int Data1   = 4;
int Data2   = 5;
int Data3   = 6;
int Data4   = 7;
int Data5   = 8;
int Data6   = 9;
int Data7   = 10;
int nAck    = 11;
int Busy    = 12;
int led     = 13; // use as status led

void setup()
{
  // Configure pins
  pinMode(nStrobe, INPUT_PULLUP);
  
  for (int n = Data0; n < (Data7+1); n++)
    pinMode(n, INPUT_PULLUP);
  
  pinMode(nAck, OUTPUT);
  pinMode(Busy, OUTPUT);
  pinMode(led, OUTPUT);
  
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  
  State = READY;
  delay(1000);
  Serial.println("Initialised");
}




void loop()
{
  while (digitalRead(nStrobe) == HIGH) {
    digitalWrite(Busy, LOW);
    digitalWrite(nAck,HIGH);
    digitalWrite(led, HIGH);
  }    
  digitalWrite(Busy, HIGH);
  digitalWrite(led, LOW);
  ProcessChar();
  digitalWrite(nAck,LOW);
  delay(5); //milliseconds. Specification minimum = 5 us
}    

void ProcessChar()
{
  byte Char;
  
  Char = digitalRead(Data0) +
         (digitalRead(Data1) << 1) +
         (digitalRead(Data2) << 2) +
         (digitalRead(Data3) << 3) +
         (digitalRead(Data4) << 4) +
         (digitalRead(Data5) << 5) +
         (digitalRead(Data6) << 6) +
         (digitalRead(Data7) << 7);
         
  Serial.print((char)Char);
}

The version above works, but hangs off the strobe signal with a polling loop. I made a version with interrupt, but it didn’t work - I didn’t have time to debug it, so quickly changed it to the above version. The interrupt version is shown below - if someone can see what I have missed with setting the interrupt handling up, then I would be grateful!

/********************************************************************************
 * PrinterCaptureInterrupt.ino
 * ------------------
 * Monitor a parallel port printer output and capture each character. Output the 
 * character on the USB serial port so it can be captured in a terminal program.
 *
 * By............: Paul Jewell
 * Date..........: 29th January 2015
 * Version.......: 0.1a
 *-------------------------------------------------------------------------------
 * Wiring Layout
 * -------------
 * 
 * Parallel Port Output               Arduino Input
 * --------------------               -------------
 * Name      Dir.   Pin                Name    Pin
 * ----      ----   ---                ----    ---
 * nSTROBE    >       1................INT0      2 (as interupt)
 * DATA BYTE  >     2-9.......................3-10    
 * nACK       <      10.........................11
 * BUSY       <      11.........................12
 * OutofPaper <      12................GND
 * Selected   <      13.................5v
 * GND        <>  18-25................GND
 *-------------------------------------------------------------------------------
 ********************************************************************************/

int nStrobe = 2;
int Data0   = 3;
int Data1   = 4;
int Data2   = 5;
int Data3   = 6;
int Data4   = 7;
int Data5   = 8;
int Data6   = 9;
int Data7   = 10;
int nAck    = 11;
int Busy    = 12;
int led     = 13; // use as status led

enum States {
  READY,
  BUSY,
  ACK
} State;

  

void setup()
{
  // Configure pins
  pinMode(nStrobe, INPUT_PULLUP);
  
  for (int n = Data0; n < (Data7+1); n++)
    pinMode(n, INPUT_PULLUP);
  
  pinMode(nAck, OUTPUT);
  pinMode(Busy, OUTPUT);
  pinMode(led, OUTPUT);
  
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  
  attachInterrupt(2,DataReady,LOW);
  State = READY;
  delay(1000);
  Serial.println("Initialised");
}

void loop()
{
  switch (State) {
    case READY:
      digitalWrite(Busy, LOW);
      digitalWrite(nAck,HIGH);
      digitalWrite(led, HIGH);
      break;
    case BUSY: // nStrobe signal received by interrupt handler
      digitalWrite(Busy, HIGH);
      digitalWrite(led, LOW);
      ProcessChar();
      State = ACK;
      break;
    case ACK:
      digitalWrite(nAck,LOW);
      delay(5); //milliseconds. Specification minimum = 5 us
      State = READY;
      break;
  }   
}

void DataReady()
{
  State = BUSY;
}

void ProcessChar()
{
  byte Char;
  
  Char = digitalRead(Data0) +
         (digitalRead(Data1) << 1) +
         (digitalRead(Data2) << 2) +
         (digitalRead(Data3) << 3) +
         (digitalRead(Data4) << 4) +
         (digitalRead(Data5) << 5) +
         (digitalRead(Data6) << 6) +
         (digitalRead(Data7) << 7);
         
  Serial.print((char)Char);
}

Next version will have SD card capture!

Paul j. Have you made a version with SD card capture?

Paul J - If you're running your PrinterCaptureInterrupt.ino code on an Uno you need to edit the following line:

attachInterrupt(2,DataReady,LOW);

to:

attachInterrupt(0,DataReady,FALLING);

The first parameter refers to the number of the interrupt rather than the Uno pin number.

Thanks for your code - I am currently using it to repurpose an old print server to do some IOT stuff and am having an enormous amount of fun with it!

Hello guys, i tried several codes, with or without interrupts, but with little issue when i print from output printer with definied Epson LX-300 driver. When i capturing data from print output, everytime data are different. When i prolong delays in code, captured data are usually same. Did you connected some extra pullup rezistors betweeen arduino pins and +5V input? Have you or can you recommend some tool to reverting the output back to pdf or text file? I have old MS DOS special computer which prints output only to LPT and i need to capture this output and save it to another machine. Have you some experiences with this reverting process? Thanks in advance.

Guys i have been trying my best to read the data that the LPT send it to my epson lx-300 but i only get strange characters i think the code drops some of the received data i use the same code that Paul j shared can any one help please??

Hello,

i have continued this project with capturing epson printer code over centronics paralell port. I used an alternative arduino nano board and a cheap sd shield from ebay. The rest of the Hardware is simple and battery based.
The captured printer instructions (on the sd card) can be executed on pc with the tool DosPrinter.exe, this prints the printing job again with the standard windows printer.

Have fun with it.

Regards

lpt-seriell.ino (5.38 KB)