Is there a way to check all inputs through 1 command on ind.IO and get the result in a byte ?
Hi,
I am trying to count pulses on 4 digital input pins with a frequency around 5Khz.
I try to do this through the interrupt generated by the expander.
After the interruptsignal is generated i need to read the imputs to check which input did generate the interrupt.
I can do this input by input but is slows down the process since every read action is a command to the expander chip. Is there a way read all inputs with 1 command and then store the result in a byte.
This byte can be used to compare with the previous input state byte to determine which input did generate the interrupt.
Regards,
Jeroen.
Hi,
I did find a way (for 2 channels for now) but i am still limited to +/- 1 Khz.
Below the part of the code to check which ch did fire the interrupt.
If anyone has a suggestion on how to improve this to get to 5 Khz. (I2C is already pimped to 400Khz via twi.h file #define TWI_FREQ 400000L
Thanks,
Jeroen
void setup() {
Serial.begin(9600);
lcd.begin();
Indio.digitalMode(1, INPUT); // Set CH1 as an input
Indio.digitalMode(8, OUTPUT); // Set CH8 as an output
attachInterrupt(7, setintflag, FALLING); // INT7 attached to the interrupt of the expander, falling edge when portchange occurs
}
void setintflag() {
interruptflag=1;
}
void loop() {
if (interruptflag){
Wire.requestFrom(33, 1); // request 1 byte from slave device #33 eg. read first inputregister
inputbyte0 = Wire.read(); // receive a byte
if (inputbyte0 & 0b10000000 == 0b10000000) { // check if ch1 is high through mask
currch1in=1;
}
else { // else ch1 is low
currch1in=0;
}
if (prevch1in == 0 and currch1in == 1) { //rising edge = increment counter and change prev state
ch1counter++;
prevch1in=1;
}
if (prevch1in == 1 and currch1in == 0) { //falling edge = change prev state
prevch1in=0;
}
if (inputbyte0 & 0b01000000 == 0b01000000) { // check if ch2 is high through mask
currch2in=1;
}
else { // else ch2 is low
currch2in=0;
}
if (prevch2in == 0 and currch2in == 1) { //rising edge = increment counter and change prev state
ch2counter++;
prevch2in=1;
}
if (prevch2in == 1 and currch2in == 0) { //falling edge = change prev state
prevch2in=0;
}
interruptflag=0;
}
First of all, did you check the timing of your Wire operations? Because if that's not fast enough, there's no trick to be added here. About your code, there are smarter ways to do things around. To fetch bits you can shift your byte left or right, so each time your bit falls directly in your variable. But you can also check them all in one go, by working directly on the entire byte in one go and then shifting the bits of the result. You can XOR the entire byte to know which bits have changed and then shift them in place, possibly in an array of counters, more or less like this: byte flag = prev ^ new; //XOR operation byte prev = new; //update prev for (byte xx=0; xx
Stefano, Problem with xor is that it matches both 0->1 and 1->0. So i stil neem to check for that. It seems to me that that part is fast enough since it happens at processor Clock speed but i will look intro it. In my first design i online had 1 input to check so i could use the interrupt to increment a timer. This worked well for 1 input with +/- 10khz squarewave in. With I2C on 400 kHz and +/- 50 bits for read and write i should be able to reach 8 kHz. At faster speeds the interrups will occure before the readcycle is finished.
A change is a change, just count twice and then divide by two at display time.
We are looking for a smart solution here, right, not logical by the book.
Da: Jeroen Hollemans [mailto:jeroen2@industruino.com]
Inviato: 22 January 2017 01:13
A: Stefano Ariel Bonvini
Oggetto: Re: Is there a way to check all inputs through 1 command on ind.IO and get the result in a byte ? (299)
Stefano, Problem with xor is that it matches both 0->1 and 1->0. So i stil neem to check for that. It seems to me that that part is fast enough since it happens at processor Clock speed but i will look intro it. In my first design i online had 1 input to check so i could use the interrupt to increment a timer. This worked well for 1 input with +/- 10khz squarewave in. With I2C on 400 kHz and +/- 50 bits for read and write i should be able to reach 8 kHz. At faster speeds the interrups will occure before the readcycle is finished.
--
Jeroen Hollemans
Sent by Industruino using Odoo
Hello,
yes there is.
I don't remember from the top of my head, but if you check the chip installed in Indio board, should start with PCA, you can then find its datasheet and there is a register that can be read through i2c to get this value.
Actually the library takes this values and check it against each byte, so you could also find reference to this register in the Indio.digitalRead function in Indio.h file, I guess.
Sorry for the unprecise answer, but I don't have a system available at the moment!
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: 1/18/17, 11:43 PM |
Seen: 3075 times |
Last updated: 1/22/17, 11:50 AM |
Stefano, Thanks for looking at it from a different view. counting every change /2 is less code and faster. I Will try this.