Arduino stuck if servo can't turn

Working on an RC car Ursa (bear) - Fully printable Monster Truck by tahustvedt - Thingiverse . I'm using Arduino MEGA2650 + BTS7960 motor ESC + MG90S servo for steering. Arduino and ESC are powered directly from 12 volts li-ion battery, and the servo is powered via 12->5volts coverter I took from car lighter charger. Whole thing is working okay, but if something is blocking front wheels from turning to specified angle - arduino just freeses. When I pick up the car - wheels are turning to "requested" position and everything is working again.

I assume that arduino waits for servo to turn to requested angle before continuing. Is there any software way to make it keep working without waiting servo to turn?

All voltages are good - I checked.

Probably not, but a glance at the code would allow you to determine that for certain.

Much more likely you have a power supply problem, which shows up when the servo is stalled.

For help on this forum, please read and follow the instructions in the "How to get the best out of this forum" post, linked at the head of every forum category.

1 Like

How much CURRENT can the converter produce? A stalled servo could draw 2 Amps or more.

Nothing much there:


#include <Servo.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//NRF24L01 VCC ………………………………………… 3.3V of STM32F103C
//NRF24L01 CSN ………………………………………… PA4 of STM32F103C
//NRF24L01 MOSI ………………………………………… PA7 of STM32F103C
//NRF24L01 GND ………………………………………… GND of STM32F103C
//NRF24L01 CE ………………………………………… PB0 of STM32F103C
//NRF24L01 SCK ………………………………………… PA5 of STM32F103C
//NRF24L01 MISO ………………………………………… PA6 of STM32F103C

#define reverselights 4
#define headlights 5
#define stoplights 6
#define servomotor 9
#define goFWD 10
#define goBCK 11
#define honker 12
#define horisontal 13
#define leftturnsig 3
#define rightturnsig 2


bool emerlightsenable = false;
bool leftlightsenable = false;
bool rightlightsenable = false;
int triggertime = 500;
long currmillis = 0;
bool emerlights = false;
bool leftlights = false;
bool rightlights = false;

byte fwdthrottle = 0;
byte revthrottle = 0;
byte stterangle = 0;
byte frwrdthrottle = 0;
byte revrsthrottle = 0;

bool headlightON = false;
int steerangle = 110;

struct Signal {
  byte leftx = 0;
  byte lefty = 0;
  byte rightx = 0;
  byte righty = 0;
  byte btn1 = 0;
  byte btn2 = 0;
  byte btn3 = 0;
  byte btn4 = 0;
  byte btn5 = 0;
  byte btn6 = 0;
  byte btn7 = 0;
  byte btn8 = 0;
  byte vari = 0;
};


Servo steering;
Servo hor;
Signal data;
const uint64_t pipeIn = 0xE9E8F0F0E1LL;
RF24 radio(7, 8); // CE, CSN   

byte stopbrightness = 0;

void ResetData()
{
  data.leftx = 127;
  data.lefty = 0;
  data.rightx = 0;
  data.righty = 127;
  data.btn1 = 0;
  data.btn2 = 0;
  data.btn3 = 0;
  data.btn4 = 0;
  data.btn5 = 0;
  data.btn6 = 0;
  data.btn7 = 0;
  data.btn8 = 0;
  data.vari = 0;
}

void debug()
{
  char buffer[250];

  sprintf(buffer, "Steering: %d, Gas: %d, Reverse: %d, Buttons: %d, %d, %d, %d, %d, %d", stterangle, fwdthrottle, revthrottle, data.btn1, data.btn2, data.btn3, data.btn4, data.btn5, data.btn6);
  Serial.println(buffer);
}

void setup()
{
  steering.attach(servomotor);
  hor.attach(horisontal);
  Serial.begin(9600);
  ResetData();
  radio.begin();
  radio.openReadingPipe(1,pipeIn);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_HIGH);
  radio.startListening();
  steering.write(130);
  analogWrite(stoplights, stopbrightness);
  ResetData();
  radio.read(&data, sizeof(Signal));
  ResetData();
}

unsigned long lastRecvTime = 0;

void recvData()
{
  while ( radio.available() ) {
    radio.read(&data, sizeof(Signal));
    lastRecvTime = millis();   // receive the data | data alınıyor

  }
}


void loop()
{
  //int starttime = millis();
  recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 1000 ) {
    ResetData(); // Signal lost.. Reset data | Sinyal kayıpsa data resetleniyor
  }

#pragma region //Processing joystick's right Y axis(gas)
  if(data.righty > 130)
  {
    frwrdthrottle = map(data.righty, 127, 255, 0, 255);
  }
  else if(data.righty < 120)
  {
    revrsthrottle = map(data.righty, 127, 0, 0, 255);
  }
  else
  {
    frwrdthrottle = 0; revrsthrottle = 0;
  }
#pragma endregion
#pragma region //Emergency lights
  if(data.btn4 == 1)
  {
    delay(200);
    if(emerlightsenable == false)
    {
      emerlightsenable = true;
      analogWrite(leftturnsig, 100);
      analogWrite(rightturnsig, 100);
    }
    else
    {
      emerlightsenable = false;
      analogWrite(leftturnsig, 0);
      analogWrite(rightturnsig, 0);
    }
    currmillis = 0;
  }
  if(emerlightsenable == true)
  {
    if(millis() - currmillis > 500)
    {
      emerlights = !emerlights;
      if(emerlights)
      {
        analogWrite(leftturnsig, 100);
        analogWrite(rightturnsig, 100);
      }
      else 
      {
        analogWrite(leftturnsig, 0);
        analogWrite(rightturnsig, 0);
      }
      currmillis = millis();
    }
  }
#pragma endregion
#pragma region //Left turn lights
  if(data.btn2 == 1)
  {
    delay(200);
    if(leftlightsenable == false)
    {
      leftlightsenable = true;
      analogWrite(leftturnsig, 100);
    }
    else
    {
      leftlightsenable = false;
      analogWrite(leftturnsig, 0);
    }
    currmillis = 0;
  }
  if(leftlightsenable == true)
  {
    if(millis() - currmillis > 500)
    {
      leftlights = !leftlights;
      if(leftlights)
      {
        analogWrite(leftturnsig, 100);
      }
      else 
      {
        analogWrite(leftturnsig, 0);
      }
      currmillis = millis();
    }
  }
#pragma endregion
#pragma region //Right turn lights
  if(data.btn3 == 1)
  {
    delay(200);
    if(rightlightsenable == false)
    {
      rightlightsenable = true;
      analogWrite(rightturnsig, 100);
    }
    else
    {
      rightlightsenable = false;
      analogWrite(rightturnsig, 0);
    }
    currmillis = 0;
  }
  if(rightlightsenable == true)
  {
    if(millis() - currmillis > 500)
    {
      rightlights = !rightlights;
      if(rightlights)
      {
        analogWrite(rightturnsig, 100);
      }
      else 
      {
        analogWrite(rightturnsig, 0);
      }
      currmillis = millis();
    }
  }
#pragma endregion
#pragma region //Honker check
  if(data.btn6 == 1)
  {
    tone(honker, 300);
  }
  else 
  {
    noTone(honker);
  }
#pragma endregion
#pragma region //Headlights switch
  if(data.btn1 == 1)
  {
    headlightON = !headlightON;
    delay(200);
  }

  if(headlightON)
  {
    analogWrite(headlights, 220);
    stopbrightness = 5;
  }
  else{
    analogWrite(headlights, 0);
    stopbrightness = 0;
  }
#pragma endregion
#pragma region //Steering
  stterangle = map(data.leftx, 0,255,0,120);
  steering.write(stterangle);
#pragma endregion
#pragma region ///Processing smooth gas
  if(frwrdthrottle > fwdthrottle)
  {
    fwdthrottle++;
    delay(2);
  }
  else if(frwrdthrottle < fwdthrottle)
  {
    fwdthrottle--;
    delay(2);
  }
  else if(frwrdthrottle == fwdthrottle)
  {
    fwdthrottle = frwrdthrottle;
  }

  if(revrsthrottle > revthrottle)
  {
    revthrottle++;
    delay(2);
  }
  else if(revrsthrottle < revthrottle)
  {
    revthrottle--;
    delay(2);
  }
  else if(revrsthrottle == revthrottle)
  {
    revthrottle = revrsthrottle;
  }
  analogWrite(goBCK, revthrottle);
  analogWrite(goFWD, fwdthrottle);
#pragma endregion
#pragma region //Stoplights setup

  if((frwrdthrottle + revrsthrottle != 0))
  {
    analogWrite(stoplights, stopbrightness);
  }
  else
  {
    analogWrite(stoplights, stopbrightness + 100);
  }
#pragma endregion
#pragma region //Reverse lights control
  if(revrsthrottle > frwrdthrottle)
  {
    analogWrite(reverselights, 200);
  }
  else
  {
    analogWrite(reverselights, 0);
  }
#pragma endregion
  //debug();
  //int thistime = millis() - starttime;
  //Serial.print("loop takes "); Serial.print(thistime); Serial.println(" milliseconds");
}

Label says 2A. But it's not overcurrent because then there should be a big voltage drop

UPD: info from datasheet of MG90s servo:

Current (idle) 10mA (typical)
Current (typical during movement) 120-250mA
Current (stall) 700mA (measured)

Try using

unsigned long currmillis;

Maybe not a cure but you will need it in the long run.

I see nothing in the code that waits for a servo to get into position. That sort of thing is rare as it requires the servo to be able to report its position, and the vast majority of servos can not do that.

So I think we have ruled out this as a software problem, so it is down to the hardware and wiring. Can you give us some more information about what you actually have, like schematics, photos and links to the components you are using.

For example:-

That is very unlikely to be a very efficient converter, probably just a couple of high wattage resistors. I suspect this arrangement is causing you problems. It is best to get a correctly rated switch mode converter. Such as those here:-
Step up / down buck boost regulator

Noted!

It's a bulk converter

Thanks for the pictures.

Do you mean a buck converter?

Looks a bit shot to me. It is possible that it can't supply enough current to turn the wheels. Are you running on carpet? If so give it a try on a solid smooth surface.

Right, buck converter.

on smooth floor it runs fine. But if I hit an obstacle with front wheels - servo is forced to turn a little - and arduino freeses. If I'm stuck on an obstacle and accidentally turned the wheels using joystick - it freeses

As there is nothing in code that indicates a wait for the servo to move into position then I have to conclude it is the hardware. Sorry I am now out of alternative ideas.

You can always use serial print statements to see where your code is at any one time, and see where the code is when it stops.

I notice you use byte variables and a byte is signed so it will only hold a maximum of +127, it could be you are asking more than this value and so getting a negative number. If this is the case try changing the byte type to a char type.

Actually, does servo talks back to arduino? I took a look at Servo.h and it's doing something with interrupts:

void Servo::write(int value)
{
  if(value < MIN_PULSE_WIDTH)
  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
    if(value < 0) value = 0;
    if(value > 180) value = 180;
    value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());
  }
  this->writeMicroseconds(value);
}

void Servo::writeMicroseconds(int value)
{
  // calculate and store the values for the given channel
  byte channel = this->servoIndex;
  if( (channel < MAX_SERVOS) )   // ensure channel is valid
  {
    if( value < SERVO_MIN() )          // ensure pulse width is valid
      value = SERVO_MIN();
    else if( value > SERVO_MAX() )
      value = SERVO_MAX();

    value = value - TRIM_DURATION;
    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

    uint8_t oldSREG = SREG;
    cli();
    servos[channel].ticks = value;
    SREG = oldSREG;
  }
}

No. "A byte stores an 8-bit unsigned number, from 0 to 255." https://docs.arduino.cc/language-reference/en/variables/data-types/byte/

Yes but it is just setting the limits on what values can be sent. It is not receiving anything from the servo.

However the documentation shows no compatibility with the STM32F103C you seem to be using.

https://docs.arduino.cc/libraries/servo/#Compatibility

Hi, @LITTLEFisky

How do you know the Mega freezes?

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Do you have a DMM? Digital MultiMeter?

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

STM32?

It stops receiving data from NRF24 module, and if turn signals on - they just stop blinking

The code in post #4 and photos with diagram at post #7

Hi, @LITTLEFisky

What about a schematic?
It would help.

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

All those commented out reference to that processor in your code. Why did you put them there?

I didn't see any diagrams in post #7 , just three photographs.

Oh, sorry, I missed that one

In the beginning this truck was based on STM32, but I have accidentally burned it. I left these lines just in case I'll switch back to stm

Sorry not a cut and paste.
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Use a pen(cil), ruler and paper please.

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

It is not hard to tell why you burned them from that physical layout. You have NO current limiting resistors fitted to those LEDs. That will damage any processor along with the LEDs. In the case of an STM32 the pins are not as robust as the Mega so the damage occurred quite quickly. With the Mega the damage will only be apparent after time but rest assured it is being damaged with that wiring leaving out the current limiting resistors there value is not critical. Try values of resistor between 240Ω and 510Ω.