Hi guys wanting to check my "logic" with an ISR pin change interrupt where i record the status of PIND before the ISR and then during the ISR followed by a bit of binary logic gives me a binary result of which pin went high or 0 if it went low, now i am assuming that only a single pin can change when the interrupt is called i.e the pin that triggered the interrupt in which case all is good.
My project uses 5 infrared sensors on pins 3-7 i am using this particular part to turn off interrupts on the other 4 sensors so that i can reliably receive the rest of the data and now to business.
// The port status of PIND called before the ISR (Initially set during setup) is as so:
Pins: 7, 6, 5, 4, 3, 2, 1, 0
0, 0, 0, 0, 0, 0, 1, 1
//Now when the interrupt is called it will look like this:
Pins: 7, 6, 5, 4, 3, 2, 1, 0
0, 0, 0, 0, 1, 0, 1, 1
//If we name them as follows we get this:
Pins: 7, 6, 5, 4, 3, 2, 1, 0
0, 0, 0, 0, 0, 0, 1, 1
0, 0, 0, 0, 1, 0, 1, 1
/*A simple way to detect which pin changed would be to use an XOR function however i'm not interested *in when one changed only in when a pin goes high, so i use an OR gate to detect all pins that are high *then an XOR to detect which pins changed from low to high between our original register and the ones *that are high now as so.
*/
Pins: 7, 6, 5, 4, 3, 2, 1, 0
Past: 0, 0, 0, 0, 0, 0, 1, 1
Current: 0, 0, 0, 0, 1, 0, 1, 1
OR: 0, 0, 0, 0, 1, 0, 1, 1
XOR: 0, 0, 0, 0, 1, 0, 0, 0
/*The above returns a binary value that can be compared using the if(Value & 0b00001000) statement *to tell you that pin 3 went high.
*/
I believe the logic is sound providing only a single pin changes per ISR the code i have wrote is as follows.
ISR (PCINT2_vect){
pdPast = pdState; //Remember our previous register.
pdState = PIND; //Get register state now.
pdOut = (pdPast | pdState) ^ pdPast; //Bitmath to get on bits then xor to find toggled bits.
currMicro = micros(); //Get current time.
iFlag = 1; //ISR indicator.
}
To detect which pin went high i use the above function in loop.
uint8_t getSensor(uint8_t pRead){
if(pRead & 0b00001000){ //Pin 3.
return 1; //Sensor 1.
}else if(pRead & 0b00010000){ //Pin 4.
return 2; //Sensor 2.
}else if(pRead & 0b00100000){ //Pin 5.
return 3; //Sensor 3.
}else if(pRead & 0b01000000){ //Pin 6.
return 4; //Sensor 4.
}else if(pRead & 0b10000000){ //Pin 7.
return 5; //Sensor 5.
}else{
return 0; //No inputs from sensor or no pulse being recieved.
}
}
Now i simply use an if function to only process the ISR results when a value greater than 0 is recorded does anyone see any problems with my code or logic above i believe this is correct however my serial monitor seems to output a few odd value.
Reciever Started...
Past: 11 - State: 11 - Output: 0 - Sensor: 0
Past: 10011 - State: 11001 - Output: 0 - Sensor: 2
Past: 1 - State: 11 - Output: 10000 - Sensor: 2
Past: 10001 - State: 10001 - Output: 10000 - Sensor: 0
Past: 10001 - State: 11001 - Output: 10000 - Sensor: 1