6 years, 5 months ago.

New to mbed trying to use interrupts on pin inputs.

I have a NUCLEO-F411RE. I am looking to interrupt on a few GPIO pins so I can record if they accidentally drop out for milliseconds.

Does anybody know examples of this sort of thing?

2 Answers

6 years, 5 months ago.

Something along the lines of this should do what you want if you want the time the pin is low for. If all you care about is whether they ever go low then you can skip the rising interrupt and timer and just set a flag or increase a count every time it goes low.

This is a very simple implementation, it has a few issues e.g. what if the pin changes while in the process of printing the output, this sort of thing can easily be fixed if it's going to be an issue.

Also I've not tested this code so I make have made some silly mistake somewhere but the basic structure should be good.

Timer lowTimer;
InteruptIn pinToMonitor(PC_3);
volatile uint32_t measuredTime = 0; // must be volatile or the main loop won't notice that it's changed. 

void OnPinLow(void) {
  lowTime.start();
}

void OnPinHigh(void) {
  lowTime.stop();
  measuredTime  = lowTime;
  lowTime.reset();
}

main () {
lowTime.reset();
pinToMonitor.fall(&OnPinLow);
pinToMonitor.rise(&OnPinHigh);
 while (true) {
   if (measuredTime) {
     pc.printf("Pin was low for %ul us\r\n",measuredTime );
     measuredTime = 0;
   }
 }
}

Accepted Answer

Yer this looks good. I am creating an emergency stop message. So if one of a bunch of pins goes down I send a CAN message with what failed.

Sending CAN message should be alot quicker than printf so should be ok ?

posted by Kieron Holt 06 Nov 2017

The issue is only if the measured time variable starts to change and in an emergency stop situation even that's not a big deal. You don't care what the value is only that something happened.

But it doesn't matter how fast it is, if you don't want an interrupt to change things then disable interrupts, make a copy of the value and then re-enable them.

If you have a group of pins and only care if they change and possibly how many times but not for how long they are low then you can do something like this:

InteruptIn pinToMonitor1(PC_3);
InteruptIn pinToMonitor2(PC_4);
InteruptIn pinToMonitor4(PC_4);

volatile uint8_t pin1Count = 0; // must be volatile or the main loop won't notice that it's changed. 
volatile uint8_t pin2Count = 0; // must be volatile or the main loop won't notice that it's changed. 
volatile uint8_t pin3Count = 0; // must be volatile or the main loop won't notice that it's changed. 
volatile bool error = false; 
void OnPin1Low(void) {
  pin1Count++;
  error  = true;
}
void OnPin2Low(void) {
  pin2Count++;
  error  = true;
}
void OnPin3Low(void) {
  pin3Count++;
  error  = true;
}
 
CANMessage errorMessage;

main () {

  // setup the CAN bus (baud rate etc...)


  // may as well set up the fixed parts of the can message in advance.
  errorMessage.id=0x200;
  errorMessage.format=CANStandard;
  errorMessage.len = 3;

  pinToMonitor1.fall(&OnPin1Low);
  pinToMonitor2.fall(&OnPin2Low);
  pinToMonitor3.fall(&OnPin3Low);
  while (true) {
    if (error) {
      __disable _irq();  // stop the interrupts for now
      errorMessage.data[0] = pin1Count;   // copy the counters to the message data
      errorMessage.data[1] = pin2Count;
      errorMessage.data[2] = pin3Count;
      pin1Count = 0;  // reset the counters
      pin2Count = 0;
      pin3Count = 0;
      error = false; // clear the error flag
      __enable_irq();  // re-enable interrupts, any changes that happened
                     // while disabled will now get processed and will be
                     // counted the next time around the loop..
      // send the can message here, it doesn't matter how long it takes because the data is already fixed.
   }
 }
}
posted by Andy A 06 Nov 2017

It does not compile? I get:

Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 6, Col: 2

Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 7, Col: 2

Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 8, Col: 2

Error: Identifier "CANMessage" is undefined in "main.cpp", Line: 10, Col: 2

Error: Identifier "CAN" is undefined in "main.cpp", Line: 12, Col: 2

Error: Identifier "p9" is undefined in "main.cpp", Line: 12, Col: 11

Error: Expected a ")" in "main.cpp", Line: 12, Col: 13

Error: Declaration is incompatible with "void error(const char *, ...)" (declared at <a href="#" onmousedown="mbed_doc_goto('/STM32_Button_Interruptextras/mbed_fb8e0ae1cceb/platform/mbed_error.h', '69'); return false;">/extras/mbed_fb8e0ae1cceb/platform/mbed_error.h:69</a>) in "main.cpp", Line: 18, Col: 16

Error: Identifier "CANStandard" is undefined in "main.cpp", Line: 50, Col: 26

Error: Identifier "pinToMonitor3" is undefined in "main.cpp", Line: 55, Col: 6

Error: Identifier "disable" is undefined in "main.cpp", Line: 60, Col: 14

Am I missing some #includes?

I added

include the mbed library with this snippet

CAN can1(p9, p10);

 if (error) 
        {
            __disable _irq();  // stop the interrupts for now
            errorMessage.data[0] = pin1Count;   // copy the counters to the message data
            errorMessage.data[1] = pin2Count;
            errorMessage.data[2] = pin3Count;
            pin1Count = 0;  // reset the counters
            pin2Count = 0;
            pin3Count = 0;
            error = false; // clear the error flag
            __enable_irq();  // re-enable interrupts, any changes that happened
                     // while disabled will now get processed and will be
                     // counted the next time around the loop..
        }
        can1.write(errorMessage);// send the can message here, it doesn't matter how long it takes because the data is already fixed.
        wait(0.5);
posted by Kieron Holt 07 Nov 2017

Did you include the mbed library? It looks like I missed that line at the start.

posted by Andy A 08 Nov 2017
6 years, 5 months ago.

me too