Hi,
can someone help me to use hardware input interrupt on Portenta H7 machine control ?
even i tried to use input inside timer callback but it didn't work and it crash !
Thanks
Hi,
can someone help me to use hardware input interrupt on Portenta H7 machine control ?
even i tried to use input inside timer callback but it didn't work and it crash !
Thanks
You are not allowed to use Serial.print in the interrupt routine!
From the mbed api references (InterruptIn - API references and tutorials | Mbed OS 6 Documentation)
Warnings:
printfs
from interrupt context, use Event instead.The "normal" arduino function attachInterrupt() works.
Thanks for your contribution!
But i didn't use any blocking problem onside or Serial ?
I tried with attachInterrupt but not working
Welcome
Are we supposed to keep guessing what you did or are you going to post the code in code tags?
sure, this one tried with standar ISR
#include <Arduino_MachineControl.h>
#include "Wire.h"
using namespace machinecontrol;
volatile byte state = LOW;
void setup() {
Serial.begin(115200);
digital_inputs.init();
attachInterrupt(digitalPinToInterrupt(DIN_READ_CH_PIN_00), blink, CHANGE);
}
void loop() {
Serial.println(state);
}
void blink() {
state = !state;
}
and the other one, tried to read inside the timer
#include <Arduino_MachineControl.h>
#include "Wire.h"
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "Portenta_H7_TimerInterrupt.h"
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "Portenta_H7_ISR_Timer.h"
using namespace machinecontrol;
volatile byte state = LOW;
Portenta_H7_Timer timer(TIM12); // Init timer TIM12
void setup() {
Serial.begin(115200);
digital_inputs.init();
bool ret = timer.attachInterruptInterval(50, callback);
}
void loop() {
Serial.println(state);
delay(50);
}
void callback(){
state = digital_inputs.read(DIN_READ_CH_PIN_00);
}
Hi @jenifenseif
The inputs of the Machine Control are connected to an i2c IO expander.
From the schematic, you can see that the interrupt pin of the IO expander is connected to the pin PB.
This pin goes LOW when a change (RISING or FALLING) occurs on any of the inputs.
To reset the interrupt pin status of the expander, a read operation must be performed. But this read with i2c is not allowed in an interrupt callback by Mbed.
So here is an example on how to detect a RISING edge on input 0:
#include <Arduino_MachineControl.h>
#include "Wire.h"
using namespace machinecontrol;
volatile bool interruptOccured = false;
void inputCallback()
{
interruptOccured = true;
}
void setup() {
Serial.begin(9600);
while(!Serial);
Wire.begin();
attachInterrupt(PB_4, inputCallback, FALLING);
if (!digital_inputs.init()) {
Serial.println("Digital input GPIO expander initialization fail!");
}
}
void loop() {
if(interruptOccured)
{
interruptOccured = false;
// Reading digital input resets the interrupt flag on the IOExpander
// And check the value to see if this is a RISING or FALLING edge
if(!digital_inputs.read(DIN_READ_CH_PIN_00))
{
Serial.println("Interrupt occured");
}
}
delay(1);
}
The issue is that the detection time depends of the works you are doing in your loop.
A solution is to dedicate the M4 core to only do this if you need a really fast detection time.
But the i2c reading to check the state still takes time (I have measured 411 µs).
Exactly, Portenta use TCA642A to interface with IO via I2C, and in general Serial communication unallowable in ISR functions.
Thanks @rreignier for your contribution !
Just in case someone gets here regarding I2C reading times, we can increase the I2C bus speed using Wire.setClock(). Using Wire.setClock(1000000) works fine, but not higher (in my tests).