Having trouble getting Interrupt to work.

I really have not done any Arduino coding for some time, and have been put to task for working on a project. If you remember those old change machines attached to cash registers, that is what this is to be operating. The user can select a number of modes and it will watch a magnet switch to release the coin. The main body of the program is not complete yet, but I was wanting to get all the background stuff done first. I have tried a number of way to get the interrupts to work (using both 0 and 1) for 2 functions, one to change mode and one to reset a progress counter. As I had not written the main body yet, I put in a simple routine just to have something in loop(). One of the main question I have is can you call another function from inside an ISR, as after the ISR updates a profile number, it calls a function to set the data involved with that profile. Also, is LCD/I2C functionality operable from an ISR, as I am not sure if it can. Also, the buttons are using an MC14490P hardware switch debouncer, which outputs a high, until the buttons are pressed, so that is why FALLING is chosen for the AttachInterrupt line…though low has been tried and it as well did not work. The AttachInterrupt lines and their ISRs are color coded.

The code as it stand so far is as below…please do not criticize on function and such, as like I said, it has been a while. This version of the code replaces the bodies of the ISRs with simple LED control, to see if that helps, in which it did not…the original code is commented out.

Hope someone can see the issue here.

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>

LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27 for a 16 chars and 2 line display

const int q1 = 5;
const int d2 = 6;
const int p3 = 7;
const int p4 = 8;
const int p5 = 9;
const int n6 = 10;
const int d7 = 11;
const int q8 = 12;
const int releasesolenoid = 4;//output to drive external release solenoid
const int cooldownSSR = A6;

const int cooldowntoggle = A7;   //toggle switch to disable delay routine
const int trigger = 13;       //switch input to start release routine
const int modechange = 2;     //interrupt switch to change modes on D2
const int countreset = 3;     //interrupt switch to reset counter on D3


int coinstep1 = 0;
int coinstep2 = 0;
int coinstep3 = 0;
int coinstep4 = 0;
int coinstep5 = 0;
int coinstep6 = 0;

int progress = 0;

const int pennydelaycount = 100;
const int nickeldelaycount = 100;
const int dimedelaycount = 100;
const int quarterdelaycount = 100;
const int cooldownminutes = 30;
int cooldowncount = 100;

volatile int profilenumber;
const int profileaddress = 0;

void setup() {
 pinMode(q1, OUTPUT);
 pinMode(d2, OUTPUT);
 pinMode(p3, OUTPUT);
 pinMode(p4, OUTPUT);
 pinMode(p5, OUTPUT);
 pinMode(n6, OUTPUT);
 pinMode(d7, OUTPUT);
 pinMode(q8, OUTPUT);
 pinMode(releasesolenoid, OUTPUT);
 pinMode(cooldownSSR, OUTPUT);
 digitalWrite(cooldownSSR, HIGH);
 
 pinMode(cooldowntoggle, INPUT);
 pinMode(trigger, INPUT);
 pinMode(modechange, INPUT);
 pinMode(countreset, INPUT);

  //Wire.beginTransmission(0x27);
 lcd.begin(16, 2); // initialize the lcd
 lcd.setBacklight(255);

 [color=orange]attachInterrupt(0, modechangeroutine, FALLING); //digitalPinToInterrupt(modechange)[/color]
 [color=limegreen]attachInterrupt(1, countresetroutine, FALLING); //digitalPinToInterrupt(countreset)[/color]

 lcd.setCursor(0, 1);
 lcd.print("Progress = ");
 
 if (EEPROM.read(profileaddress) < 1 || EEPROM.read(profileaddress) > 12);
 {
   EEPROM.update(profileaddress, 1);
 }
 profilenumber = EEPROM.read(profileaddress);
 setprofile();




}

void loop() {
 digitalWrite(d2, HIGH);
 delay(1000);
 digitalWrite(d2, LOW);
 delay(1000);

}
[color=orange]void modechangeroutine() //routine to increment mode and call profile number
{
  //profilenumber += 1;
  //setprofile();
  digitalWrite(q1, HIGH);
}[/color]


[color=limegreen]void countresetroutine() //routine to reset counter number
{
  //progress = 0;
  //cooldowncount = 0;
  //lcd.setCursor(11, 1);
  //lcd.print(progress);
  digitalWrite(q1, LOW);
}
[/color]

void cooldownroutine() // routine to turnmotor off to cool down motor and press
{
 if (digitalRead(cooldowntoggle) == HIGH)
 {
 digitalWrite(cooldownSSR, LOW);
 delay(cooldownminutes * 60 * 1000);
 digitalWrite(cooldownSSR, HIGH);
 }
 cooldowncount = 0;
}


void setprofile() //set profile routine
{  
 EEPROM.update(profileaddress, profilenumber);
 switch(profilenumber)
 {
   case 1: // Penny 3
   coinstep1 = p3;
   coinstep2 = p3;
   coinstep3 = p3;
   coinstep4 = p3;
   coinstep5 = p3;
   coinstep6 = p3;
   cooldowncount = pennydelaycount;
   lcd.setCursor(0, 0);
   lcd.print("1 Penny 3");
   break;
   case 2: // Penny 4
   coinstep1 = p4;
   coinstep2 = p4;
   coinstep3 = p4;
   coinstep4 = p4;
   coinstep5 = p4;
   coinstep6 = p4;
   cooldowncount = pennydelaycount;
   lcd.setCursor(0, 0);
   lcd.print("2 Penny 4");
   break;
   case 3: // Penny 5
   coinstep1 = p5;
   coinstep2 = p5;
   coinstep3 = p5;
   coinstep4 = p5;
   coinstep5 = p5;
   coinstep6 = p5;
   cooldowncount = pennydelaycount;
   lcd.setCursor(0, 0);
   lcd.print("3 Penny 5");
   break;
   case 4: // Penny 3-4
   coinstep1 = p3;
   coinstep2 = p4;
   coinstep3 = p3;
   coinstep4 = p4;
   coinstep5 = p3;
   coinstep6 = p4;
   cooldowncount = pennydelaycount;
   lcd.setCursor(0, 0);
   lcd.print("4 Penny 3-4");
   break;
   case 5: // Penny 3-4-5
   coinstep1 = p3;
   coinstep2 = p4;
   coinstep3 = p5;
   coinstep4 = p3;
   coinstep5 = p4;
   coinstep6 = p5;
   cooldowncount = pennydelaycount;
   lcd.setCursor(0, 0);
   lcd.print("5 Penny 3-4-5");
   break;
   case 6: // Nickel 6
   coinstep1 = n6;
   coinstep2 = n6;
   coinstep3 = n6;
   coinstep4 = n6;
   coinstep5 = n6;
   coinstep6 = n6;
   cooldowncount = nickeldelaycount;
   lcd.setCursor(0, 0);
   lcd.print("6 Nickel 6");
   break;
   case 7: // Dime 2
   coinstep1 = d2;
   coinstep2 = d2;
   coinstep3 = d2;
   coinstep4 = d2;
   coinstep5 = d2;
   coinstep6 = d2;
   cooldowncount = dimedelaycount;
   lcd.setCursor(0, 0);
   lcd.print("7 Dime 2");
   break;
   case 8: // Dime 7
   coinstep1 = d7;
   coinstep2 = d7;
   coinstep3 = d7;
   coinstep4 = d7;
   coinstep5 = d7;
   coinstep6 = d7;
   cooldowncount = dimedelaycount;
   lcd.setCursor(0, 0);
   lcd.print("8 Dime 7");
   break;
   case 9: // Dime 2-7
   coinstep1 = d2;
   coinstep2 = d7;
   coinstep3 = d2;
   coinstep4 = d7;
   coinstep5 = d2;
   coinstep6 = d7;
   cooldowncount = dimedelaycount;
   lcd.setCursor(0, 0);
   lcd.print("9 Dime 2-7");
   break;
   case 10: // Quarter 1
   coinstep1 = q1;
   coinstep2 = q1;
   coinstep3 = q1;
   coinstep4 = q1;
   coinstep5 = q1;
   coinstep6 = q1;
   cooldowncount = quarterdelaycount;
   lcd.setCursor(0, 0);
   lcd.print("10 Quarter 1");
   break;
   case 11: // Quarter 8
   coinstep1 = q8;
   coinstep2 = q8;
   coinstep3 = q8;
   coinstep4 = q8;
   coinstep5 = q8;
   coinstep6 = q8;
   cooldowncount = quarterdelaycount;
   lcd.setCursor(0, 0);
   lcd.print("11 Quarter 8");
   break;
   case 12: // Quarter 1-8
   coinstep1 = q1;
   coinstep2 = q8;
   coinstep3 = q1;
   coinstep4 = q8;
   coinstep5 = q1;
   coinstep6 = q8;
   cooldowncount = quarterdelaycount;
   lcd.setCursor(0, 0);
   lcd.print("12 Quarter 2-8");
   break;
 }
}

One of the main question I have is can you call another function from inside an ISR

You’re calling digitalWrite, so the answer is yes.
My question to you is “why are you using interrupts?”

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 
looks like this

and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

Also please use the AutoFormat tool to indent your code consistently for easier reading.

And if you are not sure how to do something why not write a 10 or 20 line program to explore the concept and learn?

...R

One reason is that if you look in cooldownroutine(), there is a multi-minute delay called and I would like to have the abilty to change modes and reset the counters during that delay time…but may just have to rule that out. Seems that Interrupts are a bit trickier than they appear.

Just generally on interrupts:

  1. Consider also using polling a digital pin in the loop() instead of either a pin change or an external interrupt instead. It could be better although sometimes an interrupt method is necessary (say to wake up from sleep mode).
  2. If you set variables in an interrupt service routine, declare these as volatile to prevent unwanted compiler optimisation.
  3. Don't do too much activity in the ISR, set flags instead and do the activity in the loop().
  4. Not all functionality is available in an ISR. For example, you should not use Serial.print() in one.

Interrupts are good to inform the MCU about the arrival of asynchronous external/internal events; else, the MCU has to spend time to poll the expected events.

@TheMemberFormerlyKnownAsAWOL. That is a remarkably long user name.

GolamMostafa:
Interrupts are good to inform the MCU about the arrival of low-latency asynchronous external/internal events; else, the MCU has to spend time to poll the expected events.

6v6gt:
@TheMemberFormerlyKnownAsAWOL. That is a remarkably long user name.

Interesting! My browser does not show the last poster name if s/he is : TheMemberFormerlyKnownAsAWOL. So, what is the solution -- should I change my browser or the referred user name is to be shortened?

6v6gt:
@TheMemberFormerlyKnownAsAWOL. That is a remarkably long user name.

pretty long

6v6gt:
@TheMemberFormerlyKnownAsAWOL. That is a remarkably long user name.

I am an unremarkably long person (1.85m)

TheMemberFormerlyKnownAsAWOL:
I am an unremarkably long person (1.85m)

Ah yes. Indeed. I knew that there would have been a rational explanation for it.

GolamMostafa:
or the referred user name is to be shortened?

Already tried that. It didn’t work out.

The long long long long (256 bits) user name has brought a remarkable beauty in the log book of the Forum; where, there are now blanks against the names of the posters. At the moment, I can visualize two blanks and there is no need to scan the names -- blank means that that long person.

ISSUE RESOLVED

POST CAN BE DELETED

krbruner:
ISSUE RESOLVED

POST CAN BE DELETED

But if you leave it up and add [SOLVED] to the thread title and tell *how *it was resolved someone else may benefit in the future.