Porqué la orden attachInterrupt se mantiene on?

Buenos días gente,

Estoy haciendo un proyecto con un potenciometro digital (AD5206) de seis canales para poder manejar 6 LEDs…pero de momento solo tengo un LED conectado. He estado mirando el tema de las interrupciones porque me interesa que al pulsar el “pushbutton” que tengo conectado al circuito el LED nos de un pulso con la máxima intensidad…pero soy nueva con Arduino y algo estoy haciendo mal. Al compilar el sketch (que adjuntaré acontinuación) no hay ningún problema…y al pulsar el botón sí que aumenta la intensidad del LED…pero no deja la interrupción y se mantiene en ese estado…cuando tenía entendido que la interrupción ocurre en un momento concreto y vuelve al estado cuando dejas de pulsar el boton…
Adjunto el código haber si me podeis dar alguna idea…gracias.

LED_Interrupt.ino (721 Bytes)

Bien, para comenzar correctamente en este foro te invito a que leas las normas del foro y luego edites tu primer post y en lugar de adjuntar el código lo pegues usando tags. Este tag (</>). las normas dicen como hacerlo pero es tan simple como pegar el código y luego click en </> arriba del primer emoticon.

Cuando vea el código y además cuando publiques un esquema o foto del esquema debidamente posteado también usando tag para imágen, al menos yo te voy a responder.

Buenas tardes,

Llevo poco tiempo trabajando con Arduino y me he encontrado con un problema a la hora de utilizar la función attachInterrupt(). Mi circuito consta de un potenciometro digital (AD5206) de seis canales, en el cual de momento solo tengo conectado un led a uno de los canales, además de un push button conectado para controlar el LED (los esquemas se pueden ver en el esquema que adjunto, solo estoy usando el canal W6 de Dig.Pot).


Conectados, por supuesto, los dos al mismo voltaje de arduino (5V) y a GND.

Mi duda es la siguiente, he estado leyendo acerca de attachInterrupt, ya que me interesa que el LED mantenga una intensidad constante hasta el momento en que, al llamar a la interrupción este nos de un flash con su intensidad máxima, y vuelva al estado de intensidad constante. Por lo que tenia entendido la interrupción se ejecuta cuando la llamas (en mi caso con el boton) y que para cuando, en mi caso, dejas de pulsar…he probado, con el mismo código a cambiar el modo de llamada de la interrupción (LOW, CHANGE, FALLING…), pero siempre me pasa lo mismo, cuando pulso el boton el LED da la intensidad que busco pero la mantiene…como si no saliera de la interrupción. He llegado a la conclusión de que puede que el código esté mal y no consigo ver donde…os lo pongo acontinuación por si me podeis echar una mano. Gracias.

#include <SPI.h>
#define buttonPin 2
#define ledPin 9

int led = 13;
int button = 2;

const int slavePinSelect = 10;
volatile int buttonState = 0;

  int level = 250;
  int channel = 5;

void setup() {
  // put your setup code here, to run once:
  pinMode(slavePinSelect, OUTPUT);
  pinMode(button,INPUT);
  SPI.begin();
  digitalPotWrite(channel, 150);
  attachInterrupt(0, Pin, CHANGE);
 
}

void loop() {
  // put your main code here, to run repeatedly:
}

void Pin(){
  buttonState = digitalRead(button);
  digitalPotWrite (channel,level);
}

void digitalPotWrite(int address, int value){
  digitalWrite(slavePinSelect, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(slavePinSelect, HIGH);
}

las fotos no se ven. Hay dos maneras de postearlas. 1. Usa un sitio como www.tinypic.com que te dará una URL que luego pegas y listo 2. la adjuntas. Luego copias la direccion del enlace. Editas el post y pegas esa dirección de enlace en el tag de imagenes. Puede parecer engorroso pero ahora es el método que yo uso.

De nuevo, edita tu segundo post y corrije esas fotos

Siento mucho las molestias...me ha costado pero espero que se vea correctamente. Gracias

No se para que quieres interrupción para algo tan simple.
Usarla te genera mas problemas que beneficios.
Porqué? Porque un botón o pulsador suele rebotar entonces asi no sabras si pasa o no, o cuantas veces lo hace.
Además channel y level deberían ser también volatiles porque se usan en la interrupción y las requires fuera.

Prueba asi, aunque en lo personal algo asi funcionará sin interrupción

#include <SPI.h>
#define MAXIMO          255 // Ajustar el máximo a lo que corresponda
const byte button 	= 2;
const byte led 		= 13;

const byte slavePinSelect = 10;

bool buttonState 	= false;
int level 			= 250;
int channel 		= 5;

void setup() {
  // put your setup code here, to run once:
  SPI.begin();
  pinMode(slavePinSelect, OUTPUT);
  pinMode(button,INPUT);
  digitalPotWrite(channel, 150);

}

void loop() {
  buttonState = digitalRead(button);
  if (buttonState && !buttonStateAnt) {// flanco positivo solamente
      level += incremento;
      if (level > MAXIMO) {
         level = MAXIMO;
         incremento = -1;
      }
      if (level <= 0) {
          level = 0;
          incremento = +1;
      } 
     digitalPotWrite (channel,level);
  }
  buttonStateAnt = buttonState;
}


void digitalPotWrite(int address, int value){
  digitalWrite(slavePinSelect, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(slavePinSelect, HIGH);
}

Pregunto: con cada pulsación no debería cambiar algo?
Tu código siempre envia channel,level fijos

Si quieres aunque yo lo odio, usa un delay(10) para evitar rebotes posibles.

Tu problema reside en que dentro de la interrupción los timers no funcionan, no deberías utilizar sentencias como delay , milis o funciones de librerías que la utilicen, como es tu caso. Las interrupciones se utilizan para operaciones simples y rápidas. En tu caso debes levantar una bandera dentro de interrupción y luego procesarla en el cuerpo principal del programa.
Saludos