0

I'm using an Arduino Mega 2560 board. I need to sense 12 digital pins (pins 36-47) coming from another board continuously and display power when they are low.

When any of the 12 pins go HIGH, an interrupt must be created. In the ISR part, I'll be making one new digital pin (PIN 35) go HIGH (this is initialized as low in setup function).

To reset from interrupt, I need to press the "#" key in the keypad. This should make PIN 35 go low again and program should function normally again.

This is my code without using Interrupt.

#include "LiquidCrystal.h"
#include <Keypad.h>

// initialize the library by providing the nuber of pins to it
LiquidCrystal lcd(8,9,4,5,6,7);
 const byte ROWS = 4; // four rows
const byte COLS = 3; // three columns
char keys[ROWS][COLS] = {
 {'1','2','3'},
 {'4','5','6'},
 {'7','8','9'},
 {'*','0','#'}
};
byte rowPins[ROWS] = {22, 24, 26, 28}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {30, 32, 34};     //connect to the column pinouts of the keypad 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
float fwd_voltage = 0.0,rev_voltage = 0.0;
float fpower,rpower;
int sensorValue=0;

void setup() {
  int i;
  for (i=36;i<48;i++) {
    pinMode(i,INPUT);
  }
  pinMode (35, OUTPUT);
  digitalWrite(35,LOW);
}

void reset () {
  while(1) {
    lcd.begin(16,2);
    lcd.setCursor(0,0);
    lcd.print("press # to reset");
    char key = keypad.getKey();
    if (key=='#') {
      digitalWrite(35, LOW);
      break;
    }
  }
}

void process(int pin, char* text) {
  if (digitalRead(pin) == HIGH && digitalRead(35)==LOW) {
    // Use HIGH instead of 1
    lcd.print(text);
    digitalWrite(35, HIGH);
    reset ();
  } else {
    int analog_value = analogRead(A0);//reading forward voltage
    int analog_valuer = analogRead(A1);//reading reverse voltage
    fwd_voltage = (analog_value * 5.0) / 1024.0;
    rev_voltage = (analog_valuer * 5.0) / 1024.0;
    fpower =  ((fwd_voltage)*(fwd_voltage)*10000);
    rpower = ((rev_voltage)*(rev_voltage)*10000);
    lcd.setCursor(0,1);
    lcd.print("REV= ");
    lcd.print(rpower);
    lcd.print("W");
    delay(500);
    lcd.setCursor(0, 0);
    lcd.print("FWD= ");
    lcd.print(fpower);
    lcd.print("W");
    delay(500);
  }
}

void loop() {
  lcd.begin(16,2);
  // set cursor position to start of first line on the LCD
  lcd.setCursor(0,0);
  process(36, "vswr");
  process(37, "thermal");
  process(38, "overdrive");
  process(39, "A1-B1 fault");
  process(40, "A1-B2 fault");
  process(41, "A1-B3 fault");
  process(42, "A1-B4 fault");
  process(43, "A2-B1 fault");
  process(44, "A2-B2 fault");
  process(45, "A2-B3 fault");
  process(46, "A2-B4 fault");
  process(47, "driver fault");
}

How do I modify the program to add an interrupt so that my board works faster and efficiently? BTW I'm new to programming so there might be some mistakes in the program and also I didn't write the program small and efficient.

The interrupt service routine should consist of this part of the above program:

lcd.print(text);
digitalWrite(35, HIGH);
reset ();

My interrupt should detect this part of the program.

if (digitalRead(pin) == HIGH && digitalRead(35)==LOW)
2

You are kind of unlucky. The ATmega2560 MCU has 32 pins capable of generating interrupts (counting the INTn and PCINTn, not sure all of them are routed to board headers), but none of the pins you have chosen is interrupt-capable.

I suggest you combine your 12 signals, using external logic, into a single interrupt signal. You would then, in the ISR, sort out which individual signal triggered the interrupt. A pair of 74HC4075 chips should be enough to OR together the 12 inputs.

  • i'll try that. What about PINCHANGEINTERRUPT library? can I use it to use my pin as interrupt pins? – aparna Dec 20 '17 at 11:03
  • @aparna: You could use pin change interrupts (PCINT) if you can rewire your project and route the 12 relevant signals to PCINT-capable pins. But beware that you get interrupted on both signal edges. If you combine the signals using external logic, a regular interrupt pin would be more convenient, as it allows you to choose either the falling or the rising edge. – Edgar Bonet Dec 20 '17 at 12:06
1

Get rid of the 2 delay calls in your process() function. You are just needing to display the error text, so you don’t really need interrupt speed.

You have a 1s delay In total for every time you call the process() function. That doesn’t seem necessary.

  • i'll get rid of delays but actually I not only need to display error text but also shutdown power of the system i'm controlling. that's why I'm making pin 35 HIGH. – aparna Dec 20 '17 at 11:32
  • How quickly does your shutdown action need to occur? If it's on the order of tenths or hundredths of a second, you can probably get away with polling. If you require millisecond response time, then you may need to try to solve the interrupt issue. – jose can u c Dec 20 '17 at 17:19
  • I think 1/100th second is enough for me. How can I improve the polling speed ? I have already got rid of delays. Moreover removing delay is making the lcd print faster and i'm unable to read. is there any better way? – aparna Dec 21 '17 at 6:13
  • @aparna: Don't refresh the LCD too often, refresh it only after a certain time has elapsed. Use millis() to know when it's the right time. See the Blink Without Delay Arduino tutorial. – Edgar Bonet Dec 21 '17 at 8:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.