PWM output on Nano

Hello,

I am using an ultrasonic distance sensor to control PWM signal to a motor driver. The closer the distance the duty cycle of PWM should increase. The PWM will only output 6 or 14 depending on PIN number. What am I doing wrong?

Using Arduino Nano & HC-S04 Ultrasonic Sensor


// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
const int motor = 6;
// defines variables
long duration;
int distance;
void setup() {
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  pinMode(motor, OUTPUT);
  Serial.begin(9600); // Starts the serial communication
}
void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2;
  // Prints the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.println(distance);
  Serial.print("PWM: ");
  Serial.println(motor);
  

  if (distance <= 40) {
    analogWrite(motor, 255);
       if (distance > 40 || distance <=80) {
    analogWrite(motor, 127);
         if (distance > 80 || distance <=120) {
    analogWrite(motor, 64);
  }
  }
  }
  else {
    analogWrite(motor, 0);
  }
  }

Welcome to the forum

   const int motor = 6;

  Serial.print("PWM: ");
  Serial.println(motor);

Can you guess why this prints 6 ?

2 Likes

means:

if (distance <= 40)  analogWrite(motor, 64);
if (distance  > 40)  analogWrite(motor, 0);
1 Like

I noticed that and changed to A6. Now it just prints 20 which is the arduino PIN number.

I'm trying to teach myself.

So don't nest the if statements like this?

Should I just write multiple if else statements?

Of course it prints 20 because that is the pin number

What is it that you actually want to print ?

it is best to use a series of if/else statements that start with the highest range and progress to the lowest distance.

if ( distance > 120 ) {
  // do something when above 120
} else if ( distance > 80 ) {
  // do something when 80-120
} else if ( distance > 40 ) {
  // do something when 40-80
} else if ( distance > 20 ) {
  // do something when 20-40
} else {
  // do something when 0-20
}

if you don't like that style, you can also use switch/case statements where the case statements specify a range

switch( distance ) {
  case 0...20:
    // do something
    break;
  case 21...40:
    // do something else
    break;
  case 41...80:
...
}
1 Like

I have no output on A6 with this code. I was hoping it would print the PWM value (i.e. 0-255)

The first you need to calculate the PWM value and store it in a variable to use it later for analogWrite() and for Serial.print().

Consider

 Serial.println(motorPwmValue);

...and how you would fill motorPwmValue with the PWM value.

Or you could lust print the value immediately after you write it to analogWrite()

    analogWrite(motor, 64);
    Serial.println("wrote 64");
1 Like

Thanks blh64. that's a big help.

They both look clean. I am not comfortable using switch/case yet but i'll save this code for when I'm learning. I really appreciate you laying out the proper structure.

This is a great idea. it only writes if the statement is evaluated true

if you want. i prefer short expressions, like:

analogWrite(motor, 255 - distance);
1 Like

Hold on -- wow -- never seen that before.
I must try that out.

It's a gnu thing.

How do I calculate this? Using map function?

I tried the code but still get no output on A6 pin. Theres not even enough output to drive an LED.

Do you know what i'm missing here?

// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
const int motor = A6;
// defines variables
long duration;
int distance;
void setup() {
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  pinMode(motor, OUTPUT);
  Serial.begin(9600); // Starts the serial communication
}
void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2;
  // Prints the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.println(distance);
  

  if ( distance > 120 ) {
  analogWrite(motor, 0);
  Serial.println("PWM 0");
} else if ( distance > 80 ) {
  analogWrite(motor, 64);
  Serial.println("PWM 64");
} else if ( distance > 40 ) {
  analogWrite(motor, 127);
  Serial.println("PWM 127");
} else if ( distance > 20 ) {
  analogWrite(motor, 255);
  Serial.println("PWM 255");
} else {
  analogWrite(motor, 255);
  Serial.println("PWM 255");
}

  }

Do you want only 4 different values like your code shows?

Or a range of 256 different values like:

If you want to save that result for printing, then something like this completely untested snippet:

    int motorPwmValue = 255 - distance;
    analogWrite(motor, motorPwmValue);
    Serial.print("wrote ");
    Serial.println(motorPwmValue);

or with map(), you might need constrain() for distances > 120:

int motorPwmValue = map(distance,0,120,255,0);
motorPwmValue = constrain(motorPwmValue,0,255);
1 Like

Calculate what ?

In your original code you were unconditionally writing a value

analogWrite(motor, 64);
    Serial.println("wrote 64");

So you can also unconditionally print the same value

1 Like

A6 is Input only (and likewise A7).

3 Likes