Go Down

Topic: Extracting integer data from binary data. (Read 819 times) previous topic - next topic

mikehiow

Mar 05, 2012, 07:44 pm Last Edit: Mar 05, 2012, 07:46 pm by mikehiow Reason: 1
Hello,

Please forgive my ignorance - I'm far more used to working with higher level languages, so getting down to the nitty gritty isn't something I'm particularly experienced with.

I'm reading data from a Weigand device, 34 bits in all, using interrupts with the following two functions from some example code;

Code: [Select]
void reader1One(void) {
 reader1Count++;
 reader1 = reader1 << 1;
 reader1 |= 1;
}

void reader1Zero(void) {
 reader1Count++;
 reader1 = reader1 << 1;
}


for those that aren't familiar with weigand, it consists of two data lines, one pulling low is a zero, the other pulling low is a one. Simples.

Now, my issue comes when I have the data, I need to pull the following two segments of binary to get the information I want;
Top line: first piece of data required
Middle line: full data received on each card swipe (as read from the same code, printing a bit at a time to the serial console)
Last line: second piece of data required
Code: [Select]

   110111110
0000110111110100110111110010110111
            10011011111001


So I need 9 bits from the 5th bit, and then 14 bits from the 14th bit. Once I have 34 bits, I attempt the following.

Code: [Select]
int serialNumber=(reader1 >> 14) & 0x3fff;
int siteCode= (reader1 >> 5) & 0x1ff;


The first piece of data (110111110) should be (int)446. The second (10011011111001) should be 9977.

These are not the results I see from my code when doing Serial.Print() on each of the above variables.

Can anyone see where I've gone wrong?

Thanks in advance,
Mike.

FWIW, if the above isn't making sense, the full (hacked up) code can be found here: http://pastebin.com/43iQ4Fud


PaulS

Quote
Middle line: full data received on each card swipe (as read from the same code, printing a bit at a time to the serial console)

Using what code?

Quote
So I need 9 bits from the 5th bit, and then 14 bits from the 14th bit. Once I have 34 bits, I attempt the following.

How is reader1 defined?

mikehiow

I did put a link in at the end of the post, but here is the full code

Code: [Select]


volatile long reader1 = 0;

volatile int reader1Count = 0;
volatile int overallCount = 0;

void reader1One(void) {
  reader1Count++;
  reader1 = reader1 << 1;
  reader1 |= 1;
}

void reader1Zero(void) {
  reader1Count++;
  reader1 = reader1 << 1;
}

void setup()
{
  Serial.begin(9600);
  Serial.print("\n");
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, RISING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, RISING); //DATA1 to pin 3
  delay(10);
  // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
  // so this gives a pulse to each reader input line to get the interrupts working properly.
  // Then clear out the reader variables.
  // The readers are open collector sitting normally at a one so this is OK
  for(int i = 2; i<4; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH); // enable internal pull up causing a one
    digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
    pinMode(i, INPUT);
    digitalWrite(i, HIGH); // enable internal pull up
  }
  delay(10);
  // put the reader input variables to zero
  reader1 = 0;
  reader1Count = 0;
}

void loop()
{
  if(reader1Count >=34){
     int serialNumber=(reader1 >> 14) & 0x3fff;
     int siteCode= (reader1 >> 5) & 0x1ff;
     Serial.print( reader1 );
     Serial.print("   ");
     Serial.print(siteCode);
     Serial.print("  ");
     Serial.println(serialNumber);
     reader1 = 0;
     reader1Count = 0;
  }
}

PaulS

Quote
I did put a link in at the end of the post

Yeah, I know. But, the proxy server blocks that site.

Quote
Long variables are extended size variables for number storage, and store 32 bits

So, how are you storing 34 bits in a long?

Code: [Select]
     Serial.print( reader1 );
     Serial.print("   ");
     Serial.print(siteCode);
     Serial.print("  ");
     Serial.println(serialNumber);

Why not add the BIN 2nd argument so that you can see what is in reader, and what the binary values of the other 2 are?

mikehiow

#4
Mar 05, 2012, 08:07 pm Last Edit: Mar 05, 2012, 08:10 pm by mikehiow Reason: 1
For some reason I thought long was 64bit. That may explain my issues then.

I don't need anything past the 27th bit, so perhaps I'll just dump anything after that rather than storing it.

Thanks for the heads up on the BIN argument, I wasn't aware it existed.


PaulS

Quote
I'm not sure what you mean by ditching the second argument, though?

Who said anything about ditching the 2nd argument? I suggested adding the second argument:
     Serial.print( reader1, BIN );
     Serial.print("   ");
     Serial.print(siteCode, BIN);
     Serial.print("  ");
     Serial.println(serialNumber, BIN);

See the data in binary...

mikehiow

Yeah, I just noticed that. I read it as bin the second argument :p

Thanks for your help. Unfortunately I don't have the stuff with me at the moment, so I'll have to try again tomorrow, but I think you may have the solution with my attempt at getting 34 bits into the long - I'm unsure what the behaviour is likely to be when going over 32bits?

In any case, the BIN argument should prove invaluable, that's kind of what I've needed all day!

PaulS

There are longer types on the Arduino - long long, for instance, that is 64 bits.

mikehiow

Hrm, do my bit masks look ok?

Whilst I can't test what I have exactly, I can test it in a little mocked up environment. I call the two interrupt functions to build the binary string I expect, and for some reason I'm getting the value I'd expect for sitecode from serialNumber, this can't be a coincidence, surely?

Code: [Select]
#include <stdio.h>

volatile long reader1 = 0;
volatile int reader1Count = 0;
void Reader1One(void) {
  reader1Count++;
  if(reader1Count <=28)
  {
   reader1 = reader1 << 1;
   reader1 |= 1;
  }
}

void Reader1Zero(void) {
  reader1Count++;
  if(reader1Count <= 28)
  {
   reader1 = reader1 << 1;
  }
}
main()
{
  Reader1Zero();Reader1Zero();Reader1Zero();Reader1Zero();Reader1One();Reader1One();Reader1Zero();Reader1One();Reader1One();Reader1One();Reader1One();Reader1One();Reader1Zero();Reader1One();Reader1Zero();Reader1Zero();Reader1One();Reader1One();Reader1Zero();Reader1One();Reader1One();Reader1One();Reader1One();Reader1One();Reader1Zero();Reader1Zero();Reader1One();Reader1Zero();Reader1One();Reader1One();Reader1Zero();Reader1One();Reader1One();Reader1One();
  int serialNumber=(reader1 >> 15) & 0x3fff;
  //int siteCode= (reader1 >> 6) & 0x1ff;

  printf("%d\n", serialNumber);

}

PaulS

You are shifting by a different amount, now. Is that intentional?

mikehiow

Just a result of playing.

Perhaps it is just coincidence.

mikehiow

FWIW, I solved my issue.

I was counting the start bit from the left rather than the right

swapping the shifts to 7 and 21 respectively solved my issue :)

Go Up