// // // lights.c // // This is the code for an ATTiny within a circuit that controls // grow lights. // The grow lights operate on a 14 hour ON/10 hour OFF cycle. // Whether they are ON vs OFF is controlled by an ATTiny that // uses a MOSFET as a logical switch for the grow lights. // There are LEDs that indicate where the timer is in the // 14 hour ON/10 hour OFF cycle. ON LEDs line up to count // the hours ON in binary, while OFF LEDs line up to count the // hours OFF in binary. // // // // Alex Berke, 2018 // Based on code supplied by Neil Gershenfeld // // (c) Massachusetts Institute of Technology 2010 // This work may be reproduced, modified, distributed, // performed, and displayed for any purpose. Copyright is // retained and must be preserved. The work is provided // as is; no warranty is provided, and users accept all // liability. // #include #include #define output(directions, pin) (directions |= pin) // set port direction for output #define input(directions,pin) (directions &= (~pin)) // set port direction for input #define set(port, pin) (port |= pin) // set port pin #define clear(port, pin) (port &= (~pin)) // clear port pin #define led_delay() _delay_ms(100) #define second_sleep() _delay_ms(1000) // The grow lights are set ON between the following hours: #define GROW_LIGHTS_ON_CYCLE_START 1 #define GROW_LIGHTS_ON_CYCLE_END 14 // The LEDs are numbeOFF by the bit they show in binary counting. #define OFF_LED_0_PIN (1 << PA7) #define OFF_LED_0_PORT PORTA #define OFF_LED_0_DIRECTION DDRA #define OFF_LED_1_PIN (1 << PB2) #define OFF_LED_1_PORT PORTB #define OFF_LED_1_DIRECTION DDRB #define OFF_LED_2_PIN (1 << PB1) #define OFF_LED_2_PORT PORTB #define OFF_LED_2_DIRECTION DDRB #define OFF_LED_3_PIN (1 << PB0) #define OFF_LED_3_PORT PORTB #define OFF_LED_3_DIRECTION DDRB #define ON_LED_0_PIN (1 << PA3) #define ON_LED_0_PORT PORTA #define ON_LED_0_DIRECTION DDRA #define ON_LED_1_PIN (1 << PA2) #define ON_LED_1_PORT PORTA #define ON_LED_1_DIRECTION DDRA #define ON_LED_2_PIN (1 << PA1) #define ON_LED_2_PORT PORTA #define ON_LED_2_DIRECTION DDRA #define ON_LED_3_PIN (1 << PA0) #define ON_LED_3_PORT PORTA #define ON_LED_3_DIRECTION DDRA #define MOSFET_PIN (1 << PA5) #define MOSFET_PORT PORTA #define MOSFET_DIRECTION DDRA void initialize_leds() { // Initialize OFF LEDs clear(OFF_LED_0_PORT, OFF_LED_0_PIN); output(OFF_LED_0_DIRECTION, OFF_LED_0_PIN); clear(OFF_LED_1_PORT, OFF_LED_1_PIN); output(OFF_LED_1_DIRECTION, OFF_LED_1_PIN); clear(OFF_LED_2_PORT, OFF_LED_2_PIN); output(OFF_LED_2_DIRECTION, OFF_LED_2_PIN); clear(OFF_LED_3_PORT, OFF_LED_3_PIN); output(OFF_LED_3_DIRECTION, OFF_LED_3_PIN); // Initialize ON LEDs clear(ON_LED_0_PORT, ON_LED_0_PIN); output(ON_LED_0_DIRECTION, ON_LED_0_PIN); clear(ON_LED_1_PORT, ON_LED_1_PIN); output(ON_LED_1_DIRECTION, ON_LED_1_PIN); clear(ON_LED_2_PORT, ON_LED_2_PIN); output(ON_LED_2_DIRECTION, ON_LED_2_PIN); clear(ON_LED_3_PORT, ON_LED_3_PIN); output(ON_LED_3_DIRECTION, ON_LED_3_PIN); } void clear_all_leds() { // Clear OFF LEDs clear(OFF_LED_0_PORT, OFF_LED_0_PIN); clear(OFF_LED_1_PORT, OFF_LED_1_PIN); clear(OFF_LED_2_PORT, OFF_LED_2_PIN); clear(OFF_LED_3_PORT, OFF_LED_3_PIN); // Clear ON LEDs clear(ON_LED_0_PORT, ON_LED_0_PIN); clear(ON_LED_1_PORT, ON_LED_1_PIN); clear(ON_LED_2_PORT, ON_LED_2_PIN); clear(ON_LED_3_PORT, ON_LED_3_PIN); } void set_timer_leds(int hour, int on_off) { // Timer LEDs should be set // Max necessary time is 14 (length of light cycle ON) if (hour == 1) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); } } else if (hour == 2) { if (on_off == 0) { set(ON_LED_1_PORT, ON_LED_1_PIN); } else { set(OFF_LED_1_PORT, OFF_LED_1_PIN); } } else if (hour == 3) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_1_PORT, ON_LED_1_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_1_PORT, OFF_LED_1_PIN); } } else if (hour == 4) { if (on_off == 0) { set(ON_LED_2_PORT, ON_LED_2_PIN); } else { set(OFF_LED_2_PORT, OFF_LED_2_PIN); } } else if (hour == 5) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_2_PORT, ON_LED_2_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_2_PORT, OFF_LED_2_PIN); } } else if (hour == 6) { if (on_off == 0) { set(ON_LED_1_PORT, ON_LED_1_PIN); set(ON_LED_2_PORT, ON_LED_2_PIN); } else { set(OFF_LED_1_PORT, OFF_LED_1_PIN); set(OFF_LED_2_PORT, OFF_LED_2_PIN); } } else if (hour == 7) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_1_PORT, ON_LED_1_PIN); set(ON_LED_2_PORT, ON_LED_2_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_1_PORT, OFF_LED_1_PIN); set(OFF_LED_2_PORT, OFF_LED_2_PIN); } } else if (hour == 8) { if (on_off == 0) { set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 9) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 10) { if (on_off == 0) { set(ON_LED_1_PORT, ON_LED_1_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_1_PORT, OFF_LED_1_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 11) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_1_PORT, ON_LED_1_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_1_PORT, OFF_LED_1_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 12) { if (on_off == 0) { set(ON_LED_2_PORT, ON_LED_2_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_2_PORT, OFF_LED_2_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 13) { if (on_off == 0) { set(ON_LED_0_PORT, ON_LED_0_PIN); set(ON_LED_2_PORT, ON_LED_2_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_0_PORT, OFF_LED_0_PIN); set(OFF_LED_2_PORT, OFF_LED_2_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } else if (hour == 14) { if (on_off == 0) { set(ON_LED_1_PORT, ON_LED_1_PIN); set(ON_LED_2_PORT, ON_LED_2_PIN); set(ON_LED_3_PORT, ON_LED_3_PIN); } else { set(OFF_LED_1_PORT, OFF_LED_1_PIN); set(OFF_LED_2_PORT, OFF_LED_2_PIN); set(OFF_LED_3_PORT, OFF_LED_3_PIN); } } } int main (void) { // // main // // set clock divider to /1 CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // Initialize LED pins initialize_leds(); // initialize MOSFET pin clear(MOSFET_PORT, MOSFET_PIN); output(MOSFET_DIRECTION, MOSFET_PIN); // main loop while (1) { // Loops through a 24 hour cycle, updating the lights given the hour in the cycle. int second, minute, hour; for (hour = 1; hour <= 24; hour ++) { clear_all_leds(); // Set MOSFET gate/grow lights ON vs OFF depending on time // and set timer LEDs accordingly. if ((hour >= GROW_LIGHTS_ON_CYCLE_START) && (hour <= GROW_LIGHTS_ON_CYCLE_END)) { // light cycle: ON set(MOSFET_PORT, MOSFET_PIN); int light_cycle_hour = hour; set_timer_leds(light_cycle_hour, 0); } else { // light cycle: OFF clear(MOSFET_PORT, MOSFET_PIN); int light_cycle_hour = hour - GROW_LIGHTS_ON_CYCLE_END; set_timer_leds(light_cycle_hour, 1); } for (minute = 1; minute <= 60; minute ++) { for (second = 1; second <= 60; second ++) { second_sleep(); // Sleep for 1 second } } } } }