I've got a rotary encoder with the model name "MAB36 12HS 5 SER" and I'm not sure how to read its output, or even interpret its datasheet. On page 2 there's a timing diagram. Is this something maybe SPI.h or some other library can handle out of the box, given the right settings, or is this some non-standard stuff I'd need to implement myself?
I've got a rotary encoder
but you want to
Read rotary decoder output
Color me confused.
It's not clear to me, though it should be to you, how many wires are coming from the device. If there are four, as I'd expect, one should be connected to ground, one should be connected to a suitable power supply (I closed the file, so I can't check the voltage it operates at), and the other two should be connected to external interrupt pins on the Arduino.
There are several libraries for reading encoder output, using interrupts or not. For a 6000 RPM encoder, interrupts are almost certainly going to be needed.
That was a typo, it's an encoder, not a decoder..
Yes there are wires for power + ground, obviously. Then there's D0, CLK and CSn. Their function is explained in the diagram I was talking about. It's some sort of synchronous serial interface. D0 is the data line, CLK is for timing and CSn for polling, I guess.
Ok, without really knowing what I'm doing, I took a shot at this.. I simply took three digital pins and started flipping CLK and CSn as shown in the timing diagram, while reading D0... and it actually yields somewhat sensible values that seem to (kind of) correspond to the physical rotation. I'm actually surprised at how easy this was.
Still, can someone tell me if this is the right way to do this? Can my code be optimised?
What's strange is that the rotation value only reaches about 240 and then starts decreasing again, when it actually should go up to 4096 for a full rotation.
int d0 = 50;
int CLK = 52;
int CSn = 53;
void setup() {
Serial.begin(9600);
pinMode(d0, INPUT);
pinMode(CLK, OUTPUT);
pinMode(CSn, OUTPUT);
digitalWrite(CSn, LOW);
digitalWrite(CLK, HIGH);
}
void loop() {
byte res = 12;
byte bits[res];
digitalWrite(CSn, HIGH);
digitalWrite(CSn, LOW);
delay(1);
for(int i = 0; i < 18; i++) { // 12-bit rotation value + 6 status bits = 18 bits to read
digitalWrite(CLK, LOW);
if(i < res) {
bits[i] = digitalRead(d0);
}
digitalWrite(CLK, HIGH);
}
int v = binaryDecode(bits, len);
Serial.println(v);
}
int binaryDecode(char* bits, int len) {
int value = 0;
for (int i=0; i< len; i++) //
{
value *= 2;
if (bits[i] == 1) value++;
}
return value;
}
Yes, that's an SSI (software serial interface) absolute encoder. There is a good reference thread here Absolute rotary Encoder SSI SPI how ? - Networking, Protocols, and Devices - Arduino Forum
I wrote this some time ago for a similar encoder, and it might give you some ideas
const int PIN_CS = 5;
const int PIN_CLOCK = 6;
const int PIN_DATA = 7;
int magnitude = 0;
int pos;
int oldPos = 0;
byte stream[16] = {0};//replace testStream with stream for actual data
//byte testStream[] = {1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}; //test data stream
//byte testStream[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; //test data stream
void setup() {
Serial.begin(115200);
//SETUP BOURNS EMS22A
pinMode(PIN_CS, OUTPUT);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, INPUT);
digitalWrite(PIN_CLOCK, HIGH);
digitalWrite(PIN_CS, LOW);
}
void loop() {
//READ BOURNS
digitalWrite(PIN_CS, HIGH);
digitalWrite(PIN_CS, LOW);
stream[16] = {0};
for (int i = 0; i < 16; i++) {
digitalWrite(PIN_CLOCK, LOW);
digitalWrite(PIN_CLOCK, HIGH);
stream[i] = digitalRead(PIN_DATA);
//pos = pos<<1 + stream[i]; can construct sum here
//packeddata = ((packeddata << 1) + inputstream); // left-shift summing variable, add pin value
}
digitalWrite(PIN_CLOCK, LOW);
digitalWrite(PIN_CLOCK, HIGH);
oldPos = pos;
//extract 10 bit position from data stream use testStream
pos = 0; //clear previous data
for (int i = 0; i < 10; i++) {
pos = pos << 1;
//pos += testStream[i]; //replace testStream with stream
pos += stream[i];
//pos = pos<<1 + stream[i];
//packeddata = ((packeddata << 1) + inputstream); // left-shift summing variable, add pin value
}
//TRANSITION TESTING!?
if(oldPos > 1021 && pos < 3) magnitude++;
if(oldPos < 3 && pos > 1021) magnitude--;
//print position 0-1023
Serial.print(pos, BIN);
Serial.print('\t');
Serial.print(magnitude);
Serial.print('\t');
Serial.println(pos);
//extract 6 bits of status
//for (int i = 10; i < 16; i++)
//Serial.println(testStream[i]);//replace testStream with stream
//Serial.println(stream[i]);
//delay(500);
}