View difference between Paste ID: tU6stCT5 and wj0wxjX1
SHOW: | | - or go back to the newest paste.
1
/*
2
Copyright 2011 Dustin L. Westaby
3
4
----------------------------------------------------------------------
5
    Stairway Light Controller for Attiny2313
6
----------------------------------------------------------------------
7
Title:      stairway.c
8
Author:     Dustin Westaby
9
Date Created:   01/19/12
10-
Last Modified:  
10+
Last Modified:
11-
Purpose:  Monitor proximity and motion sensors and animate stairway 
11+
Purpose:  Monitor proximity and motion sensors and animate stairway
12
          lighting.
13
14
Compiled with AVR-GCC WinAVR
15
16
Revisions List:
17
01/19/12 Initial draft
18
19
----------------------------------------------------------------------
20
    Fuses:
21
----------------------------------------------------------------------
22
 BrownOut Disabled
23
 CKDIV8
24
 Int RC Osc 8Mhz + 64ms
25
26
----------------------------------------------------------------------
27
    Inputs:
28
----------------------------------------------------------------------
29
 pin       port    function
30
----------------------------------------------------------------------
31
  1        RST     Unused
32
  2        PD0     Motion Sensor    (digital) (active low with pullup 10k)
33-
 23		   PC0	   Prox Sensor Low  (digital) 5 feet range
33+
 23         PC0      Prox Sensor Low  (digital) 5 feet range
34-
 24		   PC1	   Prox Sensor High (digital)
34+
 24         PC1      Prox Sensor High (digital)
35
  4        PD2     Override button  (digital) External Interrupt 0
36
37
----------------------------------------------------------------------
38
    Ouputs:
39
----------------------------------------------------------------------
40
 pin       port    function
41
----------------------------------------------------------------------
42
 14        PB0      Lighting Channel
43
 15        PB1      Lighting Channel
44
 16        PB2      Lighting Channel
45
 17        PB3      Lighting Channel
46
 18        PB4      Lighting Channel
47
 19        PB5      Lighting Channel
48
  9        PB6      Lighting Channel
49
 10        PB7      Lighting Channel
50-
  
50+
51
52-
The Prox sensors are analog, uses a comparator to convert to digital 
52+
The Prox sensors are analog, uses a comparator to convert to digital
53
and a pot to select the cutoff range.
54
55
*/
56
57
//--------------------------------------
58
//          Global Variables           |
59
//--------------------------------------
60
// 8 MHz Internal Oscillator DIV8 (used for delay subroutines)
61
// One CPU Cycle = 1us
62
#define F_CPU 8000000UL/8
63
64
enum { up, down };
65
enum { on, off };
66
enum { low, high };
67
68
//--------------------------------------
69
//              Includes               |
70
//--------------------------------------
71
#include <avr/io.h>
72
#include <util/delay.h>
73
//#include <avr/sleep.h>
74
#include <inttypes.h>
75
76
77
//--------------------------------------
78
//          Global Constants           |
79
//--------------------------------------
80
81
int START_CH = PB0; //lowest channel bit
82
int NUM_OF_CH = 6;
83
int ALL_ON  = 0xFF;
84
int ALL_OFF = 0x00;
85
86
//--------------------------------------
87-
//          Delay Subroutines          |
87+
//          Delay Subroutine           |
88
//--------------------------------------
89-
//These functions are from the delay.h include, the calls to delay functions
89+
//This function is from the delay.h include, the calls to delay functions
90
//are re-written here to allow for longer waits.
91-
void delay_ms(uint16_t ms) {
91+
void delay_ms(uint16_t ms)
92
{
93
  while ( ms )
94
  {
95
    _delay_ms(1);
96
    ms--;
97
  }
98
}
99-
void delay_us(uint16_t us) {
99+
100-
  while ( us )
100+
101
//          Other Functions            |
102-
    _delay_us(1);
102+
103-
    us--;
103+
104
void standby_sequence(int count)
105
{
106
   // Description:
107
   // This function animates a back and forth motion
108
   // Approx 4 transitions per second
109
110
   // Example:
111
   // 0 1 2 3 4 5 6 7 8  Channels
112
   // 0 1 0 1 0 1 0 1 0  Odd Count
113
   // 1 0 1 0 1 0 1 0 1  Even Count
114-
	int i;
114+
115
   int i;
116-
	//determine if count is even or odd
116+
117-
	PORTB = ALL_OFF;
117+
   //determine if count is even or odd
118-
	if (count % 2 == 0)
118+
   PORTB = ALL_OFF;
119-
	{
119+
   if (count % 2 == 0)
120-
		//every other bit, even
120+
   {
121-
		for (i=START_CH; i <= NUM_OF_CH; i+=2)
121+
      //every other bit, even
122-
		{
122+
      for (i=START_CH; i <= NUM_OF_CH; i+=2)
123-
			PORTB |= (1 << i);
123+
      {
124-
		}
124+
         PORTB |= (1 << i);
125-
	}
125+
      }
126-
	else
126+
   }
127-
	{
127+
   else
128-
		//every other bit, odd
128+
   {
129-
		for (i=(START_CH+1); i <= NUM_OF_CH; i+=2)
129+
      //every other bit, odd
130-
		{
130+
      for (i=(START_CH+1); i <= NUM_OF_CH; i+=2)
131-
			PORTB |= (1 << i);
131+
      {
132-
		}
132+
         PORTB |= (1 << i);
133-
	}
133+
      }
134
   }
135
136
137
}
138
139
void animate_sequence(int direction, int onoff)
140-
	int time = 100;
140+
141-
	int i;
141+
   int time = 100;
142
   int i;
143-
	if(direction == up)
143+
144-
	{
144+
   if(direction == up)
145-
		if (onoff == on )
145+
   {
146-
		{
146+
      if (onoff == on )
147-
			//rotates through.
147+
      {
148-
			PORTB = ALL_OFF;
148+
         // Animates by rotating through.
149-
			for (i=START_CH; i < NUM_OF_CH; i++)
149+
         PORTB = ALL_OFF;
150-
			{
150+
         for (i=START_CH; i < NUM_OF_CH; i++)
151-
				PORTB |= (1 << i);
151+
         {
152-
				delay_ms(time);
152+
            PORTB |= (1 << i);
153-
			}
153+
            delay_ms(time);
154
         }
155-
		}
155+
156-
		else
156+
      }
157-
		{
157+
      else
158-
			//rotates through.
158+
      {
159-
			PORTB = ALL_ON;
159+
         // Animates by rotating through.
160-
			for (i=START_CH; i < NUM_OF_CH; i++)
160+
         PORTB = ALL_ON;
161-
			{
161+
         for (i=START_CH; i < NUM_OF_CH; i++)
162-
				PORTB &= ~(1 << i);
162+
         {
163-
				delay_ms(time);
163+
            PORTB &= ~(1 << i);
164-
			}
164+
            delay_ms(time);
165
         }
166-
		}
166+
167
      }
168-
	}
168+
169-
	else
169+
   }
170-
	{
170+
   else
171-
		if (onoff == on )
171+
   {
172-
		{
172+
      if (onoff == on )
173-
			//reverse rotates through.
173+
      {
174-
			PORTB = ALL_OFF;
174+
         // Animates by reverse rotating through.
175-
			for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
175+
         PORTB = ALL_OFF;
176-
			{
176+
         for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
177-
				PORTB |= (1 << i);
177+
         {
178-
				delay_ms(time);
178+
            PORTB |= (1 << i);
179-
			}
179+
            delay_ms(time);
180-
		}
180+
         }
181-
		else
181+
      }
182-
		{
182+
      else
183-
			//reverse rotates through.
183+
      {
184-
			PORTB = ALL_ON;
184+
         // Animates by reverse rotating through.
185-
			for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
185+
         PORTB = ALL_ON;
186-
			{
186+
         for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
187-
				PORTB &= ~(1 << i);
187+
         {
188-
				delay_ms(time);
188+
            PORTB &= ~(1 << i);
189-
			}
189+
            delay_ms(time);
190-
		}
190+
         }
191-
	}
191+
      }
192
   }
193
194
}
195
196-
int low_read()
196+
int read_prox(int pin)
197
{
198
   // This function allows for some debouncing
199-
	if (bit_is_set(PIND, PD0))
199+
200-
	{
200+
   if (bit_is_set(PIND, pin))
201-
		delay_ms(1);
201+
   {
202-
		if (bit_is_set(PIND, PD0))
202+
      delay_ms(1);
203-
		{
203+
      if (bit_is_set(PIND, pin))
204-
			delay_ms(5);
204+
      {
205-
			return 1;
205+
         return 1;
206-
		}
206+
      }
207-
	}
207+
   }
208
209-
	return 0;
209+
   return 0;
210
}
211
212-
int high_read()
212+
213
{
214
215-
	if (bit_is_set(PIND, PD1))
215+
   //[tbd] read motion sensor
216-
	{
216+
217-
		delay_ms(1);
217+
   return 0;
218-
		if (bit_is_set(PIND, PD1))
218+
219-
		{
219+
220-
			delay_ms(5);
220+
221-
			return 1;
221+
222-
		}
222+
223-
	}
223+
   // Set direction registers
224
   // sensors data direction
225-
	return 0;
225+
   // lighting data direction
226
227
   DDRA =  0b11111111;
228
   DDRB =  0b11111111;
229
   DDRD =  0b00000000;
230
231-
	//[tbd] read motion sensor
231+
   // Enable Wake Interrupts
232
   //[TBD]
233-
	return 0;
233+
234
   // Set power down mode
235
   //[tbd]
236
237
}
238
239-
	// Set direction registers
239+
240-
	// sensors data direction
240+
241-
	// lighting data direction
241+
242
//--------------------------------------
243-
	DDRA =  0b11111111;
243+
244-
	DDRB =  0b11111111;
244+
245-
	DDRD =  0b00000000;
245+
   // Local Variables
246
   int low_store = 0, high_store = 0, sens_store;
247
   int trigger_direction;
248-
	// Enable Wake Interrupts
248+
   int counterA, counterB;
249-
	//[TBD]
249+
   int motion_store = 0;
250-
	
250+
   int TIMEOUT_MAX = 117; // approx >30 seconds, (30*1000/255) ~= 117
251-
	// Set power down mode
251+
252-
	//[tbd]
252+
   // Pin position of Prox Sensors
253
   int LOWPIN = PD0;
254
   int HIGHPIN = PD1;
255
256
   // Initialize registers
257
   init_cpu();
258
259
   // Turn off LEDs
260
   PORTB = 0x00;
261
262-
	int low_store = 0, high_store = 0;
262+
   // Loop forever
263-
	int trigger_direction;
263+
   // TBD: Replace with timeout to sleep and save power
264-
	int counterA, counterB;
264+
   while(1)
265-
	int motion_store = 0;
265+
   {
266-
	int TIMEOUT_MAX = 117; //~30 seconds
266+
      low_store = 0;
267
      high_store = 0;
268-
	init_cpu();  
268+
      counterA = 0;
269
      counterB = 0;
270-
	//turn off LEDs
270+
      motion_store = 0;
271-
	PORTB = 0x00;
271+
      sens1_store = 0;
272
      sens2_store = 0;
273-
	while(1)
273+
274-
	{
274+
      // Wait for trigger on any sensor
275-
		low_store = 0;
275+
      while((low_store != 1) &&
276-
		high_store = 0;
276+
            (high_store != 1) &&
277-
		counterA = 0;
277+
            (motion_store != 1))
278-
		counterB = 0;
278+
      {
279-
		motion_store = 0;
279+
280
         // Read the sensor data and store local
281-
		//wait for either ADC to match (ADC0 > ADC2) | (ADC1 > ADC3)
281+
         low_store    = read_prox(LOWPIN);
282-
		while((low_store != 1) && (high_store != 1) && (motion_store != 1))
282+
         high_store   = read_prox(HIGHPIN);
283-
		{
283+
         motion_store = motion_read();
284-
		
284+
285-
			//read the sensor data and store local
285+
      }
286-
			low_store = low_read();
286+
287-
			high_store = high_read();
287+
      // Determine which condition fired, so that the other may be watched later
288-
			motion_store = motion_read();
288+
      if (low_store == 1)
289
      {
290-
		}
290+
         // Low sensor fired
291-
		
291+
         trigger_direction = low;
292
293-
		//Determine which condition fired, so that the other may be watched later
293+
         // Play animations for low to high
294-
		if (low_store == 1)
294+
         animate_sequence(up, on);
295-
		{
295+
296-
			//low sensor fired
296+
      }
297-
			trigger_direction = low;
297+
      else if (high_store == 1)
298
      {
299-
			// play animations for low to high
299+
         // High sensor fired
300-
			animate_sequence(up, on);
300+
         trigger_direction = high;
301
302-
			//turn on leds in low to high sequence
302+
         // Play animations for high to low
303
         animate_sequence(down, on);
304-
			//wait for high sensor
304+
305-
			while((high_read() != 1) && (counterB <= TIMEOUT_MAX))
305+
      }
306-
			{
306+
      else
307-
				counterA++;
307+
      {
308-
				delay_ms(1);
308+
         //[tbd] motion detected animation
309-
				if (counterA >= 255)
309+
      }
310-
				{
310+
311-
					counterA = 0;
311+
      // Wait for other sensor or Timeout Counter
312-
					counterB++;
312+
      while((counterB <= TIMEOUT_MAX) && (sens1_store != 1))
313-
				}
313+
      {
314-
				
314+
315-
				if ((motion_read() == 1) || (low_read() == 1))
315+
         // Determine which is next sensor to watch
316-
				{
316+
         if (trigger_direction == low)
317-
					//motion detected, reset timer, turn lights on
317+
         {
318-
					counterB = 0;
318+
            sens1_store = read_prox(HIGHPIN);
319-
					PORTB = ALL_ON;
319+
            sens2_store = read_prox(LOWPIN);
320-
				}
320+
         }
321-
				
321+
         else if  (trigger_direction == high)
322-
				if (counterB > (2*TIMEOUT_MAX/3))
322+
         {
323-
				{
323+
            sens1_store = read_prox(LOWPIN);
324-
					//play standby animation (timeout is 2/3s complete)
324+
            sens2_store = read_prox(HIGHPIN);
325-
					standby_sequence(counterB);
325+
         }
326-
				}
326+
         motion_store = motion_read();
327
328-
			}
328+
         // Determine if timeout counter should be reset
329
         if ((motion_store == 1) || (sens2_store == 1))
330-
			//turn off LEDs
330+
         {
331-
			animate_sequence(up, off);
331+
            // Motion detected, reset timer
332
            counter_high = 0;
333-
		}
333+
334-
		else if (high_store == 1)
334+
            // Turn lights on
335-
		{
335+
            PORTB = ALL_ON;
336-
			//high sensor fired
336+
         }
337-
			trigger_direction = high;
337+
338
         // Timeout Counters, 1 tick >= 1ms.
339-
			//play animations for high to low
339+
         counter_low++;
340-
			animate_sequence(down, on);
340+
         delay_ms(1);
341
         if (counter_low >= 255)
342-
			//wait for low sensor
342+
         {
343-
			//also timeout
343+
            counter_low = 0;
344-
			while((low_read() != 1) && (counterB <= TIMEOUT_MAX))
344+
            counter_high++;
345-
			{
345+
         }
346-
				counterA++;
346+
347-
				delay_ms(1);
347+
         // Determine if timeout is 2/3rds complete
348-
				if (counterA >= 255)
348+
         if (counter_high > (2*TIMEOUT_MAX/3))
349-
				{
349+
         {
350-
					counterA = 0;
350+
            // Play standby animation
351-
					counterB++;
351+
            standby_sequence(counter_high);
352-
				}
352+
         }
353-
				
353+
354-
				if ((motion_read() == 1) || (high_read() == 1))
354+
      } // End wait for Timeout
355-
				{
355+
356-
					//motion detected, reset timer, turn lights on
356+
      // Turn off LEDs in proper sequence
357-
					counterB = 0;
357+
      if (trigger_direction == low)
358-
					PORTB = ALL_ON;
358+
      {
359-
				}
359+
         animate_sequence(up, off);
360-
				
360+
      }
361-
				if (counterB > (2*TIMEOUT_MAX/3))
361+
      else if  (trigger_direction == high)
362-
				{
362+
      {
363-
					//play standby animation (timeout is 2/3s complete)
363+
         animate_sequence(down, off);
364-
					standby_sequence(counterB);
364+
      }
365-
				}
365+
366
      // Small delay before lights are allowed to trigger again
367-
				
367+
      delay_ms(2000);
368-
			}
368+
369
   } // End Inf Loop
370-
			//turn off LEDs
370+
371-
			animate_sequence(down, off);
371+
372
373-
		}
373+