View previous topic :: View next topic |
Author |
Message |
ds
Joined: 01 Nov 2009 Posts: 15
|
get_string for RFID |
Posted: Wed Nov 04, 2009 10:45 pm |
|
|
Hi all,
so I have successfully read an RFID tag with a PIC. Only problem is that it only reads the string from the RFID reader once. I have a loop set up that would make it read over and over again. It goes through once, and I believe the code is getting stuck at the get_string function. Any ideas on what the problem is? By the way... it can successfully check whether or not it is the right card.
Thanks in advance!
Code: |
#include <16F887.h>
#device ADC=10
#fuses INTRC_IO,NOWDT,PUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP,NODEBUG
#use delay(clock=4000000)
#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)
#include <lcd16x2.c>
#include <input.c>
#include <string.h>
#define SENTANCE_LENGTH 12
void main(){
char sentance[SENTANCE_LENGTH];
char password[SENTANCE_LENGTH];
int answer;
sprintf(password,"220056CDD5");
lcd_init();
while(1){
get_string(sentance,SENTANCE_LENGTH);
lcd_putc("\f");
printf(lcd_putc,sentance);
lcd_putc("\n");
delay_ms(1000);
answer=strcmp(sentance,password);
if(answer==0){
lcd_putc("\fCorrect Card\n");
delay_ms(1000);
lcd_putc("\f");
}
else if(answer==1){
lcd_putc("\fWrong Card\n");
delay_ms(1000);
lcd_putc("\f");
}
}
}
|
|
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Thu Nov 05, 2009 1:12 am |
|
|
Are you sure the card is sending the information repeatedly? _________________ Regards
Jerson Fernandes |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Thu Nov 05, 2009 1:20 am |
|
|
yes I am sure. I think the get_string() command is the hang up. For some reason it only likes to go through once! I've tested various parts of the code using my lcd and a debugger. Is there some sort of reset for this function?
Thanks! |
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Thu Nov 05, 2009 5:00 am |
|
|
I can recommend you connect the RFID reader to your PC and look on HyperTerm what you get. There may be extra characters that you are not parsing. Only when you have the full information will it be easy to see where the problem lies. _________________ Regards
Jerson Fernandes |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Thu Nov 05, 2009 10:42 am |
|
|
Thanks guys! Right now I don't really have the means to connect to pc. My Max232 chips are coming in, and I don't have my serial to usb. I am pretty sure that the hang up is in the get_String. So maybe you are right. Maybe there is some initial bit or stop bit that get_string is not getting. Anyways, here is the what the pdf said is sent to the pic:
Quote: |
When a valid RFID transponder tag is placed within range of the activated reader, the unique ID will be transmitted as a 12-byte ASCII string via the TTL-level SOUT (Serial Output) pin in the following format:
(0x0A) Start byte (MSB)
Digit 1 Unique ID
Digit 2 Unique ID
Digit 3 Unique ID
Digit 4 Unique ID
Digit 5 Unique ID
Digit 6 Unique ID
Digit 7 Unique ID
Digit 8 Unique ID
Digit 9 Unique ID
Digit 10 Unique ID
(0x0D) Stop Bye (LSB)
The start byte and stop byte are used to easily identify that a correct string has been received from the reader (they correspond to a line feed and carriage return characters, respectively). The middle ten bytes are the actual tag's unique ID.
All communication is 8 data bits, no parity, 1 stop bit, non-inverted, least significant bit first (8N1). The baud rate is configured for 2400bps, a standard communications speed supported by most any microprocessor or PC, and cannot be changed. The Parallax RFID Reader Module initiates all communication. The Parallax RFID Reader Module can connect directly to any TTL-compatible UART or to an RS232-compatible interface by using an external level shifter.
|
Does my code match the requirements? I'm fairly new at using RS232.
Thanks for all the help guys! |
|
|
andyfraser
Joined: 04 May 2004 Posts: 47 Location: UK
|
|
Posted: Thu Nov 05, 2009 10:47 am |
|
|
You should always add ERRORS to your #use RS232 line to ensure that any errors do not lock up the RS232 receive.
Andy
www.sharpcontrols.net :: Free custom controls for .NET |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Thu Nov 05, 2009 5:17 pm |
|
|
I've added ERRORS to the RS232 and it seems to have solved the problem of the lockup! Thanks!
Now the problem is: the card ID is: 220056CDD6 ... which is 10 digits. Perfect.
However on the display... it says the correct 10 digit code the first time! (success), however on the second time around it displays an extra '2' on the front of the string. Subsequent "reads" have the correct ID, with an extra '2' on the front also. I was thinking that I need to clear the string in the loop. I did so, and still the problem arises. I even tried reducing the string size to 10 and it didn't work. After 10 reads or so, I'll get a read of just "2" on the display and then a read of "2&&" on the display. Then is will continue with the correct ID with the 2 added at the front.
Any ideas? here is my updated code:
Code: |
#include <16F887.h>
#device ADC=10
#fuses INTRC_IO,NOWDT,PUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP,NODEBUG
#use delay(clock=4000000)
#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <lcd16x2.c>
#include <input.c>
#include <string.h>
#define SENTANCE_LENGTH 32
int answer;
int i;
char sentance[SENTANCE_LENGTH];
char password[SENTANCE_LENGTH];
void main(){
sprintf(password,"220056CDD6");
lcd_init();
while(1){
sentance[0]='\0';
get_string(sentance,SENTANCE_LENGTH);
printf(lcd_putc,sentance);
delay_ms(800);
lcd_putc("\f");
}
}
|
ps I realise that sentence is spelled wrong... it was like this in some sample code so I stuck with it. haha. |
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Thu Nov 05, 2009 7:20 pm |
|
|
If you look at the datasheet section you posted, there is an additional byte (0x0A) before the actual string. You need to discard that before comparing. The first time around, the PIC might be missing the first byte and so, all works as expected. _________________ Regards
Jerson Fernandes |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Thu Nov 05, 2009 8:15 pm |
|
|
This extra "2" is really starting to bother me! Jerson, how do you suggest I get rid of the 0X0A? How big should my string length char array be if the string is only meant to be 10 useful characters? Do I really have to include the 0x0D aswell? I think it's only meant to tell the RS232 that it's done sending. The 0x0A is actually a \n (linefeed), and 0x0d is \r or carriage return. Any ideas? Thanks all for helping me get to this point! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Nov 05, 2009 8:19 pm |
|
|
Part of the answer is in that adding the ERRORS parameter caused the code to start working.
The PIC processor has a receive buffer for up to three characters. On receiving more data the UART will stall until the error condition is reset. The ERRORS parameter will add code for automatically clearing the error on every call to getc (and possibly kbhit too, I haven't checked) but the receiver hardware still holds 2 (or 3?) bytes of the old received data.
get_string will read data until a 0x0A character is received. Too bad this is the character your data starts with instead of ending with...
With your delay of 800ms the hardware receive buffer will overflow. The call to getc will clear the error, but the 2 old data characters waiting in the receive buffer most likely will not match the new arriving data.
Best solution is to roll your own get_rfid_string() function: Code: | #define RFID_START_BYTE 0x0A
#define RFID_END_BYTE 0x0D
// Description: Receive an RFID string.
// Expected receive data:
// (0x0A) Start byte (MSB)
// Digit 1 Unique ID
// Digit 2 Unique ID
// ...
// Digit 10 Unique ID
// (0x0D) Stop Byte (LSB)
// Input: max - Maximum RFID string length, including terminating 0.
// Output: s - Buffer to hold the received RFID string. Will be zero terminated.
void get_rfid_string(char* s, int8 max)
{
int8 len;
char c;
// Wait for start byte
do
{
c = getc();
} while (c != RFID_START_BYTE);
// Receive data until END byte is received or buffer full
max--; // correct for terminating zero
len=0;
while ((c != RFID_END_BYTE) && (len < max))
{
s[len++] = c;
c = getc();
};
s[len] = 0;
} |
|
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Thu Nov 05, 2009 10:30 pm |
|
|
Thanks so much for the help ckielstra! I tried the code and it works! However, the \n (0x0A) carried in by the first bit is causing the display output to be on a new line! I have been trying to throw that first bit away but haven't quite gotten it right. Do you know of a good way to do this? Also, what is the s[len]=0 for at the end? Does that terminate any characters after the last inputed character in the string? Also just out of curiosity, what does the max-- do? I saw it in the get_string function in input.c aswell.
Thanks again all of you for your help and suppport! |
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Thu Nov 05, 2009 11:49 pm |
|
|
If you doubt the first character is causing trouble, you can simply start printing from the second character like this
printf(lcd_putc,&sentance+1);
s[len] = 0 is simply ending the string with a NUL character - also called an ASCIIZ ascii zero string.
max is the maximum number of characters that can be collected into the string s _________________ Regards
Jerson Fernandes |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Fri Nov 06, 2009 12:20 am |
|
|
I tried that and it actually just prints the code on the top line first, then the second time around and subsequent times it keeps displaying on the bottom. I'm thinking there is a \n being read in. But I'm not completely sure. Also, using strcmp with what the value should be doesn't work. I think there is an extra data being read in or saved maybe. If I use the &sentance+1 in the code, the first time it can successfully compare and tell me it is the correct card. However, subsequent reads appear on the bottom of the lcd and no comparison is even made. I'm thinking there is something fishy with the first character. What would be a good way to kick it out! ? If you think that it would help.
Thanks Jerson Code: |
#define SENTANCE_LENGTH 15
int answer;
int i;
char sentance[SENTANCE_LENGTH];
char password[SENTANCE_LENGTH];
void main(){
sprintf(password,"220056CDD6");
lcd_init();
while(1){
get_rfid_string(sentance,SENTANCE_LENGTH);
printf(lcd_putc,&sentance+1);
delay_ms(800);
lcd_putc("\f");
answer=strcmp(&sentance+1,password);
if(answer==0){
lcd_putc("\fCorrect Card\n");
delay_ms(1000);
lcd_putc("\f");
}
else if(answer==1){
lcd_putc("\fWrong Card\n");
delay_ms(1000);
lcd_putc("\f");
}
}
}
|
|
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Fri Nov 06, 2009 12:36 am |
|
|
A good way to know what is within the string (an educated guess) would be to print the strlen(s). That will tell you how many characters are inside the string. Then you have to correlate with the expected data. _________________ Regards
Jerson Fernandes |
|
|
ds
Joined: 01 Nov 2009 Posts: 15
|
|
Posted: Fri Nov 06, 2009 1:28 pm |
|
|
Thanks for the tip Jerson! I got the lcd to display each set of data stored in the array for string. The first bit is in fact a 10 (which corresponds to a \n]). The last bit is a 0. This is because of the s[len]=0; at the end of the get_rfid_string function. However, for some reason, if I look at data past the zero, (where the data should technically end), I get a whole bunch of random values for string[11] and beyond.
Should I be worried about this?
Also, I tried to do a function that erased
the first bit, but didn't have success. How do you suggest I do it?
I was thinking something along the lines of
Code: |
for(i=0;i<12;i++){
if(sentance[i]==10){
sentance[i]="";
}
}
|
However, do you think it would be more appropriate to do a loop that essentially looks for "10", starts storing data, and stops when it finds a "0"?
Thanks for all the help and the tips Jerson! |
|
|
|