I am using an LED screen which consumes the following pins of my Arduino Uno: 2,3,4,5,6 and 7. I wanted to use pin 8 as an input so that whenever it is pressed, then the message changes on my LCD screen. I found the library PinChangeInt which helps change the pins used for interrupt. Here is my code:
#include <PinChangeInt.h>
#include <LiquidCrystal.h>
#include <RunningAverage.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
volatile boolean flag = false;
long previousMillis = 0,
previousMillis2 = 0,
interval = 50,
interval2 = 100;
String headerText = "Mini Voltmeter ";
unsigned long currentMillis = 0, currentMillis2 = 0;
RunningAverage myRA(20);
int samples = 0;
int switchPin = 8;
int analogPin = A5;
byte omega[8] = {
B00100,
B01110,
B10001,
B01110,
B00100,
B00100,
B11111
};
void setup() {
Serial.begin(9600);
pinMode(switchPin,INPUT);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print(headerText);
lcd.createChar(1,omega);
myRA.clr();
PCintPort::attachInterrupt(switchPin,swap,FALLING);
}
void updateMeasurement(){
int measurement = analogRead(A0);
myRA.add(measurement);
samples++;
float measurementAverage = myRA.avg();
lcd.write(" ");
lcd.setCursor(0,1);
lcd.print(measurementAverage);
lcd.write(1);
lcd.print(" -- ");
lcd.print((double)map(constrain(measurementAverage,83,789),
83,789,370,3530)/1000);
lcd.print("V");
if (samples == 300)
{
samples = 0;
myRA.clr();
}
}
void swap(){
lcd.setCursor(0,0);
if (!flag){
lcd.print("Button 1 Pressed");
}
else{
lcd.print(headerText);
}
flag = !flag;
}
void loop() {
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
updateMeasurement();
}
}// END of file
What happens is that firstly everything seems to be working as expected. I press the button and the message changes. But after some point the LCD screen starts printing some gibberish - completely random things! Especially it happens when I press the button repeatedly. Is this some kind of bug of the PinChangeInt library? If yes, can I manually tell arduino that I want to use pin 8 as an interrupt? Thanks a lot.
PaulS:
This might be a silly question, but, if pin 8 is available, why not simply move the LED screen pins up one, and use pin 2 for the interrupt pin?
I did it... and you can't guess what happened! The same! Here's the code (without the library for changing pins):
#include <LiquidCrystal.h>
#include <RunningAverage.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
volatile boolean flag = false;
long previousMillis = 0,
previousMillis2 = 0,
interval = 50,
interval2 = 100;
String headerText = "Mini Voltmeter ";
unsigned long currentMillis = 0, currentMillis2 = 0;
RunningAverage myRA(20);
int samples = 0;
int switchPin = 2;
int analogPin = A5;
byte omega[8] = {
B00100,
B01110,
B10001,
B01110,
B00100,
B00100,
B11111
};
void setup() {
Serial.begin(9600);
pinMode(switchPin,INPUT);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print(headerText);
lcd.createChar(1,omega);
myRA.clr();
attachInterrupt(0,swap,FALLING);
}
void updateMeasurement(){
int measurement = analogRead(A0);
myRA.add(measurement);
samples++;
float measurementAverage = myRA.avg();
lcd.write(" ");
lcd.setCursor(0,1);
lcd.print(measurementAverage);
lcd.write(1);
lcd.print(" -- ");
lcd.print((double)map(constrain(measurementAverage,83,789),
83,789,370,3530)/1000);
lcd.print("V");
if (samples == 300)
{
samples = 0;
myRA.clr();
}
}
void swap(){
lcd.setCursor(0,0);
if (!flag){
lcd.print("Button 1 Pressed");
}
else{
lcd.print(headerText);
}
flag = !flag;
}
void loop() {
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
updateMeasurement();
}
}// END of file
PaulS:
You seem to be unclear on what you can, and can not, do in an interrupt service routine. Setting the flag is fine. Writing to the LCD is not.
Hmmm... I can actually move the lcd writing in the loop() method and change the value of the flag in the swap(). But, why should I not write to an LCD inside such a method?
But, why should I not write to an LCD inside such a method?
Because it takes too long. During the time that the ISR is running, other interrupts can not fire, as is needed to receive serial data, update the clock, etc.
But, why should I not write to an LCD inside such a method?
Because it takes too long. During the time that the ISR is running, other interrupts can not fire, as is needed to receive serial data, update the clock, etc.
Got it! I changed the code so as to get rid of the lcd.print invocation inside swap(). Now it look like that:
#include <LiquidCrystal.h>
#include <RunningAverage.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
volatile boolean flag = false;
long previousMillis = 0,
previousMillis2 = 0,
interval = 80,
interval2 = 80;
String headerText = "Mini Voltmeter ";
unsigned long currentMillis = 0, currentMillis2 = 0;
RunningAverage myRA(20);
int samples = 0;
int switchPin = 2;
int analogPin = A5;
void setup() {
Serial.begin(9600);
pinMode(switchPin,INPUT);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print(headerText);
myRA.clr();
attachInterrupt(0,swap,RISING);
}
void updateMeasurement(){
int measurement = analogRead(A0);
myRA.add(measurement);
samples++;
float measurementAverage = myRA.avg();
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(measurementAverage);
lcd.print(" - ");
lcd.print((double)map(constrain(measurementAverage,83,789),
83,789,370,3530)/1000);
lcd.print("V");
if (samples == 300)
{
samples = 0;
myRA.clr();
}
}
void swap(){
flag = !flag;
}
void loop() {
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
updateMeasurement();
}
currentMillis2 = millis();
if(currentMillis2 - previousMillis2 > interval2) {
lcd.setCursor(0,0);
if (flag){
lcd.print("Button 1 Pressed");
}
else{
lcd.print(headerText);
}
}
}// END of file