200 lines
8.1 KiB
C++
200 lines
8.1 KiB
C++
// Used for non-latching relay control
|
|
#ifndef NonLatchingRelay_h
|
|
#include "NonLatchingRelay.h"
|
|
#endif
|
|
|
|
#ifndef Arduino_H
|
|
#include <Arduino.h>
|
|
#endif
|
|
|
|
NonLatchingRelay::NonLatchingRelay(String name, unsigned int pin, unsigned int pin_readback, unsigned int voltage_read_pin) {
|
|
this->name = name;
|
|
this->pin = pin;
|
|
this->pin_readback = pin_readback;
|
|
this->voltage_read_pin = voltage_read_pin;
|
|
|
|
pinMode(pin, OUTPUT);
|
|
pinMode(pin_readback, INPUT);
|
|
pinMode(voltage_read_pin, INPUT);
|
|
}
|
|
|
|
NonLatchingRelay::NonLatchingRelay(unsigned int pin, unsigned int pin_readback, unsigned int voltage_read_pin) {
|
|
this->pin = pin;
|
|
this->pin_readback = pin_readback;
|
|
this->voltage_read_pin = voltage_read_pin;
|
|
|
|
pinMode(pin, OUTPUT);
|
|
pinMode(pin_readback, INPUT);
|
|
pinMode(voltage_read_pin, INPUT);
|
|
}
|
|
|
|
void NonLatchingRelay::set_desired_state(unsigned char new_desired_state) {
|
|
if (new_desired_state == 0) {
|
|
desired_state = false; // Closed
|
|
} else if (new_desired_state == 1) {
|
|
desired_state = true; // Open
|
|
} else if (new_desired_state == 3) { // Keep last desired state
|
|
desired_state = desired_state;
|
|
}
|
|
}
|
|
|
|
float NonLatchingRelay::read_relay_voltage() {
|
|
// Read the voltage across the relay
|
|
unsigned int raw_read = analogRead(voltage_read_pin); // maps (0V, 5V) to (0, 1023)
|
|
float voltage = raw_read*(5.0/1024); // Voltage at the analog pin
|
|
voltage = voltage * (1/0.29078); // Accounts for the voltage divider
|
|
|
|
return voltage;
|
|
}
|
|
|
|
void NonLatchingRelay::update_actual_state() {
|
|
// Returns true if the voltage is detected
|
|
// Returns false if the voltage is NOT detected
|
|
// Let's also use a sample size of 3 and average
|
|
float voltage_sum = 0;
|
|
for (unsigned int i = 0; i < num_voltage_reads; i++) {
|
|
voltage_sum += read_relay_voltage();
|
|
}
|
|
float voltage = voltage_sum / (num_voltage_reads * 1.0);
|
|
|
|
if (voltage >= 7.5) { // A reading of 7.5 means at least 2/3 read 12V
|
|
if (actual_state == false && expected_state == true) { // If this is the first voltage we have seen since trying to turn it on
|
|
relay_first_voltage_time = millis();
|
|
}
|
|
actual_state = true;
|
|
} else {
|
|
if (actual_state == true && expected_state == false) { // If this is the first no voltage we have seen since trying to turn it off
|
|
relay_first_no_voltage_time = millis();
|
|
}
|
|
actual_state = false;
|
|
}
|
|
}
|
|
|
|
void NonLatchingRelay::update_if_pin_working() {
|
|
// This function is mainly used to check if the writing pin for the non-latching remains working while in operation
|
|
pin_actual_state = digitalRead(pin_readback);
|
|
if (pin_actual_state != pin_desired_state) { // If the readback pin is not the state at which we are telling the pin to be at
|
|
pin_working = false;
|
|
} else {
|
|
pin_working = true;
|
|
}
|
|
}
|
|
|
|
void NonLatchingRelay::update_if_relay_working() {
|
|
if (expected_state) { // Relay is expected to be on
|
|
if (millis() - relay_turned_on_time >= relay_delay) { // If it has been long enough for the relay to have 12V across it
|
|
if (actual_state) { // If there is 12V across the relay
|
|
relay_working = true;
|
|
} else {
|
|
relay_working = false;
|
|
}
|
|
} else { // There hasn't been enough time to let 12V go across the contacts
|
|
relay_working = relay_working; // Keep same state
|
|
}
|
|
} else { // The relay is supposed to be off
|
|
if (millis() - relay_turned_on_time >= relay_delay) { // If it has been long enough for the relay to have 12V across it
|
|
if (actual_state) { // If there is 12V across the relay
|
|
relay_working = false;
|
|
} else {
|
|
relay_working = true;
|
|
}
|
|
} else { // There hasn't been enough time to let 12V go across the contacts
|
|
relay_working = relay_working; // Keep same state
|
|
}
|
|
}
|
|
}
|
|
|
|
void NonLatchingRelay::turn_on_relay() {
|
|
if (expected_state == false && pin_desired_state == false) { // If the relay is expected to be in the off position and we have not already tried turning it on
|
|
digitalWrite(pin, HIGH);
|
|
pin_desired_state = true;
|
|
delayMicroseconds(5); // This is to give the Arduino enough time to turn on the digital pin and for readback to be ready
|
|
pin_actual_state = digitalRead(pin_readback);
|
|
if (pin_actual_state != pin_desired_state) { // If the setpin did not go HIGH
|
|
pin_working = false;
|
|
return;
|
|
}
|
|
// The pin is working
|
|
relay_turned_on_time = millis(); // Useful for checking if the voltage actually goes to 12V in a reasonable time
|
|
pin_working = true;
|
|
expected_state = true;
|
|
}
|
|
}
|
|
|
|
void NonLatchingRelay::turn_off_relay() {
|
|
if (expected_state == true && pin_desired_state == true) { // If the relay is expected to be in the on position and we have not already tried turning it off
|
|
digitalWrite(pin, LOW);
|
|
pin_desired_state = false;
|
|
delayMicroseconds(5); // This is to give the Arduino enough time to turn on the digital pin and for readback to be ready
|
|
pin_actual_state = digitalRead(pin_readback);
|
|
if (pin_actual_state != pin_desired_state) { // If the setpin did not go LOW
|
|
pin_working = false;
|
|
return;
|
|
}
|
|
// The pin is working
|
|
relay_turned_off_time = millis(); // Useful for checking if the voltage actually goes to 12V in a reasonable time
|
|
pin_working = true;
|
|
expected_state = false;
|
|
}
|
|
}
|
|
|
|
void NonLatchingRelay::turn_on_relay_startup() {
|
|
// Used on startup when the state of the relay is unkown and we don't expect it to be
|
|
digitalWrite(pin, HIGH);
|
|
pin_desired_state = true;
|
|
delayMicroseconds(5); // This is to give the Arduino enough time to turn on the digital pin and for readback to be ready
|
|
pin_actual_state = digitalRead(pin_readback);
|
|
if (pin_actual_state != pin_desired_state) { // If the setpin did not go HIGH
|
|
pin_working = false;
|
|
return;
|
|
}
|
|
// The pin is working
|
|
relay_turned_on_time = millis(); // Useful for checking if the voltage actually goes to 12V in a reasonable time
|
|
pin_working = true;
|
|
expected_state = true;
|
|
}
|
|
|
|
void NonLatchingRelay::turn_off_relay_startup() {
|
|
// Used on startup when the state of the relay is unkown and we don't expect it to be
|
|
digitalWrite(pin, LOW);
|
|
pin_desired_state = false;
|
|
delayMicroseconds(5); // This is to give the Arduino enough time to turn on the digital pin and for readback to be ready
|
|
pin_actual_state = digitalRead(pin_readback);
|
|
if (pin_actual_state != pin_desired_state) { // If the setpin did not go LOW
|
|
pin_working = false;
|
|
return;
|
|
}
|
|
// The pin is working
|
|
relay_turned_off_time = millis(); // Useful for checking if the voltage actually goes to 12V in a reasonable time
|
|
pin_working = true;
|
|
expected_state = false;
|
|
}
|
|
|
|
void NonLatchingRelay::control_relay() {
|
|
// This handles all of the control.
|
|
// Includes startups, initial turning on coils, stopping the coils,
|
|
// pin error checking, relay error checking, everything.
|
|
// Call this function frequently so that the pins and error messages are kept in check
|
|
|
|
if (startup) { // If this is the first time we have done anything
|
|
if (desired_state) { // We want the relay on
|
|
turn_on_relay_startup();
|
|
} else { // We want the relay off
|
|
turn_off_relay_startup();
|
|
}
|
|
startup = false;
|
|
} else { // Not startup
|
|
if (desired_state != expected_state) { // If we have not already begun the process of setting the state
|
|
if (desired_state) { // We want the relay on
|
|
turn_on_relay();
|
|
} else { // We want the relay off
|
|
turn_off_relay();
|
|
}
|
|
}
|
|
}
|
|
// Now that we have begun the sequence of flipping the relay on/off,
|
|
// we need to do the pin error checking, and relay error/state checking
|
|
update_actual_state();
|
|
update_if_pin_working();
|
|
update_if_relay_working();
|
|
} |