First time poster, if I'm in wrong area please move.
I have written a program with nano to read three rfid-readers using wiegand26. I'm running out of ideas why my code doesn't work. With readers 1 and 2 I do get the right code. But reader 3 doesn't work, it looks like something resets the bit counter.
The actual inputs are working since I can modify the L-led with them. Also if I change one of the tx bytes to the counter2-value right after reading a bit, it will put out 1, but when it get's to checking if there's anything in counter2, there never is.
Also if I move variable definitions from global to inside void loop(), the serial communication stops (so no idea what's going on then).
The goto is because, I believe it's faster than the while, but after all the optimization I have done with the original code, doesn't seem to be necessary.
Anyone can figure out why? I have battled with this program for several ten hours and probably will for many more.
I will put out the code in following messages since, it has more characters than the allowed 9000.
// serial communication. If reading is on on some reader, lets skip it.
if (Serial.available()==7 && !counter0 && !counter1 && !counter2) {
// 7 bytes recieved, that's the right amount from pc. 7th byte should always be 210
Serial.readBytes(rx, 7);
if(!rx[4] && !readerinprogress) {
if (readerdone[0]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 1; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[0];
tx[1]=tavut[1];
tx[2]=tavut[2];
tx[3]=tavut[3];
readerinprogress = 1;
} else if (readerdone[1]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 2; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[4];
tx[1]=tavut[5];
tx[2]=tavut[6];
tx[3]=tavut[7];
readerinprogress = 2;
} else if (readerdone[2]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 3; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[8];
tx[1]=tavut[9];
tx[2]=tavut[10];
tx[3]=tavut[11];
readerinprogress = 3;
}
}
// mirror last read byte back to pc. It should always be 210, if it's not, then there's
// a sync or com problem going on and the pc will flush all it's communication and try
// again.
tx[6]=rx[6];
if(rx[6] == 210) {
// command from pc
if (rx[4] == 8) { // command 8, write eeprom
tx[4] = 9;
EEPROM.write(rx[5], rx[3]);
} else if (rx[4] == 4) { // command 4, read eeprom
tx[4] = 8;
tx[5] = EEPROM.read(rx[5]);
} else if (rx[4] == 5) { // command 5, open reader 1 relay
PORTB = PORTB | B00000100; //digitalWrite(10, HIGH); // reader 1 relay
gateopen[0]=millis();
tx[4] = 4;
tx[5] = 0;
readerdone[0]=0;
} else if (rx[4] == 6) { // command 6, open reader 2 relay
PORTB = PORTB | B00001000; //digitalWrite(11, HIGH); // reader 2 relay
gateopen[1]=millis();
tx[4] = 5;
tx[5] = 0;
readerdone[1]=0;
} else if (rx[4] == 7) { // command 7, open reader 3 relay
PORTB = PORTB | B00010000; //digitalWrite(12, HIGH); // reader 3 relay
gateopen[2]=millis();
tx[4] = 6;
tx[5] = 0;
readerdone[2]=0;
}else if (rx[4] == 10) { // command 10, everything done
if(readerinprogress) {
readerdone[readerinprogress-1] = 0;
readerinprogress = 0;
}
tx[4]=0; // PC tells us work is done
tx[5]=0; // reset bytes and that's it.
}
Serial.write("PC"); // the communication must begin with PC or the pc won't regognize it.
Serial.write(tx, 7);
serialflush = millis();
} else {
while(Serial.available()) Serial.read();
}
} else if(Serial.available() > 7) {
// there are too many bytes in the buffer, let's flush them and get on with it.
while(Serial.available()) Serial.read();
} else if(millis() > serialflush+800 && millis() - 800 > serialflush) {
// flush what's been read, it has been too long for that.
while(Serial.available()>0) Serial.read();
// Coms have failed, the mirrored byte isn't 210 so the pc will know about this.
tx[6]=0;
Serial.write("PC");
Serial.write(tx, 7);
serialflush = millis();
}
goto start;
}
}
Now with scratching my head until it started bleeding I found something. First of all there's a pointer error. Just in the end of the first half of the code. tehty[1] should be tehty[2]. Probably changed it when debugging and copied the reader 2 code to reader 3 code. This didn't settle the problem as it probably wasn't my original problem.
Then I used the led on pin 13 to find out where exactly did my counter reset. It was right after the line that resets tehty[2]. Didn't seem to make any sense. I did some tinkering with the variable declarations, changed order and that did have some effect, just didn't make it work. Then I changed every array on variable bigger than they needed to be. Boom, it started working. After that I started to change them back to origininal, one by one.
The result is, that every array of unisgned long has to be one variable longer, than what I use. Now what's that about?
Edit:
I just changed the serialflush into an array and it fixed one more bug.
Here's the code after all I have been trying out. Probalby still need to share it in two, because it's quite long. I changed to mega to see if there was difference, but after modifying the code to right pins, the action didn't change. That's why there are some minor differences here.
#include <EEPROM.h>
void setup() {
// Lukijan jalat
pinMode(A8, INPUT);
pinMode(A9, INPUT);
pinMode(A10, INPUT);
pinMode(A11, INPUT);
pinMode(A12, INPUT);
pinMode(A13, INPUT);
digitalWrite(A8, HIGH);
digitalWrite(A9, HIGH);
digitalWrite(A10, HIGH);
digitalWrite(A11, HIGH);
digitalWrite(A12, HIGH);
digitalWrite(A13, HIGH);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
}
// variable definitions
byte tehty[2]; // bit is read for a reader
byte rx[6], tx[6]; // Serial bytes
byte readerdone[2]; // reader has finished reading the code
byte tavut[11]; // bytes for storaging codes
byte bit1[255]; // bits got from readers
byte bit2[255]; // bits got from readers
byte bit3[255]; // bits got from readers
unsigned long timeout[3]; // timeout for reading wiegand code
unsigned long serialflush[1]; // counter, when to flush serial
unsigned long gateopen[3]; // timer for code ok, pulses for doors/etc
unsigned int gateopentime[3]; // pulse length as ms for doors/etc
byte D1; // Datalines from readers
byte counter0; // Counter for bits from the reader
byte counter1; // Counter for bits from the reader
byte counter2; // Counter for bits from the reader
byte readerinprogress; // which reader code is sent to pc
void loop() {
gateopentime[0] = 2000;
gateopentime[1] = 2000;
gateopentime[2] = 2000;
Serial.begin(9600);
//Start the actual loop
while(true){
start:
// check if a some of the gate pulses has been on for enough time
if(PORTB & B01110000) {
if (millis() > gateopen[0] + gateopentime[0] && millis() - gateopentime[0] > gateopentime[0]) {
PORTB = PORTB & B11101111;
}
if (millis() > gateopen[1] + gateopentime[1] && millis() - gateopentime[1] > gateopentime[1]) {
PORTB = PORTB & B11011111;
}
if (millis() > gateopen[2] + gateopentime[2] && millis() - gateopentime[2] > gateopentime[2]) PORTB = PORTB & B10111111;
}
// data from reader 1
D1 = PINK & B00000011;
if (D1 == B00000011) {
tehty[0]=0; // pause between bit's on the code or code done
if(counter0) {
if (millis() > timeout[0] + 200 && timeout[0] < millis()) { // timeout on reader 1, check if there's enough bits
tx[3]=101;
if (counter0 >= 26){ // 26 bits counted reader 1
if(bit1[0]) tavut[0] = 1; else tavut[0]=0;
if(bit1[1]) tavut[0] = tavut[0] + 2;
if(bit1[2]) tavut[0] = tavut[0] + 4;
if(bit1[3]) tavut[0] = tavut[0] + 8;
if(bit1[4]) tavut[0] = tavut[0] + 16;
if(bit1[5]) tavut[0] = tavut[0] + 32;
if(bit1[6]) tavut[0] = tavut[0] + 64;
if(bit1[7]) tavut[0] = tavut[0] + 128;
if(bit1[8]) tavut[1] = 1; else tavut[1]=0;
if(bit1[9]) tavut[1] = tavut[1] + 2;
if(bit1[10]) tavut[1] = tavut[1] + 4;
if(bit1[11]) tavut[1] = tavut[1] + 8;
if(bit1[12]) tavut[1] = tavut[1] + 16;
if(bit1[13]) tavut[1] = tavut[1] + 32;
if(bit1[14]) tavut[1] = tavut[1] + 64;
if(bit1[15]) tavut[1] = tavut[1] + 128;
if(bit1[16]) tavut[2] = 1; else tavut[2]=0;
if(bit1[17]) tavut[2] = tavut[2] + 2;
if(bit1[18]) tavut[2] = tavut[2] + 4;
if(bit1[19]) tavut[2] = tavut[2] + 8;
if(bit1[20]) tavut[2] = tavut[2] + 16;
if(bit1[21]) tavut[2] = tavut[2] + 32;
if(bit1[22]) tavut[2] = tavut[2] + 64;
if(bit1[23]) tavut[2] = tavut[2] + 128;
if(bit1[24]) tavut[3] = 1; else tavut[3]=0;
if(bit1[25]) tavut[3] = tavut[3] + 2;
readerdone[0]=1;
}
counter0=0; // timeout between bits from the reader
}}
} else if (D1 == B00000001 && !tehty[0]){
timeout[0] = millis();
bit1[counter0]=0;
counter0++;
tehty[0]=1;
} else if (D1 == B00000010 && !tehty[0]){
timeout[0] = millis();
bit1[counter0]=1;
counter0++;
tehty[0]=1;
}
// data from reader 2
D1 = PINK & B00001100;
if (D1 == B00001100) {
tehty[1]=0; // pause between bit's on the code or code done
if (counter1) {
if (millis() > timeout[1] + 200 && timeout[1] < millis()) { // timeout on reader 2, check if there's enough bits
// 26 bits from reader 2
if (counter1 >= 26){
tavut[4]=0;
tavut[5]=0;
tavut[6]=0;
tavut[7]=0;
if(bit2[0]) tavut[4] = 1;
if(bit2[1]) tavut[4] = tavut[4] + 2;
if(bit2[2]) tavut[4] = tavut[4] + 4;
if(bit2[3]) tavut[4] = tavut[4] + 8;
if(bit2[4]) tavut[4] = tavut[4] + 16;
if(bit2[5]) tavut[4] = tavut[4] + 32;
if(bit2[6]) tavut[4] = tavut[4] + 64;
if(bit2[7]) tavut[4] = tavut[4] + 128;
if(bit2[8]) tavut[5] = 1;
if(bit2[9]) tavut[5] = tavut[5] + 2;
if(bit2[10]) tavut[5] = tavut[5] + 4;
if(bit2[11]) tavut[5] = tavut[5] + 8;
if(bit2[12]) tavut[5] = tavut[5] + 16;
if(bit2[13]) tavut[5] = tavut[5] + 32;
if(bit2[14]) tavut[5] = tavut[5] + 64;
if(bit2[15]) tavut[5] = tavut[5] + 128;
if(bit2[16]) tavut[6] = 1;
if(bit2[17]) tavut[6] = tavut[6] + 2;
if(bit2[18]) tavut[6] = tavut[6] + 4;
if(bit2[19]) tavut[6] = tavut[6] + 8;
if(bit2[20]) tavut[6] = tavut[6] + 16;
if(bit2[21]) tavut[6] = tavut[6] + 32;
if(bit2[22]) tavut[6] = tavut[6] + 64;
if(bit2[23]) tavut[6] = tavut[6] + 128;
if(bit2[24]) tavut[7] = 1;
if(bit2[25]) tavut[7] = tavut[7] + 2;
readerdone[1]=1;
}
counter1=0; // timeout between bits from the reader
}}
} else if (D1 == B00000100 && !tehty[1]){
timeout[1] = millis();
bit2[counter1]=0;
counter1++;
tehty[1]=1;
} else if (D1 == B00001000 && !tehty[1]){
timeout[1] = millis();
bit2[counter1]=1;
counter1++;
tehty[1]=1;
}
// data from reader 3
D1 = PINK & B00110000;
if (D1 == B00110000) {
tehty[2]=0; // pause between bit's on the code or code done
if (counter2){
if (millis() > timeout[2] + 300 && timeout[2] < millis()) { // timeout on reader 3, check if there's enough bits
// 26 bits from reader 2
if (counter2 >= 26){
tavut[8]=0;
tavut[9]=0;
tavut[10]=0;
tavut[11]=0;
if(bit3[0]) tavut[8] = 1;
if(bit3[1]) tavut[8] = tavut[8] + 2;
if(bit3[2]) tavut[8] = tavut[8] + 4;
if(bit3[3]) tavut[8] = tavut[8] + 8;
if(bit3[4]) tavut[8] = tavut[8] + 16;
if(bit3[5]) tavut[8] = tavut[8] + 32;
if(bit3[6]) tavut[8] = tavut[8] + 64;
if(bit3[7]) tavut[8] = tavut[8] + 128;
if(bit3[8]) tavut[9] = 1;
if(bit3[9]) tavut[9] = tavut[9] + 2;
if(bit3[10]) tavut[9] = tavut[9] + 4;
if(bit3[11]) tavut[9] = tavut[9] + 8;
if(bit3[12]) tavut[9] = tavut[9] + 16;
if(bit3[13]) tavut[9] = tavut[9] + 32;
if(bit3[14]) tavut[9] = tavut[9] + 64;
if(bit3[15]) tavut[9] = tavut[9] + 128;
if(bit3[16]) tavut[10] = 1;
if(bit3[17]) tavut[10] = tavut[10] + 2;
if(bit3[18]) tavut[10] = tavut[10] + 4;
if(bit3[19]) tavut[10] = tavut[10] + 8;
if(bit3[20]) tavut[10] = tavut[10] + 16;
if(bit3[21]) tavut[10] = tavut[10] + 32;
if(bit3[22]) tavut[10] = tavut[10] + 64;
if(bit3[23]) tavut[10] = tavut[10] + 128;
if(bit3[24]) tavut[11] = 1;
if(bit3[25]) tavut[11] = tavut[11] + 2;
readerdone[2]=1;
}
counter2=0; // timeout between bits from the reader
}}
} else if (D1 == B00010000 && !tehty[2]){
timeout[2] = millis();
bit3[counter2]=0;
counter2++;
tehty[2]=1;
} else if (D1 == B00100000 && !tehty[2]){
timeout[2] = millis();
bit3[counter2]=1;
counter2++;
tehty[2]=1;
}
// serial communication. If reading is on on some reader, lets skip it.
if (Serial.available()==7 /* && !counter0 && !counter1 && !counter2 */) {
// 7 bytes recieved, that's the right amount from pc. 7th byte should always be 210
Serial.readBytes(rx, 7);
if(!rx[4] && !readerinprogress) {
if (readerdone[0]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 1; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[0];
tx[1]=tavut[1];
tx[2]=tavut[2];
tx[3]=tavut[3];
readerinprogress = 1;
} else if (readerdone[1]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 2; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[4];
tx[1]=tavut[5];
tx[2]=tavut[6];
tx[3]=tavut[7];
readerinprogress = 2;
} else if (readerdone[2]) {
tx[4] = 1; // Info for PC that the code read is a new one.
tx[5] = 3; // Info for PC that which reader read the code.
// let's send last read code to the pc.
tx[0]=tavut[8];
tx[1]=tavut[9];
tx[2]=tavut[10];
tx[3]=tavut[11];
readerinprogress = 3;
}
}
// mirror last read byte back to pc. It should always be 210, if it's not, then there's
// a sync or com problem going on and the pc will flush all it's communication and try
// again.
tx[6]=rx[6];
if(rx[6] == 210) {
// command from pc
if (rx[4] == 8) { // command 8, write eeprom
tx[4] = 9;
EEPROM.write(rx[5], rx[3]);
} else if (rx[4] == 4) { // command 4, read eeprom
tx[4] = 8;
tx[5] = EEPROM.read(rx[5]);
} else if (rx[4] == 5) { // command 5, open reader 1 relay
PORTB = PORTB | B00010000; //digitalWrite(10, HIGH); // reader 1 relay
gateopen[0]=millis();
tx[4] = 4;
tx[5] = 0;
readerdone[0]=0;
} else if (rx[4] == 6) { // command 6, open reader 2 relay
PORTB = PORTB | B00100000; //digitalWrite(11, HIGH); // reader 2 relay
gateopen[1]=millis();
tx[4] = 5;
tx[5] = 0;
readerdone[1]=0;
} else if (rx[4] == 7) { // command 7, open reader 3 relay
PORTB = PORTB | B01000000; //digitalWrite(12, HIGH); // reader 3 relay
gateopen[2]=millis();
tx[4] = 6;
tx[5] = 0;
readerdone[2]=0;
}else if (rx[4] == 10) { // command 10, everything done
if(readerinprogress) {
readerdone[readerinprogress-1] = 0;
readerinprogress = 0;
}
tx[4]=0; // PC tells us work is done
tx[5]=0; // reset bytes and that's it.
}
Serial.write("PC"); // the communication must begin with PC or the pc won't regognize it.
Serial.write(tx, 7);
serialflush[0] = millis();
} else {
while(Serial.available()) Serial.read();
}
} else if(Serial.available() > 7) {
// there are too many bytes in the buffer, let's flush them and get on with it.
while(Serial.available()) Serial.read();
} else if(millis() > serialflush[0]+800 && millis() - 800 > serialflush[0]) {
// flush what's been read, it has been too long for that.
while(Serial.available()>0) Serial.read();
// Coms have failed, the mirrored byte isn't 210 so the pc will know about this.
tx[6]=0;
Serial.write("PC");
Serial.write(tx, 7);
serialflush[0] = millis();
}
goto start;
}
}
Done as you instructed. I don't expect you to do anything with the code (at least now, that I got it working).
The question is for the array sizes with the unsigned longs.
For example timeout is declared to be [3], even if I only use [2]. If it's declared smaller, the program will do unexpected things. This goes for every unsigned long I use. Is there a reason for this? Even with the only one that wasn't array (serialflush), I had to change it to an array with size of [1]. Otherwise there was some crazy things going on.
aarg:
The declaration gives the size. But arrays start at zero. So when you say timeout[2] you are indexing the 3rd element of the array.
Yes. And when it's declared as:
unsigned long timeout[2];
shouldn't there be three elements? Now I had to declare it as timeout[3], even the biggest pointer I use is [2].
PaulS:
No. The number in the braces in the declaration is the number of elements, not the upper index.
Ah, that explains a lot of what's going on. As I have done most of my programming using some sort of version of basic, I just assumed it works the same way. Thank you for clearing this for me.
As attachment is the fixed code. It reads three wiegand 26-readers without using interruptions. Probably can do more by the same logic.
Pins for the readers are A8-A13, going like D0 reader 1, D1 reader 1, D0 reader 2 and so on. Uses internal pullup resistors. Maybe there's something someone can use. Probably should get rid of my communication and relay-stuff and write their own though.