Outsider, I considered the fact that I might want to use an interrupt, however the motor only turns approximately 20 RPM. Do you still think it may be necessary? As for using a millis()-based timer, that's exactly what I've tried to do.
I've included the code I have currently, the timers in question are the first two that you'll see, the rest of the code seems to work fine. However I do need to clean it up some after I get everything working. Feel free to tear it apart and school me on better methods. I won't be offended because as I said, I'm new to this programming language.
The trouble I'm having with this code is that although it does recognize the state change on digital input 2 when monitoring the two bits "photoStalledLow" and "photoStalledHigh" using the serial print lines at the end of the program (currently commented out), the stall detection timers don't seem to be keeping time as shown by the serial print lines within each timer. This causes the LED's to randomly turn off before resuming normal operation. Probably a conflict somewhere but I'm not quite sure where to look, as each individual section of program will execute fine all on it's own. Only when I combine into this complete program them do I experience the problem.
//-------------------------------------------------------------------------------------------------------------------
// Fireplace lighting control program. Randomizes brightness of flame effect & gradually varies brightness of coal bed & logs.
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
// Hardware:
// Elegoo Uno R3 - Main Controller (ATMega 328P @ 16 MHz, 5VDC logic level)
// Adafruit PCA9685 16-Channel 12-Bit PWM Servo Driver - PWM Output Module (I2C bus address 0x40)
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
// Include libraries for I2C comms, PCA9685 PWM driver module and Entropy library (Entropy generates random numbers).
//-------------------------------------------------------------------------------------------------------------------
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <Entropy.h>
//-------------------------------------------------------------------------------------------------------------------
// Define "pwm" and I2C bus address of PCA9685.
// Declare global variables necessary for program control.
//-------------------------------------------------------------------------------------------------------------------
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
bool photoStalledLow;
bool photoStalledHigh;
unsigned long stallTimerL;
unsigned long stallTimerH;
//-------------------------------------------------------------------------------------------------------------------
// Begin setup routine.
//-------------------------------------------------------------------------------------------------------------------
// Start serial comms @ 9600 baud.
// Initialize Entropy library.
// Start PWM.
// Set PWM frequency.
// Set I2C bus speed. If Wire.setClock() is commented out, bus defaults to 100 kHz.
// Initialize digital input 2 with internal pullup for testing, to be changed to input with external pulldown resistor in final build.
void setup() {
Serial.begin(9600);
Entropy.initialize();
pwm.begin();
pwm.setPWMFreq(500);
//Wire.setClock(400000);
pinMode(2, INPUT_PULLUP);
}
//-------------------------------------------------------------------------------------------------------------------
// Begin main routine.
//-------------------------------------------------------------------------------------------------------------------
void loop() {
// Stalled/stopped motor detection.
// If photointerrupter reads LOW or HIGH for more than n milliseconds, set appropriate "Stalled" bit.
// These bits are used later in the program to enable/disable the flame effect.
if (digitalRead(2)==LOW){
signed int photo_TL = 1000;
if (millis() - stallTimerL >= (photo_TL)) {
stallTimerL += millis();
Serial.println("Timer Low");
Serial.println(stallTimerL);
photoStalledLow=1;
}
}
else photoStalledLow=0;
if (digitalRead(2)==HIGH){
signed int photo_TH = 1000;
if (millis() - stallTimerH >= (photo_TH)) {
stallTimerH += millis();
Serial.println("Timer High");
Serial.println(stallTimerH);
photoStalledHigh=1;
}
}
else photoStalledHigh=0;
// If motor is not stalled or stopped, enable LEDs.
if ((photoStalledLow==0) && (photoStalledHigh==0)) {
// Flame control. Randomize brightness of flame effects one half of the flame LED board at a time.
// Entropy format is Entropy.random(min_value, max_value)
// PWM command format is pwm.setPWM(channel, min_pulse_width, max_pulse_width)
// Minimum PWM value is 0, maximum is 4095.
int randFlame1 = Entropy.random(0,4000);
int randFlame2 = Entropy.random(0,4000);
pwm.setPWM(0, 0, (randFlame1));
pwm.setPWM(1, 0, (randFlame1));
pwm.setPWM(2, 0, (randFlame1));
pwm.setPWM(3, 0, (randFlame2));
pwm.setPWM(4, 0, (randFlame2));
pwm.setPWM(5, 0, (randFlame2));
// Coal bed control. Increment/decrement brightness of coal bed and logs.
// Entropy format is Entropy.random(max_value) OR Entropy.random(min_value, max_value)
// PWM format is pwm.setPWM(channel, min_pulse_width, max_pulse_width)
// Minimum PWM value is 0, maximum is 4095.
// Explanation: Entropy returns a random value between 0 and 5000 to be used as timer preset, therefore
// timer times out at random invervals between 0 and 5 seconds. When timer times out, add or
// subtract "1" from "i", which is the output to the setPWM command. Variables used are:
// _Rand: Timer preset
// _ETimer: holds the value of millis() from the previous scan
// i: output value to setPWM command
// v: added to "i" to increment or decrement it. Value of this variable is either 1 or -1.
signed long _random = Entropy.random(5000);
static unsigned long randTimer;
if (millis() - randTimer >= (_random)) {
randTimer += (_random);
static unsigned int i=2000;
static signed int v=1;
if (i < 4000) {
if (v == 1){
i+=v;
}
}
if (i==4000) {
v=-1;}
if (i <= 4000) {
if (v == -1) {
i+=v;
}
}
if (i==350) {
v=1;}
pwm.setPWM(6, 0, i);
pwm.setPWM(7, 0, i);
pwm.setPWM(8, 0, i); //ch 8 dead for some reason, investigate later.
pwm.setPWM(9, 0, i);
pwm.setPWM(10, 0, i);
pwm.setPWM(11, 0, i);
}
}
//Disable flame effect LED's if motor is stalled/stopped with photodetector either low or high.
//LED's are disabled by setting PWM values to zero for all channels of the PCA9685 module.
//Perhaps clean this up later and use an array or something.
if ((photoStalledLow==1)||(photoStalledHigh==1)) {
unsigned long led_Off_Delay = 1000;
static unsigned long ledOffT = millis();
if (millis() - ledOffT >= (led_Off_Delay)) {
ledOffT += (led_Off_Delay);
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
pwm.setPWM(2, 0, 0);
pwm.setPWM(3, 0, 0);
pwm.setPWM(4, 0, 0);
pwm.setPWM(5, 0, 0);
pwm.setPWM(6, 0, 0);
pwm.setPWM(7, 0, 0);
pwm.setPWM(8, 0, 0);
pwm.setPWM(9, 0, 0);
pwm.setPWM(10, 0, 0);
pwm.setPWM(11, 0, 0);
}
}
//Debugging outputs to terminal, remove these lines after program is completed.
//Serial.println("Stalled low?");
//Serial.println(photoStalledLow);
//Serial.println("Stalled high?");
//Serial.println(photoStalledHigh);
}