Poor PWM Performance When Using Serial...

Hello!

I'm having trouble using both PWM output, analogRead, and Serial.print functions and could really use some advice.

I'm working on a project that will require reading four analog inputs, mapping and comparing the inputs, driving an H-bridge IC with PWM, and also sending out I2C to another IC.

Currently, I'm reading the four analog inputs, mapping them, and driving the H-bridge IC. I would REALLY like to monitor the analog inputs on my computer to see what is going on, but whenever I try to use a Serial.print command the motor's performance becomes extremely jerky and erratic.

I understand that I'm asking the Arudino to do a lot of things simultaneously, but I really need to take a look at what the Arduino is doing in real-time..

Here's the code without any serial commands:

#include <EEPROM.h>

int TPS1;
int TPS2;
int TPS1min = EEPROM.read(0);
int TPS1max = EEPROM.read(1)+765;
int TPS2min = EEPROM.read(2)+765;
int TPS2max = EEPROM.read(3);
int PPS1;
int PPS2;
int PPS1min = 136;
int PPS1max = 966;
int PPS2min = 59;
int PPS2max = 460;
int a;
int b;

void setup()
{
pinMode(A0,INPUT);
pinMode(A1,INPUT);
pinMode(A4,INPUT);
pinMode(A5,INPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,INPUT);
pinMode(8,INPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
//TCCR0B = TCCR0B & 0b11111000 | 0x02;


}
//
void loop()
{
  PPS1 = map(analogRead(A0),PPS1min,PPS1max,0,1000); 
  PPS2 = map(analogRead(A1),PPS2min,PPS2max,0,1000); 
  TPS1 = map(analogRead(A4),TPS1min,TPS1max,0,1000);
  TPS2 = map(analogRead(A5),TPS2min,TPS2max,0,1000);
  PPS1 = constrain(PPS1,0,1000);
  a = PPS1 - TPS1;
  b = TPS1 - PPS1;
//
if ( PPS1 >= 970 )                                                                  //***WOT SWITCH***
  {
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
  }
if ( PPS1 <= 10 )                                          //***FULLY CLOSED SWITCH***
  {
  if ( TPS1 > 15 )
    {
      digitalWrite(5,HIGH);
      digitalWrite(6,HIGH);
    }
      else
  {
      digitalWrite(5,HIGH);
      digitalWrite(6,LOW);
  }
  }
else
{
            if ( PPS1 > TPS1 )                                         //SOFT UP TO 2 DEGREES DIFFERENCE
                {
                    analogWrite(5,constrain(255/a,0,255));
                    digitalWrite(6,LOW);
                }
            else                                         //SOFT UP TO 3 DEGREES DIFFERENCE
                {
                     if ( b <= 30 )
                     {
                     analogWrite(5,constrain(b*8.5,0,255));
                     digitalWrite(6,LOW);
                     }
                     else
                     {
                        digitalWrite(5,HIGH);
                        digitalWrite(6,HIGH);
                     }
                }
}
}

... and here's the code with the serial commands...

#include <EEPROM.h>

int TPS1;
int TPS2;
int TPS1min = EEPROM.read(0);
int TPS1max = EEPROM.read(1)+765;
int TPS2min = EEPROM.read(2)+765;
int TPS2max = EEPROM.read(3);
int PPS1;
int PPS2;
int PPS1min = 136;
int PPS1max = 966;
int PPS2min = 59;
int PPS2max = 460;
int a;
int b;

void setup()
{
pinMode(A0,INPUT);
pinMode(A1,INPUT);
pinMode(A4,INPUT);
pinMode(A5,INPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,INPUT);
pinMode(8,INPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
Serial.begin(9600);
//TCCR0B = TCCR0B & 0b11111000 | 0x02;


}
//
void loop()
{
  PPS1 = map(analogRead(A0),PPS1min,PPS1max,0,1000); 
  PPS2 = map(analogRead(A1),PPS2min,PPS2max,0,1000); 
  TPS1 = map(analogRead(A4),TPS1min,TPS1max,0,1000);
  TPS2 = map(analogRead(A5),TPS2min,TPS2max,0,1000);
  PPS1 = constrain(PPS1,0,1000);
  a = PPS1 - TPS1;
  b = TPS1 - PPS1;
  Serial.print("PPS1: ");
  Serial.print(PPS1);
  Serial.print("PPS2: ");
  Serial.print(PPS2);
  Serial.print("TPS1: ");
  Serial.print(TPS1);
  Serial.print("TPS2: ");
  Serial.print(TPS2);
//
if ( PPS1 >= 970 )                                                                  //***WOT SWITCH***
  {
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
  }
if ( PPS1 <= 10 )                                          //***FULLY CLOSED SWITCH***
  {
  if ( TPS1 > 15 )
    {
      digitalWrite(5,HIGH);
      digitalWrite(6,HIGH);
    }
      else
  {
      digitalWrite(5,HIGH);
      digitalWrite(6,LOW);
  }
  }
else
{
            if ( PPS1 > TPS1 )                                         //SOFT UP TO 2 DEGREES DIFFERENCE
                {
                    analogWrite(5,constrain(255/a,0,255));
                    digitalWrite(6,LOW);
                }
            else                                         //SOFT UP TO 3 DEGREES DIFFERENCE
                {
                     if ( b <= 30 )
                     {
                     analogWrite(5,constrain(b*8.5,0,255));
                     digitalWrite(6,LOW);
                     }
                     else
                     {
                        digitalWrite(5,HIGH);
                        digitalWrite(6,HIGH);
                     }
                }
}
}

It is only helpful to post code snippets that compile and demonstrate the behavior you describe. Code that doesn't include the issue, won't compile, missing declarations, etc do not really give much for people to help.

Edit: thank you for posting complete code.

James C4S:

I edited the original post to include complete codes, as requested, including both cases (functional and hindered performance). I didn't include the code because it doesn't matter what serial commands I would ask the Arduino to do, it all caused performance issues.

The first code is what works perfectly fine. The second code is what causes the issues in PWM performance. Both codes compile.

If you removed the map functions and used the raw analogread values for your if statements you could gain some speed.

You will need to do a little figuring to change the if statement to use the values that fit the analogread results. You are mapping 0 to 1000, it is almost the same as the analogread result 0 to 1023.

Hey cyclegadget,

Thanks for the advice, I've been kicking around that same idea for a while now. I would LOVE to drop the map functions because I know they take a while to compute, however, I think I'm stuck having to use them.

I have two sets of sensor data (4 total) coming from two separate devices which all produce different scales (4 different scales). I need to compare them, which becomes extremely difficult if they're still on different scales. Additionally, I'm writing code that will work with imperfect sensors that will become less accurate with age, so I need the program to have some adaptability. If the sensor ages significantly I can use a subroutine to define new a new min and max without rewriting the code.

Try bumping this up:
Serial.begin(9600);

to like 115200, same in the serial monitor, I think you'll see a big improvement.

I'm missing something - how compliler could potentially know the content of the EEPROM at compile time, when arduino even could not be connected?

int TPS1min = EEPROM.read(0);
int TPS1max = EEPROM.read(1)+765;

Hello CrossRoads:

That was the trick! I changed the baudrate and it fired right up perfectly!

If you dont mind, can you explain why that was needed to solve the problem?

To Magician:

Sorry, this program is still in the testing phase. I had another sketch that would help me determine the various min and max's and store them to the EEPROM. I havent combined the codes into the same program.

EDIT: NOT YET SOLVED...

CrossRoads:

The baudrate seems to be the issue. I tried using Serial.write for a single command "Serial.write(PPS1);" as a test, while erasing all Serial.write commands shown in the code I posted. I did this at a rate of 115200 and it worked perfectly!

But when I tried to execute the eight serial commands I posted in my original code it started to give wacky motor results again.

I can see that I've maxed out the baudrate at the Arduino serial monitor. Can I increase the baudrate and watch it with a separate serial monitor program?

I had another sketch that would help me determine the various min and max's and store them to the EEPROM.

Yes, I've got it. What I'm trying to say, you better to transfer this lines where you reading min max limits stored in EEPROM inside setup function, otherwise they are (min-max) not defined, probably some garbage value and all algorithm goes to slope.

Magician:

I see what you're saying... hmmm... good point... I'll move it around and make sure its working properly. That could be a source of some problems I haven't found yet... Thanks for the advice.

alexxander_foster:
I would REALLY like to monitor the analog inputs on my computer to see what is going on, but whenever I try to use a Serial.print command the motor's performance becomes extremely jerky and erratic.

Something I've been doing from time to time, and which may help you, is to debug via I2C or SPI, if you have the pins spare, and another Arduino around.

Particularly with SPI, which is very fast, you can shoot your debugging info off to be displayed at a sedate pace by another processor.