Tuesday, 10 March 2020

DIY-EV

The project is to build a DIY EV from scratch. Idea is to have a four-wheeled skid-steered small electric vehicle with sufficient load bearing / load pulling capacity. I will provide costs for all components used in the project.

What will the final product look like? Some thing like this -->
[This vehicle is upside down in this image].

What are the components used?

12V Brushed DC Motor + Planetary gears (2x) -- 118RPM
12V Brushed DC Motor + Planetary gears + encoders (2x) -- 118RPM
4" / 10cm plastic wheels + rubber tires (4x)
Arduino mini - 1
10A Dual motor controller (30A Peak draw) - 1
All nuts / bolts and screws were purchased from Home Depot (all screws were 6-32, and either 1" or 3/4").

I used a handheld vice drill (Amazon - ~25CAD) for drilling holes into nylon board.


Friday, 22 September 2017

Resolving Issues with Forward and Reverse Runs

In the previous post, I had mentioned how the shift from forward to reverse and vice versa was quite unpredictable with an undocumented ESC. Using a series of empirically determined instructions, I had managed to make the motor run both in forward and reverse - but strictly according to a predefined series of instructions. Whenever we changed the series of instructions, the shift from forward to reverse [or vice versa] would not happen.

Here, I present an improvement upon that code: one that takes a Serial Input - and then acts on it. In my rover, I was able to make the motor run either in forward or in reverse according to the input. The caveat is that between every shift in direction, I had added a brake instruction. I still need to check if the brake instruction can be done away with [so far, am not brave enough to do that; but eventually].

Once the code below has been compiled and uploaded, I find that using the Serial input values 2 [forward] and 4 [reverse] interspersed with 3 [brake], works reproducibly.

[Code]
/* Arduino control of standard RC car ESC. 
Has code for both forward and reverse movements. 
The code presupposes that the ESC is already armed. Given sparse documentation for the ESC, I am not examining weird behavior changes in this ESC. However, if your ESC refuses to arm, then I would suggest the code shown in post_1 be used. 

Briefly, arming the ESC involves starting at the lowest pulse rate [typically around 700 microseconds] and going up to the max [typically 2100 microseconds]; since Arduino Servo library treats ESC as servos, one can also pulse the ESC from angles 0 [corresponding to minimum pulse] to 180 [corresponding to maximum pulse]. Each pulse must be at least 20milliseconds, though I prefer 40milliseconds just to be sure. Probably better ESCs will require shorter durations at each pulse rate.

Now that all the disclaimers are done, here goes nothing.
*/


#include<Servo.h>
Servo esc; // Call the ESC "esc"
void setup()
{
  esc.attach(9);
//Again - this is useful only during the testing part. For autonomous running, it is pointless.
  int i=0;
  Serial.begin(9600);
  delay(3000);

}

void loop()
{
  int i=0;
  char input;
  // Start at Servo Degree 70 and go till just above neutral. 
  // Note, Neutral is at 94 for this ESC.
  // This will run it in one direction.
  // Name this Step 1
  input=Serial.read();
if(input == '1')
{
  for(i=70;i<95;i++)
  {
    esc.write(i);
    delay(200);
  }
}

//Run for 2 seconds at moderately high speed (70).
// Name this Step 2
if(input =='2')
{
  esc.write(70); delay(200);
}
// Apply Brakes for 40 millisecs.
// Name this Step 3

if(input == '3')
{
  esc.write(100); delay(40);

// Apply throttle in opposite direction for 2 seconds.
// Name this Step 4
if(input == '4')
{
  esc.write(110); delay(2000);
}
// Bring down throttle to neutral.
// Name this Step 5
if(input == '5')
{
  for(i=110;i>90;i--)
  {
    esc.write(i);
    delay(200);
  }
}
// Apply brakes again - to change directions for 40 millisecs.
// Name this Step 6
if(input == '6')
{
  esc.write(70); delay(40);
}
input=NULL;
}
[/Code]

Sunday, 15 January 2017

Forward and Reverse in BLDC ESC

Last post (here) we looked at the ESC control in cars, with and without brakes. Here, I provide a sample code that managed to run the car autonomously (meaning: it ran without any Tx / Rx).

#include<Servo.h>
Servo esc; // Call the ESC "esc"
void setup()
{
  esc.attach(9);
/*
As you can see - I am not arming the ESC here. For some reason, the ESC is now on a persistently armed mode now. Upon powering, the ESC automatically arms. Given sparse documentation for the ESC, I am not examining this weird behavior changes in this ESC. However, if your ESC refuses to arm, then I would suggest the code shown in post_1 be used.
*/
//Again - this is useful only during the testing part. For autonomous running, it is pointless.
  int i=0;
  Serial.begin(9600); }

void loop()
{
  int i=0;
  // Start at Servo Degree 70 and go till just above neutral. 
  // Note, Neutral is at 94 for this ESC.
  // This will run it in one direction.
  for(i=70;i<95;i++)
  {
    esc.write(i);
    delay(200);
  }
//Run for 2 seconds at moderately high speed (70).
  esc.write(70); delay(2000);
// Apply Brakes for 40 millisecs.
  esc.write(100); delay(40);
// Apply throttle in opposite direction for 2 seconds.
  esc.write(110); delay(2000);
// Bring down throttle to neutral.
  for(i=110;i>90;i--)
  {
    esc.write(i);
    delay(200);
  }
// Apply brakes again - to change directions for 40 millisecs.
  esc.write(70); delay(40);
}

This code has not been rigorously tested at all. For example, there is no reason why I used 40 millisecs instead of, say, 35. All I have noticed is that at the pulse frequency (50Hz / 20 millisecs) this code doesn't work. So, in all likelihood, 21ms could also work. Also - I don't know what will happen if I bring the run throttle (70 and 110) closer to neutral (say,
85 and 100). In some cases, the ESC behavior abruptly changes, and the direction shifting doesn't happen (it stops running in one of the directions).

However, this code has allowed the RC car to move forward and in reverse without any external input at all. (time for a drink).

Given below is a photo of the car I had used for this purpose - it is a Traxxas / TT rip-off rally frame. The big (1/10) frame has plenty of room / power for carrying the Arduino board, a 7200 mAh NiMH battery for the car, a 10000mAh USB power bank (used to power the Arduino board) and everything else in between. I have not provided the connection drawing, because it is - at this point - trivial.



I intend to slap a SONAR on it and see if it can run around and not bump into obstacles (or walls). At that point, I will post a video :-)

Till then - ciao.

k

Saturday, 7 January 2017

Understanding ESC Response

In part 1 (here) - we saw how to arm the ESC. This is an essential part of getting your machine to work; irrespective of whether it is a rover or a quadrotor. The ESCs vary in their response post arming - for instance, a quadrotor ESC will not have forward and reverse motions programmed, and hence would only go from 0 - max_speed. This will correspond (usually) to PWM widths of 700 - 2200 microseconds. The overall frequency of signal pulsing is 50Hz (I have not personally tested this, but this assumption seems to work OK for two no-name ESCs). However, for cars - their neutral position is not the zero stick position (700 uS pulse / 0º pulse in Servo library), but the middle position (91º Servo position for this particular servo), though I suspect it will vary a few angles between different pieces of the same non-standard servo. Arming the servo is something that the code from the previous blog does reproducibly, and now am fairly confident that it works.

As mentioned in the previous blog, I have been having issues with getting the rotor spinning in forward and in reverse directions. It would do either, but not both. Now, a simplistic view of how we expect a Rover (car) ESC to work is given below; without a concept of brakes. The motor turns in one direction (say, forward) if the signal is above the Neutral point - and then in the other direction (reverse) if the signal is below neutral point. Without a brake (bringing it to a stop), we have to allow the forward motion to first stop (roll to a stop) before reversing. For the sake of simplicity, we will call the signal below neutral as negative, and the signal above neutral as positive. A simple state machine describing this behavior is also shown below.





However, sudden reversal in directions - especially in high speed models (these cars can run in excess of 20kmph) can cause severe wear and tear of the gear assembly. So, this simple model of switching between one direction to other with a simple switch in signal, while attractive, is not very practical. To overcome the limitations of the Car ESCs often have this concept of a brake. A brake is usually applied by a sending a brief pulse of the opposite magnitude; and then sending pulses that correspond to the specific direction in which we need the machine to move (figure below), where the ΔFlash Pulse is the pulse given in the opposite direction to activate the brake. 

Once the brake is applied, the machine is essentially at a neutral state and can move in either direction as the state machine below depicts. The colored arrows (green and red) show the relative change of direction of the pulse provided to apply the brake.


So in theory, if the car is running in forward direction, one has to apply the brake (briefly push the throttle in opposite direction) and then choose to move in either direction (again apply the throttle in the desired direction). Sounds very simple - but didn't work very well. For instance, the ESC would completely ignore the signals given in the opposite direction (say reverse, if the brake was applied while moving forward), but heed to signals that correspond to starting state.

In order to make sure this hypothesis about brake is correct, I intercepted the Tx signal and retransmitted through the Rx (circuit image below the plot), and plotted the pulse width as a function of time. (Figure below). In summary, this theory of braking and changing directions worked - but with a caveat (more on that later). To end this post - something interesting happened during the test described above - when I changed the directions too fast, and too many times - the ESC refused to respond - this is the point beyond about 27.5 seconds (275 on the X-axis).


There seems to be an inbuilt mechanism in the ESC to protect itself and the motor (and the car) from crazy driving. Unfortunately, given that this ESC has very little or no documentation, I am left guessing all of this.

Addendum: Circuit for intercepting Rx signal and re-transmitting to ESC

Friday, 6 January 2017

ArduRover_ArmESC

I find this question often in the internet - and I also see it go unanswered. Here is a stepwise guide to arm the Brushless ESC using Arduino. The usual disclaimer applies: 1) this is a general guide to know your arming point - not a specific answer; 2) this may kill your arduino / your ESC / your motor or your computer - am not responsible.

Having gotten them out of the way:

Code: [Select]

#include <Servo.h>

Servo motor;

void setup ()
{
  motor.attach(9); 
  Serial.begin(9600);
  int i = 0;

  //Give some time before you start anything like switching on your ESC / Motor

  Serial.print("Arming Test Starts in ");
  for(i =10; i > 0; i--)
  {
     Serial.print(i);
     Serial.print(".. ");
  }

  Serial.println();

// Watch for the tone when the ESC gets armed

  for(i = 50; i < 130; i++)
  {
     motor.write(i);
     Serial.println("i");
     delay(500);
  }
}

void loop()
{
}

When I run this on my ESC, it first gives 10sec to setup / switch on all the stuff. When you switch on your ESC, you will hear a double beep (note this tone). Now the second loop after the delay starts - where it sends one degree worth of pulse every 500 millisecs to the ESC. I have intentionally made a wide range (50 - 130), whereas your ESC will probably arm very close to neutral.

When the signal to the ESC reaches 87 - 93, pay attention - the ESC will let out another beep. This is different from the one you heard when switching it on. 

There is a bit of experimentation needed here to pinpoint the exact arming position. For my ESC, now - all I do is the following, to arm it. 

Note 1: My ESC arms at a signal of "91". For your ESC, it may be 90 or 92.

Note 2: The delay is crucial. I have gone down till 200 millisecs and still got it working. Try pushing the limit, and post as reply if you can get it.

Once the ESC has been armed, then it is a simple case of treating the angle as the run signal to the ESC. For example - see the code below
Code: [Select]

void loop()
{
  motor.write(105); delay(1000);
  motor.write(91); delay(2000);
}


will repeatedly run the motor for 1 second, and brake it for 2 seconds. Now, once the ESC is armed - the signal code "91" is merely treated as a Servo angle signal and will not repeatedly arm the ESC (until you switch the power off and on again).

I am still trying to get the forward and reverse turns on my motor reliably - it happens sporadically. I will post a second post once I have got it down pat.