Buenas!!
soy un novato total, llevo una semana con mi arduino.
Tengo un programa para leer las revoluciones de un ventilador, por el puerto serie funciona bien, pero cuando intento hacer lo mismo por el display I2C que tengo no hay manera. Cuando pongo el codigo que les muestro es como si solo entrara una vez en la interrupcion.
En cuanto quito lo del display muestra el resultado cada segundo por el serial.
Me he empapado todo el tema de interrupciones, visto ejemplos pero no doy, y no salgo de esta tonteria.
La resistencia de pull-up es de 1K no tenia otra y esta conectada a la entrada de 3.3V.
Solo veo por la pantalla la palabra "Speed:" y por el puerto serie nada
Gracias por vuestra ayuda.
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // Constructor for LCD, (Address of LCD, NoOfColumns,NoOfRows
int NbTopsFan;
int Calc;
int hallsensor = 2;
typedef struct{
char fantype;
unsigned int fandiv;
}fanspec;
//Definitions of the fans
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1;
void rpm ()
{
NbTopsFan++;
}
void setup()
{
pinMode(hallsensor, INPUT);
Serial.begin(9600);
attachInterrupt(0, rpm, RISING);
lcd.init(); // initialize the lcd
lcd.backlight(); // backlight of lcd
lcd.home(); // initialize lcd cursor position
}
void loop ()
{
NbTopsFan = 0;
lcd.setCursor(2, 0);
lcd.print ("Speed:");
sei();
delay (1000);
cli();
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
lcd.setCursor(2, 1);
lcd.print (Calc,DEC);
lcd.print ("rpm");
Serial.print (Calc, DEC);
Serial.print (" rpm\r\n");
}
Muy simple. Quita todo lo que es RPM y prueba tu rutina I2C con el display.
Cuando logres que el LCD funciona bien, vuelves con ese seteo y configuración a este código y verás que facil funciona todo.
Buenas
gracias por tu respuesta. La libreria del display funciona correctamente. Por ejemplo, el siguiente programa me dice en que direccion se encuentra mi display y me lo muestra por display, desplazandose el texto por ella. Que debo hacer entonces en el programa de la interrupcion?? Gracias!!!!
/*------------------------------------------------------
Programa para buscar dispositivos I2C conectados.
Manda las direcciones que encuentra a la puerta serie
Encontrado en:
http://playground.arduino.cc/Main/I2cScanner
---------------------------------------------------------
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // Constructor for LCD, (Address of LCD, NoOfColumns,NoOfRows)
void setup()
{
Wire.begin();
lcd.init(); // initialize the lcd
lcd.backlight(); // backlight of lcd
lcd.home(); // initialize lcd cursor position
//Serial.begin(9600);
//Serial.println("\nI2C Scanner");
//lcd.setCursor(2, 0); // (column,row)
//lcd.print("nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
lcd.setCursor(2, 0);
lcd.print ("Scanning...");
//Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
lcd.setCursor(0,1);
lcd.print("I2C device found at address 0x");
//Serial.print("I2C device found at address 0x");
if (address<16)
lcd.print("0");
lcd.print(address,HEX);
for (int i=0; i <= 255; i++)
{
lcd.scrollDisplayLeft();
delay(300);
}
//Serial.print("0");
//Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
Tienes toda la razon. Pero el volatile solo me resolveria quizá el falseo de la variable pero sigo sin llegar a entender porque no veo por display el resultado de la variable Calc que son las RPM del ventilador. Muchas gracias por la ayuda
Gracias por tu ayuda Surbyte
Nada sigue sin mostrar nada
He realizado pruebas, los mensajes que ponga antes de habilitar las interrupcioné es (sei) el mensaje lo imprime, peeeeero la variable que calcula las revoluciones Calc, que como es logico hay que calcularla una vez deshabiite las interrupciones, no hay manera de imprimirla, la logica manda imprimirla a continuacion. He leido, releido, el tema de interrupciones, no entiendo como una cosa tan basica, mi primer proyecto, este dando tanta guerra.
Decir que tampoco muestra nada la salida serie.
Seguiré leyendo, a cabezon no me gana nadie.
Si se te ocurre alguna otra idea, me vendria genial
Gracias!!!!
Por cierto guerra? No sabes lo que es algo que te de guerra. Hay que probar, bien o mal algo hará la diferencia.
Busca la vuelta, ve si se reciben los pulsos. Ve cambia el nombre de calc por otro, mi compilador lo puso con otro color asociado a variables reservadas, luego le puse unsigned int y lo cambio... me quedó la duda.
Llamalo RpmCalc a ver si muestra algo.
Buenas
conclusion de las pruebas que he realizado.
He renombrado todas las variables del programa. Dejando el bucle loop sin ninguna linea comentada de la libreria del display, no se muestra ningun resultado ni en el monitor serial ni el display.
El monitor serial solo muestra su salida con el siguiente codigo
en cuanto descomento un lcd.print, lo mismo me da un texto que una variable, el monitor serial no muestra nada y el display por supuesto no saca nada.
He probado a poner el lcd.print por encima de los Serial.print, dando el mismo resultado.
Pruebo a ver si siquiera muestra un mensaje simple despues del cli y el display nada
Bueno, bueno, bueno
no entiendo nada, he puesto el print despues del sei() una vez que se activan las interrepciones y el display pinta las revoluciones peeero, no se como hacer para poner un mensaje en plan "Velocidad: XXX RPM" porque ahora el display pinta a lo loco, es decir, empieza a pintar el numero de RPM`s en la primera linea y sigue hasta que pasa a la segunda linea y asi continuamente.
El codigo con el que pinta el display seria
lo que no logro entender es que despues de deshabilitar las int, el display no pinte, y una vez que las habilito si, entiendo que es contrario a la filosofia de uso de las interrupciones, ya que deben de ser eventos para ejecutar lo necesario y marcharme de alli rapidamente, para que la CPU continue por donde se quedó antes de atender dicha interrupcion. Si yo me tengo que entretener sacando la salida por un display, no lo entiendo. En este caso es igual, solo quiero que funcione.
Si no me he explicado bien me comentais.
Solucion bajo mi punto de vista poco elegante, seguro que sabeis como hacerlo mejor.
La unica manera que he encontrado de que se mantenga el resultado en la misma linea es con un clear del display, me da la sensacion de matar moscas a cañonazos.
A ver que me comentais respecto al codigo, y lo que he comentado antes, porque funciona con las interrupciones habilitadas.
Muchas gracias!!!
Si si instrumento solo tiene que mostrar las RPM entonces la palabra speed o Velocidad la puedes imprimir una sola vez en el setup
lcd.setCursor(0,0);
lcd.print("Speed:");
Luego en el loop
Quita el lcd.clear(); y pon
lcd.setCursor(0,7); // pone el cursor en la primera línea y caracter 7
lcd.print(" "); // limpia lo que había antes
lcd.setCursor(0,7); // Vuelver a poner el cursor en el caracter 7
lcd.print(Calculorpm); // Imprime las RPM
Muchas gracias
totalmente de acuedo, me parece mejor borrar con espacios en blanco que toda la pantalla. desconocia que en el setup pudiera hacerse esto.
ahora, lo que me come por dentro es saber porque tiene que ser con las interrupciones habilitadas cuando imprime el display y no en cualquier otro sitio del bucle loop.