Hi all,
I've been working on using a harddisk motor+disk as a scroll wheel. That work is still in progress.
However, I managed to use/program an HD motor as a rotary encoder that uses áll windings to in-/decrement.
So the code below is for my 4 lead, 12 coil HDmotor with 12 pulses per revolution resolution
Maybe you can use it, maybe you can improve it.
Use it as you please and feedback would be appreciated.
Codeblock 1: Clean condensed code without comments
Codeblock 2: Code with explanation
Codeblock1
#include <Streaming.h>
#include <PinChangeInterrupt.h>
const byte L1 = 2;
const byte L2 = 3;
const byte L3 = 4;
int intOutput;
byte byteDirection = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(L1), isrRegisterPulseOnL1, RISING);
attachInterrupt(digitalPinToInterrupt(L2), isrRegisterPulseOnL2, RISING);
attachPCINT(digitalPinToPCINT(L3), isrRegisterPulseOnL3, CHANGE);
}
void trace(){
Serial << intOutput << endl;
}
void handlePulse(int intLead, boolean bDir){
if(bDir){
bitSet(byteDirection, intLead);
if(byteDirection == 7){
intOutput++;
}
}else{
bitClear(byteDirection, intLead);
if(byteDirection == 0){
intOutput--;
}
}
trace();
}
void loop() {
}
void isrRegisterPulseOnL1(){
if(digitalRead(L3)){
handlePulse(0, 1);
}else{
handlePulse(0, 0);
}
}
void isrRegisterPulseOnL2(){
if(digitalRead(L1)){
handlePulse(1, 1);
}else{
handlePulse(1, 0);
}
}
void isrRegisterPulseOnL3(){
if(digitalRead(L3)){
if(digitalRead(L2)){
handlePulse(2, 1);
}else{
handlePulse(2, 0);
}
}
}
Codeblock2
/*
Code to use all leads on a salvaged harddisk motor when using it as a rotary encoder
In this case a 4 lead motor, 1 common and 3 "signal" leads
Common connected to ground and leads L1, L2 and L3 connected to arduino inputs via an LM324 opamp
*/
#include <Streaming.h> // for serial output
#include <PinChangeInterrupt.h> // library to use NON-interrupt pins as interrupt pins
//HD Motor > LM324 > arduino pins
const byte L1 = 2; // arduino (UNO) interrupt pin
const byte L2 = 3; // arduino (UNO) interrupt pin
const byte L3 = 4; // NOT AN arduino UNO interrupt pin, PinChangeInterrupt.h is used to use it as an interrupt pin
int intOutput; // int to track output increase/decrease
// To prevent changes due to "jitter" when starting or stopping the disk
// the output value is only changed when the three previous changes were in the same direction
// This is registered in a byte, the first three bits are used to store the previous changes as 0 or 1
// The output is only increased when the byte is 0111 (dec 7) and only decreased when the byte is 0000 (dec 0)
byte byteDirection = 0;
void setup() {
Serial.begin(9600); // initialize serial communication
attachInterrupt(digitalPinToInterrupt(L1), isrRegisterPulseOnL1, RISING); // set a rising edge interrupt on pin L1
attachInterrupt(digitalPinToInterrupt(L2), isrRegisterPulseOnL2, RISING); // set a rising edge interrupt on pin L2
attachPCINT(digitalPinToPCINT(L3), isrRegisterPulseOnL3, CHANGE); // set a interrupt on pin L3, this is a CHANGE interrupt, it will be tested for RISING in isrRegisterPulseOnL3
}
void loop() {
// Move along, nothing to see here ;)
trace();
} //end loop
void trace(){
Serial << intOutput << endl; // trace function for debugging
}
// Lead 1 =========================================================================
void isrRegisterPulseOnL1() {
// To test all the leads when an interrupt is fired on one lead, uncomment the next line:
// Serial << "L1: " << digitalRead(L1) << " L2: " << digitalRead(L2) << " L3: " << digitalRead(L3) << endl;
// My results (yours might be different, depending on wiring of motor/circuit):
// clockwise: L1: 1 L2: 0 L3: 1
// counter clockwise: L1: 1 L2: 1 L3: 0
if(digitalRead(L3)){
handlePulse(0, 1);
}else{
handlePulse(0, 0);
}
}
// Lead 2 =========================================================================
void isrRegisterPulseOnL2() {
// Serial << "L1: " << digitalRead(L1) << " L2: " << digitalRead(L2) << " L3: " << digitalRead(L3) << endl;
// Result:
// clockwise: L1: 1 L2: 1 L3: 0
// counter clockwise: L1: 0 L2: 1 L3: 1
if(digitalRead(L1)){
handlePulse(1, 1);
}else{
handlePulse(1, 0);
}
}
// Lead 3 =========================================================================
void isrRegisterPulseOnL3() {
if(digitalRead(L3)){ // using the PinChangeInterrupt library only CHANGE can be detected, BUT you only want to detect a rising change by testing "if(digitalRead(L3)) is 1"
// Serial << "L1: " << digitalRead(L1) << " L2: " << digitalRead(L2) << " L3: " << digitalRead(L3) << endl;
// Result:
// clockwise: L1: 0 L2: 1 L3: 1
// counter clockwise: L1: 1 L2: 0 L3: 1
if(digitalRead(L2)){
handlePulse(2, 1);
}else{
handlePulse(2, 0);
}
}
}
void handlePulse(int intLead, boolean bDir){
if(bDir){ // direction: clockwise
bitSet(byteDirection, intLead); // set the bit, for intLead (where L1=0, L2=1, L3=2), in byteDirection
if(byteDirection == 7){ // if the previous three changes were in the same direction, byteDirection will be 0111 = dec 7
intOutput++; // increase output by 1
//trace();
}
}else{ // direction counter clockwise
bitClear(byteDirection, intLead);
if(byteDirection == 0){
intOutput--;
//trace();
}
}
}