volatile unsigned long timer; // all timer variables are unsigned long
volatile int inpulse = 1500;
volatile byte sync = 0;
int mpcount, pulse;
uint16_t Xtarget [8], Xpulse[8];
const int slowstep = 1;
const int Xtargetlow [] = {83, 83, 83, 83, 205, 205, 205, 205};
const int Xtargethigh [] = {467, 467, 467, 467, 410, 410, 410, 410};
bool start = false, RxchWas = false;
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
void setup() {
attachInterrupt(0, read_pwm, CHANGE); // Pin 2 = interrupt 0
pinMode(2, INPUT);
Serial.begin(9600);
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(50); // 50Hz, frame length 20 millis
for (int i=0; i<8; i++) {
Xtarget [i] = 308; // equivalent of 1500 micros
Xpulse [i] = 308;
}
delay(10);
}
void loop() {
while (sync == 0); // ISR sets sync to true when reading Rx pulse is complete, loop starts.
sync = 0; // stops loop after one run.
delay (6); // do an atomic copy, delayed to midframe to reduce jitter
cli();
pulse = inpulse;
sei();
// read next 8 incoming pulses, triggered by a syncpulse, map to extended range and save in array Xtarget []
if (start && pulse >=1000) {
Xtarget [mpcount] = map (pulse, 1030, 1980, Xtargetlow [mpcount], Xtargethigh [mpcount]); // extending pulse to Xtarget
mpcount += 1;
if (mpcount >7) {
start = false; // stop saving subchannels after 8 counts
delay(500); // only for testing the output by monitor, deactivate for servo operation
}
}
if (pulse >= 850 && pulse <950) { // is syncpulse
start = true;
mpcount = 0;
}
// update all servo outputs with or without changed targets, maximum step is slowstep setting
for (uint8_t j=0; j<8; j++) {
if (Xtarget [j] - Xpulse [j] >= slowstep) Xpulse [j] += slowstep;
else if (Xtarget [j] - Xpulse [j] <= -slowstep) Xpulse [j] -= slowstep;
else Xpulse [j] = Xtarget [j];
pwm.setPWM(j, 0, Xpulse [j]); // LOW>HIGH at 0, HIGH>LOW at pulselen
}
Serial.print ("pulse = "); Serial.println (pulse);
Serial.print ("Xpulse[1] = "); Serial.print (Xpulse[1]); Serial.print (" Xtarget[1] = "), Serial.println (Xtarget[1]);
}
void read_pwm(){
if (RxchWas == 0) { // if pin 2 was false previously
timer = micros(); // start timer
RxchWas = 1;
}
else if (RxchWas == 1) { // if pin 2 was already true, read timer
inpulse = ((volatile int)micros() - timer);
RxchWas = 0;
sync = 1; // start loop
}
}