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 |