rotary encoder with dc motor

Hello All! I am new with Arduino and this kind of projects so I'm sorry if the question will be too stupid :))

I am trying to write the code for two dc motors one rotary encoder for each one of them.

/* Arduino Rotary Encoder Tutorial
*

*/

#define outputA 6
#define outputB 7
int counter = 0;
int aState;
int aLastState;
void setup() {
pinMode (outputA,INPUT);
pinMode (outputB,INPUT);

Serial.begin (9600);
// Reads the initial state of the outputA
aLastState = digitalRead(outputA);
}
void loop() {
aState = digitalRead(outputA); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured
if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
counter ++;
} else {
counter --;
}
Serial.print("Position: ");
Serial.println(counter);
}
aLastState = aState; // Updates the previous state of the outputA with the current state
}

This is the code I am using for the rotary encoder and I get the numbers listed in the serial monitor. However I dont know how to change the code so I can get both encoders listed in the serial monitor at the same time.... Can someone help me update the code? Thank you very much :D. Cheers!

The simplistic (but clumsy) way to do this is to rename all the variables, pins etc that relate to the encoder in your current code by appending a zero to them. Get that working then add another set of code with a suffix of 1 on all the variables, pins etc which relates to the second encoder.

If you know anything about arrays then you will immediately see that the 2 sets of variables and pins could be held in arrays and you could iterate through the arrays, albeit only two levels, to read and report on the encoders

Thank you very much for your reply but I dont really understand what you are trying to say here :))). I have almost no knowledge about coding. this one that i've posted was copied from the internet. I dont really understand it. But I'm starting to learn haha

I suggest that first you look at and experiment with the examples in the IDE so that you understand what the commands in the current code do.

The (deliberately) clumsy method I suggested in my previous post involves adding a second complete set of the code to read the second encoder and print its values. Renaming the variables with a suffix of 0 and adding a second set with a suffix of 1 for the second encoder would be a step towards the more effective way of doing this by using arrays to hold values for both encoders but put that aside for now.

What exactly is the final aim of the project ? How are the motors required to react to turning the encoders ?

I am an architect and I'm building this moving ceiling. The project is almost done. It consists out of 64 motors and 64 encoders which control every intersection of the grid. Someone else will take care about the code and programming of the structure. I just need a simple way to print the values for two different encoders at the same time so I can check it 2by2 for every single motor. I need to make sure they spin at the exact same speed etc etc

/Users/octavian/Downloads/46937179_601296303634249_8884566990568554496_n.jpg

octavianprostean:
https://www.youtube.com/watch?v=lrA6rysG4d8

I am an architect and I'm building this moving ceiling. The project is almost done. It consists out of 64 motors and 64 encoders which control every intersection of the grid. Someone else will take care about the code and programming of the structure. I just need a simple way to print the values for two different encoders at the same time so I can check it 2by2 for every single motor. I need to make sure they spin at the exact same speed etc etc

/Users/octavian/Downloads/46937179_601296303634249_8884566990568554496_n.jpg

With the assumption that the motors only turn in one direction you could simply do this:
proportional control only (PID)
the master encoder creates the desired setpoint and we will want to follow that with the controlled motor. the further the master gets ahead of the follower the more power we apply to the follower motor

#define ClockPinMaster 2 // This is the encoder to follow (other motor)
#define ClockPinFollower 3 // this is the encoder we are controlling with the motor
volatile long EncoderMasterCounter;
volatile long EncoderFollowerCounter;
int Output;
int Kp = 1; // This mumtiplier could range from 0.001 to 255 and anywhare in between you will want to start small and increase this until you get occellations thn back down.


void onPin2CHANGECallBackFunction() {
  EncoderMasterCounter ++;
}
void onPin3CHANGECallBackFunction() {
  EncoderFollowerCounter ++;
}

void setup() {
  attachInterrupt(digitalPinToInterrupt(ClockPinMaster), onPin2CHANGECallBackFunction, RISING);
  attachInterrupt(digitalPinToInterrupt(ClockPinFollower), onPin3CHANGECallBackFunction, RISING);
}

void loop() {
  noInterrupts ();
  EncoderMasterCounter = EncoderMasterCounter - EncoderFollowerCounter;// calculate the error
  EncoderFollowerCounter = 0;
  interrupts ();
  // the EncoderMasterCounter value is now the error and should always be positive
  Output = constrain(0, 255, (EncoderMasterCounter * Kp)); // Proportional only of PID control
  analogWrite(5, Output); // PWM output for the motor (DC brushed)
}

Z


/* Arduino Rotary Encoder Tutorial
*

*/

#define outputA 6
#define outputB 7
int counter = 0;
int aState;
int aLastState;

#define outputC 8
#define outputD 9
int counter = 0;
int aState;
int aLastState;

void setup() {
pinMode (outputA,INPUT);
pinMode (outputB,INPUT);

Serial.begin (9600);
// Reads the initial state of the outputA
aLastState = digitalRead(outputA);

pinMode (outputC,INPUT);
pinMode (outputD,INPUT);

Serial.begin (9600);
// Reads the initial state of the outputA
aLastState = digitalRead(outputC);

}

void loop() {
aState = digitalRead(outputA); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured
if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
counter ++;
} else {
counter --;
}
Serial.print("Position: ");
Serial.println(counter);
}
aLastState = aState; // Updates the previous state of the outputA with the current state
}

aState = digitalRead(outputC); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured
if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
counter ++;
} else {
counter --;
}
Serial.print("Position: ");
Serial.println(counter);
}
aLastState = aState; // Updates the previous state of the outputA with the current state
}

I tried to copy paste the code and change the variables for the pins.
However I get this error:

arduinos:17:6: error: redefinition of 'int counter'
int counter = 0;
^
/Users/octavian/Downloads/arduinos/arduinos.ino:9:6: note: 'int counter' previously defined here
int counter = 0;
^
arduinos:18:6: error: redefinition of 'int aState'
int aState;
^
/Users/octavian/Downloads/arduinos/arduinos.ino:10:6: note: 'int aState' previously declared here
int aState;
^
arduinos:19:6: error: redefinition of 'int aLastState'
int aLastState;
^
/Users/octavian/Downloads/arduinos/arduinos.ino:11:6: note: 'int aLastState' previously declared here
int aLastState;
^
arduinos:63:1: error: 'aState' does not name a type
aState = digitalRead(outputC); // Reads the "current" state of the outputA
^
arduinos:65:4: error: expected unqualified-id before 'if'
if (aState != aLastState){
^
exit status 1
redefinition of 'int counter'

Do you guys know why?

#define outputA 6
#define outputB 7
int counter = 0;
int aState;
int aLastState;

#define outputC 8
#define outputD 9
int counter = 0;
int aState;
int aLastState;

You cannot reuse variable names like this. You can have only one counter, aState and aLastState. If you need similar variables they must have different names.

Then if you autoformat (ctrl-t or Tools, Auto Format) your code, you will see where misplaced curly brackets ({}) are causing errors.

Read the how to use this forum-please read sticky to see how to properly post code.

/*     Arduino Rotary Encoder Tutorial

    by Dejan Nedelkovski, www.HowToMechatronics.com

*/

//L293D
//Motor A
const int motorPin1  = 22;  // Pin 14 of L293
const int motorPin2  = 23;  // Pin 10 of L293

const int motorPin3  = 24;  // Pin 14 of L293
const int motorPin4  = 25;  // Pin 10 of L293

#define outputA 38
#define outputB 39
int counter_1 = 0;
int aState_1;
int aLastState_1;

#define outputC 40
#define outputD 41
int counter_2 = 0;
int aState_2;
int aLastState_2;

void setup() {
   //Set pins as outputs
    pinMode(motorPin1, OUTPUT);
    pinMode(motorPin2, OUTPUT);

      //Set pins as outputs
    pinMode(motorPin3, OUTPUT);
    pinMode(motorPin4, OUTPUT);
  
  pinMode (outputA, INPUT);
  pinMode (outputB, INPUT);

  Serial.begin (9600);
  // Reads the initial state of the outputA
  aLastState_1 = digitalRead(outputA);

  pinMode (outputC, INPUT);
  pinMode (outputD, INPUT);

  Serial.begin (9600);
  // Reads the initial state of the outputA
  aLastState_2 = digitalRead(outputC);
}


void loop() {
      digitalWrite(motorPin1, 0);
    digitalWrite(motorPin2, 1);

        digitalWrite(motorPin3, 0);
    digitalWrite(motorPin4, 1);
  
  
  aState_1 = digitalRead(outputA); // Reads the "current" state of the outputA
  // If the previous and the current state of the outputA are different, that means a Pulse has occured
  if (aState_1 != aLastState_1) {
    // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
    if (digitalRead(outputB) != aState_1) {
      counter_1 ++;
    } else {
      counter_1 --;
    }
    Serial.print("Position: 1:");
    Serial.println(counter_1);
  }
  aLastState_1 = aState_1; // Updates the previous state of the outputA with the current state

  aState_2 = digitalRead(outputC); // Reads the "current" state of the outputA
  // If the previous and the current state of the outputA are different, that means a Pulse has occured
  if (aState_2 != aLastState_2) {
    // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
    if (digitalRead(outputB) != aState_2) {
      counter_2 ++;
    } else {
      counter_2 --;
    }
    Serial.print("Position: 2:");
    Serial.println(counter_2);
  }
  aLastState_2 = aState_2; // Updates the previous state of the outputA with the current state
}

Yes Thx. I managed to change the variables correctly.
One more question. With this working code now I get the values of both encoders in the Serial monitor. However they are listed on the same line one beneath the other. Is there an option in the Serial Monitor to get a parallel listing? like one row just for Position 1: and one row for Position2:

Change this:

Serial.print("Position: 1:");
Serial.println(counter_1);

to this:

Serial.print("Position: 1:");
Serial.print(counter_1);

And change this:

Serial.print("Position: 2:");
Serial.println(counter_2);

to this:

Serial.print("  Position: 2:");
Serial.println(counter_2);

Is that what you meant?

And thanks for the code tags, well done.

I did that and I get this: ( Attached Print Screen )

I want to get the two encoders listed parallel at the same time like this:

Pos1 : 12 Pos2: 12
Pos1 : 13 Pos2: 13
Pos1: 14 Pos2: 14

Do you understand what I mean ? :slight_smile: Thank you

Increase the baud rate in Serial.begin() in setup() to Serial.begin(115200). Also set the baud rate in serial monitor to 115200. Does that help?

Attached you will find the new screenshot

first I changed it to Serial.begin(115200). and afterwards to 250000. Similar results. Gets better but still a little bit chaotic.

Maybe because the motors spin to quickly?

I don't think the speed of the motors is the problem. I think it is more to do with printing every time through loop(). Maybe try reducing the amount printed. Print "P1 " instead of "Position1".

same issue :frowning:

How about only printing only when one or both of the values change ?

Save the value from the previous read before reading again. Only print if teh old and new values are different

After all, if nothing changes then no output is needed