everhack Stuff I've been messing with, or just thinking about.

5Dec/110

AVR RFID Reader, part 6 – Successful Reads!

Finally!

Even after reading up on Manchester encoding from a number of sources, and reading Beth Scott's reader code & comments, I still just couldn't quite understand how to do the decoding.

My biggest problem with the reader code from part 5 was that I was only detecting the lengths of the LOW periods, but not the HIGH periods, so I was only getting half the bits.

Secondly, after a hint from a RFID reader IC datasheet (http://www.125khz-rfid-reader.com/how-the-driver-works/how-the-driver-functions), I realized I also didn't have to muck about with detecting both rising and falling edges as various other literature indicated.

"Using a clever detection method the driver only needs to detect each rising edge to determine the preceeding bit states, reducing the interrupt burden on the main application. Also only detecting each rising edge removes issues of dealing with non perfect high and low widths within each cycle – being radio they are often not perfectly 50/50, but the overall bit frequency will be relatively accurate."

At this point, I was logging the timer value for each rising edge to the serial port so I can get a look at what exactly was being received. Just as a picture tells a thousand words this text file pointed me towards what to do next.

Here's a piece of the log where I've manually annotated the lows and highs to indicate short or long lows and highs. (0 is a short low, 00 is a long low, 000 is a "triple low," which occurs only in the tag header. 1s indicate the length of the highs similarly).

Basically, the lows are easy, they're always around 900-1000 'ticks' for a short, and around 1500-1600 for a long. A triple long low is around 2500.

The highs are a little trickier. Since the carrier is pulsed, we get a rising edge every time the carriers rises above the threshold value. These show up in the log as multiple entries around 150 ticks in duration. A "short high" gives about 4, a "long high" is about 8, and a "triple long high" (seen right after the leading 000) gives about 14 of them.

180:2585 000
181:152
182:153
183:152
184:153
185:152
186:153
187:152
188:153
189:151
190:154
191:152
192:153
193:152
194:153 111
195:919 0
196:153
197:153
198:153
199:152 1
200:1065 0
201:152
202:153
203:152
204:154 1
...
235:1671 00

One additional tricky part was figuring how to detect the end of a "high" period, since the event trigger only gives rising edges, meaning I don't know the High is done before I reach the end of the Low period immediately after. To solve this, I added an Overflow interrupt handler to my input capture timer, set to a length of 200. This ensures that the overflow interrupt will always fire as soon as "no more rising edges" are detected in a sequence.

A problem I'd been having all along at home had been viewing the received signal on my analog non-storage oscilloscope due to the inability to "pause" the display, or accurately trigger on the beginning of the tag signal.

However, this was solved once I was accurately able to detect the "3T low 3T high" tag header in my code. I enabled a second debug pin and toggle it on and off each time I detect that sequence. This now finally allows me to accurately view the received manchester bits on my scope.

I still didn't quite get the idea of reconstructing the data clock, but after finding this forum comment and having a long chat with Danny at the hackerspace, I finally had my decoding approach:

http://www.sonsivri.to/forum/index.php?topic=20972.0

Basically, two things you need to do are to:
A) accurately determine where the message begins. Looking at the data, I realized there was a repeating 3T low followed by a 3T high. Since Manchester encoding forbids any high or low longer than 2T, this was clearly our header signal. Thus, the first rising edge after our 3T high marks the beginning of the actual data stream.
B) decode the 0s and 1s into the original data bits. In my case, the expanded representation of the "shorts" as 1 digit, and "longs" as two digits effectively reconstructs our clock signal, and lets us decode the stream by simply interpreting every received "01" as a data "0", and every "10" as a data "1".

Finally once you have the actual data bits, you have to convert them back to the card values, which for HID means the first 20 bits contain the "Manufacturer Code" (always constant), then 8 bits of "site code", and finally 16 bits of 'card code' and a trailing parity bit.

This is where the code stands right now. I can read both my badges pretty reliably, but the threshold voltage is still manually adjusted which limits the read distance to a very narrow range.

Next steps, I want to:
- implement a dynamic threshold voltage via PWM,
- display the decoded digits via LCD, or at least flash a LED on successful read.
- start spoofing the digits
- design a PCB and begin to package this thing

Filed under: Uncategorized No Comments
21Oct/112

RFID reader, part 5 – 1’s and 0’s, but what do they mean?

100000001000000001000110001100111011

 

0000000000000000

 

100011 001100111011000000 1000000000100 11000110011101100000001000000000100011000110011101100000001000000000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

10001100 01100111 01100000 00100000 00001000 11000110 01110110 00000010 00000000 10001100 01100111 01100000 00100000 0000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

100011000110011101100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

100011000110011 0110000000100000000 1000110001 00111011000000 1000000000100011000110011101100000001000000001

00011000110011 0110000000100000000 1000110011 00111011000000 10000000001 0011000110011 0110000000100000000

100011000100111 011000000010000000001000110011 0011101100000001000000000100011000110011101100000001000000000

100011000100111 01100000001000000000100011000110011101100000001000000000100011000110011101100000001000000000

 

 

1000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000100011001110110000000100000000010001100011001110110000000100000000100110001100111011000000100000000010001100011001111100000001000000001000110001101110110000001000000000100010001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001000110001100111011000000010000000001

This is what my reader is writing to the serial port now.

As before, the analog comparator is connected between the analog threshold voltage and the antenna signal.

The input capture interrupt function now toggles the LED and debug pins, and writes a 0 or 1 to the serial port, if the time between the last falling and rising edge from the analog comparator output occurred in one of two ranges of time. i.e, 250-1100 ticks right now for a "short", and 1101-3499 ticks for a "long".

Based on my previous reading I think I have to actually be timing how long since the last rising edge* - the catch is that the "high part" of the signal is actually constantly toggling at 250khz (every rising and falling analog comparator edge), so I have to be able to ignore the very short-duration low periods to properly time the "high part". Maybe if I just check the low period duration and don't reset the timer if it's too short, effectively filtering out the higher frequency component of the signal.

I've had a great time trying to view the signal on my analog scope. I connected one probe to the raw, rectified, a/c coupled antenna signal,  and the other probe to the debug pin on the Teensy.

Using the coarse and fine timebase controls on the scope, triggering on the debug pin, I can zoom out far enough to see the entire signal from the card. Since the signal is constantly repeating, I can get a static and unique "image" of each card's bitstream.

Playing with the potentiometer on the threshold voltage, I discovered that the ideal threshold voltage is directly related to how far away the card is. The further the card, the lower the threshold voltage.

The "depth of field" of the "best" threshold value is surprisingly low as well. Holding the card at a constant distance from the reader, I turn the knob back and forth, watching as the bits in the "bit picture" on the scope eerily flicker in and out of view, locked horizontally, but flickering more and less depending on the error rate.

Sorry, I thought I took a cellphone picture of it but I must have not hit "save" before closing the phone. I hate when I do that.

The best, most rock-solid signal is obtained (not surprisingly) when the card is laying right on the wood of the reader coil. At the best threshold setting, it reads the card only up to about a half inch from the wood.

However, by re-tuning the threshold voltage for various card-to-reader distances, I can manage to successfully lock onto the signal from up to maybe 4 inches away.

Clearly, a dynamic threshold voltage tuner seems like a worthwhile upgrade for maximum read-range flexibility.

Something else interesting that I noticed, the cards are nearly "one-sided." That is, when I flip the card over, I can only barely see the signal, probably not well enough to actually read it. My work badge is a different type of HID card and doesn't seem to have that behavior. I'll have to see if the reader on the hackerspace door does the same thing.

Back to the bits. I was really eager to see what my serial bitstream looked like, if it was repeating, the length, and so on.

Opening the log file in my text editor, I played with trying to line up sections of the text to find a repeating pattern, and its length.

Sure enough, I discovered one on each of my two hackerspace cards! But, oddly enough, the number of bits doesn't seem to match up with the expected number.

I've realized that I don't really know what encoding is being used.

From Scanlime's blog, I read that "... Cesar Fernandez described the HID card format ... The 45-bit code"... ; but in my text file, the two visually identical cards appear to give slightly different-length repeating bitstreams. (36 & 38 bits)

00000000 10001100011010000100100000001
00000000010001100011010000100100000001
00000000 10001100011010000100100000001
00000000010001100011010000100100000001
00000000 1000110001101000 100100000001
00000000 10001100011010000100100000001
0000000001000110001101000 100100000001
00000000 10001100011010000100100000001
0000000001000110001101000 100100000001
0000000001000110001101000 100100000001
00000000010001100011010000100100000001
00000000 1000110001101000 100100000001
00000000010001100011010000100100000001

Lining up the repeating rows, and adding spaces where there were missing bits, I realized that the errors nearly all occur in the same places in the signal, and so I must have a slight misalignment in my time window lengths between 0's and 1's. I'll probably have to increase the timer1 prescaler from /8 to /1 to increase the resolution my cycle counter, and create a bigger difference in values between "short" vs "long".

If the card is using around 4 "low antenna cycles" to mean short, and around 8 to mean long, I had expected that a /8 timer would give me plenty of resolution (1 timer tick per 8 16mhz clock cycles, 16 per 125khz antenna cycle, 64 timer ticks per "4 low antenna cycle" 0, and 128 ticks per 1.

However, in practice, my window sizes are currently set at 4 and 10 times larger than this, based on just experimentation and observation of the output. I think what this means is that the encoding is not quite what I'm picking up, and I'm actually reliably missing 9 or 10 bits of the true signal.

Here's my latest code.


#include <avr/interrupt.h>
#include <avr/io.h>

#define CARRIERPOS_PIN 10
#define CARRIERPOS_REG PORTC6
#define CARRIERNEG_PIN 9
#define CARRIERPOS_REG PORTC7

#define LED_PIN 11
#define LED_PORT PORTD
#define LED_REG PORTD6

// AIN0 = PB6 = detect
// ADC0 = PF0 = threshold

#define DEBUG_PORT PORTB
#define DEBUG_REG PORTB3

#define LED_ON() (LED_PORT |= _BV(LED_REG))
#define LED_OFF() (LED_PORT &= ~_BV(LED_REG))
#define TOGGLE_LED() (LED_PORT ^= _BV(LED_REG))

#define DEBUG_ON() (DEBUG_PORT |= _BV(DEBUG_REG))
#define DEBUG_OFF() (DEBUG_PORT &= ~_BV(DEBUG_REG))
#define TOGGLE_DEBUG() (PORTB ^= _BV(DEBUG_REG))

void initTimer4()
{
// pwm with dead time generator
TCCR4A = _BV(PWM4A) | _BV(COM4A0);
// no prescaler (CK/1)
TCCR4B = _BV(CS40);
// phase & frequency correct pwm
TCCR4D = _BV(WGM40);
TCCR4E = _BV(ENHC4);

//duty cycle for oscillator toggle
OCR4A = 64;
// 125k would be no prescaler, period = 128
OCR4C = 64;
}

void initTimer1()
{

TCCR1A = 0; // ctc mode 4
TCCR1B |= _BV(WGM12); // CTC mode 4
//TCCR1B &= ~_BV(ICNC1) | ~_BV(ICES1); // edge detect falling, disable noise canceler
TCCR1B &= ~_BV(ICES1);
TCCR1B |= _BV(ICNC1);

OCR1A = 255; // TOP // 64 is about 8 cycles
TCNT1 = 0;

TCCR1B = _BV(CS11); // PS = 1
}

void initAnalogComparator()
{

// AIN0 = PE6 = detect
// ADC0 = PF0 = threshold

// input capture timer1
//ACSR = _BV(ACIC);

// disable adc
ADCSRA &= ~_BV(ADEN);
// enable analog comparator mux
ADCSRB |= _BV(ACME);
// clear analog comparator interrupt flag
ACSR |= _BV(ACI);

ACSR &= ~_BV(ACIS1) & ~_BV(ACIS0) & ~_BV(ACBG);
// enable analog comparator input capture on output toggle, AIN0 connected to AC+
ACSR |= _BV(ACIC);

TIMSK1 |= _BV(ICIE1);

// ADC0 connected to AC- input
ADMUX &= ~_BV(MUX2) & ~_BV(MUX1) & ~_BV(MUX0);

// disable digital input buffer
DIDR1 |= _BV(AIN0D);

// input ddr regs, enable pull-up resistors
DDRE &= ~_BV(DDE6);
PINE &= ~_BV(PORTE6);
DDRF &= ~_BV(DDF0);
PINF &= ~_BV(PORTF0);
}

ISR(TIMER1_CAPT_vect)
{
uint16_t timer1val = ICR1;

if (bit_is_set(ACSR, ACO))
{
// change edge to descending
TCCR1B &= ~_BV(ICES1);
}
else
{
// long for 1, short for 0
if (timer1val > 1100 && timer1val 250)
{
LED_ON();
DEBUG_ON();
LED_OFF();
DEBUG_OFF();
Serial.print("0");
}
else
{
LED_OFF();
DEBUG_OFF();
}
// if the signal was below threshold for longer than 8 125khz cycles, it's a 1
// change edge to rising
TCCR1B |= _BV(ICES1);
}

// the pulse timer
TCNT1 = 0;
// clear the interrupt flag after changing edge
TIFR1 |= _BV(ICF1);

}

void setup()
{
cli();

initTimer4();
initTimer1();
initAnalogComparator();

// debug pin out / toggle on analog comparator isr & timer0
DDRB |= _BV(PORTB3) | _BV(PORTB7);
PINB |= _BV(PINB7) | _BV(PINB7);

// 125khz carrier oscillator pins 8&9, OC4A/~OC4A
pinMode(CARRIERPOS_PIN, OUTPUT);
pinMode(CARRIERNEG_PIN, OUTPUT);
// led
pinMode(LED_PIN, OUTPUT);
sei();

Serial.begin(57600);
}

void loop()
{
}

Filed under: Uncategorized 2 Comments
18Oct/110

RFID Reader, part 4, detecting bits! (well, 1’s at least)

After wrestling and backing up a bit and rewriting a good part of it, I finally got the analog comparator and input capture scheme working.

Timer1 counts continuously while the antenna signal is being generated.

The analog comparator is configured to trigger the Timer 1 Input Capture interrupt whenever the signal detector voltage crosses an analog threshold voltage.

Whenever there is a rising edge (input signal rises above threshold), I check to see if timer1 has exceeded a certain value or not. If there's been no rising edge within a certain length of time, we either have a "1" bit, OR we have no card at all.

"No card" is handled by only allowing a minimum AND maximum "low time" (I.e. 1's can only be SO long).

The picture below shows the modulated antenna signal in blue, and the detected 1-bits in yellow. Now I'm finally able to get started on actually storing 0's and 1's.

 

 

Since the input capture interrupt is called twice on every cycle, we need to know if it has been longer than about 5 or 6 complete cycles since the last FALLING edge.

Looking at the Microchip spec now, I realize I didn't QUITE implement it properly.

According to this picture, I should actually be timing the duration of consecutive cycles above AND below the threshold. I was only timing the length of the LOW portion. I'm not certain whether it really matters or not, time will tell.

 

Anyhow, this should be "good enough" for now, the next thing I'll work on is actually storing the consecutive bits and looking for a header of some kind to determine the beginning of the string. I also planned to implement some error correction by requiring several consecutive matching reads before deciding that we've actually detected the signal correctly and completely.

 

 

 

Filed under: Uncategorized No Comments
6Oct/113

RFID Reader, part 3

After a 6-week hiatus, I finally picked the RFID reader project back up. My ultimate goals have evolved a long way, but I'll reveal those later.

For now, I'm still working on the part where I need to detect the incoming signal.

Using the Teensy 2.0:

-I'm using timer4 in phase & frequency correct mode, clk/1 prescaler, with a 128 cycle period. Using the dead-band generator at 50% duty cycle, I'm getting a differential signal output to pins OC4A and ~OC4A, and am using this to drive my antenna.

-Like everyone else before me, I pass the antenna signal through a signal diode, high-pass-filter and decoupling capacitor.

The last thing I did before I stopped working on this previously, was to connect the signal to the ADC and sample as fast as possible, and light the LED if the voltage was above a hardcoded threshold value (about 0.5v I think).

Although this does successfully "work", and starts to light up when a card is within about 3" of the reader, it also has lots of false positives and lights up when you just mess with the antenna in any way.

I constantly go back to Beth Scott's  "simplest RFID reader?" forum post, as well as the Microchip 125khz RFID system design guide and AVR 32U4 datasheet for ideas and inspiration.

My latest new attempt is using an analog threshold voltage, the analog comparator, and the timer1 input capture interrupt & edge detector. The idea is, timer1 constantly counts from 0 to 0xffff with prescaler set to CLK/64 (250khz).  The TOP value could be adjusted to match the bit length of the RFID protocol to be read (*2 since we're running at double the frequency).

Reading the datasheet, I decided to try connecting AIN+ to the threshold voltage, and AIN- to the antenna signal, and enable the Timer1 Input capture feature. I set the edge detector to trigger the input capture interrupt on a Falling edge, which I figured would result when the AIN- voltage drops below the AIN+ voltage.

The input capture interrupt starts with the current value of Timer1 in the 16-bit input capture register. I figure all I need to do is store the value of the timer each time the interrupt fires. A string of 1's or other "lead-in" for an actual card value will help me determine the "beginning" or "0 offset" value of timer1.

For now, I just am trying to still flash the light whenever the interrupt fires, but my first attempt at 1am didn't result in any visible result. As is always the case, I'm sure I've just missed some essential register setting and will need to review all the init code against the datasheet again, as well as trying to get my bus pirate logic analyzer mode working again so I can get a better debug view at the pin level.

Just for grins here's my code at the moment.

#include <avr/interrupt.h>
#include <avr/io.h>

volatile uint16_t pdval;

#define CARRIERPOS_PIN 10
#define CARRIERPOS_REG PORTC6
#define CARRIERNEG_PIN 9
#define CARRIERPOS_REG PORTC7

#define LED_PIN 11
#define LED_PORT PORTD
#define LED_REG PORTD6

#define THRESHOLD_INPUT_PIN  24
#define THRESHOLD_INPUT_REG  AIN0     // aka PE6
#define THRESHOLD_INPUT_PORT PORTE

#define ANTENNA_INPUT_PIN    20
#define ANTENNA_INPUT_REG    PF1      // goes to AIN- via ADMUX
#define ANTENNA_INPUT_PORT   PORTF

#define LED_ON() (LED_PORT |= _BV(LED_REG))
#define LED_OFF() (LED_PORT &= ~_BV(LED_REG))
// Inline assembly: The nop = do nothing for one clock cycle.
#define nop()  __asm__ __volatile__("nop")

/**
 Timer4 is used in Phase/Frequency correct mode to generate a 125khz differential output
 signal used to stimulate the reader antenna.
*/
void initTimer4()
{
 // pwm with dead time generator
 TCCR4A = _BV(PWM4A) | _BV(COM4A0);
 // no prescaler (CK/1)
 TCCR4B =  _BV(CS40);
 // phase & frequency correct pwm
 TCCR4D = _BV(WGM40);
 TCCR4E = _BV(ENHC4);

 //duty cycle for oscillator toggle
 OCR4A = 64;
 // 125k would be no prescaler, period = 128
 OCR4C = 64;
}

/**
we'll try to use the input capture feature of Timer1 to determine -when- each 1 occurred.
We'll be listening for 1's, and as soon as we recognize a start sequence, we'll reset Timer1 to 0.
It will increment at 125khz along with Timer4 which is generating the differential antenna output signal.

Each time the ADC interrupt fires to indicate the antenna signal on AIN- exceeding the threshold voltage
on AIN+, we will trigger the input capture and take note of the value of Timer1. This will give us our
the cycle number in which it occurred relative to the start sequence. This would be a Falling Output Edge (I think)
since AIN- is exceeding AIN+ when the input signal rises above the threshold value.
*/

void initTimer1()
{

 // CTC mode 4; TOP = OCR1A, enable input capture noise canceler, 4 cycle delay
 // input capture set to falling edge select (0), CLK/1 prescaler
 TCCR1B = (1<<ICNC1) | (1<<WGM12) | (1<<CS10);
 // 65535 cycles to overflow at CLK/1 prescaler, maximum possible bit offset
 OCR1A = 0xFFFF;
 // enable input capture interrupt on analog comparator
 TIMSK1 |= (1<<ICIE1);
 // clear the input capture flag after enabling interrupts to avoid a false interrupt call
 TIFR1 |= (1<<ICF1);
}

void initAnalogComparator()
{
 // turn off ADEN bit to disable ADC
 ADCSRA &= (0<<ADEN);
 // connect ADC MUX to comparator AIN-
 ADCSRB |= (1<<ACME);
 // enable input capture function of Timer1. comparatur
 ACSR = (1<ACIC);
 // note: ICIE1 must be set to 1 in TIMSK1 to enable Timer1 Input Capture Interrupt
}

// each time the input capture interrupt is triggered, a falling edge was detected
// by the analog comparator. store the value in
ISR(TIMER1_CAPT_vect)
{
 // TODO: read ICR1L first, then ICR1H. to actually read the byte

 // for now we'll just turn the LED on for 8 cycles and then turn it back off.
 LED_ON();
 nop();
 nop();
 nop();
 nop();
 nop();
 nop();
 nop();
 nop();
 LED_OFF();
}

void setup()
{
 cli();

 // 125khz carrier oscillator pins 8&9, OC4A/~OC4A
 pinMode(CARRIERPOS_PIN, OUTPUT);
 pinMode(CARRIERNEG_PIN, OUTPUT);

 pinMode(ANTENNA_INPUT_PIN, INPUT);
 pinMode(THRESHOLD_INPUT_PIN, INPUT);

 // led
 pinMode(LED_PIN, OUTPUT);

 // timer4 generates the 125k differential carrier signal
 initTimer4();

 // timer1 counts to 65536 over and over again to timestamp the falling edges
 // it might be reset to 0 when we recognize a data header (series of 1s)...
 initTimer1();

 // input capture interrupt on Timer1 is triggered each time
 // the antenna signal exceeds the threshold value, giving a falling edge on the
 // comparator. for now, the LED is flashed every time the interrupt is triggered.
 initAnalogComparator();

 // enable global interrupts()
 sei();
}

void loop()
{
 while(1)
 {
 }
}
Filed under: Uncategorized 3 Comments
29Jul/110

RFID reader, part 2

After a few more days of hacking on this I'm a lot closer than I was.

At first, my avr-rfid antenna was oscillating strongly enough for the processor to run and start trying to send the code; but I couldn't see any induced signal in the reader (transmitter)'s antenna.

Finally I decided to pay attention to the schematic note "tune for 125khz resonance with C1" (http://scanlime.org/2008/08/simplest-rfid-reader/) and start playing with the reader coil windings. Previously I had been trying to tune the capacitor to the coil instead of fixing the capacitor at the spec (1nf) and tuning the coil to resonate properly.

I realized in the process I had only about 19 turns of wire in my coil instead of 30+ like are called for, and just not enough inductance. I ended up adding about 10 or 11 extra turns to around 30 like I should have done to start with, sanding off a little of the insulation every couple turns to recheck the oscillation.

I also dispensed with the single-layer wrapping of the coil wires, and instead cut "V" grooves about 1/4" down from the corners of the wood block. Now the wire is more of just a tight bundle instead of thin and wide like a ribbon.

Anyhow, after retuning my reader coil to the maximum voltage at 125khz with the 1nf capacitor, I hooked it all back up to the Teensy and VOILA I now see a pretty good variation in the reader coil when the card is near, meaning BITS!. Not only that, but i also see the same types of variation when I try my Hackerspace badge and my work badge, so I'm definitely getting closer!

I have not yet started implementing the detector code, which I'll have to port from Scanlime's original propeller assembly.. Looking at the 'scope signal I admit I still can't quite tell a 1 from a 0 though, only that there's SOME kind of deliberate modulation going on 🙂

In the photo attached, the upper (yellow) signal is the oscillation in the AVR-RFID tag. It looks to me like the first few and last few pulses are 1 cycle shorter than the ones in the middle.
 
The lower (blue) trace is the oscillation in the reader coil. When there's no tag near, the peaks go away and the signal is a nice flat 125khz sine wave. Once the tag gets close enough to run and start pulsing (1 inch or so), the wave pattern appears superimposed on it.

It looks to me like the valleys go just a little lower each time the tag pulse is wider....

The Teensy is working a little harder now, generating:

- 125khz differential 5v signal to oscillate the reader antenna

- pwm signal at 1000hz through a matched RC low pass filter to give a smooth but variable analog threshold voltage. This voltage is automatically tuned (in scanlime's implementation), along with the actual reader frequency for peak performance.

-still TODO: pulse counting on the detector circuit signal to start trying to detect some actual bits.

Filed under: Uncategorized No Comments
26Jul/112

AVR RFID reader part 1

I've been taking a break from Cricut coding to do some more work on the RFID stuff.

I decided that before I try to fix my (not working) AVR-RFID card, I should probably have my own reader. And why buy a reader when I really want to understand how it all works?

I'm following the spirit of the instructions posted at this forum by Scanlime (http://forums.parallax.com/showthread.php?105889-World-s-simplest-RFID-reader). I have two (real & working) sample cards of the right type to use as guinea pigs.

Instead of a propeller, I'm using a Teensy 2.0 AVR32U4 in "phase & frequency correct" pwm mode, using the dead time generator to create a 125khz differential signal between pins 11 & 12. Since 11 also happens to be the Teensy's LED pin, it also ends up pulsing brightly at 125khz.

The Teensy is a really great little device that I found on the hack shelf at the ATX Hackerspace, it's very compact with built-in high speed usb2, based on the ATMEGA32U4. (datasheet )

I have not yet implemented the detector circuit (that's next).

Following scanlime's directions, I wound 30 or so turns of #26 magnet wire around a spray painted wooden block" (the green wire from the Radio Shack magnet wire assortment); then a 1nf capacitor in series to the AVR's output pins, running the program below, and finally the 'scope probe up to the L/C junction to see what was up.

Good news, it was oscillating at 125khz, but the wave was not smooth, more rounded with some dips in the curve.

(no screenshot of the funky waveform, sorry)

I swapped out the capacitor a few times on my breadboard and eventually settled on 3.2nf giving the most "wavelike" curve I could manage (as seen above). 21.8v peak to peak Im pretty sure not 218.. The shape of the waveform looks to me like I may need just a little more capacitance to be quite right, but im hopeful that it wont really matter anyway.

I'll get an inductance meter reading on the reader antenna next Monday night just for curiosity sake.

(sorry no photo of the antenna yet)

Here is my current arduino code for the 125khz differential oscillator. There's not much there but those register settings are so crucial to getting it all working! I really need to learn how to do in-circuit debugging.

#include <avr/interrupt.h>
#include <avr/io.h>

void setup()
{
cli();
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);

// phase & frequency correct pwm mode 9

// PWM4A enables PWM mode based on comparator OCR4A
TCCR4C = _BV(PWM4D) | _BV(COM4D0);

// no prescaler
TCCR4B = _BV(CS40);
// enable dead time
TCCR4D = _BV(WGM40);

// 1024 prescaler
//TCCR1B = _BV(WGM13) | _BV(CS12) | _BV(CS10);

// 125k would be no prescaler, period = 128

OCR4C = 128;
OCR4D = 64;

}

void loop()
{
while(1)
{
delay(10);
}
}

sei();
}

Filed under: Uncategorized 2 Comments
21Jun/111

AVR HID RFID, take 1…

I've been slowly making progress building my own AVR RFID according to the instructions in this blog: http://scanlime.org/2011/05/duct-tape-rfid-tag-1/

After building the assembly code for HID tag type, I obtained a ATTiny85 and a handful of ATMega168s. I wanted to prototype first with the Tiny85s, but I have a cheap and plentiful source for the 168s and wanted to use those if possible: http://store.atxhackerspace.org/

Building the code for the ATMega168 turned out to be challenging, as I kept getting the same compiler error over and over and just couldn't fix it with any of the most common suggestions I found by googling:

 

C:AppDataLocalTemp/cc69IjcD.o: In function `loop': (.text+0x1d12): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'

This comment gave me the clue:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=764390

"... IOW, you are trying to RJMP to a location that
cannot be reached that way. .."

Researching rjmp vs jmp I found this thread..

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=21053&start=0

I changed the "rjmp loop" to "jmp loop" and it compiles now. Whether it works or not, we'll see 🙂

Back to the Tiny85, I got one and soldered it to a $2 Surfboard from Frys. This was my first experience hand soldering SMD components and it was pretty challenging but I managed to do a pretty good job. This was a little crazier by the fact that I had purchased 0203-sized (grain of sand) sized parts without thinking it through.

In the end, I was able to successfully solder the 2 caps in place on the surfboard. (Circled in red)

To make the antenna, I laboriously made a 66mm form out of cardboard, started winding it, and noticed a nearby beer can. Just for fun, I measured the beer can and it turned out to be... 66 mm! What are the odds?

I wound approximately 100 turns of 30 gauge magnet wire (or maybe 98... or 102... :), slipped it off the can, and stuck it to a clear packing tape backing. I soldered a 1x4 male 0.1 header strip flat against the contacts to connect the bus pirate probes up to for (very slow) programming purposes.

Ultimately, unfortunately my first test was a failure. Swiping the "badge" by the hackerspace and my office readers does not result in a beep. I'm certain the hackerspace badge is the right type. After looking closer, I realized I had attached the capacitor in series with the antenna rather than in parallel.

After fixing the error this morning (with a parts-bin capacitor roughly 100 times larger than the original :), the badge still does not garner a beep from the card reader.

 

I have to say, I'm pretty pleased with myself for just getting this far, it does look pretty neat even when it doesn't work.

Next steps: probe the antenna leads with the oscilloscope while trying to read the badge to check for resonance; also go back to the formula and try to recalculate the antenna length. Perhaps using a heavier-gauge wire or a slightly incorrect number of turns of wire resulted in a change in the resonant frequency? (I don't really know what I'm doing here yet, just learning as I go 🙂

I'll also probably also attempt to build my own reader at some point using these instructions here by the same author: http://forums.parallax.com/showthread.php?105889-World-s-simplest-RFID-reader

 

 

 

Filed under: Uncategorized 1 Comment
17Jun/110

Custom Catan Tiles

Just a little something I was playing with.. Email me (gossiphog@gmail.com) if you want the template.

Filed under: Uncategorized No Comments
17May/119

Secrets of the Cricut Carriage

I've been looking into and learning some secrets of the Cricut's cutting carriage.

First off, it appears to be a custom version of the US Cutter "Refine EcoCut" carriage. See for yourself: http://www.uscutter.com/Refine-EcoCut-Carriage_p_1669.html - the only difference I can see from the photo is there are TWO positions in the tool holder. The manual says the front hole is for the pen attachment, and the rear hole is for the blade attachment.

Regarding cutting pressure, both the Refine manual and in other places, the maximum pressure is claimed to be 400g (or 0.88 lbs). However, a colleague of mine actually tested it and got an indicated 0.4 lbs at +4 vdc. I'm planning to retest this on a running machine (after disconnecting the stepper motors!).

Finally, I originally believed this to be a solenoid, but after taking the carriage apart and checking voltage readings, it was discovered that it's actually a voice coil! Basically just like a speaker without a diaphragm. Normally, a -2vdc current biases the blade upwards, and switches to +4vdc (at maximum pressure) to press the blade downwards.

Filed under: Uncategorized 9 Comments
15Mar/110

Windows Galaxy screensaver

Here's something I did a long time ago, then re-implemented last fall for Java.. It's an updated version of the old "galaxy" screensaver mode from xlockmore, using the Sun "SaverBeans" API.

My version makes the star color change according to its speed, from dark red for slow, to orange, yellow, green, and blue for the fastest. It also makes the star sizes variable so they're not all just single pixels like in the original version. I find it pretty mesmerizing.

I had actually submitted these changes to xlockmore way back in 1997 but somehow they got removed at some point.

I've exported the Eclipse project so you can build it yourself if you want, there are a few settings that affect speed, number of stars, star size range, gravity constant and such, but I never bothered to implement a "settings" dialog so you need to recompile it to play with them. I just fiddled with it until I found something that worked well on my machine and left it alone after that.

If you run the "debug" target in the included ant script it will instead run the saver in a window.

If you just want to run it as a real screensaver (and you trust me), there's a zipfile inside called "galaxy-win32.zip" that contains the necessary files and a readme that explains how to install (basically, copy the 3 files into your c:windowssystem32 folder and check your screensavers)

enjoy!

David

Eclipse Project including Windows binaries

Filed under: Uncategorized No Comments