Go Down

Topic: I need help with my code - I want to control two motors (total beginner) (Read 299 times) previous topic - next topic

maexit

Hey,
I am an COMPLETE newb and have no idea what I am doing. So I just want to let two DC motors turn forward and backward (20 rpm gearbox). A motor shield is attached.

It should look like this -> motor1 turns 5 seconds forward (20 rpm) and then turns the same way immediately backwards (5 seconds/20rpm)

motor2 - starts at the same time like motor1, turns 3 seconds forward (10 rpm) then stops and waits 4 seconds before it drives back (3 seconds/10rpm). So that both cycles are synchrone.

Then it shall start again. I can't really program yet so I build something from things I read and example codes. Well that is my frankenstein code, it works somehow but not in the way intended and I don't understand it.

Code: [Select]

// Adafruit Motor shield library
// copyright Adafruit Industries LLC, 2009
// this code is public domain, enjoy!

#include <AFMotor.h>

AF_DCMotor motor(1);

AF_DCMotor motor2(4);


void setup() {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial.println("Motor test!");

// turn on motor
motor.setSpeed(255);
motor2.setSpeed(200)

motor.run(RELEASE);
motor2.run(RELEASE);
}

void loop() {
uint8_t i;

Serial.print("tick");

motor.run(FORWARD);
motor2.run(FORWARD);
for (i=30; i<255; i++) {
motor.setSpeed(i);
motor2.setSpeed(i);
delay(30);
}


Serial.print("tock");

motor.run(BACKWARD);
motor2.run(BACKWARD);
for (i=30; i<255; i++) {
motor.setSpeed(i);
motor2.setSpeed(i); 
delay(30);
}

Robin2

Well that is my frankenstein code, it works somehow but not in the way intended and I don't understand it.
It will be a big help if you describe in detail what it actually does and what you want it to do that is different.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

maexit

Exactly that:
It should look like this -> motor1 turns 5 seconds forward (20 rpm) and then turns the same way immediately backwards (5 seconds/20rpm)

motor2 - starts at the same time like motor1, turns 3 seconds forward (10 rpm) then stops and waits 4 seconds before it drives back (3 seconds/10rpm). So that both cycles are synchrone.

The motors have spools that roll up and unroll a string for a wood figure I made for my young son.

maexit

So I found out that the "for (i=30; i<255; i++)" is nothing useful for my needs.
But if I try to remove it, nothing happens anymore.

Robin2

Exactly that:
That sounds like what you want to happen when the program runs. But what actually happens with the existing program?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

maexit

I really appreciate your help!
I am German and have difficulties to make sense from this sentence.
So you mean what happens with my frankenstein code ? Well both motors start to turn, run for a few seconds and then run backwards. I tried to change the values but then weird stuff happens, like the motor needs 4 seconds to reach the maximum speed.

I am googling for 4 days now and try new stuff but it just wont work.

maexit

Sooo,
someone really nice over at reddit wrote me this code - it nearly works as intended.
But the motor2 turns 7 seconds forward and 4 backwards. Instead it should go 3 seconds forward take a break of 4 seconds and then go 3 backwards. Can someone identify the problem ?
Code: [Select]
#include <AFMotor.h>

AF_DCMotor motor1(1);
AF_DCMotor motor2(4);

unsigned long motor1_step1_endtime = 0;
unsigned long motor1_step2_endtime = 0;

unsigned long motor2_step1_endtime = 0;
unsigned long motor2_step2_endtime = 0;
unsigned long motor2_step3_endtime = 0;

void setMotor1_endtimes() {
    motor1_step1_endtime = millis() + 5000;
    motor1_step2_endtime = motor1_step1_endtime + 5000;
}

void setMotor2_endtimes() {
    motor2_step1_endtime = millis() + 3000;
    motor2_step2_endtime = motor2_step1_endtime + 4000;
    motor2_step3_endtime = motor2_step2_endtime + 3000;
}

void setup() {
    Serial.begin(9600);
    Serial.println("Motor Test");

    motor1.setSpeed(255);
    motor2.setSpeed(100);

    motor1.run(RELEASE);
    motor2.run(RELEASE);

}

void loop() {
    if(motor1_step1_endtime == 0) {
        setMotor1_endtimes();
    }

    if(motor2_step1_endtime == 0) {
        setMotor2_endtimes();
    }

    if(motor1_step1_endtime >= millis()) {
    motor1.run(FORWARD);
    }
    else if(motor1_step2_endtime >= millis()) {
    motor1.run(BACKWARD);
    }
    else if(motor1_step2_endtime <= millis()) {
        motor1_step1_endtime = 0;
    }


    if(motor2_step1_endtime >= millis()) {
        motor2.run(FORWARD);
    }
    else if(motor2_step2_endtime >= millis()) {
        // do nothing
    }
    else if(motor2_step3_endtime >= millis()) {
        motor2.run(BACKWARD);
    }
    else if(motor2_step3_endtime < millis()) {
        motor2_step1_endtime = 0;
    }
}

Robin2

I think this code will make your motor move through the three phases
Code: [Select]
if (motor2State == 0) {
    motor2Interval = 3000;
    motor2Direction = 'F';
}
else if (motor2State == 1) {
    motor2Interval = 4000;
    motor2Direction = 'N';
}
else if (motor2State == 2) {
    motor2Interval = 3000;
    motor2Direction = 'R';
}

if (motor2State != motor2prevState) { // change from one state to another
    motor2StartTime = millis();         // start the timer
    motor2prevState = motor2State;    // make sure the timer is only started once
    if (motor2Direction == 'F') {
        // code to make motor go forward
    }
    else if (motor2Direction == 'R') {
        // code to make motor go backwards
    }
}

if (millis() - motor2StartTime >+ motor2Interval) {
    // code to stop motor
    motor2State ++; // move to next state
    if (motor2State > 2) {
        motor2State = 0;
    }
}


To my mind it is easier to comprehend than the code in Reply #6. Note that I have simply numbered the three states 0, 1 and 2 for the movements Forward, Stationary and Reverse.


Also note that you should always use subtraction with millis() to avoid a problem when millis() rolls over.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

maexit

Thank you Robin!
But I can't implement that code without an error message.
Again I can't program yet, please be patient with me. Even simple steps or things that are obvious for you I won't understand.

I would implement it like this:
Code: [Select]
#include <AFMotor.h>

AF_DCMotor motor1(1);
AF_DCMotor motor2(4);

unsigned long motor1_step1_endtime = 0;
unsigned long motor1_step2_endtime = 0;

unsigned long motor2_step1_endtime = 0;
unsigned long motor2_step2_endtime = 0;
unsigned long motor2_step3_endtime = 0;

void setMotor1_endtimes() {
    motor1_step1_endtime = millis() + 5000;
    motor1_step2_endtime = motor1_step1_endtime + 5000;
}

void setMotor2_endtimes() {
    motor2_step1_endtime = millis() + 3000;
    motor2_step2_endtime = motor2_step1_endtime + 4000;
    motor2_step3_endtime = motor2_step2_endtime + 3000;
}

void setup() {
    Serial.begin(9600);
    Serial.println("Motor Test");

    motor1.setSpeed(255);
    motor2.setSpeed(100);

    motor1.run(RELEASE);
    motor2.run(RELEASE);

}

void loop() {
    if (motor2State == 0) {
    motor2Interval = 3000;
    motor2Direction = 'F';
}
else if (motor2State == 1) {
    motor2Interval = 4000;
    motor2Direction = 'N';
}
else if (motor2State == 2) {
    motor2Interval = 3000;
    motor2Direction = 'R';
}

if (motor2State != motor2prevState) { // change from one state to another
    motor2StartTime = millis();         // start the timer
    motor2prevState = motor2State;    // make sure the timer is only started once
    if (motor2Direction == 'F') {
        // code to make motor go forward
    }
    else if (motor2Direction == 'R') {
        // code to make motor go backwards
    }
}

if (millis() - motor2StartTime >+ motor2Interval) {
    // code to stop motor
    motor2State ++; // move to next state
    if (motor2State > 2) {
        motor2State = 0;
    }
}


But it says:'motor2State' was not declared in this scope

Robin2

In a C++ program you must declare all variables before you use them. I did not include that code. You need to add byte motor2State; at the top of your program. And similar code for the other variables. Ensure that all variables associated with millis() are defined as unsigned long.


You will find it makes your code much easier to read if you use the AutoFormat tool to indent it consistently.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Delta_G

The person at Reddit may have been nice, but they wrote code for you with a big ole bug in the timing.  Never use addition.  Always use subtraction.  All that timing math needs to be flipped.  See the Blink Without Delay example to see how those if statements should look. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Go Up