Hi.
I'm attempting to use an Adafruit Feather (M0) to gate three PWM signals from a source to their respective servos. I want the controlled PWM signals to either reflect the source inputs or (if certain conditions are met) output a fixed "neutral position" PWM signal.
The rising edge of each source PWM to the M0 generates an interrupt which sets the corresponding output PWM pin HIGH and initializes a long unsigned integer to micros().
If the condition is met, the main loop checks to see if micros() now exceeds the initialized start value + 1500 (1.5 ms). If so, the main loop lowers the M0's PWM output to the servo regardless of the current state of the source's PWM signal.
When the condition is not met, the M0 faithfully reproduces the source PWM signal to the servo.
When the condition is met, instead of outputting a 1500 us pulse to the servo, it outputs a constant high.
Debugging suggests my problem is with my "if(micros() > start + 1500)", after which the main loop is supposed to lower the PWM output to the servo. It seems straightforward, but I've read that micros() can be flakey after about 1.5 ms, and that interrupts can prevent long integers from being processed correctly in 8-bit microcontrollers.
I tried using noInterrupts() and interrupts() before & after the calculation. I made sure to characterize the long integers used in the ISRs as "volatile". It hasn't helped.
I'd be grateful for any help.
#include<Servo.h>
#define JawNeutral 1500 // Servos will be restricted to neutral position at times
#define HeadNeutral 1500 // Default = 1500 us
#define ShoulderNeutral 1500
#define StJawSigIn 0
#define JawServoOut 1
#define StHeadSigIn 5
#define HeadServoOut 6
#define StEyesSigIn 9
#define ShoulderServoOut 10
#define TnSwitch 11
volatile unsigned long JawNeutralMicrosStart;
volatile unsigned long HeadNeutralMicrosStart;
volatile unsigned long ShoulderNeutralMicrosStart;
boolean JawToNeutral = true;
boolean HeadToNeutral = true;
boolean ShoulderToNeutral = true;
void StJawRise()
{
digitalWrite(JawServoOut, HIGH);
JawNeutralMicrosStart = micros();
}
void StHeadRise()
{
digitalWrite(HeadServoOut, HIGH);
HeadNeutralMicrosStart = micros();
}
void StEyesRise()
{
digitalWrite(ShoulderServoOut, HIGH);
ShoulderNeutralMicrosStart = micros();
}
void setup() {
// put your setup code here, to run once:
pinMode(StJawSigIn, INPUT);
pinMode(JawServoOut, OUTPUT);
pinMode(StHeadSigIn, INPUT);
pinMode(HeadServoOut, OUTPUT);
pinMode(StEyesSigIn, INPUT);
pinMode(ShoulderServoOut, OUTPUT);
pinMode(TnSwitch, INPUT_PULLUP);
pinMode(13, OUTPUT);
attachInterrupt(StJawSigIn, StJawRise, RISING);
attachInterrupt(StHeadSigIn, StHeadRise, RISING);
attachInterrupt(StEyesSigIn, StEyesRise, RISING);
}
void loop() {
// put your main code here, to run repeatedly:
JawToNeutral = digitalRead(TnSwitch);
HeadToNeutral = digitalRead(TnSwitch);
ShoulderToNeutral = digitalRead(TnSwitch);
if(JawToNeutral)
{
noInterrupts();
if(micros() > JawNeutralMicrosStart + JawNeutral)
{
digitalWrite(JawServoOut, LOW);
}
interrupts();
}
else
{
if(digitalRead(StJawSigIn == LOW))
{
digitalWrite(JawServoOut, LOW);
}
}
if(HeadToNeutral)
{
noInterrupts();
if(micros() > HeadNeutralMicrosStart + HeadNeutral)
{
digitalWrite(HeadServoOut, LOW);
}
interrupts();
}
else
{
if(digitalRead(StHeadSigIn == LOW))
{
digitalWrite(HeadServoOut, LOW);
}
}
if(ShoulderToNeutral)
{
noInterrupts();
if(micros() > ShoulderNeutralMicrosStart + ShoulderNeutral)
{
digitalWrite(ShoulderServoOut, LOW);
}
interrupts();
}
else
{
if(digitalRead(StEyesSigIn == LOW))
{
digitalWrite(ShoulderServoOut, LOW);
}
}
}