Skip to content

Instantly share code, notes, and snippets.

@jasonhejna
Last active June 28, 2019 22:35
Show Gist options
  • Save jasonhejna/96f2fd01f4c29510e0dfeb6b09fe6ee4 to your computer and use it in GitHub Desktop.
Save jasonhejna/96f2fd01f4c29510e0dfeb6b09fe6ee4 to your computer and use it in GitHub Desktop.
Robotic Curtain Control
// 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 (jason.hejna@gmail.com)
// 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