I build a servo-tester using an ATMega328 (the programmer is Arduino as ISP). The space between each pulse is varying (2 x 20 mSec, then 1 x 28 mSec, and so on, on the oscilloscope). Is there a bug in the Servo library ? I use the port 8,(pin 14 / PB0). I only use the myservo1.writeMicroseconds(valeurDisplay);
(The pulse width works correctly, it is controlled by a potentiometer.)
Any idea ?
Thanks for your help
Show a schematic of your project, even if freehand;
Using the recommended tags, post your code.
1 Like
Please find here the usefull code. In the other parts of the software (e.g. the setup), I don't use the registers directly.
void ServoTester()
{
do {
// digitalWrite( 3, !digitalRead(3) ); // Pin 5 for oscilloscope
oled.setFont(SmallFont);
oled.print("Digital Servo Tester", 2, 1 );
// Reading the potentiometer and conversion for the screen
adc = analogRead(A0) ; // potentiometer read
valeurBarGraph = map(adc, 0, 1023, 1, 126); // position sur le bargraphe
valeurDisplay = map(adc, 0, 1023, 1000, 2000); // defines the numerical value displayed
myservo1.writeMicroseconds(valeurDisplay);
/*
Serial.print( "valeur Pot: "); Serial.print( adc);
Serial.print( " valeurBarGraph: "); Serial.print( valeurBarGraph);
Serial.print( " valeurDisplay: "); Serial.println( valeurDisplay);
*/
// Draw tags on the screen at 1250, 1500, and 1750 microseconds
oled.setPixel( 32, 17 );
oled.setPixel( 63, 17 );
oled.setPixel( 94, 17 );
oled.setPixel( 32, 24 );
oled.setPixel( 63, 24 );
oled.setPixel( 94, 24 );
// Display the servo bargraphe
oled.drawRect( 0, 16, 127, 25 ); // Draw the bargraph frame
oled.drawLine( valeurBarGraph, 16 , valeurBarGraph, 25 ); // Draw the vertical line
// Display the numerical pulse value
oled.setFont(BigNumbers);
pulse = map(ReadA0, 0, 1023, 1000, 2000 );
oled.printNumI( valeurDisplay, 35, 35 , 4 );
// Display the unit
oled.setFont(SmallFont);
oled.print( "uS", 95, 52 );
oled.update(); // Renew the display
oled.clrScr();
//delay(50);
} while ( digitalRead(ButtonESC) );
}
Servo Tester Digital Scheme.pdf (46.3 KB)
I have to write that the intervalls between the pulse is 2 x 20 mSec, then 1 x 28 mSec, and 2 x 20 mSec, then 1 x 28 mSec again forever. It seems that the 2 x 20 mSec can be 3 x 20mSec, or 4x 20 mSec or more. I cannot find this varies.
Thanks for your help.
Please post all of the code!
Here is the code. a large part is useless. . . .
Servo_Tester_Digital.zip (14.1 KB)
Thanks
Please, in the IDE, press ctrl-T, then shft-ctrl-C.
Then, in a new message response to this thread, press ctrl-V.
That pastes your entire code, so that we may inspect/export to our IDE, etc. with confidence.
Thanks
// Testeur de servos digital 1 voie
// The aim of this tester is to check a servo operation
// The pulse is displayed on the OLED SSD1306 128x64-B/W screen
// Author : Olivier CROISET - May-2025 : olivier.croiset@wanadoo.fr
// uProcessor : ATMega328 - Xtal 16 MHz, about 160 lines, 10 kbyte FlashRom, 510 bytes Ram
// Serial port : 57600 Bds for development
#include <Streaming.h>
#include <EEPROM.h> // used to save the setting values
#include "OLED_I2C.h" // I2C library for SSD1306 screen that allows to choose the SDA/SCL ports pins
#define SDA_pin A4 // pin 27 // can be changed
#define SCL_pin A5 // pin 28 // can be changed
#define ButtonESC 2 // pin 4
OLED oled(SDA_pin, SCL_pin);
extern uint8_t SmallFont[];
extern uint8_t BigNumbers[];
int adc; // valeur lue sur le potentiometre
float valeurDisplay; // numerical value 1000..2000 uS
float valeurBarGraph; // position on the bargaph : 0..100 for the stack mode display
int analogReadVoltage; // voltage value read on the port A4 through the 1/3 divider
float VoltageValue; // voltage value in Volts
#include <Servo.h>
Servo myservo1;
float ReadA0;
int pulse;
// ESC settings values saved in EEPROM
byte brake;
byte batt;
byte cutoff ;
byte threshold;
byte Start;
byte timing;
/////////////////////////////////////////////////////////////////////////
//Setup routine
/////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(57600);
delay(200);
Serial.println("Digital Servo Tester");
oled.begin(SSD1306_128X64);
oled.rotateDisplay(false);
// Refer to the datasheet for the resistor calculation !
analogReference(DEFAULT); // Reference = 5.0 Volts for the Vcc measurement
pinMode(A0, INPUT); // Pin 23 Potentiometer input
// pinMode(A1, INPUT);
// Create the servos output
pinMode(8, OUTPUT); // Pin 14 output servo port
myservo1.attach(8); // Pin 14 output for servo
SplashScreen();
oled.clrScr();
oled.update();
Serial.println("Setup 3");
oled.print("uS", 110, 50 );
Serial.print("Fin du setup");
pinMode(3, OUTPUT); // Pin 5 for oscilloscope
pinMode(ButtonESC, INPUT_PULLUP); // Pin 4 for ESC calibration
} // Setup
//////////////////////////////////////////////////////////////////////////
// Loop
//////////////////////////////////////////////////////////////////////////
void loop()
{
MainMenu();
} // Loop
void SplashScreen()
{
// while (analogRead(A0) < 50) { ScreenCentering(); } // Uncomment for housing machining
oled.clrScr();
oled.drawRect( 0, 0, 127, 63);
oled.setFont(SmallFont);
oled.print("Digital Servo tester", 5, 15 );
oled.print("Rev.: 1.0 May 2025", 8, 35 );
oled.print("Author : O. CROISET", 8, 45 );
oled.update();
delay(2000);
oled.clrScr();
oled.update();
}
void ScreenCentering()
// display a white rectangle to center mechanically the screen in the housing
{
oled.setFont(SmallFont);
oled.clrScr();
oled.drawRect( 0, 0, 127, 63);
oled.print("> CENTERING SCREEN <", CENTER, 10);
oled.print("Turn the ", 10, 25);
oled.print("potentiometer ", 10, 35);
oled.print("to middle position", 10, 45);
oled.update();
}
void TogglePin(byte port) // Toggle the port
{
digitalWrite(port, !digitalRead(port));
}
So, you’re doing an analog read, mapping that to a servo us, and writing that. No big deal there.
I’d suggest that something is delaying your timer1 interrupt, which is what Servo.h is using for the servo pulse train. So, we need to see what that might be. Since the loop() code just calls a function, and that function has not been provided, I’m out.
croiset:
Any idea ?
One idea is to post ALL the code.
Let me guess, all tabs in your IDE? Yeah, I separate bigger projects similarly, but it’s a pain to interact on the forum with code structured that way. Sorry to be a pain, but you could facilitate that by posting it as a single .zip file? That way, we can unzip it locally.
Second zip file . . . .
Servo_Tester_Digital.zip (14.0 KB)
1 Like
Apologies, I looked but obviously scrolled past it. Will look after dinner.
I send the file :
ServoTest.ino (1.5 KB)
and the zip files of ALL the tabs 2 times :
Servo_Tester_Digital.zip (14.0 KB)
Thanks for your help.
no, I meant “Thanks, I got it now, I’ll look at it after dinner”. Which is still pending.
xfpd
July 20, 2025, 4:48pm
17
@croiset
For future reference when faced with posting "all those tabs" versus a zip file... using Wokwi.com simulation allows all the tabs and most (probably all) of the hardware. Wokwi is also a trusted link, allows "live" editing, immediate testing, and is used by many here. Just an idea.
1 Like
Hi,
I solved the issue by removing the noInterrupts()
and Interrupts()
in the file HW_AVR.h, in the function OLED::update().
Sorry for the disturbance.
Regards.
1 Like