Hi,
I am reading a quadrature rotary encoder (GHS30-4E360BST5) with my Arduino Uno (for final usage an Arduino Nano will be used). The incoming singals will go to the two external interrupt pins of the Uno/Nano. Every Pin change with rising edge causes a ISR where I detect the rotary direction and so increment/decrement my counter value. Every 220 detected steps I want to trigger a camera for taking a picture. So I put this also in the ISRs, because this ensures the delay between the incoming 220th signal and the triggering of the camera is as small as possible.
One phase of the quadrature encoder has 360 increments. So 4*360 = 1440 steps would be possible to detect while the encoder makes a full 360° round. But I can only use 720 steps when I also want to detect the direction (this might change in between sometimes).
Rotary encoder runs with 76rrpm.
The Arduino digital Pin 10 and GND is directly connected to the trigger (galvanically isolated by an optocoupler) of the camera
Well I changed a lot at the code and I'm a little bit confused now, because sometimes it seems to me that the direction of the encoude where it counts positive changes.
Also I have the problem that suddenly the camera doesn't seem to be triggered, although it worked before. When this happened, I disconnected the Arduino to the camera trigger and triggered it manually by a switching power supply (why was set to 5V). This worked fine. So the problem seems to come from the Arduino.
Does anybody see where these problems could come from?
Here is my code:
const int phaseA = 2; // pin for green wire of encoder
const int phaseB = 3; // pin for white wire of encoder
volatile long tmp2 = 0; // for triggering the camera
volatile long counter = LOW; // counts the states of phase A and B, should be volatile so this variable (shared between main and ISR) will always be updated correctly
const long toggleStates = 220; // 220 state changes mean a very exactly tape movement of 24 mm in forward direction
const int triggerPin = 10; // toggle this digital pin for triggering the camera
void setup() {
// put your setup code here, to run once:
pinMode(triggerPin, OUTPUT);
pinMode(phaseA, INPUT_PULLUP);
pinMode(phaseB, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(phaseA),detectA, RISING); //enables external Interrupt at pin of phaseA (Arduino Uno can only use pin 2 and 3)
attachInterrupt(digitalPinToInterrupt(phaseB),detectB, RISING); //enables external Interrupt at pin of phaseB (Arduino Uno can only use pin 2 and 3)
}
void loop() {
// put your main code here, to run repeatedly:
}
//ISR for phase A
void detectA() {
// bitRead(PIND, 3) is probably the same as direct port manipulation
//byte p3 = PIND&(1<<3); // read Arduino Uno Digital Pin 3 as fast as possible
if (bitRead(PIND, 3) == LOW){ // check other phase for determine direction
counter++;
}else {
counter--;
}
if (counter == tmp2+toggleStates){
tmp2 = counter;
//digitalWrite(triggerPin, HIGH);
PORTB |= (1 << PINB2); // camera will be triggered by rising edge, so this sets Arduino Uno Digital Pin 10 to High
}else {
//digitalWrite(triggerPin, LOW);
PORTB &= ~(1 << PINB2); // turn off the camera trigger pin if it wasn't rised before (in the same isr run), so this sets Arduino Uno Digital Pin 10 to Low
}
}
//ISR for phase B
void detectB() {
// bitRead(PIND, 2) is probably the same as direct port manipulation
//byte p2 = PIND&(1<<2); // read Arduino Uno Digital Pin 2 as fast as possible
if (bitRead(PIND, 2) == HIGH){ // check other phase for determine direction
counter++;
}else {
counter--;
}
if (counter == tmp2+toggleStates){
tmp2 = counter;
//digitalWrite(triggerPin, HIGH);
PORTB |= (1 << PINB2); // camera will be triggered by rising edge, so this sets Arduino Uno Pin 10 to High
}else {
//digitalWrite(triggerPin, LOW);
PORTB &= ~(1 << PINB2); // turn off the camera trigger pin if it wasn't rised before (in the same isr run), so this sets Arduino Uno Pin 10 to Low
}
}