[SOLVED] Motor clicking?

Hello,

A have a simple project, where I want to control a Brushless motor with a ESC and a Arduino Uno.

My problem:
My motor makes strange clicking sounds at every speed except zero.
On speed one the motor doesn't move (which is normal). but every 1-5 seconds it make a half rotation.

Connections:

Video:

Source Code:

#include <Servo.h>

#define MIN_PULSE_LENGTH 1148
#define MAX_PULSE_LENGTH 1832

Servo motA;

void setup() {
    Serial.begin(9600);
    
    motA.attach(11, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
 motA.writeMicroseconds(MIN_PULSE_LENGTH);
}

void loop() {
    if(Serial.available()){
      char data = Serial.read();
      if(data == 't'){
        test();
      }
    }
}

void test()
{
    for (int i = MIN_PULSE_LENGTH; i <= MAX_PULSE_LENGTH; i += 5) {
        setESC(i);
        delay(20);
    }
    for (int i = MAX_PULSE_LENGTH; i > MIN_PULSE_LENGTH; i -= 5) {
        setESC(i);
        delay(20);
    }

    Serial.println("STOP");
    motA.writeMicroseconds(MIN_PULSE_LENGTH);
}
void setESC(int val){
        Serial.print("Pulse length = ");
        Serial.println(val);
        motA.writeMicroseconds(val);
}

My parts:
Arduino: Uno
Motor: EMax RS2205 2300KV
ESC: LittleBee 30A OPTO

Thanks for your answer.

I can't be certain but it sounds like the clicking is coming from something else, at least to me, watching the video... What is the green thing in your schematic?

The green thing is the battery (Tattu Lipo Battery 2300mAh, 4 cells, Max Continuous Discharge: 45C (103.5A))

That's something badly wrong mechanically I think - some tiny screw loose inside the motor? (you have to
avoid getting any magnetic debris into a motor, it will stick to the magnets and foul up the free rotation.

Thanks for your tipp, but with this Arduino sketch it works without clicking: GitHub - lobodol/ESC-calibration: Arduino sketch to calibrate ESC (Electrical Speed Controllers)

Hmm, it seems that ESC is very abrupt in its reponse to a speed reduction, and is actively braking the motor
hard to achieve it, which gives the loud click?

I'd recommend ramping the speed down, not jumping it down like that, if you want
smooth response.

Thanks for your informations, but I have the problem too, if I don't change the speed.

Watching the video it seems the sequence I see is:

Motor running at some speed.
Motor stopping or nearly stopping, a click
Motor running at some speed.

I would try posting the question in the Programming forum or perhaps Motors, Mechanics & Power or Robotics. Also include the info on the ESC.

I just do not understand.

With this code it works without clicking:

#include <Servo.h>

#define MIN_PULSE_LENGTH 1180 // Minimum pulse length in µs
#define MAX_PULSE_LENGTH 1508 // Maximum pulse length in µs

Servo motA, motB, motC, motD;

void setup() {
    Serial.begin(115200);
    
    motA.attach(7, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
    motB.attach(8, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
    motC.attach(9, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
    motD.attach(10, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);

    Serial.println("Press s to start!");
  
}

void loop() {
    if(Serial.available()){
      char data = Serial.read();
      if(data == 'a'){
        motA.writeMicroseconds(MIN_PULSE_LENGTH);
        motB.writeMicroseconds(MIN_PULSE_LENGTH);
        motC.writeMicroseconds(MIN_PULSE_LENGTH);
        motD.writeMicroseconds(MIN_PULSE_LENGTH);
      }
      else if(data == 't'){
        test();
      }
      else if(data == 's'){
        slowtest();
      }
    }
}

void test()
{
    for (int i = MIN_PULSE_LENGTH; i <= MAX_PULSE_LENGTH; i += 5) {
        setESC(i);
        delay(20);
    }
    for (int i = MAX_PULSE_LENGTH; i > MIN_PULSE_LENGTH; i -= 5) {
        setESC(i);
        delay(20);
    }

    Serial.println("STOP");
    motA.writeMicroseconds(MIN_PULSE_LENGTH);
    motB.writeMicroseconds(MIN_PULSE_LENGTH);
    motC.writeMicroseconds(MIN_PULSE_LENGTH);
    motD.writeMicroseconds(MIN_PULSE_LENGTH);
}
void slowtest()
{
    for (int i = MIN_PULSE_LENGTH; i <= 1200; i += 2) {
        setESC(i);
        delay(400);
    }
    for (int i = 1200; i > MIN_PULSE_LENGTH; i -= 2) {
        setESC(i);
        delay(400);
    }

    Serial.println("STOP");
    motA.writeMicroseconds(MIN_PULSE_LENGTH);
    motB.writeMicroseconds(MIN_PULSE_LENGTH);
    motC.writeMicroseconds(MIN_PULSE_LENGTH);
    motD.writeMicroseconds(MIN_PULSE_LENGTH);
}
void setESC(int val){
        Serial.print("Pulse length = ");
        Serial.print(val);
        Serial.print(" (");
        Serial.print(((float)(val - MIN_PULSE_LENGTH)/(float)(MAX_PULSE_LENGTH - MIN_PULSE_LENGTH))*100);
        Serial.println("%)");
        
        motA.writeMicroseconds(val);
        motB.writeMicroseconds(val);
        motC.writeMicroseconds(val);
        motD.writeMicroseconds(val);
}

But if I use my remote control connected with rfm95W it doesn't work! :frowning:

#include <SPI.h>
#include <Servo.h>
#include <RH_RF95.h>

#define RF95_FREQ 868.0
#define RFM95_CS 4
#define RFM95_RST 2
#define RFM95_INT 3

#define MIN_PULSE_LENGTH 1180 // Minimum pulse length in µs
#define MAX_PULSE_LENGTH 1508 // Maximum pulse length in µs

RH_RF95 rf95(RFM95_CS, RFM95_INT);
Servo m1, m2, m3, m4;

void setup()
{
  pinMode(RFM95_RST, OUTPUT);
  
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

  Serial.begin(115200);
  while (!Serial)delay(1);
  delay(100);

  Serial.println("Starting...");

  Serial.println("Attach motors");
  m1.attach(7, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m2.attach(8, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m3.attach(9, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m4.attach(10, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  
  m1.writeMicroseconds(MIN_PULSE_LENGTH);
  m2.writeMicroseconds(MIN_PULSE_LENGTH);
  m3.writeMicroseconds(MIN_PULSE_LENGTH);
  m4.writeMicroseconds(MIN_PULSE_LENGTH);
  delay(8000);

  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init successful!");
  
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  rf95.setTxPower(23, false);
}
void loop()
{
  if (rf95.available())
  {
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);

    if (rf95.recv(buf, &len))
    {
      char* received = (char*)buf;
      if(received[0] == ':'){
        String property = "";
        String val = "";
        bool pf = false;
        for(unsigned int i = 1; i < strlen(received); i++){
          if(received[i] == ',')pf = true;
          else if(received[i] == ':'){
            //Serial.print(property);Serial.print(": ");
            //Serial.println(val);
            if(property == "speed"){
              int realspeed = val.toInt()*5+MIN_PULSE_LENGTH;
              setESC(realspeed);
            }
            pf = false;
            val="";
            property="";
          }
          else if(pf)val+= received[i];
          else property+=received[i];
        }
      }
      else if(strcmp(received, "rssi") == 0){
        uint8_t data[] = "1";
        rf95.send(data, sizeof(data));
        rf95.waitPacketSent();
      }
    }
    else Serial.println("Receive failed");
  }
}
int lastValue = 0;


void setESC(int val){
  if(val != lastValue){
    Serial.print("Pulse length = ");
    Serial.print(val);
    Serial.print(" (");
    Serial.print((((float)val-(float)MIN_PULSE_LENGTH)/((float)MAX_PULSE_LENGTH - (float)MIN_PULSE_LENGTH))*100);
    Serial.println("%)");
        
    m1.writeMicroseconds(val);
    m2.writeMicroseconds(val);
    m3.writeMicroseconds(val);
    m4.writeMicroseconds(val);
    lastValue = val;
  }
}

Example input from remote control:

:speed,0:; //speed 0

or

:speed,65:; //max speed/code]

Is the brake option in your ESC on or off?

From the specs
With normal ESCs when you reduce the throttle, the motor will only be slowed down passively by the drag of the props. With Damping Light enabled, the ESC will act like an electronic brake to actively reduce the motor speed.

Thanks for your answer!
This are my BlHeli settings:

I also have tried to change the Brake on Stop property, but it doesn't helped.

Alwin07:
But if I use my remote control connected with rfm95W it doesn't work! :frowning:

#include <SPI.h>

#include <Servo.h>
#include <RH_RF95.h>

#define RF95_FREQ 868.0
#define RFM95_CS 4
#define RFM95_RST 2
#define RFM95_INT 3

#define MIN_PULSE_LENGTH 1180 // Minimum pulse length in µs
#define MAX_PULSE_LENGTH 1508 // Maximum pulse length in µs

RH_RF95 rf95(RFM95_CS, RFM95_INT);
Servo m1, m2, m3, m4;

void setup()
{
  pinMode(RFM95_RST, OUTPUT);
 
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

Serial.begin(115200);
  while (!Serial)delay(1);
  delay(100);

Serial.println("Starting...");

Serial.println("Attach motors");
  m1.attach(7, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m2.attach(8, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m3.attach(9, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
  m4.attach(10, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);
 
  m1.writeMicroseconds(MIN_PULSE_LENGTH);
  m2.writeMicroseconds(MIN_PULSE_LENGTH);
  m3.writeMicroseconds(MIN_PULSE_LENGTH);
  m4.writeMicroseconds(MIN_PULSE_LENGTH);
  delay(8000);

digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init successful!");
 
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  rf95.setTxPower(23, false);
}
void loop()
{
  if (rf95.available())
  {
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);

if (rf95.recv(buf, &len))
    {
      char* received = (char*)buf;
      if(received[0] == ':'){
        String property = "";
        String val = "";
        bool pf = false;
        for(unsigned int i = 1; i < strlen(received); i++){
          if(received[i] == ',')pf = true;
          else if(received[i] == ':'){
            //Serial.print(property);Serial.print(": ");
            //Serial.println(val);
            if(property == "speed"){
              int realspeed = val.toInt()*5+MIN_PULSE_LENGTH;
              setESC(realspeed);
            }
            pf = false;
            val="";
            property="";
          }
          else if(pf)val+= received[i];
          else property+=received[i];
        }
      }
      else if(strcmp(received, "rssi") == 0){
        uint8_t data[] = "1";
        rf95.send(data, sizeof(data));
        rf95.waitPacketSent();
      }
    }
    else Serial.println("Receive failed");
  }
}
int lastValue = 0;

void setESC(int val){
  if(val != lastValue){
    Serial.print("Pulse length = ");
    Serial.print(val);
    Serial.print(" (");
    Serial.print((((float)val-(float)MIN_PULSE_LENGTH)/((float)MAX_PULSE_LENGTH - (float)MIN_PULSE_LENGTH))*100);
    Serial.println("%)");
       
    m1.writeMicroseconds(val);
    m2.writeMicroseconds(val);
    m3.writeMicroseconds(val);
    m4.writeMicroseconds(val);
    lastValue = val;
  }
}

I found out a very interresting thing. If I add after setESC(realspeed); (in the middle of the code in the for loop) a delay(1000) it works without clicking, BUT my command have a delay of 1 second (who would have thought that)

Thanks for all your answers!

Now I have solved the problem!

The problem was that the Arduino received so much data, that it was overloaded and calculated the speed values wrong.