RFID tag as _one_ variable
Erlend
Posts: 612
I want to handle the RFID tag as one variable instead of 10 byte values. The byte codes seem to be in the range 0 - 99, but I am not sure it is always so. If it is, and I just string all the numbers together ino one integer (i,e, 44 52 87 ... becomes 445287...) the value could be as high as 10EE10 (-1), obviously blowing the LONG capacity. I may be forced to split into two LONGs and I suppose I could live with that too, if there is no, more elegant solution out there. But, that would mean I need to add some PUB to take care of comparison and lookup, etc. Same goes for a solution based on storing the tag code as a 20 char string. Ideas to a more elegant solution is appreciated.
Erlend
I am using the RFID reader object by Brandon Nimon, and the RFID hardware from Parallax.
Erlend
I am using the RFID reader object by Brandon Nimon, and the RFID hardware from Parallax.
Comments
Spin has enough string support for simple moves and compares, and a fixed stringsize makes this really easy:
Andy
How can this be? One of my cards reads: 48 49 48 48 65 54 52 56 66 68. Can't see how this could fit into 10x 4 bit?
Ariba,
I had forgotten the 'native' strcomp. This looks good, and based on the above code, all the bytes are printable characters. But it would be better to think of the tag not as a string as such, but an array of bytes, and then it does not matter if they are printable or not, right? No reason to behave and only use strcomp for real strings.
I will define thus: DAT refTag1 BYTE 48, 49, 48, 48, 65, 54, 52, 56, 66, 68 -, and next, same way for refTag2, ...etc. After that I can deal with refTag as a string, right?
And I will modify the RFID reader object to write the 10 codes into the (global) tag[] by means of passing @tag to it, right?
My Main code will have a CASE block where the action depends on which of the refTag matches the value of tag. Am I on the right track?
You can define the tag numbers in a DAT section with the ASCII charcters in quotes: But you can also write 10 decimal values as in your example, but you need to add a zero as 11th byte.
I don't know how you get the number from the RFID reader. If you read it serially byte per byte then this may work: If you have the tag characters in the @tag string then you can serach it in the refTags like that: Andy
@kuroneko
I didn't realise the 48 49 48 ... were ASCII codes for the character form of the hex code, I thought they were numerals. Sorry. that's why I could not understand how 4 bits could do 48 49 48 etc. I guess I should have recognized it from the familiar number range. I'm learning : ).
@Ariba
Thanks for the guideline. Knowing they are all ASCII codes makes it so much easier. I'm on my wings now.
Erlend
Is there a problem with using the built in functionality?
You could build a list in RAM or as part of a DAT that is formatted list this:
I could alter the software to allow tags to be zero-terminated strings and just add a parameter in the start method to reflect the option.
Bobb,
I was debugging my setup with a RFID reader written in spin, but now it is up and running, and I understand what is going on, and it is time to move over to a permanent solution. I want to use your object for that. I've seen it has lots of functionality, and I have only a few thoughts; I think it is 'cleaner' when the object is not specific to one application, so I would like to avoid putting DAT data in there. Better to pass a pointer to DAT stuff instead. And, my application is not only looking to check if the card has a valid code, but must also find which card it is. I thought I would try to implement this as an additional functionality in the object, but PASM is hard and slow for me to work on.
What I would ideally want is:
Define the ok tags in DAT in the Main code, pass a pointer to the RFID object
Have the RFID reader continously running in a separate cog, where it reads tag id, checks which of the ok tags is matching, and then writes this to a global valueID variable (an index only, i.e. 1, 2, 3,..) in Main. After 10 sec (or a parameter time) it resets the valueID by writing a -1 to it. This way it will only contain the id of a recent card swipe, and not hold on to old ones.
This would allow me - in the Main code - to anywhere in my algorithms check "who is here", by looking at valueID. No more fuzz.
I would very much appreciate help to do this!
Erlend
Using the tagloc parameter, you supply the object with an address (a "table") that has the valid tags run end-to-end as 10-byte arrays (no zero termination/delimitation).
With the tagcount parameter, you tell the object how many tags are in that table.
When a tag is read, the supplied output address contains (1) if the tag is in the supplied table, and (2) if the tag is not (or (3) if there has been a wrong tag and a correct tag scanned since the last time the value was cleared). These values are not cleared by the object, you'll have to do it in the parent object.
At the same time, the rec_tag address is populated with the 10-byte string of the tag's value, and the tag_ret address gets the tag's index (that's why -- in my tags table example above -- I have the tags numbered).
None of the return values are cleared by the object, they do get overwritten when a new tag is read though. That's all up to the parent object to detect and control that.
Thanks. I suspected tag_ret could be what I was looking for. Now all I have to sort out is the automatic clearing of an old card tag value. I don't like to have this kind of housekeeping in my Main, though. If you don't mind too much I will tweak the code to take one more parameter - auto_clear - and if >0 it will clear tag_ret to -1 after auto_clear seconds.
I am doing it this way for all the inputs in my project. Inputs are read, converted, and digital ones timetagged - outside the Main cog. Results are written back to global variables that the Main code can use without worrying about houskeeping.
Erlend
Just FYI, when you dig into it, the PASM COG just sits at a WAITPEQ Dat_p, Dat_p until a tag is read, so you would have to replace that with a loop that jumps out if the Dat_p goes high, then have a timer for when the last tag was read, and clears the values based on that. It shouldn't be too difficult.
And add this right after BigLoop:
Just to make sure I've got it (I never did get a grip on assembly, nor on Forth), here's the stiched together code:
Must admit I cannot follow it more than I can understand German, i.e. some. Where is tagno (:= tag_retAddr) given a value? And where&how is waitprd defined? And I cannot find tags (DAT) anywhere in the code.
Sorry for being PAStupidM.
Erlend
Though they help you appreciate what the high-level languages you are used to working with actually do behind the scenes (almost all high-level languages break down to languages like PASM -- SPIN is no exception).
It looks like you have the program how I described, but I am unsure it will work. I may be able to test it later today or tomorrow, and get it to work if it isn't (let me know).
Just to answer your questions:
tagnoAddr is assigned an address in SPIN, and the COG gets that address during initialization on line RDWORD tagnoAddr, p1. Then the value is populated on this line: WRWORD p1, tagnoAddr where p1 is the assigned value, and is calculated by the few lines before it. For WRWORD, the first value (the source) is the value written, and the second value (the destination) is the HUB address to write it to.
WAITPEQ, or more importantly the Dat_p (a 32-bit mask where specific bits are assigned to instruct it to wait for specific pins -- i.e. if you wait for pin 3 to go high, Dat_p has a value of %...000_0000_1000) register is assigned all the way back up in the SPIN code that starts the COG. You can store values to the DAT section in SPIN (which is a HUB address), then when the cog is started, those values are loaded into the COG as a local variable (changing the value in the PASM cog won't affect the HUB value). The mask is assigned using the |< operator.
The tags address is passed by assigning the tagcheckAddr variable. And as with tagnoAddr, the address is gathered when the COG starts on this line: RDWORD TagAddr, p1. Though, just the address is passed, the values are read from the HUB memory each time a tag is read using this line: RDBYTE tagsbyte, tagsAddr. This means the tags could actually be changed after the COG has started and the new tags would then be compared.
Erlend
I have had some errant RFID reads from due to interference or the card being on the edge of reception, so this will help (I'll be adding this and the debounce parameter to a soon to be released update on the OBEX).
Thanks a thousand. I'll sit down with this code and the textbook PASMchapter until I understand it all. But, I need to learn to walk before I fly, and I am still in the learning process wrt the COG mechanism and how it relates to the Main code. My background is from Pascal, some C, and digital Control System programming - all quite high level abstract languages - and a looong time ago. With ideas, logical flow, and program control I am fine, but the stuff specific to prop must be learned - which is part of the fun for sure. For me the prop's cog functionality is perfect because it allows me to put all the hard labor housekeeping code into 'independent lives', and concentrate on implementing my ideas in the Main code, keeping it uncluttered.
A bit off-topic, I guess.
Erlend