analogWrite only works with HIGH & LOW, no PWM

Hello,

Would appreciate if someone can help me understand why is my code only working with a duty cycle of 255 on analogWrite. And for any other value the motor is not moving at all.
If I use basic code I have no problem in making the motor run forward and reverse at any duty cycle under 255.

The idea is to move the motor from zerodegree (original state) until it reaches Ninety Degrees. This works but the motor is too fast and I need to slow it down. To my understanding ( I am a newbie ) lowering the duty cycle on the analogwrite should slow down the motor but instead nothing happens.

Thank you in advance.

#include <IRremote.h>

int OBSTACLE_DISTANCE = 0; //replace with acceptable distance
const int SPEED = 255; //find optimal speed for motor
int MAX_TIME = 8000; //seconds after which the motor will stop.
const long ZeroDegree = 0x11111111; //replace with HEX value
const long NinetyDegree = 0x2222222; //replace with HEX value
const long StopCmd = 0x33333333; //replace with HEX value

const int IRPin = 2;
const int NinetyPin = 5;
const int ZeroPin = 4;

int swZeroDegree = 0;
int swNinetyDegree = 0;

int pwm_a = 3;  //PWM control for motor output on digital pin 12
int dir_a = 12;  //direction control for motor output on digital pin 12

#define START 1
#define STOP 0

IRrecv irrecv(IRPin);

decode_results results;
void setup()
{
  Serial.begin(9600);
  pinMode(IRPin, INPUT);
  pinMode(NinetyPin, INPUT);
  pinMode(ZeroPin, INPUT);
  Serial.println("At your service sir!");
  irrecv.enableIRIn(); // Start the receiver
  pinMode(pwm_a, OUTPUT);  //Set control pins to be outputs
  pinMode(dir_a, OUTPUT);

  analogWrite(pwm_a, 100);  //set motor to run at (100/255 = 39)% duty cycle (slow)

}
void loop() {

  //State switches
  swZeroDegree = digitalRead(ZeroPin);
  swNinetyDegree = digitalRead(NinetyPin);

 if (OBSTACLE_DISTANCE == 0) { 
    if (irrecv.decode(&results) == true) 
      if (results.value == ZeroDegree)
			        if (swZeroDegree == false && swNinetyDegree == true) {
					motor(0, 0, START);
				} else if (swZeroDegree == true && swNinetyDegree == false) {
					motor(0, 0, STOP);
				} else {
					//motor(0, 0, START);
					}
			} else if (results.value == NinetyDegree) {
				if (swZeroDegree == true && swNinetyDegree == false) {
					motor(0, 1, START);
				} else if (swZeroDegree == false && swNinetyDegree == true) {
					motor(0, 1, STOP);
				} else {
					//motor(0, 1, START);
					}                
			} else if (results.value == StopCmd){
				motor(0, 0, STOP);
			}
		irrecv.resume();
		Serial.println(results.value);
		detect_switch_command();
	}
        
  }
}
void detect_switch_command() {
	unsigned long Timer = 0;

	delay(1000);

	Timer = millis();
	Serial.println(Timer);
	while(millis() - Timer <= MAX_TIME){
	   swZeroDegree = digitalRead(ZeroPin);
	   swNinetyDegree = digitalRead(NinetyPin);

	   if (swNinetyDegree == true || swZeroDegree == true) {
		 Serial.println("sw Detect Stop");
					Serial.print(swZeroDegree);
					Serial.print("-");
					Serial.println(swNinetyDegree);
		 //motor(0, 0, STOP);
                 astop();
	   }
	}
	Serial.println("Timer Stop");
	motor(0, 0, STOP);
}

void motor(int id, int direction, int mode){
     if (id== 0) {
		if(mode == START) {
			if (direction == 0){
                               forw();         //Set Motors to go forward Note : No pwm is defined with the for function, so that fade in and out works
                               fadein();       //fade in from 0-SPEED   
                               forward();    
                               Serial.print("going forward with speed: ");                            
                               Serial.println(SPEED);
			} else {
                               back();         //Set Motors to go forward Note : No pwm is defined with the for function, so that fade in and out works
                               fadein();       //fade in from 0 - SPEED  
                               backward();    
                               Serial.println("going backwards with speed: ");      
                               Serial.println(SPEED);                               
			}
		} else {	//STOP MOTOR
			//digitalWrite(dir_a, direction);  
			//digitalWrite(pwm_a, LOW);
                        Serial.println("motor fading out ");      
			fadeout(); //Fade out from SPEED to 0
		}
	 }
}

void forw() // no pwm defined
{ 
  digitalWrite(dir_a, HIGH);  //Reverse motor direction, 1 high, 2 low
}

void back() // no pwm defined
{
  digitalWrite(dir_a, LOW);  //Set motor direction, 1 low, 2 high
}

void forward() //full speed forward
{ 
  digitalWrite(dir_a, HIGH);  //Reverse motor direction, 1 high, 2 low  
  analogWrite(pwm_a, SPEED);    //set both motors to run at (100/255 = 39)% duty cycle
}

void backward() //full speed backward
{
  digitalWrite(dir_a, LOW);  //Set motor direction, 1 low, 2 high
  analogWrite(pwm_a, SPEED);   //set both motors to run at 100% duty cycle (fast)
}

void stopped() //stop
{ 
  digitalWrite(dir_a, LOW); //Set motor direction, 1 low, 2 high
  analogWrite(pwm_a, 0);    //set both motors to run at 100% duty cycle (fast)
}

void fadein()
{ 
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= SPEED; fadeValue +=5) 
  { 
     // sets the value (range from 0 to 255):
    analogWrite(pwm_a, fadeValue);   
    // wait for 30 milliseconds to see the dimming effect    
    //delay(30);                            
  } 
}

void fadeout()
{ 
  // fade out from max to min in increments of 5 points:
  for(int fadeValue = SPEED ; fadeValue >= 0; fadeValue -=5) 
  { 
    // sets the value (range from 0 to 255):
    analogWrite(pwm_a, fadeValue);
    // wait for 30 milliseconds to see the dimming effect    
    //delay(30);  
}
}

void astop()                   //stop motor A
{
  analogWrite(pwm_a, 0);   
}

Which driver IC are you using?
Where have you connected the op pins from your Driver IC?
Your outputs from mcu should go into the driver ic, I dont think analog write works that way.
If you have a ckt diagram or a setup pic link it with this.

Thank you for the reply.

I am using whatever comes with the arduino IDE Out of the box. I am not sure how to check for the drivers.

but here is the pic of the setup:

Errmm.. Could you link the sparkfun id for this IC?

Is this what you are looking for?

thank you

Remove the IRremote library and see if that resolves the problem. If that library is using the timer that analogWrite depends on, that could be the source of the problem.

I dont think you can do, what you need with this L298 driver IC.
Ok,
In a mcu, the max curent is only around 40 mA and the max voltage is 5v. to drive a motor this current is not enough, that is why you use a driver IC. You connect a external power supply to the IC, and the pwm pins from the mcu to the IC. This pwm which is connected,is only to trigger external power supply, its just like a switch.

What you are trying to do here is, you are varying the voltage of this switch. This will have not affect the motor speed.
your logic can be used only when the load is directly connected to the mcu. Like LED for instance..

Thank you both for your help very much appreciated.

After removing the IR, PWM started to work.

What do you suggest? I still need the IR to receive the commands

You'll either have to find an IR library that uses a completely software implementation, or perhaps one that uses one of the other timers (not sure if either actually exist).

Couldn't you use some of the other pwm pins that use another timer?

From the playground:
Pins 5 and 6: controlled by Timer 0
Pins 9 and 10: controlled by timer 1
Pins 11 and 3: controlled by timer 2

I noticed this library posted on the sensor forum, perhaps it would help with IR sensor and servos: http://arduino.cc/forum/index.php/topic,105232.0.html

As already explained, you need to either find an IR library that doesn't use timer 2, or change to using a different PWM pin (but not pin 11, that's also controlled by timer 2).

To use a different PWM pin, here are some possible approaches:

  1. Connect pin 3 to the pin you intend to use (pin 5, 6, 9 or 10). Leave pin 3 configured as an input, and do your pinMode() and analogWrite() calls on the other pin.

  2. Use a sharp knife to cut the trace on the underside of the motor driver PCB that connects pin 3 to the via hole. Remove the resist from the via hole, then you can solder a fine wire between it and the PWM pin you want to use.