#include // this contains all the IO port definitions #include #include #include #include #define TIMER1_PRESCALE_1 1 #define TIMER1_PRESCALE_8 2 #define TIMER1_PRESCALE_64 3 #define TIMER1_PRESCALE_256 4 #define TIMER1_PRESCALE_1024 5 #define SENSOR 3 #define HEX__(n) 0x##n##UL #define B8__(x) ((x&0x0000000FLU)?1:0) \ +((x&0x000000F0LU)?2:0) \ +((x&0x00000F00LU)?4:0) \ +((x&0x0000F000LU)?8:0) \ +((x&0x000F0000LU)?16:0) \ +((x&0x00F00000LU)?32:0) \ +((x&0x0F000000LU)?64:0) \ +((x&0xF0000000LU)?128:0) #define B8(d) ((unsigned char)B8__(HEX__(d))) void ioinit (void); // used to count how many blinks are done in a single rotation uint8_t blink_count = 0; // blinkrate, starts out at 10000 uint16_t blinkrate = 10000; // store all the image data in program memory (ROM) // instead of RAM (the default) const uint8_t large_image[] PROGMEM = { B8 (00011100), B8(01111110), B8(11000011), B8(11000011), B8(11000011), B8(00000000), B8(11111111), B8(00011000), B8(00011000), B8(00011000), B8(11111111), B8(00000000), B8(11111100), B8(01100011), B8(01100011), B8(01100011), B8(11111100), B8(00000000), B8(11111111), B8(11000011), B8(11000011), B8(11000011), B8(01111110), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(10000010), B8(01000100), B8(00101000), B8(00010000), B8(00010000), B8(00010000), B8(00010000), B8(00010000), B8(11111110), B8(01111100), B8(00111000), B8(00010000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), B8(00000000), }; // special pointer for reading from ROM memory PGM_P largeimage_p PROGMEM = large_image; #define NUM_ELEM(x) (sizeof (x) / sizeof (*(x))) int imagesize = NUM_ELEM (large_image); // this function is called when timer1 compare matches OCR1A uint8_t j = 0; SIGNAL (SIG_TIMER1_COMPA) { if (j >= imagesize) j = 0; // read the image data from ROM PORTB = pgm_read_byte (largeimage_p + j); j++; // add to the blink count. we max at 200 so we don't get an overflow. if (blink_count < 200) { blink_count++; } } int main (void) { DDRB = 0xFF; // set all 8 pins on port B to outputs DDRD = 0xFB; // one input on pin D2, this pin read the hall sensor PORTD = 0x04; // turn on pullup on pin D2 ioinit (); sei (); // Set Enable Interrupts while (1) { } } SIGNAL (SIG_INT0) { // Start the image back a pixel 1 when we see the sensor j = 0; TCNT0 = 0; // if blink_count is less than imagesize then the blinks are lasting too long and need to be shortened // I only change the rate in increments of 100. This means it my take a few revolutions to finally // get the right rate. Sometimes the sensor misses the magnet and in those cases I don't wont the rate to change drastically // I probably need to adjust where the sensor and magnet or posistioned. if (blink_count < imagesize ) { // I made an arbitrary minimum rate if ( blinkrate > 4000) { blinkrate = blinkrate - 100; } } else { // I made an arbitrary maximum rate if ( blinkrate < 40000) { blinkrate = blinkrate + 100; } } TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1; OCR1A = blinkrate; TIMSK |= 1 << OCIE1A; blink_count = 0; sei (); // Set Enable Interrupts } void ioinit (void) { // interrupt on INT1 pin falling edge (sensor triggered) and PCMSK |= (1 << PIND2); // turn on interrupts! Set the interrupt to only trigger when the sensor goes back low MCUCR = (1<