/ Trinket_Gemma_Blinky_Eyes / Trinket_Gemma_Blinky_Eyes.ino
Trinket_Gemma_Blinky_Eyes.ino
1 // SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries 2 // 3 // SPDX-License-Identifier: GPL-3.0-or-later 4 5 /* 6 Name: Blinking Eyes - based on code by Brad Blumenthal, MAKE Magazine 7 License: GPLv3 8 Modified for 8 MHz ATTiny85 and low light photocell 9 October 2013 for Adafruit Learning System 10 */ 11 12 #define SENSITIVITY 550 // photocell sensitivity (changeable) 13 #define CELL_PIN 1 // CdS Photocell voltage divider on 14 // Trinket GPIO #2 (A1), Gemma D1/A1 15 uint8_t eyes_open; 16 volatile uint8_t blink_count; 17 volatile uint8_t blink_flag; 18 volatile uint8_t tick_flag; 19 volatile uint8_t getting_brighter = 0; 20 const uint8_t min_bright=16; 21 const uint8_t max_bright=128; 22 volatile uint8_t brightness; 23 uint8_t lfsr; // Linear Feedback Shift Register 24 const uint8_t min_blink = 64u; // don't blink more than once every 3 secs or so 25 26 void setup() { 27 pinMode(0, OUTPUT); // Eyes set as output 28 pinMode(2, INPUT); // Photocell as input 29 analogWrite(0, max_bright); analogWrite(1, max_bright); // Light eyes 30 eyes_open = 1; 31 blink_flag = 0; 32 lfsr = random(100); // initialize "blinking" 33 blink_count = max(blink_count, min_blink); 34 lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xF0u); // pseudorandom blinking 35 36 // Timer1 set to CK/1024 ~10 (8) hZ at 8 MHz clock rate for blinking action 37 TCCR1 |= _BV(CS13) | _BV(CS11) | _BV(CS10); 38 TIMSK |= _BV(TOIE1); // Enable Timer/Counter1 Overflow Interrupt 39 } 40 41 void loop() { 42 uint16_t photocell; 43 photocell = analogRead(CELL_PIN); 44 if(photocell > SENSITIVITY) { // if too light, shut down eyes until it gets darker on photocell 45 tick_flag=0; 46 analogWrite(0,0); // Turn off eyes if too light out 47 } 48 if (tick_flag) { // if too bright or we've counted enough ticks (clocks for blink) 49 tick_flag = 0; 50 if (blink_flag) { 51 blink_flag = 0; 52 if (eyes_open) { 53 eyes_open = 0; 54 analogWrite(0,0); // Turn off eyes by stopping PWM 55 blink_count = (lfsr & 0x01) + 1; // off for 1-2 ticks 56 } 57 else { 58 eyes_open = 1; 59 analogWrite(0,brightness); // Turn eyes on 60 blink_count = max(blink_count, min_blink); 61 lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xF0u); // regenerate pseudorandom blink 62 } 63 } 64 else { // One "tick," but we didn't blink... work on brightness control 65 if (getting_brighter) { 66 brightness += 2; // increase brightness 67 analogWrite(0, brightness); 68 if (brightness >= max_bright) getting_brighter = 0; 69 } else { 70 brightness -= 2; // decrease brightness 71 analogWrite(0, brightness); 72 if (brightness <= min_bright) getting_brighter = 1; 73 } 74 } 75 } 76 } 77 78 ISR (TIMER1_OVF_vect) { // Every 64 times a second, check blink 79 noInterrupts(); 80 tick_flag = 1; 81 blink_count--; 82 if (!blink_count) { 83 blink_flag = 1; 84 } 85 interrupts(); 86 }