Servo Motor too fast

Hi,

I made a code to control a servo motor with Alexa. The Alexa part is ok. In fact it's all working fine but the servo motor is too fast.

This device is to control a ham radio memory knob. I can change the frequency of the radio with voice command and it's ok. But If the knob is at position (4) when I tell alexa to put it back to position (zero), the servo turn too fast and the rotary knob of the radio is skipping a frequency and the zero become position one. If I returne two position at the time, it's ok.

You can see my device if you follow the link below to my youtube.
[https://youtu.be/SxJI0r4N_qk?si=xGXmCZ6jdj0-3h0C]

You wont see the bug in the video because I'm returning to position Zero 2 positions at the time. The video is only to show you the device in action.

This is my code,

Is it possible to make the servo slower ?

/*
 *********************************************************************************
 *  Download the libraries:
 *  Espalexa Library: https://github.com/Aircoookie/Espalexa
 *  AceButton Library: https://github.com/bxparks/AceButton  
 *********************************************************************************
 *
 */

#include <WiFi.h>
#include <Espalexa.h>
Espalexa espalexa;
#include <ESP32Servo.h>

//OLED
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for SSD1306 display connected using I2C
#define OLED_RESET -1  // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Servo myServo;
int inputAngle = 0;

#define wifiLed 14
boolean connectWifi();

// WiFi Credentials
const char* ssid = "MyRooterName";
const char* password = "The Password";

// device names will be recognize by Alexa
String Device_1_Name = "Repeater";

//callback functions
void Device_1(uint8_t setU1);
int u1Value;
boolean wifiConnected = false;
unsigned long previousMillis_1;

//***********************************SETUP BEGIN
void setup(){
  
  Serial.begin(9600);

  myServo.attach(18);
  //myServo.write(angle);
  
  pinMode(wifiLed, OUTPUT);

  //Make the LED flashing while waiting for the Radio to be ON
  digitalWrite(wifiLed, LOW);
  delay(200);
  digitalWrite(wifiLed, HIGH);
  delay(400);
  digitalWrite(wifiLed, LOW);
  delay(200);
  digitalWrite(wifiLed, HIGH);
  delay(400);
  digitalWrite(wifiLed, LOW);
  delay(200);
  digitalWrite(wifiLed, HIGH);
  delay(400);
  digitalWrite(wifiLed, LOW);

  // initialize the OLED object
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
  {Serial.println(F("SSD1306 allocation failed"));
    for (;;)
    ;
  }
  display.clearDisplay();
  // Display Text
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(5, 0);
  display.println("CrossBand");
  display.setCursor(22, 20);
  display.println("VE2IBN");
  display.setCursor(5, 40);
  display.println("version 9");
  display.display();
  delay(4000);
  display.clearDisplay();

  // Initialise wifi connection
  wifiConnected = connectWifi();
  if (wifiConnected){addDevices();}
  else{Serial.println("Cannot connect to WiFi. So in Manual Mode");
  delay(1000);}
  
}//***********************************SETUP END

//connect to wifi  returns true if successful or false if not
  boolean connectWifi(){
  boolean state = true;
  int i = 0;
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");

  //Wait for connection
  Serial.print("Connecting...");
  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
  if (i > 20) {
      state = false; break;}
    i++;}
  Serial.println("");
  if (state) {
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());}
  else {Serial.println("Connection failed.");}
  return state;
}

void addDevices(){// Define your devices here for Alexa.
  
  espalexa.addDevice(Device_1_Name, Device_1);
  espalexa.begin();
}

void Device_1(uint8_t setU1){ 

  if (setU1 > 0){u1Value = (map(setU1, 0, 254, 0, 100) -1);}
} 

void servoControlStep(){

  myServo.write(inputAngle);

  if ((u1Value >=0) && (u1Value <=4)){inputAngle = 70;}
  if ((u1Value >=6) && (u1Value <=14)){inputAngle = 60;}
  if ((u1Value >=16) && (u1Value <=24)){inputAngle = 50;}
  if ((u1Value >=26) && (u1Value <=34)){inputAngle = 40;}
  if ((u1Value >=36) && (u1Value <=44)){inputAngle = 30;}
  if ((u1Value >=46) && (u1Value <=54)){inputAngle = 20;}
  if ((u1Value >=56) && (u1Value <=64)){inputAngle = 10;}
}

void timer_print(){//Serial print Data every 2 seconds

  unsigned long currentMillis_1 = millis(); 
  if (currentMillis_1 - previousMillis_1 >= 2000){
  printData();
  previousMillis_1 = currentMillis_1;
 }
}

void printData(){//for debug

  Serial.print("u1Value: ");Serial.println(u1Value);
  Serial.print("inputAngle: ");Serial.println(inputAngle);
}

void OledPrint(){

  if (u1Value == 0){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 00");}
  if (u1Value == 10){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 10");}
  if (u1Value == 20){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 20");}
  if (u1Value == 30){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 30");}
  if (u1Value == 40){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 40");}
  if (u1Value == 50){display.setTextSize(2);display.setCursor(2, 45);display.print("Memory: 50");}
}

void loop(){

servoControlStep();
timer_print();
OledPrint();

//**************************************Section for Wi-fi connect
   if (WiFi.status() != WL_CONNECTED){digitalWrite(wifiLed, LOW);}
    else{digitalWrite(wifiLed, HIGH);  
   if (wifiConnected){espalexa.loop();
   delay(1);}
   else {wifiConnected = connectWifi();
   if(wifiConnected){addDevices();}
   }  
  display.setTextSize(1);display.setCursor(35, 0);display.println("Connected");
  display.setTextSize(1);display.setCursor(25, 20);display.println(WiFi.localIP());
  display.display();
  display.clearDisplay();
  }
}

Hello! @hddforensic. You could try to implement this library into your code.
https://github.com/netlabtoolkit/VarSpeedServo

Did you look at the Servo Library's Sweep example?

The trick to controlled servo motion is to move the servo small amounts per unit time.

1 Like

Hi, I will try it. The library I'm using right now is specific to ESP32. (ESP32Servo) I will do some test to see if your suggestion is ok with an ESP32.

Hi, I just tried the library and it<s impossible to compile for ESP32.

Since this code is working with a library made for ESP32, I don't think another library will do the trick.

I need to find a way with "millis" or something like that but I don't know how.

Have you looked at the examples for the ESP32 servo?

Tom.. :smiley: :+1: :coffee: :australia:

1 Like

Putting a delay in like so might work?...

void servoControlStep(){
  
  delay(8); //Only write to servo every 8 millis

  myServo.write(inputAngle);

  if ((u1Value >=0) && (u1Value <=4)){inputAngle = 70;}
  if ((u1Value >=6) && (u1Value <=14)){inputAngle = 60;}
  if ((u1Value >=16) && (u1Value <=24)){inputAngle = 50;}
  if ((u1Value >=26) && (u1Value <=34)){inputAngle = 40;}
  if ((u1Value >=36) && (u1Value <=44)){inputAngle = 30;}
  if ((u1Value >=46) && (u1Value <=54)){inputAngle = 20;}
  if ((u1Value >=56) && (u1Value <=64)){inputAngle = 10;}
}

So long as it doesn't interfere with your wifi connections.

I will try that but with millis instead of delay.

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