Go Down

Topic: Sainsmart 1602 LCD shield causes sketch to run incorrectly (Read 2820 times) previous topic - next topic


Apr 04, 2013, 03:29 pm Last Edit: Apr 07, 2013, 12:26 am by Coding Badly Reason: 1
Hi. I'm a newbie here (this is my first post) and need some help.

I am using a sketch that I found on the internet - it is by Daniel Smith and can be found at his website  http://www.pagemac.com/source.php?f=azure/progs/arduino_hid_wiegand.ino .  It is a Wiegand decoder (Wiegand is an access control card protocol - very simple) that uses the two interrupts (pins 2 & 3) as the two inputs.

The sketch works OK when using the serial monitor.  My Sainsmart LCD also works OK when using "Hello, world" and other test sketches.  My aim is to use an LCD with Daniels' sketch so that the Arduino can be truly "standalone".  However, when the Sainsmart LCD shield is fitted, the sketch malfunctions and seems to miss most (75% - 80%) of the input pulses.

I am guessing that the interrupts are being affected by the presence of the LCD shield but I can't see why.  The LCD doesn't seem to use pins 2 or 3 ( for Sainsmart I use LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); ) so I can't see what is going wrong.

Daniel's code is below.

Many thanks in advance!!! Any help will be most appreciated.



Apr 04, 2013, 05:16 pm Last Edit: Apr 07, 2013, 12:25 am by Coding Badly Reason: 1
Hi arloG

Many thanks for replying.  Yes, the inputs to the interrupts are negative-going pulses which come for the output of the card reader.  There are usually 26 bits for a card read; each bit leaves the reader one at a time and from the appropriate output pin i.e. "1" bits are output from the "1" output pin and "0" bits are output from the "0" pin.  This signal protocol is pretty slow with approximately 2ms between each pulse.  The end of the card-read is usually determined by a timeout where no more pulses have been received after a period of time has elapsed.

Sorry about the code; I used the "copy for forum" option in the Arduino software but I must have done something wrong.  Here is the code again - hopefully looking a bit clearer!

Best regards


Code: [Select]
* HID RFID Reader Wiegand Interface for Arduino Uno
* Written by Daniel Smith, 2012.01.30
* www.pagemac.com
* This program will decode the wiegand data from a HID RFID Reader (or, theoretically,
* any other device that outputs weigand data).
* The Wiegand interface has two data lines, DATA0 and DATA1.  These lines are normall held
* high at 5V.  When a 0 is sent, DATA0 drops to 0V for a few us.  When a 1 is sent, DATA1 drops
* to 0V for a few us.  There is usually a few ms between the pulses.
* Your reader should have at least 4 connections (some readers have more).  Connect the Red wire
* to 5V.  Connect the black to ground.  Connect the green wire (DATA0) to Digital Pin 2 (INT0).  
* Connect the white wire (DATA1) to Digital Pin 3 (INT1).  That's it!
* Operation is simple - each of the data lines are connected to hardware interrupt lines.  When
* one drops low, an interrupt routine is called and some bits are flipped.  After some time of
* of not receiving any bits, the Arduino will decode the data.  I've only added the 26 bit and
* 35 bit formats, but you can easily add more.


#define MAX_BITS 100                 // max number of bits
#define WEIGAND_WAIT_TIME  3000      // time to wait for another weigand pulse.  

unsigned char databits[MAX_BITS];    // stores all of the data bits
unsigned long bitCount;              // number of bits currently captured
unsigned char flagDone;              // goes low when data is currently being captured
unsigned int weigand_counter;        // countdown until we assume there are no more bits

unsigned long facilityCode=0;        // decoded facility code
unsigned long cardCode=0;            // decoded card code

// interrupt that happens when INTO goes low (0 bit)
void ISR_INT0()
 flagDone = 0;
 weigand_counter = WEIGAND_WAIT_TIME;  

// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
 databits[bitCount] = 1;
 flagDone = 0;
 weigand_counter = WEIGAND_WAIT_TIME;  

void setup()
 pinMode(13, OUTPUT);  // LED
 pinMode(2, INPUT);     // DATA0 (INT0)
 pinMode(3, INPUT);     // DATA1 (INT1)
 Serial.println("RFID Readers");
 // binds the ISR functions to the falling edge of INTO and INT1
 attachInterrupt(0, ISR_INT0, FALLING);  
 attachInterrupt(1, ISR_INT1, FALLING);

 weigand_counter = WEIGAND_WAIT_TIME;

void loop()
 // This waits to make sure that there have been no more data pulses before processing data
 if (!flagDone) {
   if (--weigand_counter == 0)
     flagDone = 1;
 // if we have bits and we the weigand counter went out
 if (bitCount > 0 && flagDone) {
   unsigned char i;
   Serial.print("Read ");
   Serial.print(" bits. ");
   // we will decode the bits differently depending on how many bits we have
   // see www.pagemac.com/azure/data_formats.php for mor info
   if (bitCount == 35)
     // 35 bit HID Corporate 1000 format
     // facility code = bits 2 to 14
     for (i=2; i<14; i++)
        facilityCode <<=1;
        facilityCode |= databits[i];
     // card code = bits 15 to 34
     for (i=14; i<34; i++)
        cardCode <<=1;
        cardCode |= databits[i];
   else if (bitCount == 26)
     // standard 26 bit format
     // facility code = bits 2 to 9
     for (i=1; i<9; i++)
        facilityCode <<=1;
        facilityCode |= databits[i];
     // card code = bits 10 to 23
     for (i=9; i<25; i++)
        cardCode <<=1;
        cardCode |= databits[i];
   else {
     // you can add other formats if you want!
    Serial.println("Unable to decode.");

    // cleanup and get ready for the next card
    bitCount = 0;
    facilityCode = 0;
    cardCode = 0;
    for (i=0; i<MAX_BITS; i++)
      databits[i] = 0;

void printBits()
     // I really hope you can figure out what this function does
     Serial.print("FC = ");
     Serial.print(", CC = ");

Moderator edit: [code] [/code] tags added.


The code is certainly a lot easier to read now.  Thanks for fixing that.

This is not the code that you're having trouble with, though, is it?  I read your original post as saying that this code works as a stand-alone program but when you integrate the LCD code with it, you have problems.  I'm not making any rash promises about providing help but without the troublesome code, I'm pretty sure I'll be useless.  Even with the code............well, we'll see.


Well yes, it is the code that is malfunctioning - but only when the LCD shield is fitted - so there is probably nothing actually wrong with the code but something affects it when the LCD shield is fitted.

In a nutshell, the code works OK on my Uno (without LCD shield) with the card reader connected to pins 2 & 3.  For example, I show a 26 bit card to the reader and the code responds on the serial monitor with "26 bits read" and the card information.

If I power down, fit the LCD shield to the Uno, power back up, and run the serial monitor, I will get the message "6 bits read unable to decode" which the sketch is supposed to do of course if it receives anything other than 26 or 35 bits.  This will be fairly consistent (sometimes the message is reported twice on the serial monitor for one card read).

So, by just fitting the LCD shield to the Uno, it seems that it has "poisoned" the sketch (or the Uno) - for want of a better term.  Once the LCD shield has been removed, the sketch works OK.


I misunderstood your problem as your LCD code interfering with your card reader code.

Obviously there is a hardware problem here.  Have you read http://arduino.cc/forum/index.php?topic=96747.0
The poster there notes compatibility problems and suggests solutions.


Thanks very much for all of your help arloG.  I hadn't seen that so I will work on it to see if it has anything to do with my problem.

Best regards



The code is certainly a lot easier to read now.  Thanks for fixing that.

The code posting is not quite 'fixed' yet.  Now go back to your post, highlight the part that is code, and click on the 'code' button which looks like a '#' symbol.




You're right.  I should have guided the OP by pointing out how to properly post code.  Once he improved (not "fixed") I realized that his problem was not in the code.

Derek, please take the time to tell us when you're successful. 



Before realizing I shouldn't have, I bought one of these LCD keypad shields. I have been able to make it work with other things happening, specifically, a motor driver shield, and a sensor shield. So I know all about problems getting things to play nicely. ... and my soldering skills are getting better all the time! :D

ok... I open up a successful sketch... let's check out my defined pins:
Code: [Select]
#define EN1_PIN 3
#define EN2_PIN 11
#define DIR1_PIN 12
#define DIR2_PIN 13
// int a0 = 0; // CANNOT USE: pin 0 is key input from LCD!
int a1 = 0; // this has +Vcc connected to sense for max ADC value
int a2 = 0; // PF1C / PF3C connector
// int a3 = 0; // CANNOT USE: pin 3 is PWM for motor CHA
int a4 = 0; // PF09 connector
//LCD setup using LiquidCrystal library
#include <LiquidCrystal.h>
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

Right off, I'm seeing that your pins are different from mine in the LiquidCrystal instantiation, so that's possibly your problem.

Other pins I'm using above: Digital pins 3,11,12,13 for stepper motor shield; Analog pins 2 and 4 for throttle position sensors that I'm testing; and I briefly had pin 1 shorted to prove to myself that 1024 on the ADC is in fact +Vcc.

Note that digital pin 10 is separately declared; this was so I could do whatever the software fix they said to do in the other posting.

I use this keypad shield as the user interface, making my Arduino test bench autonomous. I did end up using a Mega for the bigger RAM and more pins. My next revision is to use Adafruit's 1.8 TFT w/ joystich shield as the UI for my "stack".

:) Chris

Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131