Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Help with Arduino Uno code for controlling DC Worm gear moto


#1

Hi. Im new in this field. I have Pololu High-Power 18V, 15A motor driver, Arduino uno microcontroler and DC worm gear Motor (12V) and two micro switches. Im building a prototype for tracking a solar panel. I would like to ask for a help regarding some sample code, that after tracking the panel with worm gear Motor it returns the panel in their initial position (horizontal). I have two Input PULLUP switches . So the idea is, motor start tracking and rotate 4 sec (defined with const int rotatiOnMillis = 4000) and is off for 2 sec (defined with const int motorBaseInterval = 2000).

So when (say) right-hand switch is pressed it runs the code to stop the motor and then to move the motor back to the left-hand HOME (Sleep) position. Here, in the HOME (Sleep) position the motor should stop and stay off for (let) say
15 sec (defined with const int motorSleepInterval = 15000). The problem of the code is that it stop the motor and bring back when end switch is press but it does not sleep for 15sec. And when its in HOME (Sleep ) position does not waje up and start running after those 15 sec. Any help? Here the code

[code]// ----CONSTANTS (won’t change)
#define motor_speed 750 //default motor speed @ 0.3rpm

const int motorDirection_Pin = 4; //Motor Direction pin
const int motorSpeed_Pin = 5; //Motor PWN pin
const int buttonEnd_Pin = 8; //End Button pin
const int buttonSleep_Pin = 9; //Sleep Button pin
const int rotatiOnMillis = 4000; // number of millisecs for motor rotation
const int motorBaseInterval = 2000; // number of millisecs between motor rotation
const int motorSleepInterval = 15000; // number of millisecs while motor is sleeping

//------- VARIABLES (will change)
byte buttonEnd_State = LOW;
byte buttonSleep_State = LOW;
byte motorState = HIGH;
unsigned long currentMillis; // stores the value of millis() in each iteration of loop()
unsigned long previousMotorMillis; // will store last time the motor was updated
unsigned long motorInterval = motorBaseInterval;
unsigned long motorOffMillis = motorSleepInterval;
volatile byte button_flag = 0;
volatile byte button_flag1 = 0;
volatile byte sleep_flag = 0;
//========

void setup() {

Serial.begin(9600);
// set the Motor and Buttons pins as output, INPUT_PULLUP:
pinMode(motorDirection_Pin, OUTPUT);
pinMode(motorSpeed_Pin, OUTPUT);
pinMode(buttonSleep_Pin, INPUT_PULLUP);
pinMode(buttonEnd_Pin, INPUT_PULLUP);

}

//=======
void loop() {

currentMillis = millis();
checkButtons();
execute_motor();
end_position();
sleep_position();
}

//========
void checkButtons() {
buttonEnd_State = digitalRead(buttonEnd_Pin);
buttonSleep_State = digitalRead(buttonSleep_Pin);
}

void execute_motor() {
checkButtons();
// nothing happens unless the interval has expired
if (currentMillis - previousMotorMillis >= motorInterval) {
//time is up, its time for another motor rotation
previousMotorMillis += motorInterval;
motorState = ! motorState;
if (motorState == HIGH) {
digitalWrite(motorDirection_Pin, LOW); //set direction for hinge motor rotation
analogWrite(motorSpeed_Pin, motor_speed);
motorInterval = rotatiOnMillis;
Serial.println(“motor rotation”);
}
else {
//nothing happens unless the interval has expired, still motor is not rotating
motorInterval = motorBaseInterval;
analogWrite(motorSpeed_Pin, 0); //set 0 speed for hinge motor
Serial.println(“motor stop, speed is 0”);
}
digitalWrite(motorDirection_Pin, motorState);

}
}

void end_position() {

checkButtons();
/* Check if End Button is pressed, if yes, stop the motor*/
if (buttonEnd_State == HIGH) {

analogWrite(motorSpeed_Pin, 0); //set 0 speed for hinge motor
Serial.println(“end position”);
/* Check if Sleep Button is pressed, run the motor to opposite direction till Sleep Button is pressed /
while (buttonSleep_State == LOW) {
digitalWrite(motorDirection_Pin, LOW); //set direction for hinge motor
analogWrite(motorSpeed_Pin, motor_speed);
button_flag=1;
checkButtons();
Serial.println(“end position, going home”);
}
}
}
void sleep_position(){
/
Check if Sleep Button is pressed, if its pressed stop the motor and set the sleep interval */
if (buttonSleep_State == HIGH && button_flag==1) {
analogWrite(motorSpeed_Pin, 0);
//button_flag1=1;
Serial.println(“stop, you are in sleep position now”);
motorInterval = motorSleepInterval;
Serial.println(“sleepinngg bzzzz”);
}
}[/code]


#2

[quote]end switch is press but it does not sleep for 15sec.[/quote]What does it do instead?

I notice that when you execute this line:motorInterval = motorSleepInterval;you do not also update the current time (previousMotorMillis). So the set interval can’t be correct.


#3

It stay sleeping. And after 10sc comes the “motor stop, speed is 0” (so the stop interval) and around 23 sec start rotation but not the whole rotation interval of 4 sec (just like half sec rotation) . Where should I do the updates of previousMotorMillis? aftermotorInterval = motorSleepInterval; should come previousMotorMillis+= motorInterval;? I tried that and its not working


#4

buttonEnd_Pin correspond to the (say) left hand switch (means left hand end Position) and buttonSleep_Pin correspond to the (say) wright hand switch and its say(Sleep Position). So what the program should do is the motor is off and on (off for 2 sec and on for 4 sec) till the buttonEnd_Pin (of the left hand switch) is HIGH (means is pressed). That should stop the motor and bring it back to the right hand end position( means to the position when right hand button switch - buttonSleep_Pin is HIGH). Here the motor should stop for 15 sec and than start again the off and on mode.

Hope is more clear now. Any help?


#5

Hello.

I looked at your code briefly and noticed that the following line in your code is not actually saving the time of your last motor rotation:

The code above is adding the current value of motorInterval to previousMotorMillis and not setting previousMotorMillis equal to currentMillis, so the difference in timing is not accurate for comparison. You should consider looking at this “Blink Without Delay” example on the Arduino’s website to get a better understanding of how to use the millis() function to calculate the difference from the time of your last motor rotation and the current time.

If you try modifying the code line above to previousMotorMillis = currentMillis and are not getting the expected behavior, please post your modified code along with a description of the results you are seeing compare to what you expect to see.

- Amanda


#6

So, to be clear. The system is a part of a solar panel tracking system. And this is the code only for the rotation. So the idea is the panel start rotation in the morning and rotate let we say every 10 min for let we say 2 sec. ( So means, I have defined motorBaseInterval which is the interval between rotation and should be 10 min long when motor stop. then and I have rotatiOnMillis when the motor runs and should be let we say 2 sec long). So this happen till the end limit switch is pressed.

So when left end limit switch is pressed (so normally this happen evening time) the motor should stop and than bring the panel to the Home (Sleep) position (mean motor runs in opposite direction till the right hand button switch - buttonSleep_Pin is HIGH). Here in the Home (Sleep) Position the panel should stay over the night , so means motor stop for time defined with motorSleepInterval. And in the morning start runing again the same procedure.

Hope is clear now

I made modification in the code but still not getting the wright results, as when I make the intervals very big, (for example const int motorBaseInterval = 122000; const int motorSleepInterval = 49320;) the motor never start rotating. I think this is the issue with millis. So by small intervals of motorBaseInterval = 30000; const int motorSleepInterval = 25000;) till 33 sec its works fine. What is the problem


#7

An int stores a 16-bit value, which has a range of -32,768 to 32,767. The values of your motorBaseInterval and motorSleepInterval exceed that data type’s range. You should consider using a larger data type like unsigned int (ranging from 0 to 65,535). You can find a list of data types and information about them in the “Reference” page on the Arduino’s website.

- Amanda


#8

ok I changed to const unsigned long but still not working. So made the changes here the changes I made

const unsigned long rotatiOnMillis = 2000; // number of millisecs for motor rotation const unsigned long motorBaseInterval = 4000; // number of millisecs between motor rotation const unsigned long motorSleepInterval = 15000; // number of millisecs while motor is sleeping

then in void executeMotor() {

[code]void executeMotor() {
// nothing happens unless the interval has expired
if ((unsigned long)(currentMillis - previousMotorMillis) >= motorInterval) {
//time is up, its time for another motor rotation
previousMotorMillis = currentMillis;
motorState = ! motorState;
if (motorState == HIGH) {
digitalWrite(motorDirection_Pin, LOW); //set direction for hinge motor rotation
analogWrite(motorSpeed_Pin, motor_speed);

                motorInterval = rotatiOnMillis;
            
                Serial.println("MOTOR ROTATIONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN");
                }
                    else {
                    //nothing happens unless the interval has expired, still motor is not rotating
                    motorInterval = motorBaseInterval;
                    analogWrite(motorSpeed_Pin, 0); //set 0 speed for hinge motor
                    Serial.println("motor stop, speed is 0000000000000");
                    }
            digitalWrite(motorDirection_Pin, motorState);
           
    }
    } [/code]

still not working, The motorSleepInterval is not executing correct. so after 11 sec when the buttonSleep is pressed (is HIGH) the output shows “motor stop, speed is 0000000000000” . And after 30 sec the buttonSleep is pressed it start rotating again. But, it should start rotating after 15 sec of pressing the buttonSleep ( means the motor should sleep or no rotation for 15 sec when buttonSleep is HIGH).

So Any help?


#9

It is not clear to me what your motorSleepInterval function is supposed to do, and it is difficult to help you troubleshoot the issue without seeing your entire code again. I suggest that you put some effort into debugging the code by using the Serial.println() command to print out your interval values at specific points in your code, so you can follow and modify your code accordingly. For example:

void executeMotor() {
   // nothing happens unless the interval has expired
   Serial.print("time difference: ");				         // Print string label
   Serial.println(currentMillis - previousMotorMillis);	// Print value and new line character
   Serial.print("motorInterval: ");
   Serial.println(motorInterval);
   if ((unsigned long)(currentMillis - previousMotorMillis) >= motorInterval) {
      //time is up, its time for another motor rotation
      previousMotorMillis = currentMillis; 
      motorState = ! motorState;

You might consider rewriting the code from scratch and focus on getting each component (like waiting for 15 seconds each time the buttonSleep_Pin is pressed) to work before adding more features to your code (such as stopping and moving the motor back to its home position when buttonEnd_Pin is pressed).

- Amanda


#10

I I got the output WHEN the Sleep Button is Pressed

[code]motorInterval Sleeping: 10000
time difference: 4326
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 5927
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 7529
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 9130
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 10732
motorInterval: 10000
motor stop, speed is 0

sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 1601
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 3203
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 4804
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 6406
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 8008
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 9609
motorInterval: 10000
sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 11211
motorInterval: 10000
MOTOR ROTATION

sleepinngg bzzzz
motorInterval Sleeping: 10000
time difference: 1601
motorInterval: 10000
time difference: 2702
motorInterval: 10000
time difference: 3803
motorInterval: 10000
time difference: 4904
motorInterval: 10000
time difference: 6005
motorInterval: 10000
time difference: 7106
motorInterval: 10000
time difference: 8207
motorInterval: 10000
time difference: 9308
motorInterval: 10000
time difference: 10409
motorInterval: 10000
motor stop, speed is 0
time difference: 1100
motorInterval: 4000[/code]

The problem is in the motor interval. WHEN the Sleep Button is pressed which is in the

with

the motor should not runs means

for 10 sec ( defined with this code)

And after that (after 10 sec) should do the mode which is in

(means runs for two sec ( with this commands defined )

digitalWrite(4, LOW); //set direction for hinge motor rotation analogWrite(5, motor_speed); motorInterval = rotatiOnMillis;

and stop for 4 sec which is defined with

motorInterval = motorBaseInterval; analogWrite(5, 0); //set 0 speed for hinge motor

Any help now?


#11

Thank you for clarifying what you expect your code to do. As Jim mentioned earlier in his post, your global variable previousMotorMillis is not updated to the current time in the sleep_position function, so the timing interval will have an offset from the last time you updated previousMotorMillis in your executeMotor function. You should add the following code at the bottom of the IF statement in your sleep_position function:

previousMotorMillis = millis();

- Amanda


#12

I have done it.

but still not getting the correct output. Now WHEN the Sleep Button is Pressed the time it not updating

sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 3374 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 1108 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 1108 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 1108 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 1107 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000 time difference: 1108 motorInterval: 10000 sleepinngg bzzzz motorInterval Sleeping: 10000

What is wrong now?


#13

From your output, it looks like your sleep button is being held down; not pressed (and released). When the sleep button is being held down (and your button_flag1 = 1), your program will always enter the IF statement in your sleep_position function, which will continuously reset your timer (by setting previousMotorMillis = millis()). (That is assuming your sleep_position function is still basically the same from the original code in your first post with the exception of having previousMotorMillis = millis() at the end of the function.)

If you want your timer to continue while the sleep button is held HIGH, you would need to modify your sleep_position function so that it only resets the timer when the sleep button is first pressed. One solution is to wrap previousMotorMillis = millis() in a conditional statement that checks for a sleep flag. The sleep flag is used to indicate when the program is in its sleep cycle and when it is not. You could probably use your global variable sleep_flag, which is not used any where in your original code. For example:

if (sleep_flag == 0)		 // Check if sleep cycle is not running
{
   motorInterval = motorSleepInterval;	// Set time interval
   previousMotorMillis = millis();		 // Set previous time to current time
   sleep_flag = 1;			// Indicate sleep cycle is running
}

Note that you will need to set the sleep_flag back to 0 when the sleep cycle is over.

Since it seems that you are mainly having Arduino programming issues, which are not related specifically to our high-power motor driver, you should consider posting your questions and code onto the Arduino Forum, as they have a much larger online community and focus specifically on Arduino.

- Amanda


#14

Thanks Amanda

Its works now