How to add a high/low switch to Brushless motors


I have built a Brushless motor powerwheels for my daughter which is very fast for a 5 year old, she is used to the speed (12mph) but her friends would like to drive it and I am concerned that it will be too fast for them and would like to add a switch to limit the top speed of the motors to around 50%.

i copied the Arduino code from the net and it works great but am a complete novice when it comes to changing/adding code.

Could someone with more knowledge tell me the code for adding a high/low switch and what pin for the output from the switch to run in low mode.

this is the code I used (sorry for the format) and the picture is the wiring diagram for the arduino

#include <Servo.h>
const byte servoPin = 9; // signal pin for the ESC.
const byte potentiometerPin = A0; // analog input pin for the power pedal.
int pwmVal; //Output value to ESC
int revOn = 0; //Value for reverse switch HIGH/LOW
const byte revPin = 13; //Pin for revers switch
Servo servo; //Servo object
void setup() {
pinMode(revPin, INPUT);
servo.attach(servoPin);
servo.writeMicroseconds(1500); // send "stop" signal to ESC. Also necessary to arm the ESC.
delay(7000); // delay to allow the ESC to recognize the stopped signal.
}
void loop() {
revOn = digitalRead(revPin); //Check state of reverse switch
int potVal = analogRead(potentiometerPin); // read input from potentiometer.
//If reverse switch is on HIGH set reverse PWM range
// 1500 means no accel
// < 1500 is reverse
// > 1500 is forward
if(revOn == HIGH)
{
pwmVal = map(potVal,200, 850, 1450, 1000); // maps potentiometer values to PWM value in reverse range
} else {
pwmVal = map(potVal,170, 850, 1550, 2000); // maps potentiometer values to PWM value in forward range
}
if (pwmVal < 1555 and pwmVal > 1460) //Use a range to buffer for error if accel pedal is not pressed
{
pwmVal = 1500;
}
servo.writeMicroseconds(pwmVal); // Send signal to ESC.
}

Re map pot.

The pot is an accelerator pedal on the car, I was hoping to have a switch I could wire into the car with a 5v output that I could plug into a pin on the arduino.
When the switch output is live the arduino only gives a 50% power to the esc and when it is open then the esc gives 100% power to the motors.

Use the IDE Auto Format tool on the sketch.

Then use the IDE Copy for Forum tool.

Come back here and paste into a new post, your code will look like code:

void setup() {

}

void loop() {

}

This is no doubt a trivial change once we can see the sketch.

a7

Thankyou Alto777

Hopefully this is the correct format

#include <Servo.h>
const byte servoPin = 9;           // signal pin for the ESC.
const byte potentiometerPin = A0;  // analog input pin for the power pedal.
int pwmVal;                        //Output value to ESC
int revOn = 0;                     //Value for reverse switch HIGH/LOW
const byte revPin = 13;            //Pin for revers switch
Servo servo;                       //Servo object
void setup() {
  pinMode(revPin, INPUT);
  servo.attach(servoPin);
  servo.writeMicroseconds(1500);  // send "stop" signal to ESC. Also necessary to arm the ESC.
  delay(7000);                    // delay to allow the ESC to recognize the stopped signal.
}
void loop() {
  revOn = digitalRead(revPin);                //Check state of reverse switch
  int potVal = analogRead(potentiometerPin);  // read input from potentiometer.
  //If reverse switch is on HIGH set reverse PWM range
  // 1500 means no accel
  // < 1500 is reverse
  // > 1500 is forward
  if (revOn == HIGH) {
    pwmVal = map(potVal, 200, 850, 1450, 1000);  // maps potentiometer values to PWM value in reverse range
  } else {
    pwmVal = map(potVal, 170, 850, 1550, 2000);  // maps potentiometer values to PWM value in forward range
  }
  if (pwmVal < 1555 and pwmVal > 1460)  //Use a range to buffer for error if accel pedal is not pressed
  {
    pwmVal = 1500;
  }
  servo.writeMicroseconds(pwmVal);  // Send signal to ESC.
}

OK, thanks.

It seems @bluejets took whatever trouble I refused to and spotted the solution area.

Here

    pwmVal = map(potVal, 200, 850, 1450, 1000); 

is one of two places that define the extent to which travel on the pot translate into motor speed.

So as is, 200 to 850 input go to 1450 to 1000 on the motor speed.

1000 is full speed in one direction, the other place we see 2000, full speed in the other.

A simple fix is to have a digital input which would select from two top speeds.

Literally, good enough for testing,

  if (digitalRead(speedLimiter))
    pwmVal = map(potVal, 200, 850, 1450, 1000);
  else
    pwmVal = map(potVal, 200, 850, 1450, 1250);

With the assumption of

const byte sppedLimiter = 7;  // or whatever pin you want

and in setup()

  pinMode(speedLimiter, INPUT_PULLUP);

Use the same pattern for the case where the motor is spinning in the other direction.

Experiment with the new higher limit. This can be simplified if we make it more complicated:

const int reduced = 200;

and

  if (digitalRead(speedLimiter))
    pwmVal = map(potVal, 200, 850, 1450, 1000);
  else
    pwmVal = map(potVal, 200, 850, 1450, 1000 + reduced);

If you do that both places, you can tinker by changing the manifest constant which is reduced, for which you are welcome to think of a better name.

I'm in transit, I hope that is enough to consider for now.

Lucky kids. :expressionless:

a7

1 Like

Thankyou so much a7 for such a comprehensive reply :+1:
I'll have a play with it later and see if I can get it working

NP.

Just to be sure, I've imagined a toggle switch on pin 7, other side to ground.

Switching it would switch speed limits.

A refinement woukd be to have the governed speed set by a second potentialometer, that can be in version two.

I do not recommend a pushbutton to switch between speed limits, not just because it's a bit more code, but because this should be fool proof and sorta secret. Kids are clever, so a good on/off switch hidden somewhere woukd work best.

a7

1 Like

On the Peg Perego models, the speed is a three position switch I think, reverse on a spring so driver actively holds in place to reverse, neutral (off), low and high speed, with a mechanical plastic linkage that must be moved aside after taking a screw out to allow it to move, so parents could limit the speed for younger kids.
Edit: it's been a while since pulling one of these apart, now that I think of it must have been three position with no neutral or off, it was always engaged in low or high speed and only the pedal was the actual switch to go, which is why my next post here became a concern.

Great project. If I may suggest, your design should include an emergency stop for your daughter right after the batteries, like an industrial "big red button" she could simply hit to stop. The kind that you then pop out to allow the batteries to connect.

It's common in these ride on mods, especially if you use the existing pedal, as voltage bumping may cause the accelerator to stick in the closed position.

Oh, one more thing: in your diagram, it shows 3 cell lipos for power, which is a great option for the price/ perfomance and also weight.
What are you using for voltage monitoring so the batteries don't discharge too low?
Do those ESCs do their own battery monitoring?
As you may be aware, discharging these too low can create a potential fire hazard, so for something your daughter is in, it's an important consideration.

Wait, there's a diagram? Single focus on software: I missed that.

It shows the cells in parallel, obvsly if it is 3s they are in series.

It calls the 18650 cells Lipo, LiPo, but 18650's are Li-Ion. Actually one of a number of different chemistries it seems.

@hallowed31 is absolutely correct to raise questions about the power source.

I'd add measuring each battery with an analog input, checked frequently and shut down well before you don't want to go past discharge levels.

And whatever the chemistry, I'd recommend learning more than you need to know, a good source is

These kinds of cells and batteries of them are great sources of power, and they must be treated with respect and used within specifications.

a7

1 Like

I took the unclear diagram at the words on top. I don't use that diagram program so maybe the 18650s are just the closest it has?
The 3s lipo on written on top I took to mean the type typically used in RC hobby, in parallel since I imagine the goal was a bigger gas tank and 6s bldc motors are less common. I figured OP was replacing the 12V brushed type that's typical in power wheels (although 24V versions do also exist).

Thanks again alto777
I have tried to add the data and come up with this, unfortunately I am at work and cannot test it in the car but it verified and I uploaded it to a spare Arduino I have, I also haven't added the switch yet but should be able to do that tomorrow.

Can you tell me if this is correct please, I am such a newbie but hoping to learn

#include <Servo.h>
const byte servoPin = 9;           // signal pin for the ESC.
const byte potentiometerPin = A0;  // analog input pin for the power pedal.
int pwmVal;                        //Output value to ESC
int revOn = 0;                     //Value for reverse switch HIGH/LOW
const byte revPin = 13;            //Pin for reverse switch
const byte speedLimiter = 7;       // Speedlimiter
Servo servo;                       //Servo object
void setup() {
  pinMode(revPin, INPUT);
  servo.attach(servoPin);
  servo.writeMicroseconds(1500);  // send "stop" signal to ESC. Also necessary to arm the ESC.
  delay(7000);                    // delay to allow the ESC to recognize the stopped signal.
  pinMode(speedLimiter, INPUT_PULLUP);
}
void loop() {
  revOn = digitalRead(revPin);                //Check state of reverse switch
  int potVal = analogRead(potentiometerPin);  // read input from potentiometer.
  //If reverse switch is on HIGH set reverse PWM range
  // 1500 means no accel
  // < 1500 is reverse
  // > 1500 is forward
  if (revOn == HIGH) {
    pwmVal = map(potVal, 200, 850, 1450, 1000);  // maps potentiometer values to PWM value in reverse range
  } else {
    pwmVal = map(potVal, 170, 850, 1550, 2000);  // maps potentiometer values to PWM value in forward range
  }
  if (pwmVal < 1555 and pwmVal > 1460)  //Use a range to buffer for error if accel pedal is not pressed
  {
    pwmVal = 1500;
  }
  if (digitalRead(speedLimiter))
    pwmVal = map(potVal, 200, 850, 1450, 1000);
  else
    pwmVal = map(potVal, 200, 850, 1450, 1250);
  servo.writeMicroseconds(pwmVal);  // Send signal to ESC.
}

I have a remote cut off built in and under the seat that shuts down the arduino and escs, daughter also has one in the car to turn the motors on.
Downside is it loses the braking from the motors when there is no power but she is very sensible for a 5 year old and listens to daddy lol

1 Like

:saluting_face:

Thankyou for your concern and I'm not brilliant with batteries but do know how dangerous lithium batteries can be if abused :+1:
The diagram isn't quite correct as it is the one I initially copied when I built the car.

My original plan was to use 2x 10ah lifepo batteries in parallel but the BMS kept cutting out due to current drain so I built my own 3s 42ah battery pack with built in BMS which can supply over 100a if needed. The car also has a voltage monitor set to alarm at 9.6v but it can do over 5 miles before it gets close to that voltage :joy:

You appear to have simply added the example statement after the code you had, and only one of the two I said or implied you would need, the one I wrote for one direction needs a symmetrical treatment for the other direction.

The statement was meant to replace one of the map calls, and to be used as a model for the other map call.

I was unclear, sry. I was expecting that you might have read through the code a bit.

So. This in your original

  if (revOn == HIGH) {
    pwmVal = map(potVal, 200, 850, 1450, 1000);  // maps potentiometer values to PWM value in reverse range
  } else {
    pwmVal = map(potVal, 170, 850, 1550, 2000);  // maps potentiometer values to PWM value in forward range
  }

Should be replaced by

  if (revOn == HIGH) {
    if (digitalRead(speedLimiter))
      pwmVal = map(potVal, 200, 850, 1450, 1000);
    else
      pwmVal = map(potVal, 200, 850, 1450, 1000 + reduced);
  }
  else {
    if (digitalRead(speedLimiter))
      pwmVal = map(potVal, 200, 850, 1550, 2000);
    else
      pwmVal = map(potVal, 200, 850, 1550, 2000 - reduced);
  }

This cuts the top speeds by drawing in the range from 1000 to 2000 to, for example, 1150 to 1850 (*reduced* = 150) so the max speed in one direction is at the PWM value is 1150, slower than 1000, and in the other direction 1850, slower than 2000.

Add the manifest constant reduced:

const byte speedLimiter = 7;       // Speedlimiter input pin
const int reduced = 150;    // speed reduction, larger means slower forward and reverse

I can't test it. Just @ me if it doesn't work and isn't something you can spot.

a7

1 Like

Nice, any build tips for such a battery? Pics? This sounds like a very interesting project (you've gone a lot further with modding a Power Wheels than I did).
What was the base PW model? Did you use the original plastic gearboxes and plastic wheels to allow for wheel spin, reducing stress on the plastic gears?
What motors, specifically, did you use, what ESCs?
My kids have outgrown PW size but I'd still be interested in some more of the details, if you don't mind sharing them.

Have you considered adding protection vs neighborhood boys with nefarious intent, jealous of your daughter's wheels? Way i see it, such a ride should include protection as your daughter drives the Fury Road.

Consider the following (voltage bumps to 12V nicely with no need to rewire, just remove all the safety switches, wire in a couple steering wheel mounted switches (auto/manual mode switch, manual mode fire switch), a couple of ultrasonic sensors, perhaps). Of all the Nerf blasters I've considered for a turret (all of them up until they made this gem), there simply is no substitute for the Prometheus.

Thankyou again Alto, I have never programmed in my life and if honest it's like a foreign language. I'm trying to learn the very basic concept of it though. I'll try this later[quote="alto777, post:18, topic:1283402, full:true"]

You appear to have simply added the example statement after the code you had, and only one of the two I said or implied you would need, the one I wrote for one direction needs a symmetrical treatment for the other direction.

The statement was meant to replace one of the map calls, and to be used as a model for the other map call.

I was unclear, sry. I was expecting that you might have read through the code a bit.

So. This in your original

  if (revOn == HIGH) {
    pwmVal = map(potVal, 200, 850, 1450, 1000);  // maps potentiometer values to PWM value in reverse range
  } else {
    pwmVal = map(potVal, 170, 850, 1550, 2000);  // maps potentiometer values to PWM value in forward range
  }

Should be replaced by

  if (revOn == HIGH) {
    if (digitalRead(speedLimiter))
      pwmVal = map(potVal, 200, 850, 1450, 1000);
    else
      pwmVal = map(potVal, 200, 850, 1450, 1000 + reduced);
  }
  else {
    if (digitalRead(speedLimiter))
      pwmVal = map(potVal, 200, 850, 1550, 2000);
    else
      pwmVal = map(potVal, 200, 850, 1550, 2000 - reduced);
  }

This cuts the top speeds by drawing in the range from 1000 to 2000 to, for example, 1150 to 1850 (*reduced* = 150) so the max speed in one direction is at the PWM value is 1150, slower than 1000, and in the other direction 1850, slower than 2000.

Add the manifest constant reduced:

const byte speedLimiter = 7;       // Speedlimiter input pin
const int reduced = 150;    // speed reduction, larger means slower forward and reverse

I can't test it. Just @ me if it doesn't work and isn't something you can spot.

a7
[/quote]