initial commit
commit
df14c5c690
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Filename: main.cpp
|
||||
*
|
||||
* Description: device to turn out lights in the bathroom based on a
|
||||
* PIR sensor.
|
||||
*
|
||||
* Version:
|
||||
* Created: Sat Jan 12 22:54:52 2019
|
||||
* Revision: None
|
||||
* Author: Rachel Fae Fox (foxiepaws),fox@foxiepa.ws
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Servo.h>
|
||||
|
||||
enum states { inactive = 0, active, waiting };
|
||||
|
||||
const int led = 11;
|
||||
const int pir = 6;
|
||||
const int power = 5;
|
||||
const int servo = 9 ;
|
||||
|
||||
#define MOTION_HEURUSTIC 5
|
||||
#define MILLIS 1000
|
||||
#define POWER_TIME (6 * MILLIS)
|
||||
#define CHECK_POWER_TIME (3 * MILLIS)
|
||||
|
||||
int motion = 0;
|
||||
|
||||
elapsedMillis motionTimer; // motion Timeout
|
||||
elapsedMillis powerTimer; // Power Timeout
|
||||
elapsedMillis cPowerTimer; // checkPower timeout
|
||||
|
||||
Servo lightSwitch;
|
||||
#define SERVO_RESTING_POSITION 90
|
||||
#define SERVO_SWITCH_PLATE_MOTION 20
|
||||
#define SERVO_SLEW_TIME 120
|
||||
#define SERVO_SLEW_DEG 60
|
||||
#define SERVO_SLEW_RATE (SERVO_SLEW_TIME/SERVO_SLEW_DEG)
|
||||
#define SERVO_MIN 0
|
||||
#define SERVO_MAX 180
|
||||
|
||||
enum states state = inactive;
|
||||
int powerState = 0;
|
||||
int wantedPowerState = 0;
|
||||
int servoPosition = 0;
|
||||
int servoDir = 1;
|
||||
// Saturation of servo position.
|
||||
int servoSat ( int pos ) {
|
||||
if (pos >= SERVO_MAX) {
|
||||
return SERVO_MAX;
|
||||
} else if (pos <= SERVO_MIN) {
|
||||
return SERVO_MIN;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
// function to solve a delay for a move, given a slew rate
|
||||
// this is to avoid running into a bad move where a new command
|
||||
// is sent before the servo has had time to make its move.
|
||||
void servoDelay(int oldpos, int newpos) {
|
||||
int delayTime = abs(oldpos - newpos) * SERVO_SLEW_RATE;
|
||||
delay(delayTime);
|
||||
}
|
||||
|
||||
void servoMove ( int pos ) {
|
||||
int oldPos = servoPosition;
|
||||
servoPosition = servoSat(pos);
|
||||
lightSwitch.write(servoPosition);
|
||||
servoDelay(oldPos, servoPosition);
|
||||
}
|
||||
|
||||
void servoAdd ( int amount ) {
|
||||
servoMove(servoPosition + amount );
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(led, OUTPUT);
|
||||
pinMode(pir, INPUT);
|
||||
pinMode(power, INPUT);
|
||||
lightSwitch.attach(servo);
|
||||
servoMove(SERVO_RESTING_POSITION);
|
||||
}
|
||||
|
||||
|
||||
void evalPowerState() {
|
||||
int actualPowerState = digitalRead(power);
|
||||
|
||||
switch (powerState) {
|
||||
case 0: // power off
|
||||
if (actualPowerState == 1) {
|
||||
powerState = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: // power on
|
||||
if (actualPowerState == 0) {
|
||||
powerState = 0;
|
||||
break;
|
||||
}
|
||||
if (wantedPowerState == 0) {
|
||||
servoDir = -1;
|
||||
servoMove(SERVO_RESTING_POSITION + SERVO_SWITCH_PLATE_MOTION);
|
||||
servoMove(SERVO_RESTING_POSITION);
|
||||
cPowerTimer = 0;
|
||||
powerState = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: // transitional;
|
||||
if (wantedPowerState == 0 and actualPowerState == 0) {
|
||||
powerState = 0;
|
||||
break;
|
||||
}
|
||||
if (wantedPowerState == 0 and actualPowerState == 1 and cPowerTimer >= CHECK_POWER_TIME) {
|
||||
servoMove(SERVO_RESTING_POSITION + (servoDir * SERVO_SWITCH_PLATE_MOTION));
|
||||
servoMove(SERVO_RESTING_POSITION);
|
||||
servoDir *= -1;
|
||||
cPowerTimer = 0;
|
||||
break;
|
||||
}
|
||||
if (wantedPowerState == 1 and actualPowerState == 1) {
|
||||
powerState = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void evalMainState() {
|
||||
switch (state) {
|
||||
case inactive:
|
||||
// return to inactive state if the light gets turned off.
|
||||
if (powerState == 1) {
|
||||
state = active;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case active:
|
||||
digitalWrite(led,HIGH);
|
||||
// return to inactive state if the light gets turned off.
|
||||
if (powerState == 0) {
|
||||
state = inactive;
|
||||
break;
|
||||
}
|
||||
if (powerState == 2) {
|
||||
wantedPowerState = 1;
|
||||
}
|
||||
if (digitalRead(pir)) {
|
||||
motionTimer = 0;
|
||||
}
|
||||
// if the pir has not detected motion for 5 seconds change state
|
||||
if (!digitalRead(pir) and motionTimer >= MILLIS *5) {
|
||||
state = waiting;
|
||||
// reset the power timer to start counting
|
||||
powerTimer = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case waiting:
|
||||
// return to inactive state if the light gets turned off.
|
||||
// blinky while timer is active, doubling up the motion timer use.
|
||||
if(motionTimer >= 1000)
|
||||
digitalWrite(led,HIGH);
|
||||
if(motionTimer > 2000) {
|
||||
digitalWrite(led,LOW);
|
||||
motionTimer = 0;
|
||||
}
|
||||
if (powerState == 0) {
|
||||
state = inactive;
|
||||
break;
|
||||
}
|
||||
if (digitalRead(pir)) {
|
||||
state = active;
|
||||
break;
|
||||
}
|
||||
if (powerTimer >= POWER_TIME ) {
|
||||
wantedPowerState = 0;
|
||||
state = inactive;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void loop () {
|
||||
evalMainState();
|
||||
evalPowerState();
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#+TITLE: AutoSwitcher
|
||||
|
||||
This project is separated into two parts
|
||||
|
||||
* Schematic
|
||||
All schematic stuff will probably be done in kicad, it has not yet been made.
|
||||
* Code
|
||||
Code is written using Arduino currently.
|
||||
|
||||
* License
|
||||
Code is licensed under BSD2. Design files are licensed under CC-BY
|
Loading…
Reference in New Issue