Ja die Codes von Jurs laufen alle auf Anhieb, ist schon super was der da so macht. 8)
Vor allem weil er es nicht immer testen kann.
Wegen der Performance, jurs verwendet digitalread um den Status der Pins abzufragen.
digitalread ist halt schon eine Funktion die relativ viele Takte braucht.
Alternative wäre diese Lib https://code.google.com/p/digitalwritefast/downloads/detail?name=digitalWriteFastinterruptSafe.zip&can=2&q=
Und dann einfach statt digitalRead digitalReadFast schreiben, einen Versuch wäre es wert.
Generell sehe ich die Verwendung von Interrupt performanter ??
Hier mal ein Codeschnipsel vom ardupilot Projekt.
#define MIN_PULSEWIDTH 1800 // 900
#define MAX_PULSEWIDTH 4200 // 2100
ISR(PCINT2_vect) {
if (FireISRRoutine)
FireISRRoutine();
}
volatile uint16_t MPNGRCInput::edgeTime[8]; // Save edge time for every channel in order to calculate pulse width
void MPNGRCInput::_pwm_A8_A15_isr(void)
{ //this ISR is common to every receiver channel, it is call everytime a change state occurs on a digital pin [D2-D7]
uint8_t mask;
uint8_t pin;
uint16_t cTime,dTime;
static uint8_t PCintLast;
cTime = TCNT5; // from sonar
pin = PINK; // PINK indicates the state of each PIN for the arduino port dealing with [A8-A15] digital pins (8 bits variable)
mask = pin ^ PCintLast; // doing a ^ between the current interruption and the last one indicates wich pin changed
PCintLast = pin; // we memorize the current state of all PINs [D0-D7]
// generic split PPM
// mask is pins [D0-D7] that have changed // the principle is the same on the MEGA for PORTK and [A8-A15] PINs
// chan = pin sequence of the port. chan begins at D2 and ends at D7
if (mask & 1<<0) {
if (!(pin & 1<<0)) {
dTime = (cTime-edgeTime[0]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[0] = dTime;
} else edgeTime[0] = cTime;
}
if (mask & 1<<1) {
if (!(pin & 1<<1)) {
dTime = (cTime-edgeTime[1]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[1] = dTime;
} else edgeTime[1] = cTime;
}
if (mask & 1<<2) {
if (!(pin & 1<<2)) {
dTime = (cTime-edgeTime[2]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[2] = dTime;
} else edgeTime[2] = cTime;
}
if (mask & 1<<3) {
if (!(pin & 1<<3)) {
dTime = (cTime-edgeTime[3]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[3] = dTime;
} else edgeTime[3] = cTime;
}
if (mask & 1<<4) {
if (!(pin & 1<<4)) {
dTime = (cTime-edgeTime[4]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[4] = dTime;
} else edgeTime[4] = cTime;
}
if (mask & 1<<5) {
if (!(pin & 1<<5)) {
dTime = (cTime-edgeTime[5]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[5] = dTime;
} else edgeTime[5] = cTime;
}
if (mask & 1<<6) {
if (!(pin & 1<<6)) {
dTime = (cTime-edgeTime[6]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[6] = dTime;
} else edgeTime[6] = cTime;
}
if (mask & 1<<7) {
if (!(pin & 1<<7)) {
dTime = (cTime-edgeTime[7]); if (MIN_PULSEWIDTH<dTime && dTime<MAX_PULSEWIDTH) _pulse_capt[7] = dTime;
} else edgeTime[7] = cTime;
}
// If we got pulse on throttle pin, report success
if (mask & 1<<pinRcChannel[2]) {
_valid_channels = AVR_RC_INPUT_NUM_CHANNELS;
}
}
Setup in etwa so:
FireISRRoutine = _pwm_A8_A15_isr;
PORTK = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7); //enable internal pull ups on the PINs of PORTK
PCMSK2 = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7); // enable interrupts on A8-A15 pins;
PCICR |= (1 << PCIE2); // PCINT2 Interrupt enable
Das ganze läuft auf dem Mega2560.
Zum Messen der Zeit (cTime = TCNT5;) könnte man ihmo auch millies() verwenden oä. verwenden.
Evtl. hilft es dir weiter.