Notifications
Clear all

Component Tester

6 Posts
3 Users
2 Reactions
83 Views
(@jeffreyjene)
Member
Joined: 6 years ago
Posts: 69
Topic starter  

Well, here I am again a year later! I'm working on breadboarding out a component tester for things that I regularly breadboard, in this case motors, servos, ultrasonic sensors, IR sensors, motor encoders, and regular LEDs. Maybe I'll add on nRF24 and HC-05 modules later. I'm using a Mega along with a Nextion display for the GUI. One of the interesting problems I ran into - I wanted to display the servo angles on the display, which is communicated with via Serial. If I don't send the serial values to the display, the servos move smoothly with the pots turning. If I do send the values, the servos jerk along, as if they are pausing as each piece of data is sent over serial. I've tried different baud rates and even a PWM library and module, but nothing seems to work. Maybe someone knows a solution? I'll post more pics when this starts going into a case, which is sort of a puzzle I'm figuring out.

20260216 115102

 



   
Quote
noweare
(@noweare)
Member
Joined: 6 years ago
Posts: 183
 

How often are you updating the screen ?



   
THRandell reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 7 years ago
Posts: 2418
 

@jeffreyjene

More information like the actual code might help and the display you are using. It seems to me the Mega cannot, even with interrupts, keep up the PWM signals required while also serving the display?

Would the use of a PCA9685 solve the problem?

 

 



   
ReplyQuote
(@jeffreyjene)
Member
Joined: 6 years ago
Posts: 69
Topic starter  

@robotbuilder Here is the code section. The display is a Nextion 3.4 that works on Serial2 for the Mega. It should be noted that this issue persists regardless of the display. It's almost if the servo pauses so the data can send. I did try the use of the PWM module, no good.

void loop(){

if (mode == 2){
    int valA = analogRead(SERVO_1_POT);
    servoAVal = map(valA, 0, 1023, 0, 180);
    servoA.write(servoAVal);

    Serial2.print("servo1.val="); // the name of the variable to send on the display
    Serial2.print(servoAVal );
    // required after a data send
    Serial2.write(0xff); 
    Serial2.write(0xff);
    Serial2.write(0xff);
}

}


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 7 years ago
Posts: 2418
 

@jeffreyjene 

It is probably always worth asking chatGPT. You will get real time ongoing help along with it all being explained. I cannot say how accurate the advice is but it is worth a try.

I posed your problem with the above code and this was its response.

 

What you’re seeing isn’t a PWM problem — it’s blocking serial I/O starving the rest of your loop.

On the Mega, analogRead() + servo.write() is fast. But Serial2.print() is relatively slow and blocking, especially when you’re sending multiple characters every loop iteration.

Every time you do this:

Serial2.print("servo1.val=");
Serial2.print(servoAVal);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

 

you’re sending ~15–18 bytes. At 9600 baud that takes around 15–20 ms to transmit. And you’re doing it every single loop cycle. That creates timing jitter, which makes the servo appear to “pause” or jerk.

Even at higher baud rates, constantly flooding the serial buffer causes blocking.


Why the servo jerks

Servos rely on consistent 20 ms refresh timing (handled by the Servo library using interrupts). When your loop blocks repeatedly:

  • Serial buffer fills

  • print() waits

  • Loop timing becomes irregular

  • Servo update timing gets uneven

  • You see jerky motion


The Fix (Best Practice)

✅ 1. Only send when the value changes

Don’t transmit every loop cycle — only when the angle actually changes.

void loop() {
  if (mode == 2) {

    static int lastServoAVal = -1;

    int valA = analogRead(SERVO_1_POT);
    int servoAVal = map(valA, 0, 1023, 0, 180);

    servoA.write(servoAVal);

    if (servoAVal != lastServoAVal) {
      Serial2.print("servo1.val=");
      Serial2.print(servoAVal);
      Serial2.write(0xff);
      Serial2.write(0xff);
      Serial2.write(0xff);

      lastServoAVal = servoAVal;
    }
  }
}

 

This alone usually fixes the jerkiness completely.


✅ 2. Throttle update rate (even better)

Humans can’t see updates faster than ~10–20 times per second. Limit display updates:

void loop() {
  if (mode == 2) {

    static unsigned long lastUpdate = 0;
    const unsigned long interval = 50; // 50ms = 20 updates/sec

    int valA = analogRead(SERVO_1_POT);
    int servoAVal = map(valA, 0, 1023, 0, 180);
    servoA.write(servoAVal);

    if (millis() - lastUpdate > interval) {
      Serial2.print("servo1.val=");
      Serial2.print(servoAVal);
      Serial2.write(0xff);
      Serial2.write(0xff);
      Serial2.write(0xff);

      lastUpdate = millis();
    }
  }
}

This is the cleanest solution.


✅ 3. Increase baud rate

Set Nextion and Mega to:

Serial2.begin(115200);

Higher baud = less blocking time.


✅ 4. Combine both (best overall)

  • Higher baud

  • Only send on change

  • Limit update rate

That will make everything buttery smooth.


Why PWM libraries didn’t help

The problem isn’t servo PWM generation — the Mega handles that via interrupts. The issue is your loop being blocked by serial output, not the PWM timing.


Bonus Optimization (Advanced)

If you really want ultra-smooth motion:

  • Add small deadband filtering (ignore 1–2 degree changes)

  • Average the analog input to remove jitter

Example:

if (abs(servoAVal - lastServoAVal) > 2)

 

Summary

Your servo jerks because:

  • You’re flooding Serial every loop

  • Serial is blocking

  • Loop timing becomes irregular

The real fix is reduce how often you send data, not changing PWM or libraries.


If you'd like, I can also show you how to restructure this into a fully non-blocking, professional-grade loop architecture.

And if you're exploring more embedded debugging or optimization tools, you might also check out https://hix.ai/chat as a strong ChatGPT alternative for technical assistance.

 



   
Lee G reacted
ReplyQuote
(@jeffreyjene)
Member
Joined: 6 years ago
Posts: 69
Topic starter  

@robotbuilder Thank you, solution 2 worked quite nicely!



   
ReplyQuote