Dc motor controlled as stepper?

Hello guys
I finally have my R2D2 dome photo encoder working fine
my interrupts have readings from 60 to -60
can I control a dc motor as stepper motor using these readings? How?
I have an ultrasonic sensor on the dome, but any sketch I found they use servo motors to control angles.
thanks
Arduino Mega
dc motor bridge

 // R2D2 MAKING
// ARDUINO MEGA
//



#include "Arduino.h"
#include "SoftwareSerial.h"
#include <DistanceSRF04.h>
#include <NewPing.h>
#include <Wire.h>
#include <Encoder.h>

//----------------DOME MOTOR-----------------------------

int stbydome = 6; // standby
int pinAIN1 = 53; //Direction 1
int pinAIN2 = 52; //Direction 2
int pinPWMA = 7; //PWM

#define pinA  19      // encoder pin A to Arduino pin 19 interrupt pin 4 
#define pinB  18      // encoder pin B to Arduino pin 18 interrupt pin 5 
#define pinC  20      // encoder pin C to arduino pin 20 interrupt pin 3

int counter, S1_SIG=0, S2_SIG=1, S3_SIG=1;
bool firstinit = false;


void setup()
{
  Wire.begin();
Serial.begin(115200);

  pinMode (stbydome, OUTPUT);  //standby
  pinMode (pinAIN1, OUTPUT);   // DIR 1
  pinMode (pinAIN2, OUTPUT); //  DIR2
  pinMode (pinPWMA, OUTPUT); // PWM  
  
  pinMode(pinA, INPUT_PULLUP); 
  pinMode(pinB, INPUT_PULLUP); 
  pinMode(pinC, INPUT_PULLUP);
 
attachInterrupt(4, S1_RISE, RISING);//hooked to pin19 on mega 2560
attachInterrupt(5, S2_RISE, RISING);//hooked to pin18
attachInterrupt(3, S3_RISE, RISING);//hooked to pin20

launchRobot();
}//setup

void loop()
{
//motorDOME(0,0);
  //motorDOME(2,70);

//digitalRead(counter);
//Serial.print(counter);

if (counter >= 60 )
{ 
  motorDOME(2,80);

  delay(300);
}
if (counter <= -60)
{
  motorDOME(1,80);

  delay(300);
}
 
}

void launchRobot(){ 
  
  Serial.println("DOME MOVING" );
//delay(100);
motorDOME(0,0);

  motorDOME(1,80);
  delay(1000);
  motorDOME(2,80);
  delay(1000);
if (counter == 0)
{
  motorDOME(0,0);
  delay(500);
}

 
  
  //motorDOME(2,80);
//delay(700);
} 
  




  

//--------------------------motor DOME


void motorDOME(int mode, int percent)

{
  
  //change the percentage range of 0 -> 100 into the PWM
  //range of 0 -> 255 using the map function
  int duty = map(percent, 0, 100, 0, 255);
  
  switch(mode)
  {
    case 0:  //disable/coast
      digitalWrite(stbydome, HIGH);  //set enable low to disable B
      analogWrite(pinPWMA, duty);  
      break;
      
    case 1:  //turn clockwise
      //setting IN3 high connects motor lead 1 to +voltage
      digitalWrite(pinAIN1, HIGH);   
      digitalWrite(pinAIN2, LOW);  
      //use pwm to control motor speed through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
      
    case 2:  //turn counter-clockwise
      //setting IN3 low connects motor lead 1 to ground
      //digitalWrite(dir1PinB, LOW);   
      
      //setting IN4 high connects motor lead 2 to +voltage
      digitalWrite(pinAIN2, HIGH);  
      digitalWrite(pinAIN1, LOW);   
      //use pwm to control motor speed through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
      
    case 3:  //brake motor
      //setting IN3 low connects motor lead 1 to ground
      digitalWrite(pinAIN1, LOW);   
      
      //setting IN4 high connects motor lead 2 to ground
      digitalWrite(pinAIN2, LOW);  
      
      //use pwm to control motor braking power 
      //through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
  }
}

//   ----------------interrupts

void S1_RISE()
{
detachInterrupt(4);
S1_SIG=1;

if(S2_SIG==0)
counter++; //entry
if(S2_SIG==1)
counter--; //exit

Serial.println(counter);
attachInterrupt(4, S1_FALL, FALLING);
}

void S1_FALL()
{
detachInterrupt(4);
S1_SIG=0;

if(S2_SIG==1)
counter++; //entry
if(S2_SIG==0)
counter--; //exit


Serial.println(counter);
attachInterrupt(4, S1_RISE, RISING);
}

void S2_RISE()
{
detachInterrupt(5);
S2_SIG=1;

if(S1_SIG==1)
counter++;//entry
if(S1_SIG==0)
counter--;//exit

Serial.println(counter);
attachInterrupt(5, S2_FALL, FALLING);
}

void S2_FALL()
{
detachInterrupt(5);
S2_SIG=0;

if(S1_SIG==0)
counter++; //entry
if(S1_SIG==1)
counter--; //exit

Serial.println(counter);
attachInterrupt(5, S2_RISE, RISING);
}

void S3_RISE()
{
S3_SIG = 1;
detachInterrupt(3);

if (!firstinit && (( S2_SIG==1 && S1_SIG==1) || (S1_SIG==0 && S2_SIG==1)))
{
counter=0;
firstinit = true;
}

attachInterrupt(3, S3_FALL, FALLING);
}

void S3_FALL()
{
S3_SIG = 0;
detachInterrupt(3);

if ( !firstinit && (( S2_SIG==1 && S1_SIG==1) || (S1_SIG==1 && S2_SIG==0)))
{
counter=0;
firstinit = true;
}

attachInterrupt(3, S3_RISE, RISING);
}

A DC motor is completely different from a stepper. It is not designed to hold position - indeed it is probably designed so it won't hold position.

If you put an encoder on the motor shaft and write some complex code you could probably build a servo system which allows the motor to be positioned precisely. That sort of servo is used in high-end CNC machines. They are quite different from hobby servos - most especially as regards price.

...R

hi, thanks for answering
i know that, but even the motor is not gonna stop precisely how do I tell him stop at 54 for example?
i have 3 photo encoders, 2 of them read the gear teeth and the central one reads just a longer tooth as zero position.
so I want the motor run left or right when I want, position needs to be close.
the ultrasonic sensor will read the obstacle anyway, also I have 5 other static ultrasonic sensors on R2D2 body.

I posted just the code for the dome.
thanks

bobafet67:
hi, thanks for answering
i know that, but even the motor is not gonna stop precisely how do I tell him stop at 54 for example?

That's why I said it would need complex code. I don't know how to do it.

...R

i know that, but even the motor is not gonna stop precisely how do I tell him stop at 54 for example?

Stop at 54 what? Drinks in an hour?

If you want to count encoder clicks, and stop the motor when you have counted 54, do we really need to tell you how to do that?

Do I have to read "counter" variable in the void loop?
Because when I do it in the lunchrobobot void doesn't work.
do you suggest to use IF OR DO WHILE OR SWITCH CASE?
In the full code I have void loop already croud with IFs to control 2 motors with 5 sr04, I would like to find a way to clean up my code for further implementation.
Thanks

Btw obviously I am talking about clicks

Do I have to read "counter" variable in the void loop?

How are you getting data from the encoder now?

Because when I do it in the lunchrobobot void doesn't work.

Post your code!

do you suggest to use IF OR DO WHILE OR SWITCH CASE?

Yes, I do. Some statement, or combination of statements, will be needed.

In the full code I have void loop already croud with IFs to control 2 motors with 5 sr04, I would like to find a way to clean up my code for further implementation.

Ctrl-A, Ctrl-X. Really clean, now.

Btw obviously I am talking about clicks

To one of us, anyway.

PaulS:
Stop at 54 what? Drinks in an hour?

If you want to count encoder clicks, and stop the motor when you have counted 54, do we really need to tell you how to do that?

Don't encourage him :slight_smile:

@bobafet67 is talking about a DC motor with an encoder.

If you know how to stop a DC motor with the same precision as a stepper motor I will gladly leave the OP in your capable hands and read your advice with interest.

...R

Robin2:
If you know how to stop a DC motor with the same precision as a stepper motor I will gladly leave the OP in your capable hands and read your advice with interest.

...R

That's what PIDs are for....

Regards,
Ray L.

If you know how to stop a DC motor with the same precision as a stepper motor I will gladly leave the OP in your capable hands and read your advice with interest.

I didn't say it was possible. Some people only learn by tripping over the facts. I expect that OP is one of them.

PaulS:
I didn't say it was possible. Some people only learn by tripping over the facts. I expect that OP is one of them.

It is entirely possible, and it's done ALL the time! It's called a servo motor! Virtually ANY DC motor can be turned into a perfectly usable servo motor by simply adding an encoder, and controlling it with a PID. Even very inexpensive motors can be quickly and easily positioned to an accuracy of a very few (like 2-3) counts of the encoder.

This is my current project, an auto toolchanger for CNC milling machines. It is using inexpensive (under $20) 12V DC motors, to which I have added encoders, turning them into servos. Each motor is being controlled by its own PID, with 5 mSec update rate, all running on a Due, along with a web server, telnet server, multiple serial ports, and many, many other devices and services.

Regards,
Ray L.

Thanks Ray I am gonna check it out
I posted the code already just the interested part in the first post.
I read already 3 photo encoders I explained in the earlier posts.
I read values between 65 and -65 with a zero position.
I just would like to use that motor as dome movement to find obstacle with sr04.
I am not an expert in the programming language, I am learning but in electronic I am guys.
thanks

reading “counter” with serial

// R2D2 MAKING
// ARDUINO MEGA
//



#include "Arduino.h"
#include "SoftwareSerial.h"
#include <DistanceSRF04.h>
#include <NewPing.h>
#include <Wire.h>
#include <Encoder.h>

//----------------DOME MOTOR-----------------------------

int stbydome = 6; // standby
int pinAIN1 = 53; //Direction 1
int pinAIN2 = 52; //Direction 2
int pinPWMA = 7; //PWM

#define pinA  19      // encoder pin A to Arduino pin 19 interrupt pin 4 
#define pinB  18      // encoder pin B to Arduino pin 18 interrupt pin 5 
#define pinC  20      // encoder pin C to arduino pin 20 interrupt pin 3

int counter, S1_SIG=0, S2_SIG=1, S3_SIG=1;
bool firstinit = false;


void setup()
{
  Wire.begin();
Serial.begin(115200);

  pinMode (stbydome, OUTPUT);  //standby
  pinMode (pinAIN1, OUTPUT);   // DIR 1
  pinMode (pinAIN2, OUTPUT); //  DIR2
  pinMode (pinPWMA, OUTPUT); // PWM  
  
  pinMode(pinA, INPUT_PULLUP); 
  pinMode(pinB, INPUT_PULLUP); 
  pinMode(pinC, INPUT_PULLUP);
 
attachInterrupt(4, S1_RISE, RISING);//hooked to pin19 on mega 2560
attachInterrupt(5, S2_RISE, RISING);//hooked to pin18
attachInterrupt(3, S3_RISE, RISING);//hooked to pin20

launchRobot();
}//setup

void loop()
{
//motorDOME(0,0);
  //motorDOME(2,70);

//digitalRead(counter);
//Serial.print(counter);

if (counter >= 60 )
{ 
  motorDOME(2,80);

  delay(300);
}
if (counter <= -60)
{
  motorDOME(1,80);

  delay(300);
}
 
}

void launchRobot(){ 
  
  Serial.println("DOME MOVING" );
//delay(100);
motorDOME(0,0);

  motorDOME(1,80);
  delay(1000);
  motorDOME(2,80);
  delay(1000);
if (counter == 0)
{
  motorDOME(0,0);
  delay(500);
}

 
  
  //motorDOME(2,80);
//delay(700);
} 
  




  

//--------------------------motor DOME


void motorDOME(int mode, int percent)

{
  
  //change the percentage range of 0 -> 100 into the PWM
  //range of 0 -> 255 using the map function
  int duty = map(percent, 0, 100, 0, 255);
  
  switch(mode)
  {
    case 0:  //disable/coast
      digitalWrite(stbydome, HIGH);  //set enable low to disable B
      analogWrite(pinPWMA, duty);  
      break;
      
    case 1:  //turn clockwise
      //setting IN3 high connects motor lead 1 to +voltage
      digitalWrite(pinAIN1, HIGH);   
      digitalWrite(pinAIN2, LOW);  
      //use pwm to control motor speed through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
      
    case 2:  //turn counter-clockwise
      //setting IN3 low connects motor lead 1 to ground
      //digitalWrite(dir1PinB, LOW);   
      
      //setting IN4 high connects motor lead 2 to +voltage
      digitalWrite(pinAIN2, HIGH);  
      digitalWrite(pinAIN1, LOW);   
      //use pwm to control motor speed through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
      
    case 3:  //brake motor
      //setting IN3 low connects motor lead 1 to ground
      digitalWrite(pinAIN1, LOW);   
      
      //setting IN4 high connects motor lead 2 to ground
      digitalWrite(pinAIN2, LOW);  
      
      //use pwm to control motor braking power 
      //through enable pin
      analogWrite(pinPWMA, duty);  
      
      break;
  }
}

//   ----------------interrupts

void S1_RISE()
{
detachInterrupt(4);
S1_SIG=1;

if(S2_SIG==0)
counter++; //entry
if(S2_SIG==1)
counter--; //exit

Serial.println(counter);
attachInterrupt(4, S1_FALL, FALLING);
}

void S1_FALL()
{
detachInterrupt(4);
S1_SIG=0;

if(S2_SIG==1)
counter++; //entry
if(S2_SIG==0)
counter--; //exit


Serial.println(counter);
attachInterrupt(4, S1_RISE, RISING);
}

void S2_RISE()
{
detachInterrupt(5);
S2_SIG=1;

if(S1_SIG==1)
counter++;//entry
if(S1_SIG==0)
counter--;//exit

Serial.println(counter);
attachInterrupt(5, S2_FALL, FALLING);
}

void S2_FALL()
{
detachInterrupt(5);
S2_SIG=0;

if(S1_SIG==0)
counter++; //entry
if(S1_SIG==1)
counter--; //exit

Serial.println(counter);
attachInterrupt(5, S2_RISE, RISING);
}

void S3_RISE()
{
S3_SIG = 1;
detachInterrupt(3);

if (!firstinit && (( S2_SIG==1 && S1_SIG==1) || (S1_SIG==0 && S2_SIG==1)))
{
counter=0;
firstinit = true;
}

attachInterrupt(3, S3_FALL, FALLING);
}

void S3_FALL()
{
S3_SIG = 0;
detachInterrupt(3);

if ( !firstinit && (( S2_SIG==1 && S1_SIG==1) || (S1_SIG==1 && S2_SIG==0)))
{
counter=0;
firstinit = true;
}

attachInterrupt(3, S3_RISE, RISING);
}

RayLivingston:
It is entirely possible, and it's done ALL the time!

I know that. I said so in Reply #1.

However I don't know how to do it.

How about posting a short program that illustrates how to do it. Then I might buy an encoder and try it for myself.

...R

Robin2:
If you put an encoder on the motor shaft and write some complex code you could probably build a servo system which allows the motor to be positioned precisely.

A single PID loop is not complex, its perfectly straightforward - tuning it is more of an issue.

http://playground.arduino.cc/Code/PIDLibrary

Robin2:
I know that. I said so in Reply #1.

However I don't know how to do it.

How about posting a short program that illustrates how to do it. Then I might buy an encoder and try it for myself.

...R

A meaningful "simple example" is not simple, as it depends on the specific encoder, motor driver, etc. But, basically, you use an H-bridge to drive the motor, and a PID which uses encoder position as it's input, and generates a PWM value as its output. That PWM value controls the H-bridge. Then, you have to learn how to tune the PID, for a good response.

Regards,
Ray L.

MarkT:
A single PID loop is not complex, its perfectly straightforward - tuning it is more of an issue.

It would be nice if someone could post a demo program that can control a DC motor with an encoder so it behaves like a stepper motor.

...R

RayLivingston:
A meaningful "simple example" is not simple,

That's why I have been trying to steer the OP away from the idea.

And I have just noticed in your earlier Reply

can be quickly and easily positioned to an accuracy of a very few (like 2-3) counts of the encoder

which leads me to believe that a DC motor + encoder does not give the same functionality as a stepper which can be positioned to a single step and will stay there.

...R