RPM_Motor+interrpciones+tonos

Hola amigos del foro.
estoy intentando hacer un pequeño proyectillo didactico, sobre las RPM de un motor, mediante la lectura de un diodo emisor y un photo-transistor, sobre un encoder, con arreglo a las interrupciones optengo las revoluciones, hasta ahi bien, aunque no esta muy depurada su programacion al menos optengo las RPM.
ahora me gustaria hacer, que cuando el motor esta funcionando, y por encima de unas determinadas RPM (en mi caso 3000RPM), un diodo esta encendido permanentemente, y el buzzer en estado bajo (LOW), apagado.
Pero, cuando el motor baja de unas determinadas RPM (3000), el motor se para y el led, siempre encendido pasa a parpadear y el buzzer a sonar.
Aunque me funciona (de esas maneras), soy consciente de que no esta bien, por eso recurro a Vds.
os paso el codigo y me aconsejais, (todabia soy aprendiz no me hecheis los perros..jajajajaj).
Lo que pretendo es que como veis en el codigo esque me ejecute una secuencia de tonos, cuando se cumple que el motor se para y que el led parpadee (pase de estar siempre encendido a parpadear).
y esto lo consigo (parpadeo del led), pero el buzzer solo me genera una nota fija, constante y seguida, no la cadena de tonos que tengo en las variables.

// Contador de RPM  by: kikorro
// Conexion de la entrada de la interrupcion 0  por el PIN 2
// Configurar el monitor serial a 9600 Baudios para visualizar los RPM

volatile int contador = 0;   // Variable entera que se almacena en la RAM del Micro
int paramotor=4;                  //para motor;

const int LUD_MARCHA = 13;  
// const int SONIDO_PARO = 12;
int BUZZER = 8;
int i = 1;
int tonos [] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};



void setup() {
  Serial.begin(9600);
   pinMode(2, INPUT);           // set pin to input
   pinMode (paramotor, OUTPUT);
 //pinMode (habilitarMotor, OUTPUT);
  pinMode (LUD_MARCHA, OUTPUT);
  pinMode (BUZZER, OUTPUT);
  attachInterrupt(0,interrupcion0,RISING);  // Interrupcion 0 (pin2), LOW, CHANGE, RISING, FALLING

  }                                          
void loop() {
  contador = 0;
  delay(999);                 // retardo de 1 segundo
  Serial.print(contador *10);  // Como son seis interrupciones por vuelta (contador * (60/6))
  Serial.println(" RPM");     //  El numero 6 depende del numero aspas del encoder
 // analogWrite(habilitarMotor,senalPWM);  // habilitar potencia motor
  // Condición por la cual queremos que el código se ejecute
  // si una variable 'x' es menor que 3000 RPM

if (contador > 300){
   digitalWrite(paramotor,LOW);
   digitalWrite(LUD_MARCHA, HIGH);
   noTone(BUZZER);
   
 }
else if (contador < 300){
    digitalWrite(paramotor,HIGH);
   digitalWrite(LUD_MARCHA, LOW);
   delay (200);
   digitalWrite(LUD_MARCHA, HIGH);   // enciende el LED (on)
   delay(200);                      // espera por un segundo
   digitalWrite(LUD_MARCHA, LOW);    // apaga el LED (off)
   delay(200);                        // espera por un segundo
   

    //if (i=0; i<12; i++){
    // if(digitalRead(i)==HIGH){
      tone(BUZZER, tonos[i]);
      delay(500);
    }
  } 
void interrupcion0()    // Funcion que se ejecuta durante cada interrupion
{
  contador++;           // Se incrementa en uno el contador
}

Cuando armas algo asi no puedes usar delay porque delay interrumpe el flujo del programa (NO HACE NADA)
En su lugar usa millis() y una máquina de estados.

// Contador de RPM  by: kikorro
// Conexion de la entrada de la interrupcion 0  por el PIN 2
// Configurar el monitor serial a 9600 Baudios para visualizar los RPM

volatile int contador = 0;   // Variable entera que se almacena en la RAM del Micro
int paramotor=4;                  //para motor;

const int LUD_MARCHA = 13;  
// const int SONIDO_PARO = 12;
int BUZZER = 8;
int i = 1;
int tonos [] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};
unsigned long start;
byte estado = 0;

void setup() {
  Serial.begin(9600);
   pinMode(2, INPUT);           // set pin to input
   pinMode (paramotor, OUTPUT);
 //pinMode (habilitarMotor, OUTPUT);
  pinMode (LUD_MARCHA, OUTPUT);
  pinMode (BUZZER, OUTPUT);
  attachInterrupt(0,interrupcion0,RISING);  // Interrupcion 0 (pin2), LOW, CHANGE, RISING, FALLING

  }                                          
void loop() {
  contador = 0;
  delay(999);                 // retardo de 1 segundo
  Serial.print(contador *10);  // Como son seis interrupciones por vuelta (contador * (60/6))
  Serial.println(" RPM");     //  El numero 6 depende del numero aspas del encoder
 // analogWrite(habilitarMotor,senalPWM);  // habilitar potencia motor
  // Condición por la cual queremos que el código se ejecute
  // si una variable 'x' es menor que 3000 RPM

  if (contador > 300){
     digitalWrite(paramotor,LOW);
     digitalWrite(LUD_MARCHA, HIGH);
     noTone(BUZZER);
     
  }
  else  if (contador < 300){
            switch(estado) {
              case 0: digitalWrite(paramotor,HIGH);
                      digitalWrite(LUD_MARCHA, LOW);
                      estado = 1;
                      start = millis();
                      break;
              case 1: if (millis()-start > 200UL) {
                          digitalWrite(LUD_MARCHA, HIGH);   // enciende el LED (on)
                          estado = 2;
                          start = millis();
                      }
                      break;
              case 2: if (millis()-start > 200UL) {
                          digitalWrite(LUD_MARCHA, LOW);   // enciende el LED (on)
                          estado = 3;
                          start = millis();
                      }
                      break;                      
              case 3: if (millis()-start > 500UL) {
                          tone(BUZZER, tonos[i++]);
                          if (i > sizeof(tonos))
                              i = 0;
                          estado = 4;
                      }
                      break;
              case 4: estado = 0; // reinicio?
                      break;
            }
          }
} 

void interrupcion0() {    // Funcion que se ejecuta durante cada interrupion
  contador++;           // Se incrementa en uno el contador
}

muchas gracias por tu rápida respuesta surbyte.
entiendo que me falta muchas horas de vuelo y mucho que aprender, por lo tanto te agradezco tu dedicación, y por supuesto tomo nota de tus comentarios.

haber si me pongo y subo alguna imagen del armado en la protoboar.
luego, he probado el sketch, que me has confeccionado y te comento lo siguiente:
cuando el motor baja de las 3000 RPM, efectivamente, el led pasa de su estado encendido a parpadeante y el buzzer empieza a sonar.

pero transcurrido sobre dos segundos, el motor empieza nuevamente a andar, pero como el pote resistivo hace que la tensión de alimentacion no llegue que el encoder sobrepase las 3000RPM se para, y el buzzer emite un tono, y el motor vuevamente empieza andar y asi permace en ese bucle.

cuando lo que realmente pretendo esque el pin4, que controla la alimentacion del motor a través de la bobina de un rele en este caso (NC), al cumplirse la segunda condición (ese If), es que a través del pin 4, alimente la bobina del rele y el contacto (NC pase a NO), cortando por completo la alimentación del motor y este se pare.

y que con el motor parado (pin 4), alimentando bobina del rele.
el led fijo, asociado al pin 13 de arduino, cambie su estado de fijo a parpadeante.
y que el buzzer pasivo, emita una secuencia sonora, habilitada con la variable tonos.

Bueno es por volver a reincidir nuevamente en lo mismo, por si habia alguna duda.

GRACIAS POR TODO.

pero transcurrido sobre dos segundos, el motor empieza nuevamente a andar

Bueno, veo que no analizaste lo que te hice para modificar tus delay.

Eso se llama máquina de estados.
Cuando llega al estado 4 fijate que vuelve a comenzar con el parpadeo.

Esta es tu condición if (contador < 300){
y luego ejecuta la máquina de estados del mismo modo.
Las condiciones de parado marcha supuse que estaban, y no las analicé.

cuando lo que realmente pretendo esque el pin4, que controla la alimentacion del motor a través de la bobina de un rele en este caso (NC), al cumplirse la segunda condición (ese If), es que a través del pin 4, alimente la bobina del rele y el contacto (NC pase a NO), cortando por completo la alimentación del motor y este se pare.

Luego lo veo

Nada, que no hay manera.
seguramente como bien dices, la culpa la tendran los delay.
al subir el sketch que me colgaste, arranca pero al instante, se para, sin que bajen las revoluciones.
sin embargo el codigo que te adjunte:

ESTO LO QUE HACE:

digamos que cumple las funciones,
arranca perfecto.
marca revoluciones en el monitor serie.
la salida del led esta encendida fija.
al bajar con el "pote" la tension las revoluciones bajan y se ven como van bajando en el monitor.
al llegar al umbral de (< de 300), = 3000 RPM, salta el rele y deja sin tension al motor parándolo.
el LED pasa a parpadear y el buzzer emite un unico sonido constante.
pero en el monitor serie, en vez de marcar 0 RPM, (cuando para), marca por ejemplo 2850 RPM, cuando detecto que estaba por debajo del umbral, en vez de marcar 0.

INTENTO QUE HAGA:

practicamente lo mismo, pero:
en vez de emitir un único sonido, que emita la secuencia sonora de frecuencias, cuando el motor se para y baja de las 3000RPM.
y que el monitor serie cuando se pare marque 0RPM.

OBSERVACIONES:

el contar la RPM y parar el motor, es un sketch, que ya tenía y que funciona bien, incluso al bajar las RPM de 3000, para y el monitor ya marca cero RPM.

ha sido al intentar meter las condiciones del led y del buzzer, cuando ya no consigo lo que quiero.

// Contador de RPM  by: kikorro
// Conexion de la entrada de la interrupcion 0  por el PIN 2
// Configurar el monitor serial a 9600 Baudios para visualizar los RPM

volatile int contador = 0;   // Variable entera que se almacena en la RAM del Micro
int paramotor=4;                  //para motor;

const int LUD_MARCHA = 13;  
const int SONIDO_PARO = 12;
int BUZZER = 8;
int i = 0;
int tonos [] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};



void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);           // set pin to input
 
 pinMode (paramotor, OUTPUT);

  pinMode (LUD_MARCHA, OUTPUT);
  pinMode (SONIDO_PARO, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  attachInterrupt(0,interrupcion0,RISING);  // Interrupcion 0 (pin2), LOW, CHANGE, RISING, FALLING
  pinMode(i, OUTPUT);
 
}                                          
void loop() {
 contador = 0;
  delay(999);                 // retardo de 1 segundo
  Serial.print(contador *10);  // Como son seis interrupciones por vuelta (contador * (60/6))
  Serial.println(" RPM");     //  El numero 6 depende del numero aspas del encoder
   // Condición por la cual queremos que el código se ejecute
  // si una variable 'x' es menor que 3000 RPM

 
  
if (contador > 300){
   digitalWrite(paramotor,LOW);
   digitalWrite(LUD_MARCHA, HIGH);
   digitalWrite(SONIDO_PARO, LOW);
}
else if (contador < 300){
    digitalWrite(paramotor,HIGH);{
    digitalWrite(LUD_MARCHA, LOW);
   delay (200);
   digitalWrite(LUD_MARCHA, HIGH);   // enciende el LED (on)
   delay(200);                      // espera por un segundo
    digitalWrite(LUD_MARCHA, LOW);    // apaga el LED (off)
   delay(200);                        // espera por un segundo
    digitalWrite(SONIDO_PARO, HIGH); 
     if(digitalRead(i)==HIGH){
      tone(BUZZER, tonos[i]);
      delay(500);  
     }
   } 
 }
}
void interrupcion0()    // Funcion que se ejecuta durante cada interrupion
{
 contador++;           // Se incrementa en uno el contador
}

pero en el monitor serie, en vez de marcar 0 RPM, (cuando para), marca por ejemplo 2850 RPM, cuando detecto que estaba por debajo del umbral, en vez de marcar 0.

Esto es un error del programa facilmente corregible. Como las RPM solo se actualizan cuando se cumple la ventana temporal si dejas de hacerlo entonces tienes que poner a 0 el contador.
Es algo que tu puedes corregir.

Se supone que debe indicarte motor parado.

en vez de emitir un único sonido, que emita la secuencia sonora de frecuencias, cuando el motor se para y baja de las 3000RPM.
y que el monitor serie cuando se pare marque 0RPM.

Emitir la secuencia de sonidos no hay problema te lo corrijo.

Ahora la secuencia de buzzer la voy a hacer de otro modo. Espero que funcione.

Acá esta, pruebalo y me dices

Tu lectura de RPM estaba mal, es algo que no le presté atención incialmente. No puedes leer sin detener interrupciones.
Verifica si funciona.

// Contador de RPM  by: kikorro
// Conexion de la entrada de la interrupcion 0  por el PIN 2
// Configurar el monitor serial a 9600 Baudios para visualizar los RPM

volatile int contador = 0;   // Variable entera que se almacena en la RAM del Micro
int paramotor=4;                  //para motor;

const int LUD_MARCHA = 13;  
// const int SONIDO_PARO = 12;
int BUZZER = 8;
int i = 1;
int tonos [] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};
unsigned long start;
byte estado = 0;
byte estadoBuzzer = 0;
int rpmcopy;

void setup() {
  Serial.begin(9600);
   pinMode(2, INPUT);           // set pin to input
   pinMode (paramotor, OUTPUT);
 //pinMode (habilitarMotor, OUTPUT);
  pinMode (LUD_MARCHA, OUTPUT);
  pinMode (BUZZER, OUTPUT);
  attachInterrupt(0, interrupcion0, RISING);  // Interrupcion 0 (pin2), LOW, CHANGE, RISING, FALLING
}                                          

void loop() {
  
  if (millis() - tiempo > 999) {
      detachInterrupt(0);
      rpmcopy = contador;

      Serial.print(rpmcopy *10);  // Como son seis interrupciones por vuelta (contador * (60/6))
      Serial.println(" RPM");     //  El numero 6 depende del numero aspas del encoder
      // analogWrite(habilitarMotor,senalPWM);  // habilitar potencia motor
      // Condición por la cual queremos que el código se ejecute
      // si una variable 'x' es menor que 3000 RPM
      contador = 0;
      attachInterrupt(0,interrupcion0,RISING);  // Interrupcion 0 (pin2), LOW, CHANGE, RISING, FALLING
  }


  if (rpmcopy > 300){
     digitalWrite(paramotor,LOW);
     digitalWrite(LUD_MARCHA, HIGH);
     noTone(BUZZER);
  } else {
        switch(estado) {
          case 0: digitalWrite(paramotor,HIGH);
                  digitalWrite(LUD_MARCHA, LOW);
                  estado = 1;
                  start = millis();
                  break;
          case 1: if (millis()-start > 200UL) {
                      digitalWrite(LUD_MARCHA, HIGH);   // enciende el LED (on)
                      estado = 2;
                      start = millis();
                  }
                  break;
          case 2: if (millis()-start > 200UL) {
                      digitalWrite(LUD_MARCHA, LOW);   // enciende el LED (on)
                      estado = 3;
                      startbuzzer = start = millis();
                  }
                  break;                      
          case 3: if (millis()-start > 500UL) {
                      suena_buzzer();
                      start = millis();
                      estado = 4;
                  }
                  break;
          case 4: if (millis() - start > 1200UL) {     // tiempo que suena el buzzer
                      estado = 0; // reinicio?
                  }
                  break;
        }
  }
} 

void interrupcion0() {    // Funcion que se ejecuta durante cada interrupion
  contador++;           // Se incrementa en uno el contador
}


void suena_buzzer() {
  if (millis() - startbuzzer > 100UL) { // cambiar 200 por mas o menos tiempo a gusto
      tone(BUZZER, tonos[i++]);        // empieza con la primer frecuencia
      if (i > sizeof(tonos)) i = 0;    // si llega al ultimo valor del vector lo pone a 0
      startstartbuzzer = millis();
  }  
}

hola nuevamente, surbyte.
bueno lo he cargado, y funciona sobre un segundo mas o menos y se para, comienza la secuencia de tonos, y cuando acaba de hacer la secuencia arranca sobre otro segundo y se para.

al intentar cargarlo, me ha dao tres errores de que faltaban las variables: tiempo y startbuzzer,que veras ya cargadas en la cabecera y corregido startstartbuzzer.

gracias, por tu dedicacion, y perdida desinteresada de tiempo.

A vueltas con el tema.
os comento, he encontado este sketch, para medir la revoluciones, el cual he probado y es super preciso y muy estable, y me gustaria implementarlo en el proyecto, que llevo dias dando vueltas.
ahora a ver si algún al caritativa, me puede dar luces y partiendo del mismo, como implementar, que el motor al descender de unas determinadas RPM, active un PIN, yo he puesto el pin 4, y me pare el motor, pero mientras esta funcionando un led este constantemente encendido (yo he puesto pin 13).
al bajar de las RPM (ejemplo 3000), el led pasa a parpadear y el buzzer emite una secuencia de sonidos.
eso seria todo, espero que alguno me pueda hechar una mano.
gracias.

Este seria el sketch inicial.

volatile unsigned int counter = 0;  //This variable will increase on the rotation of encoder
unsigned long lastTime = 0;         // will store last time value was sendt
const long interval = 1000;         // interval at which to send result in milli second.  1000 ms = 1 second

void setup() {
  Serial.begin (9600);
  pinMode(2, INPUT);           // set pin to input
  digitalWrite(2, HIGH);       // turn on pullup resistors
  //Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
}

void loop() {
//  Chedk if it's time to sendt data
  if(timeIntervall()) {
    sendData();
    resetSampling();
  }
}

void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  counter++;
}

void sendData() {
  Serial.print("Pulsos por segundo = ");
  Serial.print(counter);      // Sending cout / time
  float speedOut = map(counter, 0, 10, 0, 100);      // change from 400 pulse pr / second to 100 m/h
  Serial.print("\t RPM = ");
  Serial.println(speedOut);
}
void resetSampling() {
  counter = 0;
}

boolean timeIntervall() {
  unsigned long currentTime = millis();
  // Chedk if it's time to make an interupt
  if (currentTime - lastTime >= interval) {
    lastTime = lastTime + interval;
    return true;
  } else if (currentTime < lastTime) {
    // After 50 day millis() will start 0 again
    lastTime = 0;
  } else {
    return false;
  }
}

posterior mente estas serian mis variables, para que hiciese, lo que espero, pero al intercalarlas dentro del void loop, no responde a lo que yo quiero.

int paramotor=4;                  //para motor;
const int LUD_MARCHA = 13; 
int BUZZER = 8;
int i = 0;
int tonos [] = {261, 277,};