View difference between Paste ID: DeVL7Ddu and fs0gKCsq
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