Reading data from parallel port interface

I am a newbie to the Arduino and I hope to get help from you guys.

I tried to read the parallel data from a machine with the Arduino Mega board. The handshaking connection looks working well. I got the data, but only a few characters look right and other characters are off on the last 4 bits. For example, the data is supposed to be 7, which is b0011,0111. But it shows as 0011,1100 (>) or 0011,1111(?). I could not get the pattern of error, I can only ensure that the first 4 bits are always correct.

Does anyone have the same experience before? I really have no clue for debugging? I have double checked the wirings on these 8 data bits lines. And I tried with different baud rate and delays. The problem cannot be fixed.

The codes are from Ecirbaf in this forum. I did not change the codes at all. And the pin connections are similar. Instead of the “selected” pin, I connected the Vcc pins from the machine to the Vin pin in Arduino board.

/********************************************************************************
 * 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
 * Modification : Change Interrupt Routine so Arduino respond "faster" to Printer
 *                Writing Busy Signal directly from interrupt routine
 *                Ecirbaf 12 Jan 2017
 *                Test on a PC with a "generic Printer Text only" printer
 *                Printing a test page OK
 *                Even if using somme accent characters
 *                Depend How your Terminal Software is handling that.
 *-------------------------------------------------------------------------------
 * 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(38400);    // ** Actual com port could at least go this speed  ** //
  while (!Serial) {
    ;
  }
  

 attachInterrupt(0,Interrupt,FALLING);  // ** Name :Interrupt,  was clearer for me than DataReady  ** //


  State = READY;
  delay(100);
  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;
  // ** All this case is made during Interrupt (Avoid some missed characters with "fast" printer) **
  
    case ACK:
      digitalWrite(nAck,LOW);
      delay(1); //milliseconds. Specification minimum = 5 us    ** Reduced to 1 is ok **
      State = READY;
      break;
  }   
}

void Interrupt()
{
    digitalWrite(Busy, HIGH);
    digitalWrite(led, LOW);
    ProcessChar();
    State = ACK;
}

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);
}

You wrote:"Instead of the "selected" pin, I connected the Vcc pins from the machine to the Vin pin in Arduino board.".

Does this mean you are powering the Arduino from some parallel printer pins? I have never seen a parallel port with Vcc pins. Are sure the Vcc is > 7 volts.

Paul

Thanks for your reply.

The machine has 4 pins that provide the power supply to the printer and its circuit. These power supplies are all at 5V. I know they are not between 7 and 12V, I just don't know where to connect them. I also connect the Arduino board to the laptop with a USB connection. I believe the USB will power up the board rather than the 5V Vcc input.

The reason I connected with Vcc pin on the board is that in the manual it says that all 4 pins need to be connected. Do they affect the DATA input pins if I connect these 5V pins to the Vcc?

I will try to remove these pins to see what happen.

I found the bug now.
The problem is if I use this to read, the last 4 bits are always right.
Char = digitalRead(Data0) +
(digitalRead(Data1) << 1) +
(digitalRead(Data2) << 2) +
(digitalRead(Data3) << 3) +
(digitalRead(Data4) << 4) +
(digitalRead(Data5) << 5) +
(digitalRead(Data6) << 6) +
(digitalRead(Data7) << 7);

If I switch the order and read the first 4 bits, Data 4-7, these 4 bits are right.

Anyone knows the reason for this?

You are making the assumption you mystery machine is sending ASCII characters over the parallel port. With no documentation, how can you be sure?

Paul

Because the first character I received is always correct. And then if I choose to read whatever 4 bits first, these first 4 bits are correct as well. The rest 4 bits are sometimes right, sometimes wrong. I am assuming it is the speed issue, but I cant figure out right now.

Reading more of the code you provided in the first post, I believe you are confusing his monitoring of a parallel port COMING from a pc and GOING to a printer. You are looking at something that is COMING from another machine, not a PC printing text on an attached printer.

Paul

I would try to use direct port reads; my suspicion is that the reads are too slow, and mixing up one byte with the next. Try putting 6 pins on the analog pins (say the 6 highest bits, in order highest on A5 (PC5), and third-lowest on A0 (PC0)), and the two low bits on digital pins 8 (lowest bit) and 9.

Then read like this:

Char=(PINC<<2)+(PINB&3);

This whole thread is just a bunch of guessing because the OP is unwilling or unable to identify the machine he is monitoring.

My suspicion is port he is looking at was originally connected to something with a 7-segment display and displayed only numbers. The 4 bits are the only ones necessary for such a value. The other bits probably identify the individual position that gets the number.

Paul