Advertisement
grist

ATtiny85 Blinking Eyes

Nov 29th, 2014
341
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.84 KB | None | 0 0
  1. /*
  2.  * ATtiny85_Eyes.c
  3.  *
  4.  * Created: 11/25/2014 7:36:41 PM
  5.  *  Author: grist.carrigafoyl
  6.  
  7.  Some code to make 2 LEDs behave kind of like eyes.
  8.  
  9.  Want periodic blinking and the occasional wink.
  10.  
  11.  
  12.  */
  13. #define F_CPU 8000000UL // 8Mhz
  14.  
  15. #define LEFT_EYE PB0  // pin5
  16. #define RIGHT_EYE PB1 // pin6
  17. #define DELAY_MIN   20000 // about 6 seconds, rand() will add 0 - 32767 to this
  18.  
  19. // Using the ADC as a random seed
  20. #define ADMUX_BITS      0b0000  // All default (VCC ref, ADLAR unset)
  21. #define ADC_PIN         PB3  // an unconnected pin that will be floating
  22.  
  23. // macros to set eye brightness
  24. #define SET_RIGHT_EYE_LEVEL(x)  OCR0A = (255 - x)
  25. #define SET_LEFT_EYE_LEVEL(x)   OCR0B = (255 - x)
  26.  
  27. #include <avr/io.h>
  28. #include <avr/interrupt.h>
  29.  
  30. // volatile because it's changed in the interrupt routine.
  31. volatile unsigned long counter = 0;
  32.  
  33.  
  34. // function prototypes
  35. void wink(uint8_t eye);
  36. void winkwink();
  37. void blink();
  38. void delay(unsigned int time);
  39. void fade_up(int delay_length);
  40. int read_adc();
  41.  
  42. int main(void)
  43. {
  44.     srand(read_adc()); // Should be fairly random with a floating pin
  45.    
  46.     unsigned int delay_time;
  47.     int action;
  48.    
  49.     // Set the LED pins as output
  50.     DDRB = _BV(LEFT_EYE) | _BV(RIGHT_EYE);
  51.    
  52.     // Enable ALL the Timer0 output compare interrupts!
  53.     TIMSK = _BV(OCIE0A) | _BV(OCIE0B) | _BV(TOIE0);
  54.    
  55.     // Settings for the delay timer
  56.     TIMSK |= _BV(TOIE1); // overflow timer 1
  57.    
  58.     // start the delay timer
  59.     TCCR1 = _BV(CS12); // prescaler 8
  60.    
  61.     // start the PWM timer, prescaler 64, for around 485Hz
  62.     TCCR0B = _BV(CS01) | _BV(CS00);
  63.    
  64.     // Enable global interrupts
  65.     sei();
  66.    
  67.     // Time to get started
  68.    
  69.     fade_up(200);
  70.     while(1)
  71.     {
  72.         action = rand(); // 0 - 32767
  73.         // Change the thresholds to make actions more or less likely
  74.         if (action < 25000) {
  75.             blink();
  76.         } else if (action < 28000) {
  77.             wink(RIGHT_EYE);
  78.         } else if (action < 31000) {
  79.             wink(LEFT_EYE);
  80.         } else {
  81.             winkwink();
  82.         }
  83.        
  84.         delay_time = rand() + DELAY_MIN;
  85.         delay(delay_time);
  86.        
  87.     }
  88. }
  89.  
  90.  
  91. void blink()
  92. // Blink the eyes
  93. {
  94.     int i; // brightness
  95.     int delay_length = 2; // delay between changing brightness levels.
  96.  
  97.     for (i=255;i>0;i--) {
  98.         SET_LEFT_EYE_LEVEL(i);
  99.         SET_RIGHT_EYE_LEVEL(i);
  100.         delay(delay_length);
  101.     }
  102.     delay(1000);
  103.     for (i=0;i<255;i++) {
  104.         SET_LEFT_EYE_LEVEL(i);
  105.         SET_RIGHT_EYE_LEVEL(i);
  106.         delay(delay_length);
  107.     }
  108. }
  109.  
  110.  
  111. void wink(uint8_t eye)
  112. // Wink an eye
  113. {
  114.     int i; // brightness
  115.     int delay_length = 2; // delay between changing brightness levels.
  116.    
  117.     for (i=255;i>0;i--) {
  118.         if (eye == RIGHT_EYE) {
  119.             SET_RIGHT_EYE_LEVEL(i);
  120.         } else {
  121.             SET_LEFT_EYE_LEVEL(i);
  122.         }
  123.         delay(delay_length);
  124.     }  
  125.     delay(1000);   
  126.     for (i=0;i<255;i++) {
  127.         if (eye == RIGHT_EYE) {
  128.             SET_RIGHT_EYE_LEVEL(i);
  129.         } else {
  130.             SET_LEFT_EYE_LEVEL(i);
  131.         }
  132.         delay(delay_length);
  133.     }
  134.  
  135.    
  136. }
  137.  
  138. void winkwink()
  139. // Wink both eyes in quick succession
  140. {
  141.     wink(RIGHT_EYE);
  142.     delay(1000);
  143.     wink(LEFT_EYE);
  144. }
  145.  
  146. void fade_up(int delay_length)
  147. // Fade both eyes up slowly.
  148. {
  149.     int i; // brightness
  150.     for (i=1;i<255;i++) {
  151.         TCNT0 = 0; // reset the hardware counter
  152.         SET_LEFT_EYE_LEVEL(i);
  153.         SET_RIGHT_EYE_LEVEL(i);
  154.         delay(delay_length);
  155.     }
  156. }
  157.  
  158. void delay(unsigned int time)
  159. // an arbitrary blocking delay
  160. {
  161.     TCNT1 = 0; // reset the hardware counter
  162.     counter = 0; // this is incremented by the overflow interrupt
  163.     while (counter < time) {
  164.         // dum de doo, twiddle twiddle.
  165.     }
  166. }
  167.  
  168. int read_adc()
  169. // Read the analog value from the ADC input pin. Using this as a random
  170. // seed as the pins are floating and could return almost anything.
  171. {
  172.    
  173.     // ADC settings. Check with data sheet that this is what you want
  174.     ADCSRA |= _BV(ADEN) | // Enable ADC
  175.         (_BV(ADPS0)) | // set pre-scaler to clock/128
  176.         (_BV(ADPS1)) | // 8MHz/128 = 62.5Khz (aiming for 50 - 200)
  177.         (_BV(ADPS2));  // so this is good
  178.     // Code based on samples from http://avrbasiccode.wikispaces.com/
  179.     int ret_val;
  180.  
  181.     // Assumes ADCSRA enabled and prescalars are set already
  182.     // Set the input channel and other ADMUX bits
  183.     ADMUX = (ADMUX_BITS << 4) | ADC_PIN;
  184.    
  185.     // Take a reading
  186.     ADCSRA |= _BV(ADSC); // start a single conversion
  187.     while (ADCSRA & _BV(ADSC)); // wait until conversion is done
  188.    
  189.     ret_val = ADCL; // Get ADCL first for 10bit and combine with ADCH
  190.     return((ADCH << 8) | ret_val);
  191. }
  192.  
  193. // Interrupt routines. Using COMPA & COMPB to generate PWM signals
  194. // on the two output pins. PWM frequency works out at about 495Hz
  195. ISR(TIMER0_OVF_vect)
  196. // Timer 0 overflow, so end of the pulse
  197. {
  198.     PORTB = 0; // might as well turn 'em all off in one hit. no other output pins in this application.
  199. }
  200.  
  201. ISR(TIMER0_COMPA_vect)
  202. // Start of the pulse for the left eye
  203. {
  204.     PORTB |= _BV(LEFT_EYE);
  205. }
  206.  
  207. ISR(TIMER0_COMPB_vect)
  208. // Start of the pulse for the right eye
  209. {
  210.     PORTB |= _BV(RIGHT_EYE);
  211. }
  212.  
  213. ISR(TIMER1_OVF_vect)
  214. // Overflow for timer 1. Used for the delay timer
  215. {
  216.     counter++;
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement