Barcode Scanner - Arduino seems to hang

Hello guys!

I’m new here :slight_smile: And unfortunately, I was not able to solve my problem yet :frowning:

A couple of months ago, I bough an Uno and a barcode scanner. I want to make a small personal project to scan some barcodes and store them into a MySQL database. Then a front-end interface will be needed but for now, that’s not yet part of this equation.

I searched from some examples on the internet and I was able to modified the code and put my barcode reading some codes and print them into the serial monitor interface.

What’s the problem? After some codes - and sometimes it is on the 4th try, sometimes it is on the 20th time - the arduino seems to hang up and nothing more is displayed on the serial interface.

Trying to troubleshoot this, I put some debug in place and also set up a switch button with an interrupt associated to print some variables.

The barcode scanned is also the same - 56000702 - my pack of cigarettes :slight_smile:

The code:

/*
Barcode Scanner                                                        
  This code reads the input from a ps/2 keyboard or keyboard-like        
  device (e.g. a barcode scanner), translates the scan-codes into        
  numbers (only numbers from 0 to 9 can be used at the moment)           
  It is nowhere near a complete implementation of the ps/2 protocol,     
  but it should give you a starting point.                               
  mys .// Benjamin Maus ( benjamin.maus <at> allesblinkt.com )          
  2007                                                                   
*/

int clockPin = 8;
int dataPin = 4;
int SCAN_ENTER = 0x5a;
int SCAN_BREAK = 0xf0;
int breakActive = 0;
byte scanCodes[10] = {0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46}; 
char characters[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
char buffer[64] = {}; // This saves the characters (for now only numbers) 
int bufferPos = 0;

boolean logging = true;
String debbug = "";
int valueOfDataReads = 0;


void setup() {
  //input mode for data and clock pin of the barcode scanner
  pinMode(dataPin, INPUT_PULLUP);                                               
  pinMode(clockPin, INPUT_PULLUP);

  // Attach an interrupt to the second ISR vector, which corresponds to the PIN number 3 - switch button
  attachInterrupt(1, InterruptChangeState, RISING);

  //begin serial interface
  Serial.begin(9600);
}

void loop() {
  if(logging) Serial.println("-= loop() - before dataRead()");
  dataRead();
  if(logging) Serial.println("-= loop() - after dataRead()");
  if(logging) Serial.println("-= loop() - before printBuffer()");
  printBuffer();
  if(logging) Serial.println("-= loop() - after printBuffer()");
  if(logging) Serial.println("-= loop() - before cleanBuffer()");
  cleanBuffer();
  if(logging) Serial.println("-= loop() - after cleanBuffer()");
}



/**
 * Interrupt function for when the user triggers the switch button
 */
void InterruptChangeState(){
  Serial.println("");
  Serial.println(valueOfDataReads);
  Serial.println(debbug);
}


void printBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    if(buffer[i] != 0)   Serial.print( buffer[i] );
  }
  Serial.println("");
}

void cleanBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    buffer[i] = 0;
  }     
}

/**
 * Function that will return the value read by the barcode scanner
 */
void dataRead() {
  byte val;
  valueOfDataReads++;
  debbug = "";
  if(logging) Serial.println("-= inside dataRead() - Before WHILE");
  while(val != SCAN_ENTER){
    val = 0;
    while (digitalRead(clockPin));  // Wait for LOW - Clock is high when barcode is idle.    
    debbug+="FIRST LOW\n";                                                                           
    // Skip start state and start bit                                      
    while (!digitalRead(clockPin)); // Wait for HIGH.             
    debbug+="FIRST HIGH\n";     
    while (digitalRead(clockPin));  // Wait for LOW.   
    debbug+="SECOND LOW\n";      
 
    for (int offset = 0; offset < 8; offset++) {                             
      while (digitalRead(clockPin));         // Wait for LOW               
      val |= digitalRead(dataPin) << offset; // Add to byte                
      while (!digitalRead(clockPin));        // Wait for HIGH              
    }                
                                                          
    // Skipping parity and stop bits down here.                            
    while (digitalRead(clockPin));           // Wait for LOW.  
    debbug+="FIRST PARATY LOW\n";         
    while (!digitalRead(clockPin));          // Wait for HIGH.   
    debbug+="FIRST PARATY HIGH\n";       
    while (digitalRead(clockPin));           // Wait for LOW.     
    debbug+="SECOND PARATY LOW\n";     
    while (!digitalRead(clockPin));          // Wait for HIGH.
    debbug+="SECOND PARATY HIGH\n";
    
    if (val != SCAN_BREAK && val != SCAN_ENTER) {
      if(breakActive == 1){
        breakActive = 0;
        debbug+="UN-----BREAK!\n\n";
      }
      else{
        for (int i = 0; i < sizeof(characters); i++) {                                                                 
        if(scanCodes[i] == val){                                                                                          
          buffer[bufferPos] = characters[i];
          debbug+="BUFFER POSITION: ";
          debbug+="" + (String)bufferPos + "\n";
          bufferPos++;
          debbug+="CHARACTER: ";
          debbug+="" + (String)characters[i] + "\n";
          break;                                                       
          }                                                                    
        }  
      }
    }          
    else if (val == SCAN_BREAK){
      debbug+="BREAK!\n\n";
      breakActive = 1;                             
    }
    else if (val == SCAN_ENTER){
      breakActive = 0;                          
      debbug+="ENTER!\n\n";   
    } 
    else{
      debbug+="\n\n\nJust to be sure that this is not the case...!\n\n\n";   
    }
  }
  if(logging) Serial.println("-= loop() - ENTER detected. Leaving dataRead()...");  
  breakActive = 0;  
  bufferPos = 0;                      
}

The output of those println() functions:
-= loop() - before dataRead()
-= inside dataRead() - Before WHILE
-= loop() - ENTER detected. Leaving dataRead()…
-= loop() - after dataRead()
-= loop() - before printBuffer()
56000702
-= loop() - after printBuffer()
-= loop() - before cleanBuffer()
-= loop() - after cleanBuffer()
-= loop() - before dataRead()
-= inside dataRead() - Before WHILE
-= loop() - ENTER detected. Leaving dataRead()…
-= loop() - after dataRead()
-= loop() - before printBuffer()
56000702
-= loop() - after printBuffer()
-= loop() - before cleanBuffer()
-= loop() - after cleanBuffer()
-= loop() - before dataRead()
-= inside dataRead() - Before WHILE
-= loop() - ENTER detected. Leaving dataRead()…
-= loop() - after dataRead()
-= loop() - before printBuffer()
56000702
-= loop() - after printBuffer()
-= loop() - before cleanBuffer()
-= loop() - after cleanBuffer()
-= loop() - before dataRead()
-= inside dataRead() - Before WHILE
-= loop() - ENTER detected. Leaving dataRead()…
-= loop() - after dataRead()
-= loop() - before printBuffer()
56000702
-= loop() - after printBuffer()
-= loop() - before cleanBuffer()
-= loop() - after cleanBuffer()
-= loop() - before dataRead()
-= inside dataRead() - Before WHILE

5
FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
BUFFER POSITION: 0
CHARACTER: 5
FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
BREAK!

FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
UN-----BREAK!

FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
BUFFER POSITION: 1
CHARACTER: 6
FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
BREAK!

FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
UN-----BREAK!

FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
FIRST LOW
FIRST HIGH
SECOND LOW
FIRST PARATY LOW
FIRST PARATY HIGH
SECOND PARATY LOW
SECOND PARATY HIGH
FIRST LOW
FIRST HIGH
SECOND LOW
FIRST LOW

Anyone can give me an hand in here? I’m really running out of ideas of what’s going on… Probably you will solve this in a blink of an eye :slight_smile:

Thank you very much!

Cheers

Do NOT print to the serial port inside an ISR! That will ALWAYS eventually cause a crash.

Regards,
Ray L.

RayLivingston, thank you for the information! I know that - unfortunately this is the only way that I have (or at least, that I know...) to troubleshoot. Anyway, when the interruption is called, the problem is already there.

Cheers

No ideas? :(

Get rid of the print in the interrupt

Change 9600 from Serial.begin(9600); to 115200

Don't use the String class to build a huge string (debug needs only 1 b by the way) - it pokes hole in your memory like crazy... get rid of this debbug horror :) => Print smaller debug stuff as you go like 1,2,3,4,5 to show where you are ... longer strings are jamming your serial out buffer (64 chars) and print becomes blocking and then you might miss some bits and never recover because you are off one or a few bits

When you do bufferPos++; test you don't overflow your buffer

When you enter dataRead the local variable val is not initialised. If you are unlucky the value on the stack it is pointing to is SCAN_ENTER and you don't enter your while loop

Hi J-M-L,

First, thank you very much for the help - much appreciated.

  1. The interrupt is now commented;
  2. I tried the Serial.begin() with the 115200 parameter - the output was weird stuff. Rollback on this one;
  3. Debug is now reduced as per recommendation;
  4. the val variable is now initialized always at 0 when the dataRead() function is called;

After 5 tries, the result is the same. The code:

/*
Barcode Scanner                                                        
  This code reads the input from a ps/2 keyboard or keyboard-like        
  device (e.g. a barcode scanner), translates the scan-codes into        
  numbers (only numbers from 0 to 9 can be used at the moment)           
  It is nowhere near a complete implementation of the ps/2 protocol,     
  but it should give you a starting point.                               
  mys .// Benjamin Maus ( benjamin.maus <at> allesblinkt.com )          
  2007                                                                   
*/

int clockPin = 8;
int dataPin = 4;
int SCAN_ENTER = 0x5a;
int SCAN_BREAK = 0xf0;
int breakActive = 0;
byte scanCodes[10] = {0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46}; 
char characters[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
char buffer[64] = {}; // This saves the characters (for now only numbers) 
int bufferPos = 0;

//boolean logging = false;
String debbug = "";
int valueOfDataReads = 0;


void setup() {
  //input mode for data and clock pin of the barcode scanner
  pinMode(dataPin, INPUT_PULLUP);                                               
  pinMode(clockPin, INPUT_PULLUP);

  // Attach an interrupt to the second ISR vector, which corresponds to the PIN number 3 - switch button
  //attachInterrupt(1, InterruptChangeState, RISING);

  //begin serial interface
  Serial.begin(9600);
}

void loop() {
  //if(logging) Serial.println("-= loop() - before dataRead()");
  dataRead();
  //if(logging) Serial.println("-= loop() - after dataRead()");
  //if(logging) Serial.println("-= loop() - before printBuffer()");
  printBuffer();
  //if(logging) Serial.println("-= loop() - after printBuffer()");
  //if(logging) Serial.println("-= loop() - before cleanBuffer()");
  cleanBuffer();
  //if(logging) Serial.println("-= loop() - after cleanBuffer()");
}



/**
 * Interrupt function for when the user triggers the switch button
 */
void InterruptChangeState(){
  //Serial.println("");
  //Serial.println(valueOfDataReads);
  //Serial.println(debbug);
}


void printBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    if(buffer[i] != 0)   Serial.print( buffer[i] );
  }
  Serial.println("");
}

void cleanBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    buffer[i] = 0;
  }     
}

/**
 * Function that will return the value read by the barcode scanner
 */
void dataRead() {
  byte val = 0;
  valueOfDataReads++;
  debbug = "";
  
  Serial.println("1");
  
  while(val != SCAN_ENTER){
    val = 0;
    while (digitalRead(clockPin));  // Wait for LOW - Clock is high when barcode is idle.                                                                    
    // Skip start state and start bit                                      
    while (!digitalRead(clockPin)); // Wait for HIGH.               
    while (digitalRead(clockPin));  // Wait for LOW.   
    for (int offset = 0; offset < 8; offset++) {                             
      while (digitalRead(clockPin));         // Wait for LOW               
      val |= digitalRead(dataPin) << offset; // Add to byte                
      while (!digitalRead(clockPin));        // Wait for HIGH              
    }                
                                                          
    // Skipping parity and stop bits down here.                            
    while (digitalRead(clockPin));           // Wait for LOW.  
    while (!digitalRead(clockPin));          // Wait for HIGH.       
    while (digitalRead(clockPin));           // Wait for LOW.     
    while (!digitalRead(clockPin));          // Wait for HIGH.
    
    if (val != SCAN_BREAK && val != SCAN_ENTER) {
      if(breakActive == 1){
        breakActive = 0;
      }
      else{
        for (int i = 0; i < sizeof(characters); i++) {                                                                 
        if(scanCodes[i] == val){                                                                                          
          buffer[bufferPos] = characters[i];
          bufferPos++;
          break;                                                       
          }                                                                    
        }  
      }
    }          
    else if (val == SCAN_BREAK){
      breakActive = 1;                             
    }
    else if (val == SCAN_ENTER){
      breakActive = 0;                          
    } 
  }
  Serial.println("2");  
  breakActive = 0;  
  bufferPos = 0;                      
}

The output:
1
2
56000702
1
2

1
2
56000702
1
2

1
2
56000702
1
2

1
2
56000702
1
2

1
2
56000702
1
2

1

Any more ideas?

Thank you once more.

  1. I tried the Serial.begin() with the 115200 parameter - the output was weird stuff. Rollback on this one;

==> of course you need to change the speed in your arduino IDE console to match the 115200 :slight_smile: (look at the bottom of your console, there is a pop up which probably says 9600 at the moment)


Skip start state and start bit
    while (!digitalRead(clockPin)); // Wait for HIGH.               
    while (digitalRead(clockPin));  // Wait for LOW.

are you really skipping 2 bits there or only one?


Can you test bufferPos for overflow and print an error message in that case? ('When you do bufferPos++;

Hi again J-M-L,

Thank you once more for your patience.
Regarding baud rate, got it - already set to 115200. Such a noob I am :slight_smile:

Regarding those 2 bits that the code is skipping, I think that the implementation is right - at least, it seems so. It is part of the code that I did not touch.

I’m printing the bufferPos right now and it does not seems a buffer overflow problem :frowning:

The code:

/*
Barcode Scanner                                                        
  This code reads the input from a ps/2 keyboard or keyboard-like        
  device (e.g. a barcode scanner), translates the scan-codes into        
  numbers (only numbers from 0 to 9 can be used at the moment)           
  It is nowhere near a complete implementation of the ps/2 protocol,     
  but it should give you a starting point.                               
  mys .// Benjamin Maus ( benjamin.maus <at> allesblinkt.com )          
  2007                                                                   
*/

int clockPin = 8;
int dataPin = 4;
int SCAN_ENTER = 0x5a;
int SCAN_BREAK = 0xf0;
int breakActive = 0;
byte scanCodes[10] = {0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46}; 
char characters[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
char buffer[64] = {}; // This saves the characters (for now only numbers) 
int bufferPos = 0;

//boolean logging = false;
String debbug = "";
int valueOfDataReads = 0;


void setup() {
  //input mode for data and clock pin of the barcode scanner
  pinMode(dataPin, INPUT_PULLUP);                                               
  pinMode(clockPin, INPUT_PULLUP);

  // Attach an interrupt to the second ISR vector, which corresponds to the PIN number 3 - switch button
  //attachInterrupt(1, InterruptChangeState, RISING);

  //begin serial interface
  Serial.begin(115200);
}

void loop() {
  //if(logging) Serial.println("-= loop() - before dataRead()");
  dataRead();
  //if(logging) Serial.println("-= loop() - after dataRead()");
  //if(logging) Serial.println("-= loop() - before printBuffer()");
  printBuffer();
  //if(logging) Serial.println("-= loop() - after printBuffer()");
  //if(logging) Serial.println("-= loop() - before cleanBuffer()");
  cleanBuffer();
  //if(logging) Serial.println("-= loop() - after cleanBuffer()");
}



/**
 * Interrupt function for when the user triggers the switch button
 */
void InterruptChangeState(){
  //Serial.println("");
  //Serial.println(valueOfDataReads);
  //Serial.println(debbug);
}


void printBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    if(buffer[i] != 0)   Serial.print( buffer[i] );
  }
  Serial.println("");
}

void cleanBuffer(){
  for (int i = 0; i < sizeof(buffer); i++) {                                                                 
    buffer[i] = 0;
  }     
}

/**
 * Function that will return the value read by the barcode scanner
 */
void dataRead() {
  byte val = 0;
  valueOfDataReads++;
  debbug = "";
  
  Serial.println("1");
  
  while(val != SCAN_ENTER){
    val = 0;
    while (digitalRead(clockPin));  // Wait for LOW - Clock is high when barcode is idle.                                                                    
    // Skip start state and start bit                                      
    while (!digitalRead(clockPin)); // Wait for HIGH.               
    while (digitalRead(clockPin));  // Wait for LOW.   
    for (int offset = 0; offset < 8; offset++) {                             
      while (digitalRead(clockPin));         // Wait for LOW               
      val |= digitalRead(dataPin) << offset; // Add to byte                
      while (!digitalRead(clockPin));        // Wait for HIGH              
    }                
                                                          
    // Skipping parity and stop bits down here.                            
    while (digitalRead(clockPin));           // Wait for LOW.  
    while (!digitalRead(clockPin));          // Wait for HIGH.       
    while (digitalRead(clockPin));           // Wait for LOW.     
    while (!digitalRead(clockPin));          // Wait for HIGH.
    
    if (val != SCAN_BREAK && val != SCAN_ENTER) {
      if(breakActive == 1){
        breakActive = 0;
      }
      else{
        for (int i = 0; i < sizeof(characters); i++) {                                                                 
        if(scanCodes[i] == val){                                                                                          
          buffer[bufferPos] = characters[i];
          Serial.print(bufferPos);
          bufferPos++;
          break;                                                       
          }                                                                    
        }  
      }
    }          
    else if (val == SCAN_BREAK){
      breakActive = 1;                             
    }
    else if (val == SCAN_ENTER){
      breakActive = 0;                          
    } 
  }
  Serial.println("");
  Serial.println("2");  
  breakActive = 0;  
  bufferPos = 0;                      
}

And the console output:
1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
01234567
2
56000702
1

2

1
0123456

As we can check, it hangs up in the middle of the buffer.
Made a couple of tests and the position is not the same every time - 7th position in this example, but it can hang up on the 4th, 3rd, etc.

Just for troubleshoot purpose, I took off the +5v of the barcode scanner and connect again to force an hardware reboot or something - still the same. Nothing after that…

More ideas please !

Thank you.

Print the val you are building and see if it’s not int the expected range

You are most likely getting stuck in one of your infinite while for some reason. I would write a function to wait for high or low with a x ms timeout returning a boolean stating if it timed out. If so just discard that read

For readability and intellectual satisfaction change

const byte clockPin = 8;
const byte dataPin = 4;
const byte SCAN_ENTER = 0x5a;
const byte SCAN_BREAK = 0xf0;

Also if things are very quick - digitalRead might miss something - I would read status using PORT operations