Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Copyright 2011 Dustin L. Westaby
- ----------------------------------------------------------------------
- Stairway Light Controller for Attiny2313
- ----------------------------------------------------------------------
- Title: stairway.c
- Author: Dustin Westaby
- Date Created: 01/19/12
- Last Modified:
- Purpose: Monitor proximity and motion sensors and animate stairway
- lighting.
- Compiled with AVR-GCC WinAVR
- Revisions List:
- 01/19/12 Initial draft
- ----------------------------------------------------------------------
- Fuses:
- ----------------------------------------------------------------------
- BrownOut Disabled
- CKDIV8
- Int RC Osc 8Mhz + 64ms
- ----------------------------------------------------------------------
- Inputs:
- ----------------------------------------------------------------------
- pin port function
- ----------------------------------------------------------------------
- 1 RST Unused
- 2 PD0 Motion Sensor (digital) (active low with pullup 10k)
- 23 PC0 Prox Sensor Low (digital) 5 feet range
- 24 PC1 Prox Sensor High (digital)
- 4 PD2 Override button (digital) External Interrupt 0
- ----------------------------------------------------------------------
- Ouputs:
- ----------------------------------------------------------------------
- pin port function
- ----------------------------------------------------------------------
- 14 PB0 Lighting Channel
- 15 PB1 Lighting Channel
- 16 PB2 Lighting Channel
- 17 PB3 Lighting Channel
- 18 PB4 Lighting Channel
- 19 PB5 Lighting Channel
- 9 PB6 Lighting Channel
- 10 PB7 Lighting Channel
- The Prox sensors are analog, uses a comparator to convert to digital
- and a pot to select the cutoff range.
- */
- //--------------------------------------
- // Global Variables |
- //--------------------------------------
- // 8 MHz Internal Oscillator DIV8 (used for delay subroutines)
- // One CPU Cycle = 1us
- #define F_CPU 8000000UL/8
- enum { up, down };
- enum { on, off };
- enum { low, high };
- //--------------------------------------
- // Includes |
- //--------------------------------------
- #include <avr/io.h>
- #include <util/delay.h>
- //#include <avr/sleep.h>
- #include <inttypes.h>
- //--------------------------------------
- // Global Constants |
- //--------------------------------------
- int START_CH = PB0; //lowest channel bit
- int NUM_OF_CH = 6;
- int ALL_ON = 0xFF;
- int ALL_OFF = 0x00;
- //--------------------------------------
- // Delay Subroutine |
- //--------------------------------------
- //This function is from the delay.h include, the calls to delay functions
- //are re-written here to allow for longer waits.
- void delay_ms(uint16_t ms)
- {
- while ( ms )
- {
- _delay_ms(1);
- ms--;
- }
- }
- //--------------------------------------
- // Other Functions |
- //--------------------------------------
- void standby_sequence(int count)
- {
- // Description:
- // This function animates a back and forth motion
- // Approx 4 transitions per second
- // Example:
- // 0 1 2 3 4 5 6 7 8 Channels
- // 0 1 0 1 0 1 0 1 0 Odd Count
- // 1 0 1 0 1 0 1 0 1 Even Count
- int i;
- //determine if count is even or odd
- PORTB = ALL_OFF;
- if (count % 2 == 0)
- {
- //every other bit, even
- for (i=START_CH; i <= NUM_OF_CH; i+=2)
- {
- PORTB |= (1 << i);
- }
- }
- else
- {
- //every other bit, odd
- for (i=(START_CH+1); i <= NUM_OF_CH; i+=2)
- {
- PORTB |= (1 << i);
- }
- }
- }
- void animate_sequence(int direction, int onoff)
- {
- int time = 100;
- int i;
- if(direction == up)
- {
- if (onoff == on )
- {
- // Animates by rotating through.
- PORTB = ALL_OFF;
- for (i=START_CH; i < NUM_OF_CH; i++)
- {
- PORTB |= (1 << i);
- delay_ms(time);
- }
- }
- else
- {
- // Animates by rotating through.
- PORTB = ALL_ON;
- for (i=START_CH; i < NUM_OF_CH; i++)
- {
- PORTB &= ~(1 << i);
- delay_ms(time);
- }
- }
- }
- else
- {
- if (onoff == on )
- {
- // Animates by reverse rotating through.
- PORTB = ALL_OFF;
- for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
- {
- PORTB |= (1 << i);
- delay_ms(time);
- }
- }
- else
- {
- // Animates by reverse rotating through.
- PORTB = ALL_ON;
- for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
- {
- PORTB &= ~(1 << i);
- delay_ms(time);
- }
- }
- }
- }
- int read_prox(int pin)
- {
- // This function allows for some debouncing
- if (bit_is_set(PIND, pin))
- {
- delay_ms(1);
- if (bit_is_set(PIND, pin))
- {
- return 1;
- }
- }
- return 0;
- }
- int motion_read()
- {
- //[tbd] read motion sensor
- return 0;
- }
- void init_cpu()
- {
- // Set direction registers
- // sensors data direction
- // lighting data direction
- DDRA = 0b11111111;
- DDRB = 0b11111111;
- DDRD = 0b00000000;
- // Enable Wake Interrupts
- //[TBD]
- // Set power down mode
- //[tbd]
- }
- //--------------------------------------
- // Main |
- //--------------------------------------
- int main (void)
- {
- // Local Variables
- int low_store = 0, high_store = 0, sens_store;
- int trigger_direction;
- int counterA, counterB;
- int motion_store = 0;
- int TIMEOUT_MAX = 117; // approx >30 seconds, (30*1000/255) ~= 117
- // Pin position of Prox Sensors
- int LOWPIN = PD0;
- int HIGHPIN = PD1;
- // Initialize registers
- init_cpu();
- // Turn off LEDs
- PORTB = 0x00;
- // Loop forever
- // TBD: Replace with timeout to sleep and save power
- while(1)
- {
- low_store = 0;
- high_store = 0;
- counterA = 0;
- counterB = 0;
- motion_store = 0;
- sens1_store = 0;
- sens2_store = 0;
- // Wait for trigger on any sensor
- while((low_store != 1) &&
- (high_store != 1) &&
- (motion_store != 1))
- {
- // Read the sensor data and store local
- low_store = read_prox(LOWPIN);
- high_store = read_prox(HIGHPIN);
- motion_store = motion_read();
- }
- // Determine which condition fired, so that the other may be watched later
- if (low_store == 1)
- {
- // Low sensor fired
- trigger_direction = low;
- // Play animations for low to high
- animate_sequence(up, on);
- }
- else if (high_store == 1)
- {
- // High sensor fired
- trigger_direction = high;
- // Play animations for high to low
- animate_sequence(down, on);
- }
- else
- {
- //[tbd] motion detected animation
- }
- // Wait for other sensor or Timeout Counter
- while((counterB <= TIMEOUT_MAX) && (sens1_store != 1))
- {
- // Determine which is next sensor to watch
- if (trigger_direction == low)
- {
- sens1_store = read_prox(HIGHPIN);
- sens2_store = read_prox(LOWPIN);
- }
- else if (trigger_direction == high)
- {
- sens1_store = read_prox(LOWPIN);
- sens2_store = read_prox(HIGHPIN);
- }
- motion_store = motion_read();
- // Determine if timeout counter should be reset
- if ((motion_store == 1) || (sens2_store == 1))
- {
- // Motion detected, reset timer
- counter_high = 0;
- // Turn lights on
- PORTB = ALL_ON;
- }
- // Timeout Counters, 1 tick >= 1ms.
- counter_low++;
- delay_ms(1);
- if (counter_low >= 255)
- {
- counter_low = 0;
- counter_high++;
- }
- // Determine if timeout is 2/3rds complete
- if (counter_high > (2*TIMEOUT_MAX/3))
- {
- // Play standby animation
- standby_sequence(counter_high);
- }
- } // End wait for Timeout
- // Turn off LEDs in proper sequence
- if (trigger_direction == low)
- {
- animate_sequence(up, off);
- }
- else if (trigger_direction == high)
- {
- animate_sequence(down, off);
- }
- // Small delay before lights are allowed to trigger again
- delay_ms(2000);
- } // End Inf Loop
- while(1); // Ending infinite loop (just in case)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement