SHOW:
|
|
- or go back to the newest paste.
| 1 | /* | |
| 2 | - | Copyright 2011 Dustin L. Westaby |
| 2 | + | |
| 3 | Cortana Arduino Code for the ATTiny45 by Dustin Westaby | |
| 4 | - | ---------------------------------------------------------------------- |
| 4 | + | |
| 5 | - | Prop Circuit for Attiny45 |
| 5 | + | Version History: |
| 6 | - | ---------------------------------------------------------------------- |
| 6 | + | 2/13/11 Initial Draft and test circuit |
| 7 | - | Title: cortana.c |
| 7 | + | 2/14/11 Updated Comments, re-arranged structure |
| 8 | - | Author: Dustin Westaby |
| 8 | + | 9/17/11 Timer Off Code Added |
| 9 | - | Date Created: 2/13/11 |
| 9 | + | 9/27/12 converted to arduino, expanded animations (Ryuuzaki Julio) |
| 10 | - | Last Modified: 9/17/11 |
| 10 | + | 11/29/12 cleaned up and rewrote logic |
| 11 | - | Purpose: Animated output to LEDs |
| 11 | + | |
| 12 | Ouputs: | |
| 13 | - | Compiled with AVR-GCC WinAVR |
| 13 | + | |
| 14 | 2 PB3 = LED | |
| 15 | - | Revisions List: |
| 15 | + | |
| 16 | - | 2/13/11 Initial Draft and test circuit |
| 16 | + | |
| 17 | - | 2/14/11 Updated Comments, re-arranged structure |
| 17 | + | |
| 18 | - | 9/17/11 Timer Off Code Added |
| 18 | + | |
| 19 | */ | |
| 20 | - | ---------------------------------------------------------------------- |
| 20 | + | |
| 21 | - | Fuses: |
| 21 | + | |
| 22 | - | ---------------------------------------------------------------------- |
| 22 | + | |
| 23 | - | BrownOut Disabled |
| 23 | + | //arduino specific digital pin numbers |
| 24 | - | CKDIV8 |
| 24 | + | int myPins[6] = {2,3,4,1,0};
|
| 25 | - | Int RC Osc 8Mhz + 64ms |
| 25 | + | |
| 26 | //performs subtraction then ensures positive result | |
| 27 | - | ---------------------------------------------------------------------- |
| 27 | + | #define ABS_SUB(a, b) ((a) < (b)? ((b) - (a)): ((a) - (b))) |
| 28 | - | Inputs: |
| 28 | + | |
| 29 | - | ---------------------------------------------------------------------- |
| 29 | + | /* -------------------- */ |
| 30 | - | Power up |
| 30 | + | /* Helper Functions */ |
| 31 | /* -------------------- */ | |
| 32 | - | ---------------------------------------------------------------------- |
| 32 | + | |
| 33 | - | Ouputs: |
| 33 | + | // the setup routine runs once when you press reset: |
| 34 | - | ---------------------------------------------------------------------- |
| 34 | + | void setup() |
| 35 | {
| |
| 36 | - | ---------------------------------------------------------------------- |
| 36 | + | int i; |
| 37 | ||
| 38 | // initialize the digital pin as an output. | |
| 39 | for (i=0;i<=4;i++) | |
| 40 | {
| |
| 41 | pinMode(myPins[i], OUTPUT); | |
| 42 | } | |
| 43 | - | ---------------------------------------------------------------------- |
| 43 | + | |
| 44 | - | Notes: |
| 44 | + | |
| 45 | - | ---------------------------------------------------------------------- |
| 45 | + | |
| 46 | - | -Program is free to modify, but please keep my name on the author list. |
| 46 | + | void delay_ms(uint16_t ms) |
| 47 | {
| |
| 48 | while ( ms ) | |
| 49 | {
| |
| 50 | - | //-------------------------------------- |
| 50 | + | _delay_ms(1); |
| 51 | - | // Global Variables | |
| 51 | + | ms--; |
| 52 | - | //-------------------------------------- |
| 52 | + | } |
| 53 | - | // 8 MHz Internal Oscillator DIV8 (used for delay subroutines) |
| 53 | + | |
| 54 | - | // One CPU Cycle = 1us |
| 54 | + | |
| 55 | - | #define F_CPU 8000000UL/8 |
| 55 | + | void delay_us(uint16_t us) |
| 56 | {
| |
| 57 | - | // Enumerate up down for use in the fade loops |
| 57 | + | while ( us ) |
| 58 | - | enum { up, down };
|
| 58 | + | {
|
| 59 | _delay_us(1); | |
| 60 | - | //Option to disable the time out turn off |
| 60 | + | us--; |
| 61 | - | //0 = OFF, 1 = ON |
| 61 | + | } |
| 62 | - | #define TIMER_ENABLE 1 |
| 62 | + | |
| 63 | ||
| 64 | - | //-------------------------------------- |
| 64 | + | /* -------------------- */ |
| 65 | - | // Includes | |
| 65 | + | /* Animation Functions */ |
| 66 | - | //-------------------------------------- |
| 66 | + | /* -------------------- */ |
| 67 | - | #include <avr/io.h> |
| 67 | + | |
| 68 | void blinkBlink(int delayTime, int MaxFlickr) | |
| 69 | - | #include <avr/sleep.h> |
| 69 | + | |
| 70 | - | #include <inttypes.h> |
| 70 | + | int i, RandomFlickrAmmount; |
| 71 | ||
| 72 | //randomize number of blinks and delay to help blinking look more alive | |
| 73 | - | //-------------------------------------- |
| 73 | + | RandomFlickrAmmount = random(1,MaxFlickr); |
| 74 | - | // Delay Subroutines | |
| 74 | + | |
| 75 | - | //-------------------------------------- |
| 75 | + | for (i = 0; i <= RandomFlickrAmmount; i++) |
| 76 | - | //These functions are from the delay.h include, the calls to delay functions |
| 76 | + | {
|
| 77 | - | //are re-written here to allow for longer waits. |
| 77 | + | //Turn ON all LEDs 01234 |
| 78 | - | void delay_ms(uint16_t ms) {
|
| 78 | + | PORTB = 0b00011111; |
| 79 | - | while ( ms ) |
| 79 | + | delay(delayTime - RandomFlickrAmmount); |
| 80 | - | {
|
| 80 | + | |
| 81 | - | _delay_ms(1); |
| 81 | + | //Turn OFF all LEDs 01234 |
| 82 | - | ms--; |
| 82 | + | PORTB = 0b00000000; |
| 83 | - | } |
| 83 | + | delay(delayTime - RandomFlickrAmmount); |
| 84 | } | |
| 85 | ||
| 86 | - | void delay_us(uint16_t us) {
|
| 86 | + | } //end blink function |
| 87 | - | while ( us ) |
| 87 | + | |
| 88 | - | {
|
| 88 | + | void spinSpin(int count_delay) |
| 89 | - | _delay_us(1); |
| 89 | + | |
| 90 | - | us--; |
| 90 | + | int i; |
| 91 | - | } |
| 91 | + | int repeat = random(1,3)*5; //random number of spins times 5 LEDs |
| 92 | int circle_direction = random(0,1); //random selection of clockwise or counterclockwise animations | |
| 93 | int pin_to_on = random(0,4); //random starting LED position for animation (on) | |
| 94 | - | //-------------------------------------- |
| 94 | + | int pin_to_off = random(0,4); //random starting LED position for animation (off) |
| 95 | - | // Sleep Subroutine | |
| 95 | + | |
| 96 | - | //-------------------------------------- |
| 96 | + | //loop ends after random number of spins |
| 97 | - | void shutdown_and_sleep(void) {
|
| 97 | + | for (i = 0; i <= repeat; i++) |
| 98 | {
| |
| 99 | - | //setup low power sleep mode |
| 99 | + | if (circle_direction == 1) |
| 100 | - | set_sleep_mode(SLEEP_MODE_PWR_DOWN); |
| 100 | + | {
|
| 101 | //each animation section turns off one LED and turns on one LED | |
| 102 | - | //send to sleep |
| 102 | + | digitalWrite(myPins[pin_to_on++], HIGH); |
| 103 | - | sleep_mode(); |
| 103 | + | digitalWrite(myPins[pin_to_off++], LOW); |
| 104 | } | |
| 105 | - | //NOT HIT |
| 105 | + | else |
| 106 | - | while(1); |
| 106 | + | {
|
| 107 | //each animation section turns off one LED and turns on one LED | |
| 108 | digitalWrite(myPins[pin_to_on--], HIGH); | |
| 109 | digitalWrite(myPins[pin_to_off--], LOW); | |
| 110 | } | |
| 111 | - | //-------------------------------------- |
| 111 | + | |
| 112 | - | // Main | |
| 112 | + | //delay before next spin animation |
| 113 | - | //-------------------------------------- |
| 113 | + | delay(count_delay); |
| 114 | - | int main (void) |
| 114 | + | |
| 115 | //the following overrun check works because circle_direction can only be 0 or 1. | |
| 116 | //When circle_direction is 0, the pin_to_on pin_to_off are decremented, down to 0. The overrun check compares to 0, then sets to 4. | |
| 117 | - | /* ---------------------------------------------------------------- */ |
| 117 | + | //When circle_direction is 1, the pin_to_on pin_to_off are incremented, up to 4. The overrun check compares to 4, then sets 0. |
| 118 | - | /* Initialization */ |
| 118 | + | if (pin_to_on == circle_direction*4) |
| 119 | - | /* ---------------------------------------------------------------- */ |
| 119 | + | {
|
| 120 | - | //Variables used for animations |
| 120 | + | pin_to_on = ABS_SUB(circle_direction*4,4); |
| 121 | - | int i, count_delay, direction; |
| 121 | + | } |
| 122 | - | int time_on, time_off, max_value, min_value, rate_of_change; |
| 122 | + | if (pin_to_off == circle_direction*4) |
| 123 | - | int time_to_off, cycle_count, fade_inc_count; |
| 123 | + | {
|
| 124 | pin_to_off = ABS_SUB(circle_direction*4,4); | |
| 125 | - | //Initialize Port B is an output |
| 125 | + | |
| 126 | - | DDRB = 0b00011111; |
| 126 | + | //one rotation complete |
| 127 | //speed up the spinning, down to 16 | |
| 128 | - | /* ---------------------------------------------------------------- */ |
| 128 | + | if (count_delay > 16) |
| 129 | - | /* Spin Circle Four Times (approx 1s) */ |
| 129 | + | {
|
| 130 | - | /* ---------------------------------------------------------------- */ |
| 130 | + | count_delay = count_delay - 2; |
| 131 | - | i=0; |
| 131 | + | } |
| 132 | - | count_delay=50; //Delay between circle movement is 50ms |
| 132 | + | } |
| 133 | - | for (i = 0; i < 4; i++) |
| 133 | + | |
| 134 | - | {
|
| 134 | + | } //end loop |
| 135 | - | PORTB = 0b00000001; //Turn ON only LED 0 for defined delay (50ms) |
| 135 | + | |
| 136 | - | delay_ms(count_delay); |
| 136 | + | } //end spin function |
| 137 | - | PORTB = 0b00000010; //Turn ON only LED 1 for defined delay (50ms) |
| 137 | + | |
| 138 | - | delay_ms(count_delay); |
| 138 | + | /* -------------------- */ |
| 139 | - | PORTB = 0b00000100; //Turn ON only LED 2 for defined delay (50ms) |
| 139 | + | /* Main Function */ |
| 140 | - | delay_ms(count_delay); |
| 140 | + | /* -------------------- */ |
| 141 | - | PORTB = 0b00001000; //Turn ON only LED 3 for defined delay (50ms) |
| 141 | + | |
| 142 | - | delay_ms(count_delay); |
| 142 | + | void loop() |
| 143 | - | PORTB = 0b00010000; //Turn ON only LED 4 for defined delay (50ms) |
| 143 | + | |
| 144 | - | delay_ms(count_delay); |
| 144 | + | int i = 0; |
| 145 | - | } |
| 145 | + | int count_delay, e, repeat; |
| 146 | int time_on, time_off, max_value, min_value, rate_of_change; | |
| 147 | - | /* ---------------------------------------------------------------- */ |
| 147 | + | boolean fade_direction; |
| 148 | - | /* All ON Long (0.8 seconds) */ |
| 148 | + | int Chances_of_Flickr; |
| 149 | - | /* ---------------------------------------------------------------- */ |
| 149 | + | int Chances_of_Spin; |
| 150 | - | PORTB = 0b00011111; //Turn ON all LEDs 01234 for 800ms |
| 150 | + | int X_Loops; |
| 151 | - | delay_ms(800); |
| 151 | + | int randomInt; |
| 152 | ||
| 153 | - | /* ---------------------------------------------------------------- */ |
| 153 | + | /* Set output pins */ |
| 154 | - | /* Blink Blink */ |
| 154 | + | DDRB = 0b00011111; |
| 155 | - | /* ---------------------------------------------------------------- */ |
| 155 | + | |
| 156 | - | PORTB = 0b00000000; //Turn OFF all LEDS 01234 for 100ms |
| 156 | + | /* ---------------------------------------------------------------- */ |
| 157 | - | delay_ms(100); |
| 157 | + | /* All OFF Short */ |
| 158 | - | PORTB = 0b00011111; //Turn ON all LEDs 01234 for 10ms |
| 158 | + | /* ---------------------------------------------------------------- */ |
| 159 | - | delay_ms(10); |
| 159 | + | |
| 160 | - | PORTB = 0b00000000; //Turn OFF all LEDs 01234 for 100ms |
| 160 | + | count_delay = 20; //Delay starting point |
| 161 | - | delay_ms(100); |
| 161 | + | for (i = 0; i <= 4; i++) |
| 162 | - | PORTB = 0b00011111; //Turn ON all LEDs 01234 for 100ms |
| 162 | + | {
|
| 163 | - | delay_ms(100); |
| 163 | + | digitalWrite(myPins[i], LOW); //turn off each of the 4 LEDs in sequence |
| 164 | delay(count_delay*2 + i*20); //delay increases after each iteration | |
| 165 | - | /* ---------------------------------------------------------------- */ |
| 165 | + | } |
| 166 | - | /* Fade In and Out Continuous (Software PWM) */ |
| 166 | + | |
| 167 | - | /* ---------------------------------------------------------------- */ |
| 167 | + | /* ---------------------------------------------------------------- */ |
| 168 | - | max_value=500; //Max of 500us for LEDs ON |
| 168 | + | /* Spin Circle (single runner) */ |
| 169 | - | min_value=5; //Max of 5us for LEDs OFF |
| 169 | + | /* ---------------------------------------------------------------- */ |
| 170 | - | time_on=min_value; //Set Starting Time ON to 5us |
| 170 | + | |
| 171 | - | time_off=max_value; //Set Starting Time OFF to 500us |
| 171 | + | repeat = 8; //Number of spins |
| 172 | - | rate_of_change=2; //This is the speed that the fade goes between min and max |
| 172 | + | count_delay = 60; //Delay between circle movement in ms |
| 173 | - | direction=down; //Direction is defined for the direction of the fade (in or out) |
| 173 | + | |
| 174 | - | |
| 174 | + | for(e = 0; e <= repeat; e++) |
| 175 | - | time_to_off=5*(54); //About 5 minutes (54 fades per minute) |
| 175 | + | {
|
| 176 | - | cycle_count=0; //Use to count the number of times fades to dark |
| 176 | + | for (i = 0; i <= 4; i++) |
| 177 | - | fade_inc_count=0; //Used to count iterations of the fade loop |
| 177 | + | {
|
| 178 | digitalWrite(myPins[i], HIGH); | |
| 179 | - | /* Note: The direction is backwards on purpose, causes the light animation to |
| 179 | + | delay(count_delay); |
| 180 | - | look like it hiccuped for the first fade cycle before reaching a steady fade. */ |
| 180 | + | digitalWrite(myPins[i], LOW); |
| 181 | } | |
| 182 | - | while(1) |
| 182 | + | |
| 183 | - | {
|
| 183 | + | if (count_delay >= 6) |
| 184 | - | //The ratio of ON time and OFF time determines the brightness of the LEDs (DUTY CYLE) |
| 184 | + | {
|
| 185 | - | //By continuously varying the ON time versus the OFF times we get a fade effect. |
| 185 | + | count_delay = count_delay - 6; |
| 186 | - | PORTB = 0b00011111; //Turn ON all LEDs 01234 |
| 186 | + | } |
| 187 | - | delay_us(time_on); |
| 187 | + | } |
| 188 | - | PORTB = 0b00000000; //Turn OFF all LEDs 01234 |
| 188 | + | |
| 189 | - | delay_us(time_off); |
| 189 | + | /* ---------------------------------------------------------------- */ |
| 190 | /* Spin Circle (chased runner) */ | |
| 191 | - | //This is the TimeOut code. Breaks loop.turning off the LEDs. |
| 191 | + | /* ---------------------------------------------------------------- */ |
| 192 | - | if (TIMER_ENABLE) |
| 192 | + | |
| 193 | - | {
|
| 193 | + | spinSpin(16); //spin with constant speed of 16ms |
| 194 | - | fade_inc_count++; |
| 194 | + | |
| 195 | - | if (fade_inc_count>(max_value/2)) |
| 195 | + | /* ---------------------------------------------------------------- */ |
| 196 | - | {
|
| 196 | + | /* All ON Long */ |
| 197 | - | fade_inc_count=0; |
| 197 | + | /* ---------------------------------------------------------------- */ |
| 198 | - | cycle_count++; |
| 198 | + | |
| 199 | count_delay = 20; //Delay starting point | |
| 200 | - | if (cycle_count > time_to_off) |
| 200 | + | |
| 201 | - | {
|
| 201 | + | for (i = 0; i <= 4; i++) |
| 202 | - | shutdown_and_sleep(); |
| 202 | + | {
|
| 203 | - | //does not return |
| 203 | + | digitalWrite(myPins[i], HIGH); //turn on each of the 4 LEDs in sequence |
| 204 | - | break; |
| 204 | + | delay(count_delay*2 + i*20); //delay increases after each iteration |
| 205 | - | } |
| 205 | + | } |
| 206 | - | } |
| 206 | + | delay(200); |
| 207 | - | } |
| 207 | + | |
| 208 | /* ---------------------------------------------------------------- */ | |
| 209 | - | if (direction==up) |
| 209 | + | /* Blink Blink */ |
| 210 | - | {
|
| 210 | + | /* ---------------------------------------------------------------- */ |
| 211 | - | //In the UP direction the Time ON increases while the Time OFF decreases. |
| 211 | + | |
| 212 | - | //The result is that the LEDs get brighter |
| 212 | + | blinkBlink(50,5); |
| 213 | - | time_on+=rate_of_change; |
| 213 | + | delay_ms(100); |
| 214 | - | time_off-=rate_of_change; |
| 214 | + | blinkBlink(50,2); |
| 215 | delay(200); | |
| 216 | - | //When the end of the fade is reached, switch directions |
| 216 | + | |
| 217 | - | if (time_on>max_value) |
| 217 | + | /* ---------------------------------------------------------------- */ |
| 218 | - | direction=down; |
| 218 | + | /* Fade In and Out Continuous (Software PWM) */ |
| 219 | - | } |
| 219 | + | /* ---------------------------------------------------------------- */ |
| 220 | - | else |
| 220 | + | |
| 221 | - | {
|
| 221 | + | max_value = 400; //Max for LEDs ON in us |
| 222 | - | //In the DOWN direction the Time ON decreases while the Time OFF increases. |
| 222 | + | min_value = 3; //Max for LEDs OFF in us |
| 223 | - | //The result is that the LEDs get dimmer |
| 223 | + | time_on = min_value; //Set Starting Time ON to min |
| 224 | - | time_on-=rate_of_change; |
| 224 | + | time_off = max_value; //Set Starting Time OFF to max |
| 225 | - | time_off+=rate_of_change; |
| 225 | + | rate_of_change = 1; //This is the speed that the fade goes between min and max |
| 226 | fade_direction = false; //Direction is defined for the direction of the fade (in or out) | |
| 227 | - | //When the end of the fade is reached, switch directions |
| 227 | + | Chances_of_Flickr = 2; //The breathing animation has 2 in X_Loops chances of flickering. |
| 228 | - | if (time_on<=min_value) |
| 228 | + | Chances_of_Spin = 1; //The breathing animation has 1 in X_Loops chances of Spining. |
| 229 | - | direction=up; |
| 229 | + | X_Loops = 3000; |
| 230 | - | } |
| 230 | + | |
| 231 | - | } |
| 231 | + | while(true) // Repeat Forever |
| 232 | {
| |
| 233 | - | //this code should not be hit, the following is just in case |
| 233 | + | |
| 234 | - | set_sleep_mode(SLEEP_MODE_PWR_DOWN); |
| 234 | + | //Turn ON all LEDs 01234 |
| 235 | - | sleep_mode(); |
| 235 | + | PORTB = 0b00011111; |
| 236 | - | while(1); // Ending infinite loop |
| 236 | + | delay_us(time_on); |
| 237 | ||
| 238 | - | } |
| 238 | + | //Turn OFF all LEDs 01234 |
| 239 | PORTB = 0b00000000; | |
| 240 | delay_us(time_off); | |
| 241 | ||
| 242 | if (fade_direction==true) | |
| 243 | {
| |
| 244 | //In the UP direction the Time ON increases while the Time OFF decreases. | |
| 245 | //The result is that the LEDs get brighter | |
| 246 | time_on += rate_of_change; | |
| 247 | time_off -= rate_of_change; | |
| 248 | ||
| 249 | //When the end of the fade is reached, switch directions | |
| 250 | if (time_on>max_value) | |
| 251 | {
| |
| 252 | fade_direction = false; | |
| 253 | } | |
| 254 | } | |
| 255 | else | |
| 256 | {
| |
| 257 | //In the DOWN direction the Time ON decreases while the Time OFF increases. | |
| 258 | //The result is that the LEDs get dimmer | |
| 259 | time_on -= rate_of_change; | |
| 260 | time_off += rate_of_change; | |
| 261 | ||
| 262 | //When the end of the fade is reached, switch directions | |
| 263 | if (time_on <= min_value) | |
| 264 | {
| |
| 265 | fade_direction=true; | |
| 266 | } | |
| 267 | } | |
| 268 | ||
| 269 | //Throughout the sequence, random chance of blinking or spinning instead of normal fading | |
| 270 | randomInt= random(1, X_Loops); | |
| 271 | if (randomInt <= Chances_of_Flickr) | |
| 272 | {
| |
| 273 | blinkBlink(15, 4); | |
| 274 | } | |
| 275 | ||
| 276 | if (randomInt >= X_Loops-Chances_of_Spin) | |
| 277 | {
| |
| 278 | spinSpin(30); //spin with increasing speed, from 20 to 16ms | |
| 279 | } | |
| 280 | ||
| 281 | } //end inf loop | |
| 282 | ||
| 283 | } // end main loop |