Vechten met de kattenchipDit is een verslag van mijn pogingen zelf een op de Arduino gebaseerde chip-detector te bouwen voor de chips die in mijn katten zijn geïmplanteerd. En om maar meteen met de deur in huis te vallen: dat valt niet mee.Ik ben een type dat eerder leert van proberen dan van vlijtig studeren en dan is de eerste voorwaarde dat je zelf een chip hebt om mee te experimenteren, want mijn katten zijn niet van het soort dat rustig blijft zitten als je met allerlei apparaten op ze af komt. Zou ik ook niet doen. Als je een automatisch kattenluik koopt, van Sureflap bijvoorbeeld, dan krijg je daar een paar penningen bij die je aan de halsband van de kat kunt hangen. Jammer genoeg werken die penningen op een andere golflengte en een andere code dan de geïmplanteerde chips en zijn dus waardeloos voor de experimenten. Dus wandelde ik bij de plaatselijke dierenarts naar binnen en vroeg of zij zo'n implantatie-chip voor me had. Ze vertelde me echter dat die dingen nogal streng geregistreerd worden en dat ze er niet zomaar eentje kon meegeven. Misschien... misschien..., als er ooit eentje bij het implanteren op de grond viel... Dat was ongeveer een jaar geleden. En toen werd ik een paar weken geleden opeens gebeld: ja, er was er eentje over en die mocht ik op komen halen! Dank je wel, dierenartsen en medewerkers van de Eenhoorn in Panningen!
![]() het eerste wat ik deed: de kleine kattenchip in een stukje plakband vouwen en aan een sleutelhanger vastmaken tegen het kwijtraken.
Op jacht naar de dataHet leuke van Arduino is dat een heleboel mysterieuze dingen die je vroeger met soldeerbouten, transistors en condensators op moest lossen, nu beschikbaar zijn als modules die met een eenvoudige programmeertaal aan te spreken zijn. Neem bijvoorbeeld het bouwen van een thermostaat die onder de 20 graden de verwarming laat aanslaan. Vroeger was dat een hoop getrut, nu kun je een programma schrijven alsif (temperature<20) then zet_verwarming_aan();Okee, okee, programmeren is misschien ook niet ieders roeping en het kan nog knap lastig worden, maar het is een stuk eenvoudiger dan solderen. En dank zij de grote aantallen hobbyisten en professionals die met Arduinos in de weer ziijn, kun je voor de gekste dingen zulke modules kopen: temperatuur, bewegingsmelders, licht, geluid, noem maar op... Geen van die dingen kost meer dan een paar Euro en een Arduino-kloon is ook beneden te tien Euro te krijgen. Een dure hobby is het dus niet. ...Alle soorten modules zijn dus te krijgen, behalve onze kattenchips... Kattenchips (laten we ze zo maar noemen) zijn zogenaamde RFID chips. RFID, ofwel Radio-Frequency IDentification, dat is de technologie om met een chipkaart deuren te openen, de technologie die bij de uitgang piept als je iets vergeet af te rekenen, de technologie voor een heleboel dingen. In principe heeft iedere RFID chip zijn eigen unieke code. Bij de eenvoudiger types is dat gewoon een nummer. Bij zaken als het identificeren van dieren is het echter een stuk ingewikkelder. Met name in de USA zijn er een dozijn verschillende manieren om die code te interpreteren en ook in andere werelddelen is het een bonte verzameling standaarden. In Europa hebben we ons gelukkig op een vaste standaard vastgelegd en dat is de zogenaamde ISO-11784/5. Op de volgende Wikipedia pagina is die standaard tot in details uitgelegd. Maar dat het een standaard is, maakt het niet gemakkelijker om hem uit te lezen. Het irritante is dat er zoals ik al zei voor de zotste dingen Arduino modules en voorbeeldprogrammas zijn, maar voor onze kattenchip is op het hele internet niets, maar dan ook helemaal niets te vinden. Ja, roependen in de woestijn op allerlei forums die zo'n ding willen bouwen zijn er genoeg, maar oplossingen, ho maar! Ook RFID modules zijn in overvloed te koop, maar voordat je iets vindt dat zelfs qua techniek compatibel is heb je het hele project al bijna opgegeven. De hardwareDe goedkoopste RFID systemen voor de Arduino kosten een of twee Euro en bestaan uit een module en een paar blanco kaarten en sleutelhangers. Werkt prima, maar niet voor kattenchips. Dat heeft te maken met de frequentie. En 13.56 MHz komt helaas niet eens in de buurt.De volgende groep is die van 125 Khz zoals de RDM600 en aanverwante modules. Iets duurder en veelbelovend, vooral omdat sommige dierenchips daar inderdaad mee kunnen worden gelezen. Helaas. Niet die van mijn kat. Een waarschuwing is hier op zijn plaats: sommige van die modules beweren inderdaad de ISO standaard op 125 Khz te kunnen lezen, maar voorlopig is me dat niet gelukt, waarschijnlijk omdat de chips in de katten echt op 134 Khz zijn ingesteld. En dan tenslotte de frequentie die we moeten hebben: 135 Khz. Met 30 Euro behoorlijk aan de prijs, voor een Arduino module tenminste, vooral als je niet weet of het ook zal werken, maar vooruit. Ik heb me uit China een "134.2K Long distance RFID AGV Animal Tag Reader Module TTL Interface ISO11784/85 FDX-B" laten komen, compleet met antenne en 'oormerk' om mee te spelen. En inderdaad: een blauw lichtje vertelt me dat de kattenchip nu in ieder geval wordt herkend en ik kan data op de Arduino uitlezen. Hoera!
![]() Testopstelling. Antenne, FDX-lezer en Arduino. Op de voorgrond de kattenchip aan de sleutelhanger en het meegeleverde oormerk.
De softwareSo far, so good. Maar data uitlezen wil nog niet zeggen dat ik het 15-cijferige, unieke nummer van mijn katten eruit kan opmaken.Je zou hopen dat de informatie op die Wiki-pagina daar inzicht in zou geven. maar de gegevens zijn eerst bitwise gecodeerd, en de Arduino geeft bytes van acht bits. De module verzorgt de vertaling van die bitwise codering naar bytes, dus dat is geen probleem. Als je dan weet dat een tag begint met een byte met een waarde van 2 en eindigt met een byte van 3 dan heb je ook het datapakketje te pakken: 8003A55E030120010000000000綬� (testchip 1) 3181F54B404830110000000000綬� (testchip 2)Op dit ogenblik kunnen we dus wel een uniek nummer uit de chip lezen en de module gebruiken om onze twee katten te herkennen. Voerbakjes, kattenluiken en wat dies meer zij binnen mijn eigen kring zijn dus in feite geregeld. Alleen zou het een stuk eleganter zijn als we de code konden kraken, zodat hetzelfde nummer wordt teruggegeven als op de papieren staat, het land herkend kan worden, de checksum klopt, zodat we foute lezingen kunnen herkennen enzo. Nu wordt het dus echt moeilijk. Verder snuffelen op het internet leert ons dat de cijfertjes en lettertjes die ik heb uitgelezen hexadecimale code bevatten. Voor hackers van de oude stempel zoals ik is dat een tamelijk eenvoudige code. maar nu hebben we dus een extra vertaalslag nodig. Het programma dat we gaan schrijven doet dus het volgende:
#include <SoftwareSerial.h> #include "BigNumber.h" #define LENGTH 35 char message[LENGTH]; char buff[LENGTH]; unsigned long lastSignal = 0; bool transmission = false; byte state = 1; int pos; SoftwareSerial Chiplezer = SoftwareSerial(4,5); BigNumber num = 1; // ---------------------- setup --------------------- void setup() { Serial.begin(115200); Chiplezer.begin(9600); BigNumber::begin (); // initialize library Serial.println("Start"); lastSignal = millis(); } //------------------------- main --------------------- void loop() { switch (state) { case 1: { if (Chiplezer.available() > 0) { lastSignal = millis(); pos = 0; state = 2; } break; } case 2: { if (Chiplezer.available() > 0 && pos < LENGTH) { lastSignal = millis(); message[pos] = Chiplezer.read(); pos++; } if (millis() - lastSignal > 100) state = 3; if (pos >= LENGTH) { delay(300); state = 1; } } break; case 3: { byte check = message[1]; for (int i = 2; i < 27; i++) { check = check ^ message[i]; } if (check == message[27]) { BigNumber id; BigNumber countryNbr; id=hexInDec(message, 1, 10); countryNbr=hexInDec(message, 11, 4); Serial.print("CardNumber="); Serial.println(id); Serial.print("Country="); Serial.println(countryNbr); state = 4; } break; } case 4: { delay(2000); state = 1; break; } } //switch } // ----------------------------------------------------------- BigNumber hexInDec(char message[], int beg , int len) { BigNumber mult = 1; BigNumber nbr = 0; BigNumber b=0; BigNumber bb=0; int nextInt; for (int i = beg; i < beg + len; i++) { // Serial.print(i);Serial.print("\t"); Serial.print(message[i]); // Serial.print("\t");Serial.println(nbr); nextInt = message[i]; if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9); if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15); if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15); nextInt = constrain(nextInt, 0, 15); bb=nextInt; b=mult * bb; nbr += b; mult *= 16; } return nbr; } |