Jump to content
43oh

Parallax RFID reader


Recommended Posts

I saw touch ported some rfid reader code to msp430, and so I thought I'd share what I've got for the Parallax RFID reader. The code is a bit bloated and inefficient, but it seems to work well. It compiles from about 1300B to 1500B program size in CCS, depending on if optimization is used, and uses 60B RAM.

 

Most of the work is done in software, so TimerA and the USI are free. I couldn't get it to run at 1MHz, so you'll need an MSP430 with calibration constants or a clock source. It works fine at 8MHz or higher.

 

I used a voltage divider to bring the reader's 5V data line down, and powered the reader with my launchpad's TP1 and TP4 test points.

 

#include "msp430g2231.h"
#include 

#define	PIN_RFID_DATA			BIT7					// normally high
#define PIN_RFID_ENABLE			BIT4  					// active LOW
#define PIN_LED					BIT0

#define RFID_BAUD				2400
#define MCLK_FREQUENCY			8000000
#define WDT_DIVIDER				512
#define BYTES_PER_MESSAGE		12
#define BYTES_PER_TAG			10
#define N_ALLOWED_TAGS			1
#define RESULT_SUCCESS			0
#define RESULT_TIMEOUT			1
#define RESULT_ERROR			2
#define RESULT_NO_DATA			3
#define READER_WARMUP			800
#define MIDSCAN_TIMEOUT			200

const char tags[N_ALLOWED_TAGS][bYTES_PER_TAG] = {'3', '6', '0', '0', '6', '2', '2', 'B', 'A', 'E'};
const unsigned long WDT_FREQUENCY = MCLK_FREQUENCY / WDT_DIVIDER;

volatile unsigned long wdtCounter = 0;
unsigned int stateCount;
char rfidData[bYTES_PER_MESSAGE] = {0};
char rfidByte;
char bitIndex = 0;
char newByte = 0;
volatile char haveNewByte = false;
volatile char busy = false;
char wdtTicksPerBit;

unsigned long millis(){
return wdtCounter / ((float)WDT_FREQUENCY / 1000);
}

void delayMillis(unsigned long milliseconds){
unsigned long wakeTime = wdtCounter + (milliseconds * WDT_FREQUENCY / 1000);
while(wdtCounter < wakeTime);
}

void addBits(char n, char state){
int i;
if(state)
	for(i = 0; i < n; i++){
		rfidByte |= 0x01 << bitIndex;
		bitIndex++;
	}
else
	for(i = 0; i < n; i++){
			rfidByte &= ~(0x01 << bitIndex);
		bitIndex++;
	}
}

char scanTag(){
unsigned long timeout = millis() + READER_WARMUP;
char byteIndex = 0; 
P1OUT &= ~PIN_RFID_ENABLE;

while(!haveNewByte){
	if(millis() > timeout){
		P1OUT |= PIN_RFID_ENABLE;
		busy = false;
		return RESULT_NO_DATA;
	}
}

if(newByte == 0x0A){
	while(byteIndex < BYTES_PER_MESSAGE){
		timeout = millis() + MIDSCAN_TIMEOUT;
		rfidData[byteIndex] = newByte;
		byteIndex++;
		haveNewByte = false;

		while(!haveNewByte){
			if(millis() > timeout){
				P1OUT |= PIN_RFID_ENABLE;
				busy = false;
				return RESULT_TIMEOUT;
			}
		}
	}
	P1OUT |= PIN_RFID_ENABLE;
	return RESULT_SUCCESS;
}
else{
	P1OUT |= PIN_RFID_ENABLE;
	haveNewByte = false;
	busy = false;
	return RESULT_ERROR;
}
}

char isValidTag(){
char iTag;
char iByte;
char valid = true;

for(iTag = 0; iTag < N_ALLOWED_TAGS; iTag++){
	for(iByte = 0; iByte < BYTES_PER_TAG & valid; iByte++){
		if(rfidData[iByte + 1] != tags[iTag][iByte])
			valid = false;
	}
}
return valid;
}

void handleMessage(){
if(isValidTag())
	P1OUT ^= PIN_LED;
}

void main(void){
DCOCTL = CALDCO_8MHZ;
BCSCTL1 = CALBC1_8MHZ;
WDTCTL = WDTPW + WDTTMSEL + WDTIS1;// + WDTIS0;
IE1 |= WDTIE;                             		// Enable WDT interrupt

wdtTicksPerBit = ((float)WDT_FREQUENCY / RFID_BAUD);

P1IE |= PIN_RFID_DATA;
P1IES |= PIN_RFID_DATA;
P1DIR |= PIN_RFID_ENABLE + PIN_LED;
P1OUT |= PIN_RFID_ENABLE + PIN_LED;

_BIS_SR(GIE);									// enable interrupts

while(1){
	switch(scanTag()){
		case RESULT_SUCCESS:
			handleMessage();
			delayMillis(1000);
			break;
		case RESULT_NO_DATA:
			delayMillis(1000);
			break;
		// nothing here for RESULT_ERROR
		// just scan the tag again right away
	}
}
}

#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void){
stateCount++;
wdtCounter++;
}

#pragma vector=PORT1_VECTOR
__interrupt void Port1(void){
static char state;
unsigned int nBits;
P1IES ^= PIN_RFID_DATA;								// capture both edges
P1IFG &= ~PIN_RFID_DATA;

if(!busy){
	bitIndex = 0;		
	busy = true;
	state = 0;
	stateCount = wdtTicksPerBit * -1;  // ignore start bit
}
else{

	nBits = (stateCount / wdtTicksPerBit);

	// trim off the stop bit if the last data bit is also a "1"
	// maybe catch some other unexpected behavior too
	if(nBits + bitIndex > 8)
		nBits = 8 - bitIndex;
	addBits(nBits, state);

	state ^= BIT0;
	stateCount = 0;
}
if(bitIndex == 8){
	busy = false;
	newByte = rfidByte;
	haveNewByte = true;
}
}

 

This was part of a project I was working on to tweet when my cats poop. I was using some RF Link boards from eBay so I wouldn't need a data connection to the litter box. It turns out RF Links are very noisy, and the code for wireless was just too big for my 2K flash MSP430's. I've got some 8K's on order, but for now my cats' bowel movements will continue to remain a mystery.

Link to post
Share on other sites

This was part of a project I was working on to tweet when my cats poop. I was using some RF Link boards from eBay so I wouldn't need a data connection to the litter box. It turns out RF Links are very noisy, and the code for wireless was just too big for my 2K flash MSP430's. I've got some 8K's on order, but for now my cats' bowel movements will continue to remain a mystery.

 

Thanks for sharing NTM. How do you know if your cats poop? weight?

Link to post
Share on other sites

I ordered some sample RFID "keychains" from TI that should work with the Parrallax reader (that's what I got them for). They are small, black cylinders, maybe 4mm diameter, about 25-30mm long, with a hole through one end (comes on a "spiral-ring" key ring). I mention this because they might fit well on a cat's collar. ;)

 

http://focus.ti.com/docs/prod/folders/print/ri-trp-rfob.html

Link to post
Share on other sites
I ordered some sample RFID "keychains" from TI that should work with the Parrallax reader (that's what I got them for). They are small, black cylinders, maybe 4mm diameter, about 25-30mm long, with a hole through one end (comes on a "spiral-ring" key ring). I mention this because they might fit well on a cat's collar. ;)

 

http://focus.ti.com/docs/prod/folders/print/ri-trp-rfob.html

 

The TI tags say that they are 134khz tags. The Parrallax RFID reader uses 125khz tags.

Link to post
Share on other sites
The TI tags say that they are 134khz tags. The Parrallax RFID reader uses 125khz tags.

Darn! I just saw they were in "Low Frequency" range, I hadn't looked up the specifics on either part. :oops: Just rolling the dice, I guess. These fobs are nice, though; I may eventually have to work on a reader for them. :?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...