I try to make a worktime counting system with Arduino Uno (will be replaced by pro) and Wiegand reader.
Arduino sends the facility code and the card code trow USB serial to Raspberry PI.
Arduino controlls the led and the buzzer of the RFID Reader trow digital 5 and 6. 9 is used to catch powerdown from the power supply module and to shutdown the raspberry pi with digital pin 8. I see the problem with interupts in this tread:program that works for some days then it stops. - Programming Questions - Arduino Forum but when i try the things described there nothing diffeent happens - arduino still crashes. I also try to power the reader from arduino or from the power source 13V - but it's till crash. Also I get the Data1 and Data0 with 2pcs. 10kOm resistor to +5V.
The arduino is powered up from the USB port of Raspberry PI.
I understand when it's stop work because - reader flash ones and beep ones when the card is preset and then the arduino make it flash and beep second time as confirmation for 200ms. So when it stop working - I don't hear the second beep. Also I don't see the card number from the Raspberry PI side.
Here is the code:
/*
* 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!
*/
//#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#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 char bitCount=0; // 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 code1
String vps=0; //TAG_CONCAT
//LiquidCrystal_I2C lcd(0x27,16,2);
void ISR_INT0(){
bitCount++;
databits[bitCount]=0;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1(){
bitCount++;
databits[bitCount]=1;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void setup()
{
Serial.begin(9600);
pinMode(8, OUTPUT);
digitalWrite(8, LOW);
pinMode(9, INPUT);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
// lcd.init(); lcd.backlight();
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
unsigned int weigand_counterCopy;
// This waits to make sure that there have been no more data pulses before processing data
// weigand_counter is updated inside an ISR so access it safely
noInterrupts (); weigand_counter--;
weigand_counterCopy = weigand_counter; interrupts ();
if (!flagDone) {if (weigand_counterCopy == 0) flagDone = 1; }
//if (!flagDone) { if (--weigand_counter == 0) flagDone = 1; }
if (bitCount > 0 && flagDone) {
unsigned char i;
if (bitCount == 26){
for (i=2; i<=9; i++) {
facilityCode <<=1; facilityCode |= databits[i];
}
for (i=10; i<bitCount; i++) {
cardCode <<=1; cardCode |= databits[i];
}
vps=String(facilityCode)+"_"+String(cardCode);
digitalWrite(6, LOW); digitalWrite(5, LOW);
Serial.print(vps);Serial.println();delay(200);
digitalWrite(6, HIGH); digitalWrite(5, HIGH);
bitCount = 0; facilityCode = 0; cardCode = 0; for (i=0; i<MAX_BITS; i++) { databits[i] = 0; }
}
}
if (digitalRead(9) == HIGH ){
digitalWrite(8, HIGH);
} else {digitalWrite(8, LOW);}
}
Thanks for advice.
I change it.
The sketch will be loaded in to device tommorow and will see how it works next week.
I am curious - could you explain me more about why the string variable can cause problem?
I always whant to know how and why the things work or don't work.
I am curious - could you explain me more about why the string variable can cause problem?
I have read a number of complaints about memory leaks in sketches that use String objects. Since the objects weren't necessary in your case I figured that eliminating them might help.
I try it, but it still crash.
May be it's not a crash, but something wrong in code.
I am pointing to "wiegand counter" part.
I see that the wiegand counter counts outside the bitcount=26 if fragment.
Now I change it to this, but will check if it works tommorow:
/*
* 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!
*/
//#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#define MAX_BITS 100 // max number of bits
volatile unsigned char databits[MAX_BITS]; // stores all of the data bits
volatile unsigned char bitCount=0; // number of bits currently captured
volatile unsigned char flagDone; // goes low when data is currently being captured
volatile unsigned int wc; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code1
unsigned int wcCopy;
//LiquidCrystal_I2C lcd(0x27,16,2);
void ISR_INT0(){
bitCount++;
databits[bitCount]=0;
flagDone = 0;
wc = 3000;
}
void ISR_INT1(){
bitCount++;
databits[bitCount]=1;
flagDone = 0;
wc = 3000;
}
void setup()
{
Serial.begin(9600);
pinMode(8, OUTPUT);
digitalWrite(8, LOW);
pinMode(9, INPUT);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
// lcd.init(); lcd.backlight();
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
wc = 3000;
flagDone = 1;
}
void loop()
{
unsigned int wcCopy;
// This waits to make sure that there have been no more data pulses before processing data
// weigand_counter is updated inside an ISR so access it safely
if (!flagDone) {
noInterrupts ();
wc--;
wcCopy = wc;
interrupts ();
if (wcCopy == 0) { flagDone = 1;} }
//Serial.print(bitCount);Serial.print("-");Serial.println(wc);
if (bitCount > 0 && flagDone) {
unsigned char i;
if (bitCount == 26){
for (i=2; i<=9; i++) {
facilityCode <<=1; facilityCode |= databits[i];
}
for (i=10; i<bitCount; i++) {
cardCode <<=1; cardCode |= databits[i];
}
digitalWrite(6, LOW); digitalWrite(5, LOW);
Serial.print(facilityCode);
Serial.print("_");
Serial.println(cardCode);
//delay(200);
digitalWrite(6, HIGH); digitalWrite(5, HIGH);
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++) { databits[i] = 0; }
flagDone = 1; wc = 3000;
}
}
if (digitalRead(9) == HIGH ){
digitalWrite(8, HIGH);
} else {digitalWrite(8, LOW);}
}
Maybe you are getting more then 100 bits. Try adding code to check the count:
void ISR_INT0(){
bitCount++;
if (bitCount < MAX_BITS) // Don't want to store more than the array can hold!
databits[bitCount]=0;
flagDone = 0;
wc = 3000;
}
Tommorow will test the new sketch and post it if it's ok.
Is it possible to be from the distance between reader and arduino (around 7mt.)?
I think that if it is it must be not work at all. But it works for about half an hour and then stop.
The power source is usb port from raspberry pi for the arduino. The reader I try on the high voltage power source - swiched power supply with battery reservation 13.8V. The Raspberry pi is powered from the same source but with amsr1 - 7805 - voltage regulator at 1A. So when the reader is connected to 13.8V it makes more friquent crash, which make no sence because it works from 5 to 18V and the Data 1 and Data 0 are always 5V.
May be I will try to connect the reader after the voltage regulator and change the regulator with 1.5A current. But this is also make no sence because the reader pull up around 70mA.
Another Idea is to try to connect two arduinos on one reader - the first to be the crashing one and the second I will restart each 2-3minutes.
On the second I will attach serial console to see what happen and may be use more serial.prints.
It still won't work.
I begin to think that the reader is a problem or/and the switched power supply.
Here is the code:
/*
* 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!
*/
//#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#define MAX_BITS 100 // max number of bits
volatile unsigned char databits[MAX_BITS]; // stores all of the data bits
volatile unsigned char bitCount=0; // number of bits currently captured
volatile unsigned char flagDone; // goes low when data is currently being captured
volatile unsigned int wc; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code1
unsigned int wcCopy;
//LiquidCrystal_I2C lcd(0x27,16,2);
void ISR_INT0(){
bitCount++;
if (bitCount <= 26){databits[bitCount]=0;}
flagDone = 0;
wc = 3000;
}
void ISR_INT1(){
bitCount++;
if (bitCount <= 26){databits[bitCount]=1;}
flagDone = 0;
wc = 3000;
}
void setup()
{
Serial.begin(9600);
pinMode(8, OUTPUT);
digitalWrite(8, LOW);
pinMode(9, INPUT);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
// lcd.init(); lcd.backlight();
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
wc = 3000;
flagDone = 1;
}
void loop()
{
unsigned int wcCopy;
if (!flagDone) {
noInterrupts ();
wc--;
wcCopy = wc;
interrupts();
if (wcCopy == 0) { flagDone = 1;}
}
//Serial.print(bitCount);Serial.print("-");Serial.println(wc);
if (bitCount > 0 && flagDone) {
unsigned char i;
if (bitCount == 26){
noInterrupts ();
for (i=2; i<=9; i++) {
facilityCode <<=1; facilityCode |= databits[i];
}
for (i=10; i<bitCount; i++) {
cardCode <<=1; cardCode |= databits[i];
}
interrupts();
digitalWrite(6, LOW); digitalWrite(5, LOW);
Serial.print(facilityCode);
Serial.print("_");
Serial.println(cardCode);
delay(200);
digitalWrite(6, HIGH); digitalWrite(5, HIGH);
noInterrupts ();
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++) { databits[i] = 0; }
flagDone = 1; wc = 3000;
interrupts();
}
}
if (digitalRead(9) == HIGH ){
digitalWrite(8, HIGH);
} else {digitalWrite(8, LOW);}
}
I post below my last sketch. It works perfect and fast.
But regarding the hardware:
reader is connected to 5V from the Arduino - tommorow I will try with 13.8V and 12.0V.
Before it won't work for long on external power supply for the reader.
The reader power +5V, GND, DATA 0 and DATA1, LED control pin and buzzer control pin
are on screw type connectors mounted on arduino prototyping sheld.
I remove all unused pins of the sheld, only Digital 5, 2 and 3, 5V and GND left.
Also change 5V power stabilizer with 1.5Amps - AMSR1.5.
Then connect to it rasberry pi, and connect arduino with usb to rasberry pi.
The only problem now is to see if the reader and arduino will work on 13.8V and 12V from
external supply, but arduino will be still powered from the usb of the rasberry pi.
The 5V power of the reader makes it to read on small distance.
Tommorow I will write if I successes.
Meanwhile its good for interupt sketches to have an dissasebler tool and to see how
the compiler change the sketch. The cpp and hex files are in user temp directory after compilation.
But I will never return to Assembler programing of a pic controller as example.
It works stable on 13.8V.
Someone should put the last sketch as a example of wiegand 26bit reading.
P.S.: I also experiment with two way communication between Raspberry PI and Arduino.
This will be use to grand access for doors and etc.
Also connecting more arduinos with USB hub.
After few days work it can't read Data 1 and Data 0, may be it's the reader.
We change the power suppy of the reader with 5VDC.
But on 13.8VDC should not be a problem because the reader works up to 16VDC.
I have simmilar system with ID-12 from sparkfun - it works with arduino uno + ethernet sheild, but it always connected to the network
and it has continious ability to open HTML GET method files on our server. It work from 6 months without a problem.
But here the card code is in ASCII HEX format and it's more long than wiegand - I don't know why.