Indio digital input interrupt usage
Is the interrupt pin on the PCA9555 digital input expander chip connected to the CPU with Industruino Indio?? If so what pin is it connected too? I want to read an open collector digital hall effect sensor and I don't like the idea of polling the digtial inputs.
Tom
Hi Tom,
The interrupt pin of the expander on the 24V digital side is connected to pin D8 (PCINT 4) of the 32u4 Topboard.
Please use this code as an example to trigger an interrupt on CH1. It will show "waiting" on the LCD screen, when status of any channel on the 24V side changes it will show "triggered":
#include <Indio.h>
#include <Class_define.h>
#include <Wire.h>#include <UC1701.h>
static UC1701 lcd;volatile int modeFlag = 0;
void setup() {
Serial.begin(9600);
Indio.digitalMode(1,INPUT); // Set CH1 as an input
Indio.digitalMode(8,OUTPUT); // Set CH7 as an output
lcd.begin(); //enable LCD
// Enable Pin Change Interrupt 4.
PCMSK0 = (1 << PCINT4);
PCICR = (1 << PCIE0);
// Global Interrupt Enable
sei();
}
ISR (PCINT0_vect)
{
modeFlag = 1;
}void loop() {
Serial.print(Indio.digitalRead(1),BIN); // Read CH1 one, print state to serial.
Indio.digitalWrite(8,LOW); // Set CH8 to low
lcd.setCursor(0, 0);
lcd.print("waiting ");
if (modeFlag == 1) {
lcd.setCursor(0, 0);
lcd.print("triggered");
delay(1000);
modeFlag = 0;
}
delay(500);
}
If more than 1 channel needs to be detected by the interrupt a small comparison routine can be run inside the interrupt service routine, which compares the status of the channels pre-inerrupt to the current status.
Hope this helps.
Best Regards,
Loic
UPDATE:
Please try this code, I've tested it with 24V square wave at 10Khz, it should show the incoming frequency on the LCD display:
#include <Indio.h>
#include <Class_define.h>
#include <Wire.h>#include <UC1701.h>
static UC1701 lcd;volatile int fallingEdge = 0;
volatile int risingEdge = 1;long previousMicros = 0;
long pulseWidth = 0; // interval at which to blink (milliseconds)
long frequency = 0;int pulseFlag = 0;
void setup() {
Serial.begin(9600);
Indio.digitalMode(1,INPUT); // Set CH1 as an input
Indio.digitalMode(8,OUTPUT); // Set CH7 as an output
Indio.digitalWrite(8,LOW); // Set CH8 to high (24V, or whatever your Vin voltage).lcd.begin(); //enable LCD
// Enable Pin Change Interrupt 6.
PCMSK0 = (1 << PCINT4);
PCICR = (1 << PCIE0);
// Global Interrupt Enable
sei();
}
ISR (PCINT0_vect)
{
unsigned long currentMicros = micros();
if (risingEdge == 1){
risingEdge = 0;
}
else{
risingEdge = 1;
pulseWidth = currentMicros - previousMicros;
previousMicros = currentMicros;
}
}void loop() {
frequency = (1000000 / pulseWidth);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(frequency);
delay(500);
}
Hi!
Unfortunately I haven't managed to get this working on the 1286 board. Int seems that the pin PC6 can't be used as interrupt pin.
You probably will have to debounce the detector signal.
The best way for me was to connect the detector to a solid state relay, which does not generate rebounds. The detector activates the relay, which sends a clean signal to the digital input.
Also you can do it via software, discarding interrupts generated with a difference of less than 3000 microseconds for example.
Thanks Loic! This is now working. However I would like to build on the example a little bit, it may also be useful to others in the future. Some background; I am trying to measure the speed of a rotating wheel using a digital hall effect sensor. I have this setup so it generates a square wave pulse as the tooth passes the sensor. The output of this sensor goes to CH1 of the Indio digital input. The supply for the sensor comes from CH2 of the Indio which is set as a digital output. I have checked with my scope that the sensor generates a clean square wave as the tooth passes the sensor and it seem to do so correctly.
In my interrupt handler I increment an integer variable as so:
ISR (PCINT0_vect)
{
counter ++;
}
I was expecting to see 2 interrupts generated for each passing of the tooth (one rising and one for falling), in fact it seems that 4 interrupts are generated per tooth passing but it doesn't seem to be totally consistent. My original plan was to read the state of the digital input in the interrupt handler to check for a rising, on the initial interrupt, then a falling of the digital input, on the second interrupt, which would then start a timer which can be used to compute the speed the next time the tooth is detected. Now comes the second issue, readng the Indio digital inputs causes the cpu to hang if done so within an interrupt. I suspect this is because global interrupts are disabled during the routing and the Indio digital read somehow relies upon interrupts.
Can you see a reason why I might be seeing more than 2 interrupts per tooth passing and whats the best way to perform a digital read during an interrupt?
Your answer
Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!
Keep Informed
About This Forum
This community is for professionals and enthusiasts of our products and services.
Read GuidelinesQuestion tools
Stats
Asked: 2/27/15, 12:44 PM |
Seen: 6333 times |
Last updated: 3/21/16, 11:53 AM |