Pulse Sensor on Adafruit GEMMA
(Updated with GitHub repo: https://github.com/victorbutler/gemma-heartbeat)
For the T-Shirt I'm making, (link) I needed a way to measure someone's pulse. The pulse sensor Adafruit sells has some example code that runs on a regular 5 volt Arduino, but GEMMA isn't your everyday Arduino clone. It runs on an ATtiny85 (vs ATmega328) and has some limitations. It runs at a lower voltage and has less timers.
To get the timers working, this is what you need to do. Find the following code in Interrupt.ino:
void interruptSetup(){ // Initializes Timer2 to throw an interrupt every 2mS. TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED } ISR(TIMER2_COMPA_vect){ // triggered when Timer2 counts to 124
And replace it with this:
void interruptSetup() { // Initializes Timer1 to throw an interrupt every 2mS. // The ATtiny85 datasheet (pages 89-92) really helped me out here - and lots of trial and error: http://www.atmel.com/images/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf TCCR1 = 0; TCCR1 |= _BV(CTC1); //clear timer1 when it matches the value in OCR1C TCCR1 |= _BV(CS12) | _BV(CS11) | _BV(CS10); //set prescaler to divide by 64 - 8MHz/64 = 125kHz frequency for each timer tick TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value /** * We can do some simple math here for timer calculations * GOAL: We want a 2ms trigger, which in Hertz is 500Hz (1/2ms) * What we have: 125khz timed clock (thanks to the 64 prescalar) * 125khz/500Hz = 250, so we need to count from 1 to 250 (or 0 to 249) and then execute our interrupt service routine */ OCR1A = 249; //set the match value for interrupt - 125kHz/250 = 500Hz = 2ms (don't forget we start at a zero count, not 1) OCR1C = 249; //and the same match value to clear the timer - otherwise it will continue to count and overflow sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED } ISR(TIMER1_COMPA_vect){ // triggered when Timer1 counts to 254
With this, your timer should fire as expected. Here's a link to the entire Interrupts.ino file.
I hope this helps anyone trying to port over the code to work with GEMMA. I didn't go through everything you need to do to convert the code, but this was the biggest hiccup I encountered.
As an aside, another pain in the ass was figuring out that the input from pin 2 is read in through pin 1 via analogRead(1). I figured this out late.
If requested, I can write a post outlining the entire process. Good luck!
Here’s the GitHub repository with the code that runs the Pulse Sensor Amped on the Adafruit Gemma.
https://github.com/victorbutler/gemma-heartbeat