Autor Tema: Ejemplos de Interrupt Service Routine (ISR) en arduino  (Leído 4203 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado CompSystems

  • PIC18
  • ****
  • Mensajes: 488
    • Home Page
Ejemplos de Interrupt Service Routine (ISR) en arduino
« en: 26 de Octubre de 2015, 00:05:29 »
Hola, mi interés sobre impresoras3d me llevo a programar en ARDUINO

anexo un ejemplo simple usando dos interrupciones de las 6 que soporta arduino

mas info en:
http://gammon.com.au/interrupts
Código: C++
  1. // Circuito: cambia el estado de un LED conectado al pin46 por medio de un pulsador con antirrebote que activa la interrupcion #0 por un flanco de bajada
  2.  
  3.   //Board Digital - Pins Usable For Interrupts
  4.   //Mega, Mega2560, MegaADK  
  5.   #define INTERRUPTION0_PIN 2 // pin para la interrupcion #0
  6.   #define INTERRUPTION1_PIN 3
  7.   #define INTERRUPTION2_PIN 21
  8.   #define INTERRUPTION3_PIN 20
  9.   #define INTERRUPTION4_PIN 19  
  10.   #define INTERRUPTION5_PIN 18 // pin para la interrupcion #5
  11.  
  12.     //defines when the interrupt should be triggered. (activada)
  13.    #define low_to_high_trig RISING // to trigger when the pin goes from low to high (increasing)
  14.    #define high_to_low_trig FALLING // to trigger when the pin goes high to low (descendente)
  15.    #define change_trig      CHANGE // activa la interrupción cada vez que el pin cambia de valor de 0-1 or de 1-0
  16.    #define in_low_trig LOW // to trigger the interrupt whenever the pin is low,
  17.    #define in_HIGHT_trig HIGH //to trigger the interrupt whenever the pin is high. (Arduino Due, Zero only)
  18.  
  19. // Las variables ha modificar de la funcion de interrupcion, se deben definir como VOLATILES
  20. // La palabra clave volatile es un modificador que añadido a una variable, advierte al compilador que esta puede ser modificada por una rutina en segundo plano (background), por una rutina de interrupción, o por un dispositivo de entrada salida. Es decir, que puede sufrir modificaciones fuera del control del programa.
  21. // La declaración de un objeto con este atributo, previene al compilador de hacer ninguna asunción sobre el valor del objeto mientras se ejecutan instrucciones en las que esté involucrado, advirtiéndolo que dicho valor puede cambiar en cualquier momento.  También previene al compilador de que no debe hacer de dicho objeto una variable de registro.
  22. // fuente http://www.zator.com/Cpp/E3_2_1d.htm
  23.    
  24.    volatile int led_pin_state = HIGH;  
  25.    #define LED_PIN 46
  26.    const byte PUSH_BUTTON_SWITCH = INTERRUPTION0_PIN;
  27.    
  28. void setup() {
  29.  
  30.   pinMode(INTERRUPTION0_PIN, INPUT); // No hay necesidad de definirlo como entrada
  31.   attachInterrupt(digitalPinToInterrupt(INTERRUPTION0_PIN), blink_LED_ISR, high_to_low_trig);
  32.   pinMode(INTERRUPTION1_PIN, INPUT); // No hay necesidad de definirlo como entrada
  33.   attachInterrupt(digitalPinToInterrupt(INTERRUPTION1_PIN), Action2_ISR, high_to_low_trig);
  34.  
  35.   pinMode(LED_PIN, OUTPUT);
  36.   // open the serial port at 9600 bps
  37.   Serial.begin(9600);
  38.  
  39. }// end setup
  40.  
  41. void loop() {
  42.    digitalWrite(LED_PIN, led_pin_state);
  43.    
  44. }// end loop
  45.  
  46. // Interrupt #0 Service Routine
  47. void blink_LED_ISR() { // invierte el valor entre HIGH y LOW y viceversa
  48.   Serial.println("Inicia Funcion para la interrupcion #0");
  49.   led_pin_state = !led_pin_state;
  50.   Serial.println("Cambio del estado a: "+String(led_pin_state)+"\n");
  51. }
  52.  
  53. // Interrupt #1 Service Routine
  54. void Action2_ISR() {
  55.   Serial.println("Inicia Funcion para la interrupcion #1");
  56. }
  57.  
  58. /*
  59.                
  60.                        /
  61. PIN46: O--/\/\/\--*--|>|--*---¬
  62.                               |
  63.                              _|__
  64.                             / / /
  65.            1K       LED    GND
  66.  
  67.            * +5v
  68.            |
  69.            |    
  70.            >  
  71.            <  1k
  72.            >      pushButtom
  73.            |       __|__
  74.            |        
  75.  PIN2: O-- *---*---|  |--*----¬
  76.                |         |    |
  77.                |---| (----    |
  78.                    + -        |                    
  79.                     10uF     _|__
  80.                             / / /                      
  81.      
  82. http://www.retrojunkie.com/asciiart/electron/circuits.htm          
  83.  */
« Última modificación: 27 de Octubre de 2015, 23:44:14 por CompSystems »
Desde Colombia

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #1 en: 26 de Octubre de 2015, 05:10:10 »
Eso es para asignarle una funcion a un pin especialmente estos vectores:

Código: [Seleccionar]
4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
 5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
 6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)

attachInterrupt() es un hook para las interrupciones.

Estaria bueno que tambien pongas un ejemplo de una interrupcion cualquiera como el Timer :P
O tambien se configuran por igual los demas ?

Perdon ya lo encontre:

Código: C
  1. // SPI interrupt routine
  2. ISR (SPI_STC_vect)
  3. {
  4. byte c = SPDR;  // grab byte from SPI Data Register
  5.  
  6.   // add to buffer if room
  7.   if (pos < sizeof buf)
  8.     {
  9.     buf [pos++] = c;
  10.     }  // end of room available
  11. }  // end of interrupt routine SPI_STC_vect

Con ISR y especificando en el argumento el vector

Código: [Seleccionar]
17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
18  SPI Serial Transfer Complete                    (SPI_STC_vect)
19  USART Rx Complete                               (USART_RX_vect)

« Última modificación: 26 de Octubre de 2015, 05:13:21 por KILLERJC »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #2 en: 26 de Octubre de 2015, 07:01:24 »
Me parece muy buena iniciativa el hilo.
Por otra parte creo que hay que desmitificar la supuesta simplicidad del Arduino.

El Arduino UNO (una de las placas más conocidas de las varias decenas de placas Arduino que existen) lleva incorporado un microcontrolador Atmel ATmega328P.
Ese microcontrolador tiene 23 diferentes vectores de interrupción (contando con el reset) y algunos vectores de interrupción manejan hasta 8 interrupciones diferentes (como las interrupciones externas por cambio de estado de un pin).

El software estandar de Arduino está pensado para facilitar el manejo de unas pocas interrupciones, pero también se pueden manejar todas las demás de forma sencilla (como ha posteado Killer)
Arduino es una placa muy completa que tiene unos pocos atajos pensados para los no iniciados, pero mantiene toda su capacidad sin limitaciones para los que conozcan bien el micro.

Para más información:
   Atmega 328P Datasheet
   Avr GCC Toolchain

Un saludo.
« Última modificación: 26 de Octubre de 2015, 07:04:52 por Picuino »

Desconectado CompSystems

  • PIC18
  • ****
  • Mensajes: 488
    • Home Page
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #3 en: 27 de Octubre de 2015, 13:56:25 »
Según lo que dice autor de la pagina menciona en el primer post, algo unas adiciones, algunas faltan por complementar, y tengo algunas dudas, ...

Cuando escribas una rutina de servicio de interrupción (ISR) el código contenido en este debe ser

• Que sea corto, la subrutina debe ser lo mas corta posible

• No use funciones delay(),

yo pregunto ni siquira  delayMicroseconds()?

• No hacer impresiones del puerto serial

en el código anterior realizo despliegue de info, solo como ejemplo mostrativo
Serial.println("Inicia Función para la interrupción #0"); ...

• Hacer variables compartidas con el código principal (MAIN) como volátil, se explico arriba

• No trate de activar o desactivar las interrupciones dentro de la ISR. Por que? creo que esto lo hacia con micros FREESCALE hace 5 años. ¿Cómo se usa detachInterrupt()?

no hay un ejemplo en la referencia de comandos del sitio de ARDUINO https://www.arduino.cc/en/Reference/DetachInterrupt

-------------------------

Un ejemplo de la misma pagina, no se define BUTTON como INPUT,  pinMode (BUTTON, INTPUT);  implica que un pin DIGITAL por defecto esta configurado como ENTRADA?.
La sentencia digitalWrite (BUTTON, HIGH);  activa el pull-up del pin?

Código: C++
  1. // Ejercicio usando un suiche para activar la interrupcion#0 por cambio de valor de 0-1 or de 1-0
  2.  
  3. #define ARDUINO_BOARD Arduino_MEGA_2560
  4.  
  5.   #if ARDUINO_BOARD == Arduino_MEGA_2560 /* Mega, Mega2560, MegaADK */
  6.   //#then
  7.     const byte LED_PIN = 46;
  8.     #define INTERRUPTION0_PIN 2 // pin para la interrupcion #0
  9.     const byte BUTTON_SWITCH = INTERRUPTION0_PIN;
  10.   #else
  11.     // defina los pines correspondientes a su placa
  12.   #endif //BOARDS_H
  13.  
  14.    //defines when the interrupt should be triggered. (activada)
  15.    #define low_to_high_trig RISING // to trigger when the pin goes from low to high (increasing)
  16.    #define high_to_low_trig FALLING // to trigger when the pin goes high to low (descendente)
  17.    #define change_trig      CHANGE // activa la interrupción cada vez que el pin cambia de valor de 0-1 or de 1-0
  18.    #define in_low_trig LOW // to trigger the interrupt whenever the pin is low,
  19.    #define in_HIGHT_trig HIGH //to trigger the interrupt whenever the pin is high. (Arduino Due, Zero only)
  20.  
  21. // Interrupt Service Routine (ISR)
  22. void switchPressed() {
  23.   Serial.println("Inicia Funcion para la interrupcion #0");
  24.   if (digitalRead (BUTTON_SWITCH) == HIGH)
  25.     digitalWrite (LED_PIN, HIGH);
  26.   else
  27.     digitalWrite (LED_PIN, LOW);
  28. }  // end of switchPressed
  29.  
  30. void setup()  {
  31.   pinMode (LED_PIN, OUTPUT);  // so we can update the LED // Para que podamos actualizar el LED
  32.   pinMode (BUTTON_SWITCH, INPUT);  // no hay necesidad de definirlo como ENTRADA
  33.   digitalWrite (BUTTON_SWITCH, HIGH);  // set internal pull-up resistor
  34.  
  35.   attachInterrupt (digitalPinToInterrupt(INTERRUPTION0_PIN), switchPressed/*()*/, change_trig);  // attach interrupt handler
  36.   Serial.begin(9600);
  37. }  // end of setup
  38.  
  39. void loop() {
  40.   // loop doing nothing  // Bucle sin hacer nada
  41. }
  42.  
  43. /*
  44.                
  45.                        /
  46. PIN46: O--/\/\/\--*--|>|--*---¬
  47.                               |
  48.                              _|__
  49.                             / / /
  50.            1K       LED    GND
  51.  
  52.  
  53.  
  54.            * +5v
  55.            |
  56.            |    
  57.            >  
  58.            <  1k
  59.            >        switch
  60.            |        /
  61.            |       /  |
  62.  PIN2: O-- *---*--/   |--*----¬
  63.                |         |    |
  64.                |---| (----    |
  65.                    + -        |                    
  66.                     10uF     _|__
  67.                             / / /                      
  68.      
  69.            
  70.  */



[/code]
« Última modificación: 27 de Octubre de 2015, 23:27:27 por CompSystems »
Desde Colombia

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #4 en: 27 de Octubre de 2015, 14:35:52 »
Todas tus preguntas son faciles de responder. xD

Citar
yo pregunto ni siquira  delayMicroseconds()?
NO, el delay es NO bueno ( dirian los gringos ), nunca un delay es bueno, y menos en una interrupcion

Citar
Por que? creo que esto lo hacia con micros FREESCALE hace 5 años.

Simple... Todo depende de la arquitectura. Algunos micros no poseen "prioridades" en las interrupciones. Entonces cuando estan en una interrupcion se desactiva la entrada a cualquier otra interrupcion.
Supongamos que entro a la interrupcion del timer, desactiva las interrupciones, en medio de la interrupcion del timer llego un dato, entonces espera que termine la interrupcion del timer y vuelve activar las interrupciones, cuando se activan, se observa que esta la interrupcion del dato y se ejecuta. Una ves dentro al igual que pasa cuando estuvo el timer, las interrupciones estan desactivadas.

Distinto es si tenes un micro con prioridades, en estos se suele entrar a una interrupcion, y las interrupciones quedan activas. Si ocurre una interrupcion con menor prioridad/la misma solo queda como "pendiente" es decir sigue la interrupcion en curso, si ocurre una de mayor prioridad, entonces salta a la nueva interrupcion, termina esa, vuelve a la anterior, termina esa y ejecuta las demas con prioridades menores. Como una interrupcion dentro de una interrupcion.

Ahora partiendo de esto.. Tenes que comprender el por que no debe durar mucho, es decir, no deberia haber funciones que ocupen demasiado tiempo, LCD, UART, SPI, etc en el que se manden muchos datos y tenga que esperar el micro para poder meter mas en el buffer, tampoco delays, por que si vos haces eso, estas evitando que otras interrupciones se puedan ejecutar.

Citar
¿Cómo se usa detachInterrupt()?

Con respecto a attachInterrupt y detachInterrupt para mi es un hook ( es decir un pedazo de codigo) el cual mantiene los punteros a las funciones, esto permite podes cambiar las funciones de las interrupciones sin tener que grabar nuevamente la flash. Es decir dinamicamente

Syntax

detachInterrupt(interrupt)
detachInterrupt(digitalPinToInterrupt(pin));
detachInterrupt(pin)   (Arduino Due, Zero only)


De tu ejemplo (codigo 1er pagina):

detachInterrupt(digitalPinToInterrupt(INTERRUPTION0_PIN));

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #5 en: 27 de Octubre de 2015, 14:54:11 »
Citar
Un ejemplo de la misma pagina, no se define BUTTON como INPUT,  pinMode (BUTTON, INTPUT);  implica que un pin DIGITAL por defecto esta configurado como ENTRADA?.
La sentencia digitalWrite (BUTTON, HIGH);  activa el pull-up del pin?

datasheets... datasheeeeeeeet ..sheeeeeeeit

Citar
Each port pin consists of three register bits: DDxn, PORTxn, and PINxn. As shown in ”Register
Description” on page 92, the DDxn bits are accessed at the DDRx I/O address, the PORTxn bits
at the PORTx I/O address, and the PINxn bits at the PINx I/O address.
The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one,
Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input
pin.

If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is
activated. To switch the pull-up resistor off, PORTxn has to be written logic zero
or the pin has to
be configured as an output pin. The port pins are tri-stated when reset condition becomes active,
even if no clocks are running.

If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven
high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port
pin is driven low (zero)
.

DDx comienza con valores 0 al inicio. ( Asi que como entrada )
PORTx cuando es entrada actua como activador de pull-up, eso si el bit PUD en el registro MCUCR esta en 0, si esta en 1 deshabilita los pull-up y no le da importancia a lo que escribas ahi.

Si esta como salida el  PORTx es la salida.

Entonces...
No se necesitaria nada para ponerlo como entrada por que ya esta como entrada.
Y usa digitalWrite (BUTTON, HIGH); el cual escribiria en el PORTx. si sabes que esta como entrada solo activaria el pull-up

Fuente:
Datasheet del ATMega328P
« Última modificación: 27 de Octubre de 2015, 15:58:42 por KILLERJC »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5470
    • Electrónica Didacta
Re:Ejemplos de Interrupt Service Routine (ISR) en arduino
« Respuesta #6 en: 27 de Octubre de 2015, 16:44:55 »
me incluyo en la clase  :-)

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek


 

anything