Arduino interrupt Pin

In my program I use both a timerInterrupt which is triggered every 1 second to calculate the water flow during this time interval and two Interrupts which when active increment the variables Pulscount and Pulscount1 which will be used later for the water flow calculation. I use the arduino mega 2560 for this purpose. According to the data sheet the InterruptPin are at Pin 2, 3, 18, 19, 20 and 21. When I use Pin 18 and 19 my program works without problems. But when I use Pin (2, 3, 20 and 21) the values displayed on the LCD are strange and sometimes the brightness of the LCD decreases. Does anyone have an idea of the source of the problem?

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

float cfactor1 = 7;
byte interrupt1 = 18;
byte sensorPin1 = 6;
volatile byte pulseCount1;
float flowRate1;
unsigned int f_ml1;
unsigned long t_ml1;
unsigned long oldTime1;

float cfactor = 7;
int interrupt = 19;
byte sensorPin = 5;
volatile byte pulseCount;
float flowRate;
unsigned int f_ml;
unsigned long t_ml;
unsigned long oldTime;

int semic;
int semic1;

LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup()
{
  lcd.init();
  lcd.backlight();

  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  pinMode(sensorPin1, INPUT);
  digitalWrite(sensorPin1, HIGH);

  cli(); // disable interrupts
  // reset
  TCCR1A = 0; //set TCCR1A register to 0000
  TCCR1B = 0; //set TCCR1B register to 0
  TCNT1 = 0; // reset counter value
  OCR1A = 15624; //compare match register für 1 Sekunde (15624pulse vorher)
  // set prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TCCR1B |= (1 << WGM12); //turn on CTC mode
  TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
  sei(); //allow interrupts

  attachInterrupt(digitalPinToInterrupt(interrupt), pulseCounter, RISING);
  attachInterrupt(digitalPinToInterrupt(interrupt1), pulseCounter1, RISING);
}

void loop()
{
  lcd.setCursor(0, 0);
  lcd.print("a:");
  lcd.print(int(flowRate));
  lcd.print(".");
  semic = (flowRate - int(flowRate)) * 10;
  lcd.print(semic, DEC) ;
  lcd.print("L/min");


  lcd.setCursor(0, 2);
  lcd.print("b:");
  lcd.print(int(flowRate1));
  lcd.print(".");
  semic1 = (flowRate1 - int(flowRate1)) * 10;
  lcd.print(semic1, DEC) ;
  lcd.print("L/min");

}


ISR(TIMER1_COMPA_vect) { // function which will be called when an interrupt occure at timer 1

  if ((millis() - oldTime) > 1000)
  {


    //flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / cfactor;
    flowRate = ((1000.0 / 1000) * pulseCount) / cfactor;
    oldTime = millis();
    f_ml = (flowRate / 60) * 1000;
    t_ml += f_ml;
    Serial.print("Current flow: ");
    Serial.print(int(flowRate));
    Serial.print(".");
    semic = (flowRate - int(flowRate)) * 10;
    Serial.print(semic, DEC) ;
    Serial.print("L/min");
    Serial.print("  Total: ");
    Serial.print(t_ml);
    Serial.println("mL");
    pulseCount = 0;
    attachInterrupt(interrupt, pulseCounter, RISING);




    //flowRate1 = ((1000.0 / (millis() - oldTime1)) * pulseCount1) / cfactor1;
    flowRate1 = ((1000.0 / 1000) * pulseCount1) / cfactor1;
    oldTime1 = millis();
    f_ml1 = (flowRate1 / 60) * 1000;
    t_ml1 += f_ml1;
    Serial.print("Current flow1: ");
    Serial.print(int(flowRate1));
    Serial.print(".");
    semic1 = (flowRate1 - int(flowRate1)) * 10;
    Serial.print(semic1, DEC) ;
    Serial.print("L/min1");
    Serial.print("  Total: ");
    Serial.print(t_ml1);
    Serial.println("mL1");
    pulseCount1 = 0;
    attachInterrupt(interrupt1, pulseCounter1, RISING);
  }
}
void pulseCounter()
{
  pulseCount++;
}

void pulseCounter1()
{
  pulseCount1++;
}

You are really jammering on the LCD, no need to write to it so often.

You are doing too much work in the ISRs.

You are serial printing from the ISRs, never a good idea to the point of being referred to as forbidden.

It’s not forbidden obvsly, but it is a bad idea.

Set flags in the ISRs, do the work when you see the flags up in you loop().

Try that.

Also, why is there an attachInterrupt in the ISR? Did you see this in code you stole borrowed from?

You could prolly code this w/o using interrupts at all, but that’s another discussion.

a7

Why use millis within the timer interrupt? If you use millis, you can do that within loop() and need no interrupt at all, which is much better and doesn't interfere with your prints.
Interrupts are only needed for really fast response times. What is the frequency of your pulses?

1 Like

Didn’t see that tree in the forest.

a7

Thinking about it, milli() has no place in the TimerInterrupt. If I don't perform these operations in the loop using milli(), it's because I'll put my main code there later. The flow rate that has to be measured constantly will be measured in parallel at specific time intervals in the timerinterrupt. Also the number of pulses counted per second is relatively high (about 100 pulses), that's why I use the interrupt

Not sure I understand what you are saying; however, there is no reason for the timer interrupt if you properly code loop() without using delay() calls. You can leave the pulse counter interrupts.

1982 called, it wants its baud rate back. This is killing your loop. Try 500000.

Also each LCD section takes 11 ms or so... you might need to rethink that.

Etcetera.

Will anything be scheduled at 100 Hz? Tell us more or make it clear(er).

a7

Good to be clearer, the program in the loop represents that of the operation of a water purification system. The program in the loop being very long (almost 400 lines of code) I preferred not to post it. in parallel with the operation of the system, some parameters such as the water flow must be measured by a sensor at precise time intervals. the sensor delivers to its output only pulses that must be counted (pulseCount and PulseCount1) during this time interval specified (in this case 1 second). this will make it possible to calculate the water flow. That is why I am using timerInterrupt to calculate it every one second

Pins 20 and 21 are the Wire/TWI/I2C pins that you are using to talk to your LCD. You can't use than for interrupts when you are using them for the LCD.

You can get more interrupts using "Pin Change" interrupts. The PinChangeInterrupt library makes that fairly easy.

1 Like

In Datasheet Arduino Mega2560, DigitalPin 0 and 1 are SCL and SDL just like DigitalPin 20 and 21. So for my LCD I am using Pin 1 and 2 so that I can use Pin 20 and 21 for Interrupt. Do you think this can also be a problem?

The ATmega2560 datasheet does not use Arduino pin numbers. The Arduino IDE uses Arduino pin numbers.

On the Arduino MEGA 2560, Pin 0 is RXD0, known in the ATmega2560 datasheet as PE0 (PORTE bit 0). On the Arduino MEGA 2560, Pin 1 is TXD0, known in the ATmega2560 datasheet as PE1 (PORTE bit 1). Neither is SDA or SCL.

There are two Arduino pins connected to each of the TWI pins. Pin 20 and the "SDA" pin near the USB jack are both connected to PD1 (PORTD bit 1). Pin 21 and the "SCL" pin near the USB jack are both connected to PD0 (PORTD bit 0).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.