I've tried several different takes on this, this just happens to be what I have saved at the moment.
#include <SPI.h>
enum PinAssignments {
encoderPinA = 2,
encoderPinB = 3
};
#define SCK 13 //Clock
#define MOSI 11 //MOSI
#define RST 12
//channel address'
static byte DACA = 0x10;
static byte DACB = 0x12;
static byte DACC = 0x14;
static byte DACD = 0x16;
//Channel values
volatile unsigned int valA, valB, valC, valD; //not in use yet
volatile unsigned int encoderPos;
unsigned int lastReportedPos = 1;
boolean A_set = false;
boolean B_set = false;
void setup(){
//=====DAC
DDRB = B00111100; //sets my SPI ports as outputs
digitalWrite(RST,LOW); //required for the dac
SPI.begin();
SPI.setDataMode(SPI_MODE1);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4); //I've tried 2-16 w/ the same results
digitalWrite(RST,HIGH); //Starts all dac channels at 0x00
//=====Encoder
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
digitalWrite(encoderPinA, HIGH); // turn on pullup resistor
digitalWrite(encoderPinB, HIGH); // turn on pullup resistor
attachInterrupt(0, doEncoderA, CHANGE);
attachInterrupt(1, doEncoderB, CHANGE);
}
void loop(){
if (lastReportedPos != encoderPos) {
dacWrite(DACA,encoderPos);
lastReportedPos = encoderPos;
}
}
dacWrite function
void dacWrite(byte dacActive, int dacValue){
PORTB = 0x04; //toggles latch, Pin 10
SPI.transfer(dacActive); //command byte
SPI.transfer(highByte(dacValue));
SPI.transfer(lowByte(dacValue));
PORTB = 0x00;
}
doEncoder function from the playground.
void doEncoderA(){
A_set = digitalRead(encoderPinA) == HIGH;
encoderPos += (A_set != B_set) ? +1 : -1;
}
void doEncoderB(){
B_set = digitalRead(encoderPinB) == HIGH;
encoderPos += (A_set == B_set) ? +1 : -1;
}
I've also tried using direct port manipulation for the doEncoder function. I believe retrolefty posted this in a different thread. Obviously the rest of the sketch was changed to use this code. In this setup I was just using a single interrupt to lessen its impact.
void doEncoderA() {
if (PIND & 0x04) { // test for a low-to-high interrupt on channel A, same as if(digitalRead(encoderPinA) == HIGH)
if ( !(PIND & 0x10)) { // check channel B for which way encoder turned, same as if(digitalRead(encoderPinB) == LOW)
encoderPos = ++encoderPos; // CW rotation
PORTD = PIND | 0x40; // set direction output pin to 1 = forward, same as digitalWrite(encoderdir, HIGH);
}
else {
encoderPos = --encoderPos; // CCW rotation
PORTD = PIND & 0xBF; // Set direction output pin to 0 = reverse, same as digitalWrite(encoderdir, LOW);
}
}
else { // it was a high-to-low interrupt on channel A
if (PIND & 0x10) { // check channel B for which way encoder turned, same as if(digitalRead(encoderPinB)==HIGH)
encoderPos = ++encoderPos; // CW rotation
PORTD = PIND | 0x40; // Set direction output pin to 1 = forward, same as digitalWrite(encoderdir, HIGH);
}
else {
encoderPos = --encoderPos; // CCW rotation
PORTD = PIND & 0xBF; // Set direction output pin to 0 = reverse, same as digitalWrite(encoderdir, LOW);
}
}
PORTD = PIND | 0x80; // digitalWrite(encoderstep, HIGH); generate step pulse high
PORTD = PIND | 0x80; // digitalWrite(encoderstep, HIGH); add a small delay
PORTD = PIND & 0x7F;
dacWrite(DACA,encoderPos); // digitalWrite(encoderstep, LOW); reset step pulse
}