Advertisement
dlwestab

StairLight - Draft B

Jan 23rd, 2012
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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:
  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
  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.  
  51.  
  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 Subroutine           |
  88. //--------------------------------------
  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)
  92. {
  93.   while ( ms )
  94.   {
  95.     _delay_ms(1);
  96.     ms--;
  97.   }
  98. }
  99.  
  100. //--------------------------------------
  101. //          Other Functions            |
  102. //--------------------------------------
  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.  
  115.    int i;
  116.  
  117.    //determine if count is even or odd
  118.    PORTB = ALL_OFF;
  119.    if (count % 2 == 0)
  120.    {
  121.       //every other bit, even
  122.       for (i=START_CH; i <= NUM_OF_CH; i+=2)
  123.       {
  124.          PORTB |= (1 << i);
  125.       }
  126.    }
  127.    else
  128.    {
  129.       //every other bit, odd
  130.       for (i=(START_CH+1); i <= NUM_OF_CH; i+=2)
  131.       {
  132.          PORTB |= (1 << i);
  133.       }
  134.    }
  135.  
  136.  
  137. }
  138.  
  139. void animate_sequence(int direction, int onoff)
  140. {
  141.    int time = 100;
  142.    int i;
  143.  
  144.    if(direction == up)
  145.    {
  146.       if (onoff == on )
  147.       {
  148.          // Animates by rotating through.
  149.          PORTB = ALL_OFF;
  150.          for (i=START_CH; i < NUM_OF_CH; i++)
  151.          {
  152.             PORTB |= (1 << i);
  153.             delay_ms(time);
  154.          }
  155.  
  156.       }
  157.       else
  158.       {
  159.          // Animates by rotating through.
  160.          PORTB = ALL_ON;
  161.          for (i=START_CH; i < NUM_OF_CH; i++)
  162.          {
  163.             PORTB &= ~(1 << i);
  164.             delay_ms(time);
  165.          }
  166.  
  167.       }
  168.  
  169.    }
  170.    else
  171.    {
  172.       if (onoff == on )
  173.       {
  174.          // Animates by reverse rotating through.
  175.          PORTB = ALL_OFF;
  176.          for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
  177.          {
  178.             PORTB |= (1 << i);
  179.             delay_ms(time);
  180.          }
  181.       }
  182.       else
  183.       {
  184.          // Animates by reverse rotating through.
  185.          PORTB = ALL_ON;
  186.          for (i=( START_CH + NUM_OF_CH - 1); i >= 0; i--)
  187.          {
  188.             PORTB &= ~(1 << i);
  189.             delay_ms(time);
  190.          }
  191.       }
  192.    }
  193.  
  194. }
  195.  
  196. int read_prox(int pin)
  197. {
  198.    // This function allows for some debouncing
  199.  
  200.    if (bit_is_set(PIND, pin))
  201.    {
  202.       delay_ms(1);
  203.       if (bit_is_set(PIND, pin))
  204.       {
  205.          return 1;
  206.       }
  207.    }
  208.  
  209.    return 0;
  210. }
  211.  
  212. int motion_read()
  213. {
  214.  
  215.    //[tbd] read motion sensor
  216.  
  217.    return 0;
  218. }
  219.  
  220.  
  221. void init_cpu()
  222. {
  223.    // Set direction registers
  224.    // sensors data direction
  225.    // lighting data direction
  226.  
  227.    DDRA =  0b11111111;
  228.    DDRB =  0b11111111;
  229.    DDRD =  0b00000000;
  230.  
  231.    // Enable Wake Interrupts
  232.    //[TBD]
  233.  
  234.    // Set power down mode
  235.    //[tbd]
  236.  
  237. }
  238.  
  239.  
  240. //--------------------------------------
  241. //               Main                  |
  242. //--------------------------------------
  243. int main (void)
  244. {
  245.    // Local Variables
  246.    int low_store = 0, high_store = 0, sens_store;
  247.    int trigger_direction;
  248.    int counterA, counterB;
  249.    int motion_store = 0;
  250.    int TIMEOUT_MAX = 117; // approx >30 seconds, (30*1000/255) ~= 117
  251.  
  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.    // Loop forever
  263.    // TBD: Replace with timeout to sleep and save power
  264.    while(1)
  265.    {
  266.       low_store = 0;
  267.       high_store = 0;
  268.       counterA = 0;
  269.       counterB = 0;
  270.       motion_store = 0;
  271.       sens1_store = 0;
  272.       sens2_store = 0;
  273.  
  274.       // Wait for trigger on any sensor
  275.       while((low_store != 1) &&
  276.             (high_store != 1) &&
  277.             (motion_store != 1))
  278.       {
  279.  
  280.          // Read the sensor data and store local
  281.          low_store    = read_prox(LOWPIN);
  282.          high_store   = read_prox(HIGHPIN);
  283.          motion_store = motion_read();
  284.  
  285.       }
  286.  
  287.       // Determine which condition fired, so that the other may be watched later
  288.       if (low_store == 1)
  289.       {
  290.          // Low sensor fired
  291.          trigger_direction = low;
  292.  
  293.          // Play animations for low to high
  294.          animate_sequence(up, on);
  295.  
  296.       }
  297.       else if (high_store == 1)
  298.       {
  299.          // High sensor fired
  300.          trigger_direction = high;
  301.  
  302.          // Play animations for high to low
  303.          animate_sequence(down, on);
  304.  
  305.       }
  306.       else
  307.       {
  308.          //[tbd] motion detected animation
  309.       }
  310.  
  311.       // Wait for other sensor or Timeout Counter
  312.       while((counterB <= TIMEOUT_MAX) && (sens1_store != 1))
  313.       {
  314.  
  315.          // Determine which is next sensor to watch
  316.          if (trigger_direction == low)
  317.          {
  318.             sens1_store = read_prox(HIGHPIN);
  319.             sens2_store = read_prox(LOWPIN);
  320.          }
  321.          else if  (trigger_direction == high)
  322.          {
  323.             sens1_store = read_prox(LOWPIN);
  324.             sens2_store = read_prox(HIGHPIN);
  325.          }
  326.          motion_store = motion_read();
  327.  
  328.          // Determine if timeout counter should be reset
  329.          if ((motion_store == 1) || (sens2_store == 1))
  330.          {
  331.             // Motion detected, reset timer
  332.             counter_high = 0;
  333.  
  334.             // Turn lights on
  335.             PORTB = ALL_ON;
  336.          }
  337.  
  338.          // Timeout Counters, 1 tick >= 1ms.
  339.          counter_low++;
  340.          delay_ms(1);
  341.          if (counter_low >= 255)
  342.          {
  343.             counter_low = 0;
  344.             counter_high++;
  345.          }
  346.  
  347.          // Determine if timeout is 2/3rds complete
  348.          if (counter_high > (2*TIMEOUT_MAX/3))
  349.          {
  350.             // Play standby animation
  351.             standby_sequence(counter_high);
  352.          }
  353.  
  354.       } // End wait for Timeout
  355.  
  356.       // Turn off LEDs in proper sequence
  357.       if (trigger_direction == low)
  358.       {
  359.          animate_sequence(up, off);
  360.       }
  361.       else if  (trigger_direction == high)
  362.       {
  363.          animate_sequence(down, off);
  364.       }
  365.  
  366.       // Small delay before lights are allowed to trigger again
  367.       delay_ms(2000);
  368.  
  369.    } // End Inf Loop
  370.  
  371.   while(1);                 // Ending infinite loop (just in case)
  372.  
  373. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement