Help! Controlling DC Motor 3-speed, reverse direction fan application

I would like help creating the programming code for this particular arudino application.

(1) i would like to create a 3-speed fan. The speed should be controlled by 1 push-button with a pulldown resistor and the direction should be controlled by a pushbutton with a pulldown resistor. When pushed once, the fan should rotate at minimum speed (pwm = 100), pushed a second time speed 2 = 178, pushed a third time speed 3 = 255 and fourth time speed =0.

(2) the direction control button should be default = clockwise when turning on the fan but should be able to reverse direction at the same speed setting it is pressed on. Fir example, if fan is turned on at speed 3, pressing the switch direction button should have the same speed but in the other direction.

(3) This should be accomplished with toggle switches, so no need to hold down the buttons.

Components to be used:

  • a L293D motor driver
  • Two pushbuttons as toggle switches
  • Two pulldown resistors 1kOhm
  • 6V power source for motor

Can anyone please help me with the coding to accomplish this? I am able to set up the circuitry to this problem but i need help with the code.

Thank you for any assistance.

Hello bfar86
Post your current sketch, well formated, with comments and in so called code tags "</>" and a schematic, not a Fritzy diagram, to see how we can help.
Have a nice day and enjoy coding in C++.
Дайте миру шанс

CODE:

// constants won't change. They're used here to set pin numbers:
const int speedPin = 5; // the number of the speed pushbutton pin
const int directionPin = 6; // the number of the direction pushbutton pin
const int ledPin = 13; // the number of the LED pin to indicate press of button
const int motorIn1 = 2; // Input 1
const int motorIn2 = 4;	// Input 2

int spVal = 0; 
int speed1 = 100;	// First Speed
int speed2 = 178;	// Second Speed
int speed3 = 255;	// Third Speed

// Variables will change:
int speedButtonState; // the current reading from the input speed pin
int lastSpeedButtonState = LOW; // the previous reading from the input pin
int directionButtonState;		// vaiable to implement switch direction
int lastDirectionButtonState = LOW;

// the following variables are long's because the time, measured in miliseconds, will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
/******************************************************************************/

void setup() 
{
 //set theled,motors as OUTPUT,button as INPUT
 pinMode (speedPin, INPUT);
 pinMode (ledPin, OUTPUT);
 pinMode (motorIn1,OUTPUT);
 pinMode (motorIn2,OUTPUT);
 Serial.begin(9600);
}

void loop() 
{
 // read the state of the switch into a local variable:
 int speedReading = digitalRead (speedPin);
 if (speedReading != lastSpeedButtonState) // If the button state is different from last time 
  	{ 
  	 lastDebounceTime = millis(); // reset the debouncing timer
 	} 
 if ((millis() - lastDebounceTime) > debounceDelay) 
 	{ 
	 if (speedReading != speedButtonState) 
 	{
 speedButtonState = speedReading; // Store the state of button in speedButtonState 
 
 // only toggle the LED if the new button state is HIGH
 if (speedButtonState == HIGH)
 	{
 	digitalWrite (ledPin, HIGH); //turn on the LED
 	spVal = spVal + 1;
 	if (spVal >= 4)  // When stat >= 4, set it as 0. 
 		{
 		spVal = 0;
		}
	}
 else
 {
 	digitalWrite (ledPin, LOW);
 }
 } 

 switch(spVal)
 {
    case 1:
    clockwise (speed1);// When stat=1, set the rotate speed of the motor as speed1 = 100
    break;
    case 2:
    clockwise (speed2);// When stat=2, set the rotate speed of the motor as speed2 = 178
    break;
    case 3:
    clockwise (speed3);// When stat=3, set the rotate speed of the motor as speed3 = 255
    break;
    default:
    clockwise(0);
  }
 
 // save the reading. Next time through the loop,
 // it'll be the lastButtonState:
 lastSpeedButtonState = speedReading;
}
/***********************************************************/
void clockwise(int Speed)
{
 digitalWrite (motorIn1, 0);
 digitalWrite (motorIn2, 1);
 analogWrite (motorIn2, Speed);
}

void counterclockwise(int Speed)
{
 digitalWrite (motorIn1, 1);
 digitalWrite (motorIn2, 0);
 analogWrite (motorIn1, Speed);
}
/************************************************************/
```````````````````````````````````````````````````

I have the speed control down and that seems to be working fine. I am having trouble with implementing the code for the direction switch with the same speed setting as before I press Button 2 (direction switch button).

Get into the habit of clicking Tools->Auto Format from time to time. This will help you get the indentation right in your code. Indentation does not affect the way the code works, but it does help you understand if you have { and } in the correct places.

I would use delay(), not millis() for debouncing buttons. It would make the code simpler without causing any problems in this case.

Hello bfar86
My proposal is to extend the switch/case structure with a nested switch/case for direction as follows:
Start of proposal:

.......
enum Directions {ClockWise, CounterClockWise} directions = ClockWise;
switch (spVal)
{
case 1:
  switch (directions) {
    case ClockWise:
      clockwise (speed1);// When stat=1, set the rotate speed of the motor as speed1 = 100
      break;
    case CounterClockWise:
      counterclockwise(speed1);
      break;
  }
  .........

End of proposal

Have a nice day and enjoy coding in C++.
Дайте миру шанс!

Thank you for those tips. I will be sure to implement the autoformat and delay into future projects.

But you plan to ignore my advice for this project?

And also this project. Thanks again.

Thank your for this. I will try to implement this strategy in my project. I will let you know how it goes.

I suggest changing

int speed1 = 100;	// First Speed
int speed2 = 178;	// Second Speed
int speed3 = 255;	// Third Speed

to

const byte speed[4] = {0, 100, 178, 255};

Then, you won't need the switch-case statement, you only need write

clockwise (speed[spVal]);

I have an alternative suggestion to that given by @paulpaulson

Replace these functions

void clockwise(int Speed)
{
 digitalWrite (motorIn1, 0);
 digitalWrite (motorIn2, 1);
 analogWrite (motorIn2, Speed);
}

void counterclockwise(int Speed)
{
 digitalWrite (motorIn1, 1);
 digitalWrite (motorIn2, 0);
 analogWrite (motorIn1, Speed);
}

with a single function

void spin(byte speed, byte direction)
{
  if (direction == 0)
  {
    analogWrite (motorIn1, 0);
    analogWrite (motorIn2, speed);
  }
  else
  {
    analogWrite (motorIn2, 0);
    analogWrite (motorIn1, speed);
  }
}

Might be a good idea to run motor to stop first before reversing.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.