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
// ----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");
}
}
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? after motorInterval = motorSleepInterval; should come previousMotorMillis+= motorInterval;? I tried that and its not working
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.
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:
previousMotorMillis += motorInterval;
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.
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
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.
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() {
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);
}
}
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).
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).
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:
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.