Inyerrupcciones y LCD

:slight_smile: Buenas primero me presento soy Daniel Franco Ramos y ante todo gracias por la ayuda.
Mi problema es que estoy realizando un proyecto de un medidor de pulso y uso la Interrupci贸n 2, mas concreta-mente el Timer 2 en modo comparaci贸n. esta interrupci贸n deshabilita los 3 y 11 hasta ah铆 todo bien. Mi problema es que mi proyecto va montado con LCD que 16x2 que van conectados tambien en esa patilla si alguien me puede decir como cambiar la conexi贸n del LCD o alguna otra soluci贸n lo agradeceria

No entiendo porque dices que deshabilita "los 3 y 11". La IRQ 2 no deshabilita nada que no quieras deshabilitar.

Porque no comienzas incluyendo tu c贸digo, y tu esquema y vemos como reubicarlo
Pero la libreria LiquidCrystal.h permite que uses cualquier pin para las conexiones del LCD

Mira esto:

El circuito:

  • LCD RS pin to digital pin 12

  • LCD Enable pin to digital pin 11

  • LCD D4 pin to digital pin 5 // se usa modo 4 bits

  • LCD D5 pin to digital pin 4

  • LCD D6 pin to digital pin 3

  • LCD D7 pin to digital pin 2

  • LCD R/W pin to ground

  • 10K resistor:

  • ends to +5V and ground

  • wiper to LCD VO pin (pin 3)

/* Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 
 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

Buenas he estado mirando en el datasheet y no encuentro la referencia exacta de porque se deshabilita eh pin 3 y el 11. eso lo le铆 en un sitio donde te ayudaba a configurar la interrupcion interna te dejo mi codigo aunque aun no tengo metido la parte del lcd y me faltan cosas para acabarlo.
code:[
/*Variables a usar en la interrupcion por eso son volatiles no necesitan comunicacion con
el programa exterior */
volatile int Vm =515; /valor medio de las se帽ales despues de haber hecho varias pruebas/
volatile int Se帽al; //Variable que nos da el valor del sensor analogico
volatile unsigned long Contador = 0; //Contador de tiempo
volatile unsigned long UltimoLatido = 0; //tiempo del ultimo latido

void loop(){
Time = millis(); // tiempo en ms

// configurar la interrpcion para cada 2ms la lea

TCCR2A = 0x02; //activa el bit OCR2A y esto pone el comparador el modo
TCCR2B = 0x06; // activa in prescalado de 256
OCR2A = 0X7C; // Es el bit de comparacion establecido en 124
TIMSK2 = 0x02; // activa el bit OCIE2A que habilita la interrupcion del timer 2 en comparacion
sei(); // Activa las interrupciones

ISR(TIMER2_COMPA_vect){
cli(); //desactiva las interrupciones temporalmente
Se帽al = analogRead(pulsePin); //leer la entrada del sensor
Contador += 2; //contador de tiempo
int TDUL = Contador - UltimoLatido; // tiempo transcurrido desde el ultimo latido

/vamos a buscar las pulsaciones el pico y el valle siempre y cuando hayamos encontrado
el latido primero estas condicion solo sirve una vez encontrado
/
if((Se帽al < Vm)&&(Pulso == false)&&(TDUL>(TEL/5)*3)){//evitar la onda peque帽a

if(Se帽al < V){ //V es el punto minimo de la onda
V = Se帽al; //Asignar a V el valor de se帽al
}
}

if((Se帽al > Vm) && (Se帽al > P)){ /si la se帽al es mayor que P y mayor que el valor medio asignamos el valor maximo/
P = Se帽al; // P es el maximo
}

/*quermos encontrar por primera vez el pulso para ello descartamos cualquier pulsacion
que asi que descartamos cualquier anomalia el ritmo maximo de pulsaciones en esfuerzo
ronda los 200 a 210 pulsaciones por minuto y con un ataque a al corazon podria llegar
a las 250 o incluso mas fijare un maximo de 250 pulsaciones por minuito mas de eso no
se identificara solo detectara un fallo o un aviso de ataque cardicaco grave */
if(TDUL > 240){
if( (Se帽al > Vm) && (Pulso == false) && (TDUL > (TEL/5)*3)){
Pulso = true;
digitalWrite(blinkPin,HIGH);
TEL = Contador - UltimoLatido;
UltimoLatido = Contador;

if(latido2){
latido2 = false;
for(int i=0; i<=9; i++){
grupo = TEL;

  • }*
  • }*
  • if(latido1){*
  • latido1 = false;*
  • latido2 = true;*
  • sei();*
  • return;*
  • }*
  • ]*

Que mezcla de cosas.
A ver si lo ordenamos un poco.
Primero ya entiendo que quieres hacer.
Arduino tiene una estructura que se debe respetar.

Define's
variables
setup()
loop()

Rutinas necesarias en el loop()

Bien bajo ese criterio hay cosas que corregir.
No estoy seguro del uso de volatile para las variables globales.
Falta algo en el loop o interpreto que tu ISR tiene c贸digo ue no le pertenece

/*Variables a usar en la interrupcion por eso son volatiles no necesitan comunicacion con
el programa exterior */
volatile int Vm =515; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽/*valor medio de las se帽ales despues de haber hecho varias pruebas*/ 聽 聽 聽 
volatile int Se帽al; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽//Variable que nos da el valor del sensor analogico
volatile unsigned long Contador = 0; 聽 聽 //Contador de tiempo
volatile unsigned long UltimoLatido = 0; //tiempo del ultimo latido

void setup() {
// configurar la interrpcion para cada 2ms la lea
 
 聽cli()
 聽TCCR2A = 0x02; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 //activa el bit OCR2A y esto pone el comparador el modo 
 聽TCCR2B = 0x06; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // activa in prescalado de 256
 聽OCR2A = 0X7C; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// Es el bit de comparacion establecido en 124
 聽TIMSK2 = 0x02; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // activa el bit OCIE2A que habilita la interrupcion del timer 2 en comparacion
 聽sei(); 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Activa las interrupciones

 ISR(TIMER2_COMPA_vect){
 聽 聽cli(); 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽//desactiva las interrupciones temporalmente
 聽 聽Se帽al = analogRead(pulsePin); 聽 聽 聽 聽 //leer la entrada del sensor
 聽 聽Contador += 2; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽//contador de tiempo
 聽 聽int TDUL = Contador - UltimoLatido; 聽 // tiempo transcurrido desde el ultimo latido
 聽 
 聽 聽/*vamos a buscar las pulsaciones el pico y el valle siempre y cuando hayamos encontrado
 聽 聽el latido primero estas condicion solo sirve una vez encontrado*/
 聽
 聽 if((Se帽al < Vm)&&(Pulso == false)&&(TDUL>(TEL/5)*3)){ 聽//evitar la onda peque帽a
 聽 
 聽 聽 聽if(Se帽al < V){ 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 //V es el punto minimo de la onda 聽 聽 
 聽 聽 聽 聽V = Se帽al; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 //Asignar a V el valor minimo de la se帽al
 聽 聽 聽}
 聽 聽}
 聽 
 聽 聽if((Se帽al > Vm) && (Se帽al > P)){ 聽 聽 聽 聽/*si la se帽al es mayor que P y mayor que el valor medio asignamos el valor maximo*/
 聽 聽 聽P = Se帽al; 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// P es el maximo
 聽 聽}
 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 
 聽 聽 
 聽 聽 /*queremos encontrar por primera vez el pulso para ello descartamos cualquier pulsacion
 聽 que asi que descartamos cualquier anomalia el ritmo maximo de pulsaciones en esfuerzo
 聽 ronda los 200 a 210 pulsaciones por minuto y con un ataque a al corazon podria llegar
 聽 a las 250 o incluso mas fijare un maximo de 250 pulsaciones por minuto mas de eso no
 聽 se identificara solo detectara un fallo o un aviso de ataque cardicaco grave */

 聽 if(TDUL > 240){
 聽 聽 if( (Se帽al > Vm) && (Pulso == false) && (TDUL > (TEL/5)*3)){
 聽 聽 聽 Pulso = true;
 聽 聽 聽 digitalWrite(blinkPin,HIGH);
 聽 聽 聽 TEL = Contador - UltimoLatido;
 聽 聽 聽 UltimoLatido = Contador;
 聽 聽 
 聽 聽 
 聽 聽 if(latido2){
 聽 聽 聽 latido2 = false;
 聽 聽 聽 for(int i=0; i<=9; i++){
 聽 聽 聽 聽 grupo = TEL;
 聽 聽 聽 }
 聽 聽 }
 聽 聽 if(latido1){
 聽 聽 聽 latido1 = false;
 聽 聽 聽 latido2 = true;
 聽 聽 聽 sei(); 聽 聽 聽 聽 聽 // ojo con esto activas interrupciones si latido1 es 1 y sino?????
 聽 聽 聽 return;
 聽 聽 }
}

void loop() { 聽 // por ahora a menos que te malinterprete no hay nada en el loop???
}

Finalmente no hay nada que active la interrupci贸n externa que mencionas?

Este c贸digo se aplica para la int0 del UNO que es el pin 2, tomado de este link

int pin = 13;
volatile int state = LOW;

void setup()
{
 聽pinMode(pin, OUTPUT);
 聽attachInterrupt(0, blink, CHANGE); 聽// 0 es int0 pin2 1 int1 pin 3
}

void loop(){
 聽digitalWrite(pin, state);
}

void blink(){
 聽state = !state;
}

NOTA IMPORTANTE: No te conozco pero te recomiendo tengas mucho cuidado con lo que estas haciendo.
Si se e trata de un equipo m茅dico (como parece), espero que no sea un desfribilador, si lo es, el campo el茅ctrico generado en la descarga puede hacer que el arduino se comporte mal.
Tal vez solo es un monitor card铆aco y tienes que tomar alguna decisi贸n, en cuyo caso es mas simple pero no menos responsable.
Ojala puedas lograr que funcione correctamente. La responsabilidad civil en estos casos nos puede arruinar la vida profesional.

Dicho esto, o mejor, advertido, estoy para ayudarte en lo que necesites.

No te preocupes no tengo intenci贸n de electrocutar a nadie y conozco los riesgo de la electricidad en el cuerpo pero mi proyecto no tiene ningun riesgo lo que intento hacer es un monitor card铆aco como bien has dicho pero por una t茅cnica no invasiva que es la pulsioximetr铆a que mediante un led y una ldr se detecta el pulso. Solo tienes un sensor de pinza en el dedo. Bueno solo aclararte eso para que veas que no ayudas a un loco, Bueno y decirte que muchas gracias por tu respuesta voy a echar un vistazo a lo que me has comentado y ya te dir茅.

bien... como siempre postean parte del c贸digo uno se imagina cualquier escenario. Arduino es fant谩stico pero tiene algunos cuestiones en los que debe prestarsele atenci贸n.

Okay.

Bueno tu mismo dijiste que el c贸digo estaba inconcluso pero al menos ahora tiene orden pero no se para donde vas.
Eso que mostraste parecia estar concentrado en la rutina del timer. O sea tomas muestras a intervalos regulares, cuentas y puedes sacar los BPM (beats per minute), ademas de medir cuestiones importantes de la gr谩fica sistole/di谩stole.

Mira te explico un poco mi idea es hacer un programa principal que cuando detecte el pulso encienda y apague un led con cada pulso, otro que cambie su intensidad seg煤n la onda card铆aca y que me imprima los valores en un lcd y tambi茅n que me los mande hacia la computadora para crear una interfaz con otro programa seguramente matlab yy con esa se帽al recibida mostrar la onda card铆aca en el ordenador. la idea es que pueda funcionar conectado al ordenador con su interfaz o no conectado solo mostrando pulsaciones en LCD. En este momento estaba centrado en el trabajo de la interrupci贸n porque es lo que menos manejo por eso mi c贸digo esta bastante desordenado.
Mi idea es que mi interrupci贸n lea cada 2ms valla asignando los valores m谩ximos y m铆nimos y encuentre las pulsaciones esa es mas o menos la parte del codigo que he puesto y que es la que he estado probando he necesitado muchas pruebas para poder identificar bien el pico de la onda ahora me toca calcular las pulsaciones por minuto.
Bueno todo esto viene a que para adelantar trabajo me puse a ver como se conectaba un lcd que no fuera pinchado porque la caja que compre no me lo permite y me vi en el problema de que vi que utilizaba los pines que supuestamente deshabilita mi interrupci贸n interna y quise resolver el problema antes que otros.
Ademas es mi primera vez programando arduino y tengo algunos l铆os grandes.
Solo decirte que muchas gracias por tu ayuda.

Con respecto al LCD ya te expliqu茅 que es lo que menos debe quitarte el sue帽o. A menos que este cableado y use el pin2 fisicamente hablando, sino lo conectas a cualquier pin.
Como te puse antes.

El resto va como te dije. Tienes tu interrupci贸n cada 2mseg. Eso digamos funciona.
Entonces la int0 en el pin2 no la necesitas. ya est谩s en camino.
Lo que falta es sumar el LCD, y presentar los BPM (beats per minute) o PPM (pulsos por minuto) como quieras llamarlo.
Toma una foto del LCD a ver si es com煤n, y otra con undiagrama que muestre que pines te quedan o lo escribes.
Y asignamos los pines al LCD y ya lo tienes en camino.

Una sugerencia, yo hice un proyecto con un LCD, y vi que daba bastantes mejores resultados el usar un conversor I2C para el LCD. Los hay muy baratos, se simplifica mucho el cableado y el resultado es muy bueno.

Muchas gracias todas sugerencias son buenas. Una pregunta a ver si me la podeis aclarar no tengo muy claro si un return en lenguaje arduino te saca de la interrupcion se que en leguaje C si alguien me puedo contestatar

Una buena respuesta esta en este link, supongo que por las cosas que manejas no tienes problemas con el ingl茅s.

Gracias surbyte he tenido una semana ocupada y no he podido mirarlo antes el link esta bien he le铆do parte del foro aunque mi ingles no he tan bueno como quisiera para entenderlo todo bien y el traductor pone cosas rara pero haciendo pruebas con un programa b谩sico de interrupci贸n que he creado me he dado cuenta de que el return te saca de la interrupci贸n como era normal, muchas gracias por tu aportaci贸n.

Bueno insisto con ordenar las cosas y como parte de tu mayor consulta tiene que ver con el LCD y elproblema con el pin 3 y 11, te voy a pedir que hagas un esquema de las cosas que tienes conectadas al arduino.

Hazlo a mano alzada o con algun programa y lo subes para poder entender todo. Incluye el LCD tal como lo tienes conectado.

Bueno sigo esperando que me llegue mi pantalla as铆 que no puedo enviar la foto en el momento que llegue os la mando. y ahora una duda que tengo a ver si me la pod茅is resolver si no veis conveniente resolverla aqu铆 abrir茅 otro hilo. Mi duda es como consigo detectar el maximo de la onda del pulso, no se si me explico voy cogiendo maximos pero no se como detectar el maximo del pulso.

聽 /*Habilitar la Interrupcion y sus contactos*/
聽 #include <avr/io.h>聽 聽 聽 聽 聽 聽 //incluir y habilitar las entradas y las interrrupciones
聽 #include <avr/interrupt.h>
聽 
聽 
聽 /*Declaracion De Variables*/
聽 volatile int Contador;
聽 volatile int Senal;聽 聽 聽 聽 聽 聽 聽 聽 聽  // Guarda los datos de la se帽al del sensor
聽 long Time = 0;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Variable que va a guardar el Tiempo
聽 const int analogInPin = A0;聽 聽 聽 聽 聽  // Entrada del Sensor Analogico 
聽 int LedPin=13;
聽 volatile int H =512;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // VAlor del Pico聽 
聽 volatile int L = 512;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // Valor del valle
聽 volatile unsigned long UL = 0;
聽 volatile int TEL = 600;
 
 
 
 void setup(){
 Serial.begin(115200);聽 聽 聽 聽 聽 聽 聽 聽 聽 // velocidad a la que ira el procesador
 pinMode(LedPin, OUTPUT);
聽 
聽 TCCR2A = 0x02;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  //activa el bit OCR2A y esto pone el comparador el modo聽 
聽 TCCR2B = 0x06;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // activa in prescalado de 256
聽 OCR2A = 0X7C;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Es el bit de comparacion establecido en 124
聽 TIMSK2 = 0x02;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // activa el bit OCIE2A que habilita la interrupcion del timer 2 en comparacion
聽 sei();聽 聽 聽 聽  // Activa las i
 }
 void loop(){
聽  
聽 Serial.print("sensor = " );聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  
聽 Serial.print(Senal);聽 聽 聽 
聽 Serial.print("\t Contador = ");聽 聽 聽 
聽 Serial.println(Contador);聽  
聽 Serial.print("\t Maximo = ");聽 聽 聽 
聽 Serial.println(H);
聽 Serial.print("\t Minimo = ");聽 聽 聽 
聽 Serial.println(L); 
聽 

 }
 
 
ISR(TIMER2_COMPA_vect){聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // entra cuando timer2 cuenta 124
聽 cli(); 
 Senal = analogRead(analogInPin);聽  
 digitalWrite(LedPin, !digitalRead(LedPin));
 Contador +=2;
 int Tm = Contador - UL;
 if(Senal > 600 && Tm > (UL/5)*3 )
 if(Senal > H){
 H = Senal;
 }
 if(Senal <L){
 L = Senal;
 }
 
}


Aqui dejo las fotos de la pantalla ha tardado un poco en llegarme

0 fotos

djfr0002:

Aqui dejo las fotos de la pantalla ha tardado un poco en llegarme

A ver si alguien me puede echar una mano para que solo me cuente un pulso aqui dejo el codigo el bit bandera no se me desactiva en el momento que quiero

聽 /*Habilitar la Interrupcion y sus contactos*/
聽 #include <avr/io.h>聽 聽 聽 聽 聽 聽 //incluir y habilitar las entradas y las interrrupciones
聽 #include <avr/interrupt.h>
聽 
聽 
聽 /*Declaracion De Variables*/
聽 volatile unsigned long Contador;
聽 volatile int Senal;聽 聽 聽 聽 聽 聽 聽 聽 聽  // Guarda los datos de la se帽al del sensor
聽 long Time = 0;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Variable que va a guardar el Tiempo
聽 const int analogInPin = A0;聽 聽 聽 聽 聽  // Entrada del Sensor Analogico 
聽 int LedPin=13;
聽 volatile int H =512;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Valor del Pico聽 
聽 volatile int L = 512;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // Valor del valle
聽 volatile unsigned long UL = 0;
聽 volatile int TEL = 600;
聽 volatile int Umbral;
聽 volatile boolean Subiendo = false;聽 聽 // onda subiendo
聽 volatile boolean Bajando = false;聽 聽  // onda bajando
聽 volatile boolean Fs = false;聽 聽 聽 聽 聽 // Final de Subida
聽 volatile boolean Fb = false;聽 聽 聽 聽 聽 // Final de Bajada
聽 volatile int Tm = 0;
聽 int Pulso =0;

聽 
 
 
 void setup(){
 Serial.begin(115200);聽 聽 聽 聽 聽 聽 聽 聽 聽  // velocidad a la que ira el procesador
 pinMode(LedPin, OUTPUT);
聽 
聽 TCCR2A = 0x02;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  //activa el bit OCR2A y esto pone el comparador el modo聽 
聽 TCCR2B = 0x06;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // activa in prescalado de 256
聽 OCR2A = 0X7C;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // Es el bit de comparacion establecido en 124
聽 TIMSK2 = 0x02;聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // activa el bit OCIE2A que habilita la interrupcion del timer 2 en comparacion
聽 sei();聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // Activa las i
 }
 void loop(){
聽  
聽 Serial.print("sensor = " );聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  
聽 Serial.print(Senal);聽 聽 聽 
聽 Serial.print("\t Contador = ");聽 聽 聽 
聽 Serial.println(Contador);聽  
聽 Serial.print("\t Maximo = ");聽 聽 聽 
聽 Serial.println(H);
聽 Serial.print("\t Minimo = ");聽 聽 聽 
聽 Serial.println(L); 
聽 Serial.print("\t Pulso = ");
聽 Serial.println(Pulso);
聽 Serial.print("\t Fs Fb Sub Baj = ");
聽 Serial.print(Fs);
聽 Serial.print(Fb);
聽 Serial.print(Subiendo);
聽 Serial.print(Bajando);
聽 Serial.print("\t Umbral = ");
聽 Serial.print(Umbral);
聽 Serial.print("\t Tm = ");
聽 Serial.print(Tm);
聽 Serial.print("\t Contador = ");
聽 Serial.print(Contador);
聽 Serial.print("\t UL = ");
聽 Serial.print(UL);
聽 
聽 if (Fs){
聽 聽 Fs = false;
聽 聽 Pulso += 1;
聽 聽 

聽 }

 }
 
 
ISR(TIMER2_COMPA_vect){聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽  // entra cuando timer2 cuenta 124
聽 cli(); 
 Senal = analogRead(analogInPin);聽  
 digitalWrite(LedPin, !digitalRead(LedPin));
 Contador +=2;
 Umbral = (H + L)/2;
 
 if((Senal < Umbral) && (Tm > (UL/5)*3) ){
 if(Senal < L){

 Bajando = true;
 Subiendo = false;
 L = Senal;
 }
 }
 if((Senal > Umbral) && (Senal > H) ){
 
 Subiendo = true;
 Bajando = false;
 H = Senal;
 }
 if (Subiendo && (Senal < H) && (! Fs) ){
 
 Subiendo = false;
 Tm = Contador - UL;
 UL = Contador;
 H = 512;
 Fs = true;
 
 }
 
}