General > General Technical Chat
Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
elcrni:
Something like this, seems to work... again, uses 2 pins, not sure how i do it with one pin though.
--- Code: ---#define encoderA 2
#define encoderB 3
volatile int8_t altAB = 0;
volatile int encoderCount = 0;
int8_t steps[16] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
ISR(TIMER1_COMPA_vect) {
altAB <<= 2;
altAB &= B00001100;
altAB |= (digitalRead(encoderA) << 1) | digitalRead(encoderB);
encoderCount += steps[altAB];
}
void setup() {
pinMode(encoderA, INPUT);
pinMode(encoderB, INPUT);
noInterrupts();
TIMSK1 |= (1<<OCIE1A);
TCCR1A = 0;
TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS10);
// Frequency = 16000000 / 1024 / 31 = sampling rate;
OCR1A = 31;
interrupts();
}
void loop() {
}
--- End code ---
btw, i would love to test this frequency but not sure how to connect the oscilloscope, to what pins that is
Many thanks,
Alek
MarkF:
You will have to check my code.
I typically use Microchip PIC processors and rarely do any Arduino coding. :D
Answer to #1:
Two pins, one read.
You have pins 2 and 3 for the encoder.
I believe these are PortB bits 2 and 3.
Let's assume the encoder switch is on pin 1 (PortB bit 1) with pull-up resistor.
Answer to #2:
To check the ISR() timing with a Mega pin, pick an unused pin and toggle it inside the ISR() routine.
Let's pick pin 0 (PortB bit 0) for timing check.
Hence:
--- Code: ---
// global variables
int count=0; // encoder turn count used in loop() function
uint8_t sw0=0; // encoder switch flag used in loop() function
uint8_t last_sw0=0;
ISR(TIMER1_COMPA_vect) {
uint8_t pins, pinA, pinB, pinS;
digitalWrite(0, HIGH); // set pin 0 high when entering ISR(), check this pin with scope
// Read encoder
pins = PORTB; // Read both encoder inputs at once to avoid any time delay between pin sampling
pinS = (pins >> 1) & 0x01; // encoder switch
pinA = (pins >> 2) & 0x01; // encoder A
pinB = (pins >> 3) & 0x01; // encoder B
// Decode gray_code
. . .
// Encoder switch
if (last_sw0 != 0 && pinS == 0) {
sw0 = 1; // set switch flag when depressed
}
last_sw0 = pinS;
digitalWrite(0, LOW); // set pin 0 low when leaving ISR()
}
void loop() {
int local_count;
if (count != 0) {
local_count = count;
count = 0; // reset encoder turn count
// process encoder turns here using local_count variable
. . .
}
if (sw0) {
sw0 = 0; // reset encoder switch flag
// process encoder switch depressed
. . .
}
// Do non-encoder tasks here
. . .
}
void setup() {
pinMode(0, OUTPUT); // scope timing check
pinMode(1, INPUT); // encoder switch
pinMode(2, INPUT); // encoder A
pinMode(3, INPUT); // encoder B
}
--- End code ---
MarkF:
In order to read Port B, I believe the command should be
pins = PINB;
and not
pins = PORTB;
elcrni:
Many thanks MarkF.
In a meantime i got the code changed:
--- Code: ---#define encoderA 2
#define encoderB 3
volatile int encoderCount = 0;
boolean A_set = false;
boolean B_set = false;
ISR(TIMER1_COMPA_vect) {
if ( digitalRead(encoderA) != A_set ) { // debounce once more
A_set = !A_set;
if ( A_set && !B_set )
encoderCount ++;
}
if ( digitalRead(encoderB) != B_set ) {
B_set = !B_set;
if ( B_set && !A_set )
encoderCount --;
}
}
void setup() {
pinMode(encoderA, INPUT);
pinMode(encoderB, INPUT);
TIMSK1 |= (1<<OCIE1A);
TCCR1A = 0;
TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS10);
// Frequency = 16000000 / 1024 / 15 = sampling rate;
OCR1A = 31;
sei();
Serial.begin(115200);
}
void loop() {
while(true) {
Serial.println(encoderCount);
delay(100);
}
}
--- End code ---
I added Serial just so i can check if it's working.
It does work, nicely, although on restart it starts at 1 rather than at 0, for some reason, but it works.
Now, will have to study your code, seems more elegant to my untrained eye :-)
thanks,
Alek
MarkF:
I would set the prescaler to 256 and the OCR1A to 125. You do not want a fractional divisor.
In your case the timing is not critical. Best case is to always try to have an integer divisor.
16000000 / 256 / 500 = 125
16000000 / 1024 / 500 = 31.25
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version