|
| 1 | +// SPDX-FileCopyrightText: 2018 Anne Barela 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 | +} |
0 commit comments