Hi, I need to read data from four encoders with my Arduino Mega. I noticed that the Mega has 6 interrupt inputs so I can't directly connect all the encoder phases to the board...
In my application only one encoder is running at a time so I could reat only the running encoder (I now what is runnin).
So I can use only 2 interrupt and connect the right encoder. I don't know how to switch from the 4 encoders there is a circuit to manage the encoder selection? I could use some transistors? and manage the selection with 8 digital output? Is this a right way?
You can use outputs for each encoder for the quadrature state of
each encoder. Add an XOR chip between each state and the encoder output.
Use an OR chip to combine the XORs for one interrupt from each encoder.
You could then burn inputs to read each encoder or update the outputs with
an experimental direction if it clears the interrupt, you know it was right.
if not, try the other direction. If neither worked, you've missed a pulse.
You can then monitor all four at the same time.
You can minimize the number of ports used. 4 encoders in this arrangement
would use 4*4 + 4 interrupts or 20 ports.
You could use 2 ports to write to a serial port expander.
Use some imagination.
Dwight
I'd given it some more thought.
It could be done with as few as 6 ports and two ICs.
Use 2 ea 74HC4052 to select the 4 quadrature
signals. Use 4 inputs to monitor the 4 signals.
2 ports to address the 74HC4052s.
For those inputs that previously were 0's the last time,
enable their interrupts for a positive signal.
For those that were 1's the last time enable interrupt
on a negative value.
Keep a table for each encoder. Tie a scanning routine
to a time alarm to step through each enables based on the table.
If an interrupt happens, a signal has changed.
If you only need to look at one at a time, just selecting the
address with the two ports is enough.
Dwight
I think you'd have better luck using 8 pins with PCINT signals.
For example, use the 8 pins on this port for the 4 pairs if PCINTs:
volatile boolean fired = false;
// handle pin change interrupt for D8 to D13 here
ISR (PCINT0_vect)
{
static byte pinA, pinB;
static boolean ready;
static unsigned long lastFiredTime;
byte newPinA = digitalRead (Encoder_A_Pin);
byte newPinB = digitalRead (Encoder_B_Pin);
if (pinA == newPinA &&
pinB == newPinB)
return; // spurious interrupt
// so we only record a turn on both the same (HH or LL)
// Forward is: LH/HH or HL/LL
// Reverse is: HL/HH or LH/LL
if (newPinA == newPinB)
{
if (ready)
{
if (millis () - lastFiredTime >= ROTARY_DEBOUNCE_TIME)
{
if (newPinA == HIGH) // must be HH now
{
if (pinA == LOW)
fileNumber ++;
else
fileNumber --;
}
else
{ // must be LL now
if (pinA == LOW)
fileNumber --;
else
fileNumber ++;
}
if (fileNumber > MAX_FILE_NUMBER)
fileNumber = 0;
else if (fileNumber < 0)
fileNumber = MAX_FILE_NUMBER;
lastFiredTime = millis ();
fired = true;
}
ready = false;
} // end of being ready
} // end of completed click
else
ready = true;
pinA = newPinA;
pinB = newPinB;
} // end of PCINT2_vect