Also am serial port liegt es definitiv nicht, jedenfalls wenn man nicht auf dem selben board das trigger signal in loop() erzeugt. Ich habe gerade mit 2 arduinos herumprobiert.
Ich schicke ein 5kHz signal auf den interrupt pin (digital2) und verwende die micros() funktion fuer gute zeitaufloesung.
Da ich mal davon ausgehe, dass du keine HF spindel hast, nehme ich von nun an 1kHz als signal, was bei 16 pulsen per revolution ca. 3750 rpm entspricht.
micros() hat eine granularitaet von 4µs, was hier ca. +- 10rpm entspricht. Daher macht speed als float-variable keinen sinn.
Hier der code fuer den frequenz generator:
void setup() {
// put your setup code here, to run once:
DDRD |= _BV(PD2);
}
void loop() {
// put your main code here, to run repeatedly:
//delayMicroseconds(500); // fuer hohe RPM
delay(10); // fuer niedrige RPM
PORTD &= ~_BV(PD2); // low
//delayMicroseconds(500);
delay(10);
PORTD |= _BV(PD2); // high
}
und dein code in etwas veraenderter/verkuerzter form:
int i; // Getriebeübersetzung
int s; // Sinunsfunktion
////
int R = 12; // Rechteckausgang
////
int Dir = 9; // Rechteckausgang
int En = 8; // Rechteckausgang
double w; // Omega
////
unsigned int RPM; // Spindeldrehzahl pro minute
#define PPR 16UL // pulse per revolution
////
volatile unsigned long T1; //Zeitstepel 1
volatile unsigned long T2; //Zeitstepel 2
// Encoder Interruptports
#define A 2 //Belegung der Encoderkanale A
void setup() {
i=40;
pinMode(R,OUTPUT);
pinMode(En,OUTPUT); //Enable Pin
pinMode(Dir,OUTPUT); //Direction Pin
pinMode(13,OUTPUT); // fuer diagnose LED
Serial.begin(9600); // initialize the serial port:
attachInterrupt(0,CHAInt, RISING); // Interrupt 0 führt CHAInt aus mit steigender Flanken
pinMode(A,INPUT); // Pin2 als Input
digitalWrite(A,HIGH); // Interne Pull Ups benutzt
}
void loop() {
cli();
unsigned long T1_temp = T1; // in microsekunden
unsigned long T2_temp = T2;
sei();
unsigned long DELTA = T2 - T1;
RPM = (unsigned int)( 1000000UL * 60UL / ( PPR * DELTA ) );
Serial.print("rpm: ");
Serial.println(RPM);
Serial.print("delta T in microsekunden: ");
Serial.println(DELTA);
}
void CHAInt ()
{
// PORTB |= _BV(PB5); // L-LED (13) an
if( PIND & _BV(PD2) )
{
T1 = T2;
T2 = micros();
}
// PORTB &= ~_BV(PB5); //L-LED (13) aus
}
Das funktioniert wunderbar, wohlgemerkt mit 2 boards. Beides auf einem laufen zu lassen ist verboten. Sollte der sinn deiner 'sinus' funktion darin bestehen auf dem selben board das rechtecksignal zu erzeugen, welches dann wiederum den interrupt triggert... autsch!