Problem with analogWrite

Hi, new to the group and arduino. I am having issues with my analogWrite commands. MEGA 2560 powered via 3 amp external supply.
I do not have access to my script at the moment but here is my concept.
In my setup: I have 3 functions that I am defining that seems to have a conflict. I do not know if it is a timer conflict or what. The 1st function reads a ppm value for channel 2 from a rc receiver via sbus protocol. This value is converted via a library to a PWM value. The function analogWrites to PWM pin 3 and 4 if value is less than 120. If the value is greater than 134, it analogWrites to PWM 3 and 4as well.
The 2nd function does the same as the 1st except it is reading channel 3 from the rc receiver and writes that value to PWM pin 5 and 6.

The 3rd function has the same structure but it reads a value from rc receiver channel 4 and analogWrites to all 4 of the previous pins depending on the value of the input from the receiver.

My loop calls each one of these functions. The 1st two functions by themselves, work as intended as does the 3rd function if the 1st two are disabled. If all three functions are enabled in the loop, it appears that they may be "fighting" each other for control over the 4 PWM pins.
Being as that functions 1 and 2 work as intended as long as function 3 is disabled, I decided to disable function 3 and change function #2 to analogWrite to the same PWM pins as function #1. I got the same result as I did if all three functions were enabled. (the apparent conflict)
Does this sound like a timer conflict or by design, am I not supposed to write to a PWM pin from multiple functions.
The PWM pins are connected to the common contacts on 4 separate relays which are switch by digitalWrite to set the direction of 4, 12 vdc motors via 4 IBT_2 BTS7690 motor controllers which have their own power supply and both arduino and the IBT_2s "grounds", are common to each other.
I know I should attach my code for reference beforehand but I hope to get an idea of what may be going on.
Thanks in advance. Love the group, I have learned alot while trolling around.

Welcome to the forum

Until you post your code it will be difficult to provide help. Which Arduino board are you using, how is it powered and what are the PWM pins driving ?

You can certainly write to a PWM pin from multiple functions because the functions will not be running at the same time

1 Like

This does not narrow it down enough, can you post an annotated schematic showing how this has been wired. Be sure to show all connections, power, ground and power sources. Also post links to technical information on the hardware devices. At this point I will take a SWAG and say you are overloading the Mega regulators or power source. Here are a few rules:
Gil's Crispy Critter Rules, they apply to processor hardware:
Rule #1. A Power Supply the Arduino is NOT!
Rule #2. Never Connect Anything Inductive to an Arduino!
Rule #3 Don't connecting or disconnecting wires with power on.
Rule #4 Do not apply power to any pin unless you know what you are doing.
LaryD's Corollarys
Coro #1 when first starting out, add a 220R resistor in series with both Input and Output pins.
Coro #2 buy a DMM (Digital Multi-meter) to measure voltages, currents and resistance.
Violating these rules tends to make crispy critters out of Arduinos.

Sorry, this is also my first time using Fritzing.

#include <PPM.h>
#include <Servo.h>

#define CHANNELS 8   // max ppm channels
#define PPM_PIN 2    // receiver ppm pin
#define Thr1 3       //Thruster 1 pin
#define Thr2 4       //Thruster 2 pin
#define Thr3 5       //Thruster 3 pin
#define Thr4 6       //Thruster 4 pin
#define UDThr 7      //UD Thruster pin

       //xxxxPWMCtrl:  Digital Out to relay: Low to energize relay to Normally Open contact = Motor Reverse Direction...//
       //xxxxPWMCtrl:  Digital Out to relay: High-- relay is "off"-- Normally Closed contact = Motor Forward Direction...//
#define Thr1PWMCtrl 50      //Allow 1 PWM out to control direction via relay switching
#define Thr2PWMCtrl 51      //Allow 1 PWM out to control direction via relay switching
#define Thr3PWMCtrl 52      //Allow 1 PWM out to control direction via relay switching
#define Thr4PWMCtrl 53      //Allow 1 PWM out to control direction via relay switching
#define UDThrPWMCtrl 49      //Allow 1 PWM out to control direction via relay switching

Servo tilt;   // create servo object to control a servo

int ch1;
int ch2;
int ch3;
int ch4;
int ch5;
int ch6;
int ch7;
int ch8;

int tiltval;    // variable to read the value from the analog pin


void setup() {
  ppm.begin(PPM_PIN, CHANNELS);
  tilt.attach(11);    // attaches the servo on pin 11 to the servo object
  pinMode(Thr1, OUTPUT);
  pinMode(Thr2, OUTPUT);
  pinMode(Thr3, OUTPUT);
  pinMode(Thr4, OUTPUT);
  pinMode(UDThr, OUTPUT);

  pinMode(Thr1PWMCtrl, OUTPUT);
  pinMode(Thr2PWMCtrl, OUTPUT);
  pinMode(Thr3PWMCtrl, OUTPUT);
  pinMode(Thr4PWMCtrl, OUTPUT);
  pinMode(UDThrPWMCtrl, OUTPUT);
  
  
  Serial.begin(9600);
}
void LeftThrusters() {
  int motorSpeed;
    if (ch3 < 120) {  //set motor dir for Down
              // speed proportional to stick dist from neutral
              //  map(channel, neut, low or high, 0, 255)
    motorSpeed = map(ch3, 127, 0, 0, 255);
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr1, motorSpeed); 
    analogWrite(Thr4, motorSpeed); 
    digitalWrite(Thr1PWMCtrl, LOW);     //Setting LOW turns relay "on" for Reverse Direction of thruster.  Allows use of ONE PWM signal to IBT_2 motor controller.
    digitalWrite(Thr4PWMCtrl, LOW);     //Each of the 4 horizontal thruster motors, has it's own IBT_2 motor controller.  
    } else if (ch3 > 134) {               //Each IBT_2 requires a signal for both right and left (forward and reverse in my case)  The relays allow me to use 1 signal wire to each motor controller.  "My attempt to save PWM pins for future expansion"
    motorSpeed = map(ch3, 127, 254, 0, 255);    
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr1, motorSpeed); 
    analogWrite(Thr4, motorSpeed); 
    digitalWrite(Thr1PWMCtrl, HIGH);    //Setting HIGH leaves relay "off" for Forward Direction of thruster.  Allows use of ONE PWM signal to IBT_2 motor controller.   
    digitalWrite(Thr4PWMCtrl, HIGH);
    } 
    
      else { 
    analogWrite(Thr1, 0); 
    analogWrite(Thr4, 0); 
    digitalWrite(Thr1PWMCtrl, HIGH);
    digitalWrite(Thr4PWMCtrl, HIGH);
    }
}
void RightThrusters() {
  int motorSpeed;
    if (ch2 < 120) {  
              // speed proportional to stick dist from neutral
    motorSpeed = map(ch2, 127, 0, 0, 255);
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr2, motorSpeed); 
    analogWrite(Thr3, motorSpeed); 
    digitalWrite(Thr2PWMCtrl, LOW);
    digitalWrite(Thr3PWMCtrl, LOW);
    } else if (ch2 > 134) { 
    motorSpeed = map(ch2, 127, 254, 0, 255);
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr2, motorSpeed); 
    analogWrite(Thr3, motorSpeed); 
    digitalWrite(Thr2PWMCtrl, HIGH);
    digitalWrite(Thr3PWMCtrl, HIGH);
    } else { 
    analogWrite(Thr2, 0); 
    analogWrite(Thr3, 0); 
    digitalWrite(Thr2PWMCtrl, HIGH);
    digitalWrite(Thr3PWMCtrl, HIGH);
    }
}
void Strafe() {
  int motorSpeed;
    if (ch4 < 120) {  //set motor dir for Strafe Left
              // speed proportional to stick dist from neutral
    motorSpeed = map(ch4, 127, 0, 0, 255);
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr1, motorSpeed); 
    analogWrite(Thr2, motorSpeed); 
    analogWrite(Thr3, motorSpeed); 
    analogWrite(Thr4, motorSpeed); 
    digitalWrite(Thr1PWMCtrl, LOW);
    digitalWrite(Thr2PWMCtrl, HIGH);
    digitalWrite(Thr3PWMCtrl, LOW);
    digitalWrite(Thr4PWMCtrl, HIGH);
    } else if (ch4 > 134) { //set motor dir for Strafe Right
    motorSpeed = map(ch4, 127, 254, 0, 255);
    if (motorSpeed>255) motorSpeed=255;  //over is bad
    analogWrite(Thr1, motorSpeed); 
    analogWrite(Thr2, motorSpeed); 
    analogWrite(Thr3, motorSpeed); 
    analogWrite(Thr4, motorSpeed); 
    digitalWrite(Thr1PWMCtrl, HIGH);
    digitalWrite(Thr2PWMCtrl, LOW);
    digitalWrite(Thr3PWMCtrl, HIGH);
    digitalWrite(Thr4PWMCtrl, LOW);
    } else { 
    analogWrite(Thr1, 0); 
    analogWrite(Thr2, 0); 
    analogWrite(Thr3, 0); 
    analogWrite(Thr4, 0); 
    digitalWrite(Thr1PWMCtrl, HIGH);
    digitalWrite(Thr2PWMCtrl, HIGH);
    digitalWrite(Thr3PWMCtrl, HIGH);
    digitalWrite(Thr4PWMCtrl, HIGH);
    }
}

// void UDThruster() {
//   int motorSpeed;
//     if (ch1 < 120) {  //set motor dir for Down
//               // speed proportional to stick dist from neutral
//     motorSpeed = map(ch1, 128, 0, 0, 255);
//     if (motorSpeed>255) motorSpeed=255;  //over is bad
//     analogWrite(UDThr, motorSpeed);
//     digitalWrite(UDThrPWMCtrl, LOW);
//     } else if (ch1 > 134) { //set motor dir for Up
//     motorSpeed = map(ch1, 128, 254, 0, 255);
//     if (motorSpeed>255) motorSpeed=255;  //over is bad
//     analogWrite(UDThr, motorSpeed);
//     digitalWrite(UDThrPWMCtrl, HIGH); 
//     } else { 
//     analogWrite(UDThr, 0);
//     digitalWrite(UDThrPWMCtrl, HIGH); 
//     }
//}      

void tiltCam()  {
  tiltval = ch5;
  tiltval = map(tiltval, 0, 254, 0, 75);
  tilt.write(tiltval);
  Serial.println(ch5);
  delay(15);
}

void loop() { //                                                                             THr1               Thr2                                                                                
  ch1 = ppm.getPWM(1);  //PWM value  for Up/Down Thrusters
  ch2 = ppm.getPWM(2);  //PWM value  for Right Side Horizontal Thrusters (2)                     Thruster Layout              
  ch3 = ppm.getPWM(3);  //PWM value  for Left Side Horizontal Thrusters  (2)                     
  ch4 = ppm.getPWM(4);  //PWM value  for Strafe control of all Horizontal Thrusters (4)      Thr4               Thr3
  ch5 = ppm.getPWM(5);  //SparePWM value
  ch6 = ppm.getPWM(6);  //SparePWM value
  ch7 = ppm.getPWM(7);  //SparePWM value
  ch8 = ppm.getPWM(8);  //SparePWM value

  LeftThrusters(); 
  RightThrusters();
  Strafe();
  
  //UDThruster();
  //tiltCam();
  

  
}








  







How do these issues manifest themselves ?

V-in of a Mega needs 7volt minimum.
Why the relay module. The Mega can control the motor drivers directly.
Leo..

I didn't really study your code but one thing that can foul-up PWM is to analogWrite() every millisecond or so, every time through the loop.

PWM is "set and forget" so you should only re-write when you want to change it.

If I enable the "Strafe" function and try to "drive" my ROV, the motors respond as in a "jerky" or hesitant manner. They almost appear to be energizing in Forward and Reverse simultaneously in an erratic and random frequency. Kinda of like a "brake" feature. The Strafe function seems to operate more normal than the Left and Right functions when all three are enabled. If I disable or uncomment the Strafe call in the loop, then the Left and Right functions both respond to the RC control sticks as planned. Also, if only the Strafe function is enabled, all four motors respond as intended.

I will adjust the voltage to the Mega and give that a shot... I had not thought about this. Thanks...
I am using the relay module in my attempt to keep as many PWM pins open for future expansion or features on the ROV. Currently, based on the value of the PPM input from the RC receiver, the functions either turn on or off the corresponding relay to send the arduino PWM signal to the appropriate L_Enable or R_Enable pin on the motor control. This allows me to use only 1 PWM pin to control the direction and speed of a given motor.

I didn't utilize any delay per function as can be seen. I was thinking that since I want the functions to respond immediately to the the RC control sticks, that I should not use any delay. But after reading your statement it does seem as though that could help. This is going to be an underwater rov so a spot on immediate response is not absolutely necessary. Would you recommend adding a delay to the end of each function or should I find a way to monitor for an input value "change" to start the function? Thanks, DVDdoug...

The Mega has 15 PWM pins, so 12 left if you had used the EN pins of the motor drivers for speed control.
If you want more pins, then use port expanders, not relays.
Leo..

Thanks everyone for the advice and insight. I ended up removing the following from each of the functions.

    } else { 
    analogWrite(Thr1, 0); 
    analogWrite(Thr2, 0); 
    analogWrite(Thr3, 0); 
    analogWrite(Thr4, 0); 
    digitalWrite(Thr1PWMCtrl, HIGH);
    digitalWrite(Thr2PWMCtrl, HIGH);
    digitalWrite(Thr3PWMCtrl, HIGH);
    digitalWrite(Thr4PWMCtrl, HIGH);
    delay(10);
    }

I then created a new function as shown below to set everything to the desired values and states.

void clearPWMCtrl() {
  if (ch1 > 120 && ch1 < 134 && ch2 > 120 && ch2 < 134 && ch3 > 120 && ch3 < 134 && ch4 > 120 && ch4 <134) {
  digitalWrite(Thr1PWMCtrl, HIGH);
  digitalWrite(Thr2PWMCtrl, HIGH);
  digitalWrite(Thr3PWMCtrl, HIGH);
  digitalWrite(Thr4PWMCtrl, HIGH);
  analogWrite(Thr1, 0); 
  analogWrite(Thr2, 0); 
  analogWrite(Thr3, 0); 
  analogWrite(Thr4, 0);
  }    
}

Prior to making this change, I connected my O-Scope to two of the digital outputs. When function "Strafe" was enabled, the 4 digital outputs were pulsing. Basically creating a PWM signal to my relay coils. It appears that each of the previous functions were fighting for control over the relay state. Everything is as smooth as silk now and I am very pleased. I will be adjusting my Vin for the Arduino to 7.6 volts as suggested by Wawa.
So thanks to all for helping out a newbie to arduino and the forum. I honestly expected to be treated like an idiot or told to do a search before posting. That did not happen so, kudos to all of you.

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