Last active
June 28, 2019 22:35
-
-
Save jasonhejna/96f2fd01f4c29510e0dfeb6b09fe6ee4 to your computer and use it in GitHub Desktop.
Robotic Curtain Control
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Stage Curtain Control System | |
// | |
// A Hall Effect Sensor is used to count the rotations of the drive motor. Two relays are used to power the motor on in either direction. | |
// Input is provided by an Up, and Down button operating on 12v DC. | |
// Input may be added later using WiFi, or Schedules. | |
// | |
// Author: Jason Hejna ([email protected]) | |
// Author: Mukesh Ramani | |
//void count_motor_rotation(void); | |
SYSTEM_MODE(MANUAL); | |
// Define Relay Pins | |
int RELAY1 = D3; | |
int RELAY2 = D4; | |
//int RELAY3 = D5; | |
//int RELAY4 = D6; | |
// Define Hall Effect Pin | |
int HALLEFFECT = A2; | |
// Buttons | |
int UPBUTTON = D5; | |
int upButton; | |
int DOWNBUTTON = D6; | |
int downButton; | |
bool upState = false; | |
bool downState = false; | |
bool isRunning = false; | |
// Constants | |
int min_position = -5; | |
int max_position = 5; | |
// Declare Variables | |
int error_state = false; | |
int rotation_count; | |
int active_rotation_count; | |
int hallSensor = 0; | |
int hallState0 = 0; | |
int hallState1 = 0; | |
int hallState2 = 0; | |
int curtainUpDownState = -1; | |
// EEPROM | |
int addr = 25; | |
uint16_t initValue; | |
bool eeprom_write_needed = false; | |
ApplicationWatchdog wd(20000, System.reset); | |
// Serial Logging Library | |
//SerialLogHandler logHandler; | |
// Timer for detecting if Hall Effect sensor fails to detect motor rotation | |
//void sensor_fail_detected() { | |
// Log.info("Hall Effect Sensor fail"); | |
// error_state = true; | |
//} | |
// | |
//// Interupt Timer for detecting Hall Effect sensor failure | |
//Timer sensor_check_timer(3000, sensor_fail_detected); | |
//void fall_off_timer() { | |
// if (!sensor_check_timer.isActive()) { | |
// sensor_check_timer.reset(); | |
// } | |
//} | |
void setup() { | |
// connect to particle cloud | |
Particle.connect(); | |
//Initilize the relay control pins as output | |
pinMode(RELAY1, OUTPUT); | |
pinMode(RELAY2, OUTPUT); | |
//pinMode(RELAY3, OUTPUT); | |
//pinMode(RELAY4, OUTPUT); | |
// Initialize all relays to an OFF state | |
digitalWrite(RELAY1, LOW); | |
digitalWrite(RELAY2, LOW); | |
//digitalWrite(RELAY3, LOW); | |
//digitalWrite(RELAY4, LOW); | |
//EEPROM.put(addr, 0); | |
// Check EEPROM | |
EEPROM.get(addr, initValue); | |
if (initValue == 0xFFFF) { | |
// EEPROM was empty -> initialize value | |
// Assume first run and set value to 0 | |
// Note: recalibration required if condition met | |
rotation_count = 0; | |
EEPROM.put(addr, rotation_count); | |
//Log.info("EEPROM is empty"); | |
} | |
else { | |
// Load rotation_count from EEPROM into memory | |
EEPROM.get(addr, rotation_count); | |
//Log.info("EEPROM is populated %d", rotation_count); | |
} | |
active_rotation_count = rotation_count; | |
Particle.variable("active_rotation_count", active_rotation_count); | |
// Initialize Hall Effect Sensor | |
pinMode(HALLEFFECT, INPUT); | |
//attachInterrupt(HALLEFFECT, count_motor_rotation, CHANGE); | |
// Initialize Push Buttons | |
pinMode(UPBUTTON, INPUT); | |
pinMode(DOWNBUTTON, INPUT); | |
} | |
void loop() { | |
// Read button values | |
upButton = digitalRead(UPBUTTON); | |
if (upButton) { | |
if (!isRunning) { | |
isRunning = true; | |
System.disableUpdates(); | |
noInterrupts(); | |
curtainUpDownState = 1; | |
upState = true; | |
} | |
} | |
downButton = digitalRead(DOWNBUTTON); | |
if (downButton) { | |
if (!isRunning) { | |
isRunning = true; | |
System.disableUpdates(); | |
noInterrupts(); | |
curtainUpDownState = -1; | |
downState = true; | |
} | |
} | |
//if (errorState) { | |
// digitalWrite(RELAY1, LOW); | |
// digitalWrite(RELAY2, LOW); | |
//} | |
if (upState && downState) { | |
// Error: motor cannot travel in two directions | |
digitalWrite(RELAY1, LOW); | |
digitalWrite(RELAY2, LOW); | |
upState = false; | |
downState = false; | |
} | |
else if(upState && rotation_count <= max_position) { | |
digitalWrite(RELAY1, HIGH); | |
digitalWrite(RELAY2, LOW); | |
// Add timeout if no rotation is detected after n seconds | |
//fall_off_timer(); | |
} | |
else if(downState && rotation_count >= min_position) { | |
digitalWrite(RELAY1, LOW); | |
digitalWrite(RELAY2, HIGH); | |
// Add timeout if no rotation is detected after n seconds | |
//fall_off_timer(); | |
} | |
else { | |
digitalWrite(RELAY1, LOW); | |
digitalWrite(RELAY2, LOW); | |
upState = false; | |
downState = false; | |
interrupts(); | |
System.enableUpdates(); | |
Particle.process(); | |
// backup eeprom | |
if (eeprom_write_needed) { | |
// TODO: run in timeout function | |
eeprom_write_needed = false; | |
EEPROM.put(addr, rotation_count); | |
active_rotation_count = rotation_count; | |
isRunning = false; | |
} | |
} | |
// Keep running count of motor rotation | |
count_motor_rotation(); | |
} | |
void count_motor_rotation() { | |
// capture Hall Effect to count motor shaft rotations | |
hallState0 = hallSensor; // Assign value before loop | |
hallSensor = digitalRead(HALLEFFECT); // 0 is on, 1 is off | |
hallState1 = hallSensor; // Assign value after read | |
if (hallState0 == 1 && hallState1 == 0 && hallState2 == 1) { | |
// should be off, on, and off again to trigger an increment | |
rotation_count += curtainUpDownState; | |
eeprom_write_needed = true; | |
//Log.info("rotations count %d", rotation_count); | |
//sensor_check_timer.stop(); | |
} | |
hallState2 = hallSensor; // Assign value after check | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment