Differential Steering Car With Arduino
by wsurging in Circuits > Arduino
11621 Views, 13 Favorites, 0 Comments
Differential Steering Car With Arduino
Hey, everyone, I'm wsurging, and I'm sending out my new car tutorial again. This is almost the same structure as the previous steering gear, but the rear wheel has added a RC model differential. Unfortunately, there is no With the addition of a shock absorber system, this car model has been ready for a long time, but it has not been sent out and it is here today.
The car model is also the rear drive structure. The front wheel is responsible for steering and the rear wheel is driven. Compared with the previous one, the car with the differential has a quicker steering, and the car model also uses the high-speed motor RS380. This car model can also be used directly. RC accessories to control, add electronic governor and remote control.
Let's take a look at how to install it. I will list the parts used in detail, let us look at it:
Accessories
The required accessories are:
Frame
Arduino UNO R3 motherboard
Expanding board
Motor drive module
PS2 wireless controller SONY (model remote control or gun remote control)
lithium polymer battery(Li-Po 2S)
Steering Cup and Transmission Shaft
Each of the accessories is 2 sets, 2 sets can be assembled, and subsequent installation on the chassis.
- Black steering cup x 2
- Rotary axis x 2
- Bearing x 4 (inside 4 outside 8mm, inner 8 outside 12mm)
- Pin x 2
- Hexagon x 2
- Wheels x 2
- M4 locknut x 2
- 65mm wheel x 2
Install Servo Accessories
Fix the L-bracket to the servo, pay attention to the length of the bracket (red circle). Before installing the steering angle on the steering gear, please center it at 90° (1500μs) to facilitate subsequent installation and commissioning.
- M2.5 x 10mm screw x 1
- M3 x 6mm screw x 1
- M3 x 8mm screws x 4
- M2.5 locknut x 1
- M3 nuts x 4
- MG996R servo x 1
- Ball head lever (short) x 1
- Rudder angle x 1
- L type bracket x 1
- Name :MG996R
- Voltage: 4.8-7.2V
- Current :400-800MA
- Steering gear torque: 10kg.cm
- Extreme angle: 180°
- Wire length: 30CM
- Gear material: metal
- Control system: change pulse width
Servo wiring: digital port I/O4
Connecting 2 Side Steering Cups
The long connecting rod is in the upper hole and connects the 2 side steering cups; the short connecting rod is in the lower hole, the steering cup is connected on one side, the rudder angle is connected on the other side, and the long and short connecting rods are not in the same hole position.
Long link hole spacing 65mm, short link hole spacing 46mm, fine adjustment if deviation.
- M2.5 x 10mm screw x 3
- Long and short connecting rod x 2
Flat Front Part
Before installation, make sure that the chassis is facing forward and backward, bend upwards, and fix the previously equipped steering gear and steering cup to the chassis. The steering cup is fixed on both sides by the copper column support, and the plastic cylinder is placed under the steering cup (the front and rear heights are consistent) , the steering cup fixing screw can not be tightened to ensure flexible steering.
- Chassis x 1
- M3 x 26mm copper pillars x 4
- M2.5 x 8mm screws x 2 (UP)
- M2.5 x 12mm screw x 2 (DOWN)
- M3 x 8mm screw x 12
- M3 nut x 4
- Black cylindrical x 2 (red box)
Rear Wheel Differential Section
The rear wheel seat needs to be fixed lastly. The drive shaft is fixed to the output shaft firstly. The rear wheel is installed similarly to the front wheel; the rear wheel seat is installed in the left and right, *the top R is installed on the left side, and the standard L is installed on the right side.
The lower support is a Z-shaped structure. The installation needs to pay attention to the direction, close to the differential box width, and the wheel base is narrow. If it is unclear, it can be consistent with the viewing angle in the figure.Upper support fixation requires removal of screws for installation.
- Differential x 1
- Transmission shaft x 2
- Triangle bracket x 4
- Z type bracket x 4
- Rear wheel seat x 2
- Bearings x 4
- Hexagonal adapter x 2
- Pin x 2
- Aluminum cylinder x 2(Fixed between the upper support (triangle) and rear wheel seat)
- 65mm wheel x 2
- M2 x 12mm screw x 2
- M2 locknut x 2
- M2.5 x 16mm screws x 4
- M2.5 x 25mm screw x 2
- M2.5 x 30mm screws x 2
- M2.5 Locknut x 8
- M4 Locknut x 2
Differential Box Fixed to Chassis
Fit the copper gear to the input shaft of the reduction gear box, fix the locking screw to the D type plane, fix it tightly with an L-type wrench, and fix the differential box on the chassis
- M2.5 x 8mm screw x 4
- Bull gear 0.5 die 54 teeth x 1
Motor Fixing
The motor is first fixed to the large bracket, and then fixed to the chassis. The bracket is fixed with M3 screws. The motor is fixed on the bracket and the left and right positions of the motor can be adjusted to set the tightness of the gear.
- M2.5 x 5mm screws x 2 (flat head screws)
- M3 x 6mm screw x 3 (with gasket)
- L type motor bracket
- RS380 DC motor
parameter:
- Operating voltage range: 3.0-9.0V
- Rated voltage: 7.2V
- No load speed: 16200rpm
- No load current: 0.50A
- Rated speed: 14000rpm
- Maximum current: 3.29A
- Rated torque: 110g.cm
- Rated power: 15.8W
- Starting torque: 840g.cm
The red dot of the electrode is positive.
Upper Chassis Mounting (Acrylic)
Upper chassis is made of acrylic material, with Arduino UNO and Raspberry Pi holes integrated,Rocker switch installed in rectangular hole
- M3 x 8mm screws x 9
- M3 x 35mm copper pillars x 5
- Rocker Switch x 1
- Acrylic x 1
Anti-collision Cotton
The red circle is the copper column fixing hole, and the bumper cotton is pressed with a gasket
- M3 x 8mm screw x 8
- M3 gasket x 4
- M3 x 16mm copper column x 4
- Anti-collision cotton x 1
Motor Drive Module
MD01电机驱动器由单个H桥驱动器IC和四个外部N沟道MOS晶体管组成。其体积小巧(长*宽:3.3 * 2cm),主板支持5.9V至30V宽电压输入,连续电流可达到17A,支持100%脉宽调制。该模块通过方向DIR引脚和速度控制PWM引脚实现电动机的正向,反向和速度控制。
控制端子支持1.8V-5V逻辑输入,驱动器IC集成了PWM电流调节功能,可限制电机浪涌电流。SLP引脚的低电平允许MD01驱动器模块进入低功耗模式,从而导致大约9uA的低静态电流消耗。
注意:SLP低功耗模式是默认的低电平,使用时需要将SLP引脚保持高电平,如果不需要使用低功耗模式,则可以直接连接+ 5V。
- 工作电压:5.9-13V
- 工作电流:17A
- 逻辑输入:1.8V,3.3V,5V(最大)
- PWM频率:100kHz
- 电流检测:50mV / A(仅在正向或反向时有效)
- 反射电压保护:无(VM和GND不得接反)
Remote Control (2.4Ghz)
2.4Ghz remote control We use Sony's PS2, you can also use the RC model controller; if you have an electronic governor, you probably don't need Arduino UNO to join in, but we are learning to use Arduino.
The handle is equipped with an adapter plate for easy wiring and reverse connection protection. The interface is up to the bottom:GND VCC DAT CMD CS CLK
/****************************************************************************
* The program controls the forward and backward * movement of the motor through the Y-axis of the left joystick, * the X-axis of the right joystick controls the left and right of the servo, * the button part also writes forward and backward, * and the right button controls the left and right. *****************************************************************************/ #include <Servo.h>#include <PS2X_lib.h>
//for v1.6 PS2X ps2x; Servo myservo;
#define PS2_DAT A0 #define PS2_CMD A1 //PS2 #define PS2_SEL A2 #define PS2_CLK A3 #define PWM 5 //Motor A's pin #define DIR 6 //Motor A's pin #define SERVOPIN 4 //servo's pin
#define SERVOMIN 40 //the angle of servo #define SERVOMID 90 #define SERVOMAX 130 #define TURNLEFT myservo.write(SERVOMIN) //turn left #define TURNMID myservo.write(SERVOMID) //turn middle #define TURNRIGHT myservo.write(SERVOMAX) //turn right #define MOTORFOWARD setMotor(100) //motor forward PWM #define MOTORBACK setMotor(-100) //motor back PWM #define MOTORSTOP setMotor(0) //motor stop PWM
bool EnableRockerR = 1; bool EnableRockerL = 1; int RMid = 0 ; int LStop = 0 ;
#define pressures false #define rumble false int error = 0; byte type = 0; byte vibrate = 0; void(* resetFunc) (void) = 0;
void setup() { Serial.begin(57600); pinMode(PWM, OUTPUT); pinMode(DIR, OUTPUT); myservo.attach(SERVOPIN); SERVOMID; delay(300); error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
if (error == 0) { Serial.print("Found Controller, configured successful "); Serial.print("pressures = "); if (pressures) Serial.println("true "); else Serial.println("false"); Serial.print("rumble = "); if (rumble) Serial.println("true)"); else Serial.println("false"); Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;"); Serial.println("holding L1 or R1 will print out the analog stick values."); Serial.println("Note: Go to www.billporter.info for updates and to report bugs."); } else if (error == 1) Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
else if (error == 2) Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
else if (error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
type = ps2x.readType(); switch (type) { case 0: Serial.print("Unknown Controller type found "); break; case 1: Serial.print("DualShock Controller found "); break; case 2: Serial.print("GuitarHero Controller found "); break; case 3: Serial.print("Wireless Sony DualShock Controller found "); break; } }
void loop() { if (error == 1) //skip loop if no controller found resetFunc(); ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
if (ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed Serial.println("Start is being held"); if (ps2x.Button(PSB_SELECT)) Serial.println("Select is being held");
if (ps2x.ButtonPressed(PSB_PAD_UP)) { Serial.println("PAD_UP just pressed"); MOTORFOWARD; EnableRockerL = 0; }else if(ps2x.ButtonReleased(PSB_PAD_UP)) { Serial.println(" PAD_UP just released"); MOTORSTOP; EnableRockerL = 1; LStop = 0; }
if (ps2x.ButtonPressed(PSB_PAD_DOWN)) { Serial.println("PAD_DOWN just pressed"); MOTORBACK; EnableRockerL = 0; }else if(ps2x.ButtonReleased(PSB_PAD_DOWN)) { Serial.println(" PAD_DOWN just released"); MOTORSTOP; EnableRockerL = 1; LStop = 0; }
if (EnableRockerL) { //Forward and Back if (0 <= ps2x.Analog(PSS_LY) && ps2x.Analog(PSS_LY) <= 110) { digitalWrite(DIR, HIGH); analogWrite(PWM, map(ps2x.Analog(PSS_LY), 0, 110, 255,0)); LStop = 0; } else if (255 >= ps2x.Analog(PSS_LY) && ps2x.Analog(PSS_LY) >= 140) { digitalWrite(DIR, LOW); analogWrite(PWM, map(ps2x.Analog(PSS_LY), 140, 255, 0,255)); LStop = 0; } else { if(LStop == 0){ MOTORSTOP; LStop ++; } } }
if (ps2x.ButtonPressed(PSB_CIRCLE)) { //will be TRUE if button was JUST pressed Serial.println("Circle just pressed"); TURNRIGHT; EnableRockerR = 0; } else if (ps2x.ButtonReleased(PSB_CIRCLE)) { Serial.println("Circle just released"); TURNMID; EnableRockerR = 1; RMid = 0; } if (ps2x.ButtonPressed(PSB_SQUARE)) { //will be TRUE if button was JUST released Serial.println("Square just pressed"); TURNLEFT; EnableRockerR = 0; } else if (ps2x.ButtonReleased(PSB_SQUARE)) { //will be TRUE if button was JUST released Serial.println("Square just released"); TURNMID; EnableRockerR = 1; RMid = 0; } if (EnableRockerR) { //Left and Right if (0 <= ps2x.Analog(PSS_RX) && ps2x.Analog(PSS_RX) <= 110) { myservo.write(map(ps2x.Analog(PSS_RX), 0, 110, 40,90)); RMid = 0; } else if (255 >= ps2x.Analog(PSS_RX) && ps2x.Analog(PSS_RX) >= 140) { myservo.write(map(ps2x.Analog(PSS_RX), 140, 255, 90,130)); RMid = 0; }else { if(RMid == 0){ TURNMID; RMid ++; } } }
if (ps2x.NewButtonState(PSB_CROSS)) { //will be TRUE if button was JUST pressed OR released Serial.println("X just changed"); MOTORSTOP; } delay(50); }
void setMotor(int Speed) //Motor drive function { if (Speed > 0) { digitalWrite(DIR, HIGH); analogWrite(PWM, Speed); } else if(Speed < 0){ digitalWrite(DIR, LOW); analogWrite(PWM, -Speed); }else{ digitalWrite(PWM, LOW); digitalWrite(DIR, LOW); } }
RC Receiver(FS-TH9X)
If you are using a model remote, you can control your robot as follows. I simply wrote some code with the interrupt, and if you need it, you can improve it and make it better.I am using the FS-TH9X. I am using the left and right throttles. In order to return, I use the right joystick to control the forward and backward movement of the robot. When I center, I stop. The left joystick controls the left and right steering. For me, it may be used. Not used to it, if you need FS-TH9X information, please Google.
I use CH3 (throttle) and CH4 (direction). It is easy to use when wiring. It is OK to supply the receiver with 5v and GND. Use the 5V pin on the Arduino UNO. Maybe UNO may not provide enough. The current is used to maintain the normal operation of the receiver and servo. At this time, you need an external power supply to supply power to the servo or receiver. Of course, you need to supply the ground.
Wiring:
CH3>>Arduino I/O2
CH4>>Arduino I/O3
//The two channels of the receiver are connected to the
//digital port 2 and 3 of the arduino respectively. int ppm1 = 2; int ppm2 = 3;unsigned long rc1_PulseStartTicks,rc2_PulseStartTicks; volatile int rc1_val, rc2_val;
void setup() { Serial.begin(9600); pinMode(ppm1, INPUT); //PPM inputs from RC receiver pinMode(ppm2, INPUT); attachInterrupt(0, rc1, CHANGE); // Level change trigger interrupt attachInterrupt(1, rc2, CHANGE); }
void rc1(){ // did the pin change to high or low? if (digitalRead( ppm1 ) == HIGH) rc1_PulseStartTicks = micros(); // store the current micros() value else rc1_val = micros() - rc1_PulseStartTicks; }
void rc2(){ // did the pin change to high or low? if (digitalRead( ppm2 ) == HIGH) rc2_PulseStartTicks = micros(); else rc2_val = micros() - rc2_PulseStartTicks; }
void loop() { Serial.print("CH1: ");Serial.print(rc1_val); Serial.print(" ");//print values Serial.print("CH2: ");Serial.println(rc2_val); delay(200); }
Remember to turn on the transmitter first when controlling
#include <Servo.h>
Servo myservo; //The two channels of the receiver are connected to the digital port 2 and 3 of the arduino respectively. int ppm1 = 2; int ppm2 = 3;
int servo = 4; //Servo pin int PWM = 5; //Motor pin int DIR = 6; //Motor pin
unsigned long rc1_PulseStartTicks,rc2_PulseStartTicks; volatile int rc1_val, rc2_val;
void setup() { Serial.begin(9600); pinMode(DIR ,OUTPUT); pinMode(PWM ,OUTPUT); myservo.attach(servo); pinMode(ppm1, INPUT); //PPM inputs from RC receiver pinMode(ppm2, INPUT); attachInterrupt(0, rc1, CHANGE); // Level change trigger interrupt attachInterrupt(1, rc2, CHANGE); }
void rc1(){ // did the pin change to high or low? if (digitalRead( ppm1 ) == HIGH) rc1_PulseStartTicks = micros(); // store the current micros() value else rc1_val = micros() - rc1_PulseStartTicks; }
void rc2(){ // did the pin change to high or low? if (digitalRead( ppm2 ) == HIGH) rc2_PulseStartTicks = micros(); else rc2_val = micros() - rc2_PulseStartTicks; }
void loop() { if(rc1_val < 1100){ rc1_val = 1100; } if(rc1_val > 1900){ rc1_val = 1900; } if(rc2_val < 1100){ rc2_val = 1100; } if(rc2_val > 1850){ rc2_val = 1850; } if(rc1_val >= 1100 && rc1_val <= 1490) { digitalWrite(DIR ,LOW); analogWrite(PWM,map(rc1_val,1100,1490,255,0)); } else if(rc1_val >= 1510 && rc1_val <= 1900) { digitalWrite(DIR ,HIGH); analogWrite(PWM,map(rc1_val,1510,1900,0,255)); }else{ digitalWrite(PWM, LOW); digitalWrite(DIR, LOW); } if(rc2_val >= 1100 && rc2_val <= 1490) { myservo.write(map(rc2_val,1100,1490,40,89)); } else if(rc2_val >= 1510 && rc2_val <= 1850) { myservo.write(map(rc2_val,1510,1850,91,130)); } delay(15); }