Skip to content

Instantly share code, notes, and snippets.

@sixtyfive
Created November 11, 2017 12:45
Show Gist options
  • Save sixtyfive/5a7bef8d79dc644e9abb23aabfb014d7 to your computer and use it in GitHub Desktop.
Save sixtyfive/5a7bef8d79dc644e9abb23aabfb014d7 to your computer and use it in GitHub Desktop.
#define F_CPU 1000000UL // keep internal clock at 1 MHz, should be sufficient
#include <TinyWireM.h> // required by TinyDS1307
#include <USI_TWI_Master.h> // using I2C via the chip's USI
#include <TinyDS1307.h> // using the RTC - ATTN: the header needed changing to set the RTCs
// memory size to 0 because setting it to its actual value (56 bytes)
// grows the sketch beyond bounds!
#include <PinChangeInterrupt.h> // using PCINTs instead of INTs
#include <avr/io.h> // direct port manipulation
#include <util/delay.h> // to have a substitute for delay()
// Uncomment to initialize RTC after loss of power, etc.
// (need to set time inside setup() first!)
#define SET_RTC_TIME TRUE
// pins
#define SDA 0 /* PB0 or pin 5 */
#define RELAY 1 /* PB1 or pin 6 */
#define SCL 2 /* PB2 or pin 7 */
#define BUTTON 3 /* PB3 or pin 2 */
#define LED 4 /* PB4 or pin 3 */
// abstractions
#define UIV_ON HIGH
#define UIV_OFF LOW
#define INV_ON LOW
#define INV_OFF HIGH
// settings
#define LED_BLINK_FREQ 750 /* milliseconds */
// list of operating states
enum opstates {
OFF, /* to coincide with 0/LOW/FALSE */
ON, /* to coincide with 1/HIGH/TRUE */
AUTO /* the only one that can not be treated as boolean */
};
// globals (ew!)
unsigned long led_blink_moment = 0 /* milliseconds */;
unsigned char led_state = UIV_OFF;
unsigned char relay_state = INV_OFF;
volatile enum opstates op_state = AUTO;
void setup()
{
// pinMode(RELAY, OUTPUT);
// pinMode(LED, OUTPUT);
// pinMode(BUTTON, INPUT);
DDRB = 0b00010010; // PB1 and PB4, pins 6 and 3
// (all zeroes are inputs by default)
// the button doesn't sit on pin 7, which is the only one supporting INTn
// style interrupts. pin 2 is PCINTn style, so can't use attachInterrupt().
attachPCINT(digitalPinToPinChangeInterrupt(BUTTON), cycle_opstate, RISING);
TinyWireM.begin();
tinyrtc.begin();
#ifdef SET_RTC_TIME
if (!tinyrtc.isrunning()) // if the #define is set, we always want to adjust the time
tinyrtc.adjust(2017,11,11, 14,12,00);
#endif
}
void loop()
{
set_led_state();
set_relay_state();
}
void cycle_opstate()
{
// go from AUTO to ON to OFF to AUTO, and so forth...
if (op_state < AUTO) {
op_state = op_state + 1; // can't opstate++ - it's an enum!
} else {
op_state = OFF;
}
// ensure a bit of a nicer transition
led_state = UIV_OFF;
led_blink_moment = millis();
}
void blink_led()
{
unsigned long current_time = millis();
if (current_time - led_blink_moment >= LED_BLINK_FREQ) {
led_blink_moment = current_time;
led_state = !led_state;
}
}
void set_led_state()
{
if (op_state == AUTO) {
blink_led();
} else {
led_state = op_state; // yup, this is crazy, because i'm crazy.
// works because usually HIGH==1 and LOW==0,
// also see enum declaration comments.
}
if (digitalRead(LED) != led_state) digitalWrite(LED, led_state);
// if (led_state != (PINB & 1 << PB4)) PORTB = (led_state << PB4);
}
void parker_lewis_clock_check()
{
tinyrtc.read();
unsigned char the_hour = tinyrtc.hour(); // char is smaller than int and sufficient for a 0-23 value
// unsigned char the_hour = 22; // for debugging only
switch (the_hour) {
case 0 ... 5 /* night */: relay_state = INV_OFF ; break;
case 6 ... 9 /* morning */: relay_state = INV_ON ; break;
case 10 ... 16 /* noon break */: relay_state = INV_OFF ; break;
case 17 ... 23 /* evening */: relay_state = INV_ON ; break;
}
}
void set_relay_state()
{
if (op_state == AUTO) {
parker_lewis_clock_check();
} else {
relay_state = !op_state; // inverted because the relay goes ON on LOW!
// possible because the first two enum states
// correspond to HIGH (1) and LOW (0).
}
if (digitalRead(RELAY) != relay_state) {
// if (relay_state != (PINB & 1 << PB1)) {
digitalWrite(RELAY, relay_state);
// PORTB = (relay_state << PB1);
// no more space left to include delay(),
// but need some buffering for the button
_delay_ms(350 /* milliseconds */);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment