Skid Steering to Dynamic Steering

Hi there. This code was written for skid steering, but needs to be altered to achieve dynamic, two-wheel front drive steering (casters in the rear). Basically, I'd like the left-right toggle on the radio controller to decrease the voltage as the toggle is pushed all the way to each side until it reaches 0, once it returns to the center both motors would just resume matching speeds. Maybe this is obvious to you - I'm just trying to turn what I imagine into reality.

The guy who wrote it is unavailable, now, and it's fallen to me, a mechanics guy who is completely new to this world. I've been doing some research, but my head is spinning. Can anyone help me out?

#define MTR 5 //motor right
#define MTL 6 //motor left
#define DIR_R 7 //right direction
#define DIR_L 8 //left direction
#define FWD LOW
#define RVS HIGH
void setup() {
  pinMode(10,INPUT); //Channel 1 (steer)
  pinMode(11,INPUT); //Channel 3 (throttle)
  pinMode(9,INPUT); //Channel 5 (direction)
  pinMode(MTR,OUTPUT);
  pinMode(MTL,OUTPUT);
  pinMode(FWD,OUTPUT);
  pinMode(RVS, OUTPUT);
  Serial.begin(9600);
}

int steer; //steering number
int throttle; //throttle number
int pwm = 0; // pwm number
int fwd = 1 ; 
int direc = analogRead(A0);
void speedFunct(){
  //full power
  if(pwm >= 250){
    analogWrite(MTR,255);
    analogWrite(MTL,255);
  }
  //no power
  else if(pwm <= 0){
    analogWrite(MTR,0);
    analogWrite(MTL,0);
  }
  //percentage of power (duty cycle)
  else{
    analogWrite(MTR,pwm);
    analogWrite(MTL,pwm);
  }
}
void steerFunct(){
  //drive straight
  if(1450 < steer < 1550){
    if(fwd == 1){
       digitalWrite(DIR_R, FWD);
       digitalWrite(DIR_L, FWD);
    }
    else{
       digitalWrite(DIR_R, RVS);
       digitalWrite(DIR_L, RVS);
    }
     speedFunct();
      delay(5);
  }
  //steer right
  if(steer >= 1550){
    digitalWrite(DIR_R, RVS);
    digitalWrite(DIR_L, FWD);
    speedFunct();
    delay(5);
  }
  //steer left
  if(steer <= 1450){ // 1400
    digitalWrite(DIR_R, FWD);
    digitalWrite(DIR_L, RVS);
    speedFunct();
    delay(5);
  }
}

void loop() {
  //Pin setup
  steer = pulseIn(10, HIGH, 250000);
  throttle = pulseIn(11, HIGH, 250000);
  direc = pulseIn(9, HIGH, 250000);
  Serial.println(throttle);
  Serial.println(steer);
  /***Direction control***/
  //Forward
  if(direc <= 1000){
    analogWrite(DIR_R, FWD);
    analogWrite(DIR_L, FWD);
    pwm = map(throttle, 990, 1983 ,0 ,255);
    fwd = 1;
    steerFunct();
    delay(5);
    Serial.print("Direction: ");
    Serial.println("Forward");
    Serial.println("\n");
    
  }
  //Reverse
  if(direc >= 1900){
    digitalWrite(DIR_R, RVS);
    digitalWrite(DIR_L, RVS);
    pwm = map(throttle, 990, 1983 ,0 ,255);
    fwd = 0;
    steerFunct();
    delay(5);
    Serial.print("Direction: ");
    Serial.println("Reverse");
    Serial.println("\n");
  }
  //Dead Zone(No movement)
  if(1400 < direc && direc < 1500){
    //pwm = 0;
    //speedFunct();
    digitalWrite(MTR, LOW);
    digitalWrite(MTL,LOW);
    delay(5);
    Serial.print("Direction: ");
    Serial.println("Stop");
    Serial.println("\n");
  }
  
  delay(5);
}```

You are working on a informatic project. And what is most needed on an informatic project is information.

Can you post a picture or a hand-made-drawing what exactly a skid-steering is?
And how does the dynamic two-wheel front-drive steering look like.
Should driving left/right be done by turning the wheels into a different direction and "dynamic means the amount of how much inner/outside-wheel have to turn

or does dynamic mean different rpms on left/right wheel?

As a general hint: Names in a program should be ALL selfexplaining
"Something short like "MTR" does not explain what the function is
it should be called "MotorRight_Pin" that would be fully self-explaining and needs no additional comment.
As you are coming from mechanics
saying "a nut" is not sufficient.
Mimimum would be saying the size additional the material, normal height or flat
self-locking or not etc.

It is the same thing with electronics.

What basic principle is your "toogle" using?
ist it a potentiometer?
a rotary-encoder ?
a switch left/right?

best regards Stefan

C and C++ do not do ranges like this, The statement is treated as:
if((1450 < steer) < 1550){
Since the (1450 < steer) results in a true/false (1 or 0) the second comparison (1 < 1550) or (0 < 1550) is always true.

You want:
if((1450 < steer) && (steer < 1550)){

Generally we're better at electronics and software than mechanics. So I personally have no idea what the difference between "Skid Steering" and "Dynamic Steering" means to you. Can you explain it in terms of what should actually be happening to the motors and/or anything else involved?

And I'm guessing by "toggle" you actually mean a joystick on on a radio transmitter. Is that right? Your code seems to be reading 3 channels from some sort of radio receiver.

Steve

Hi,
Can you tell us what Arduino controller the code is for?
Can you post the circuit diagram of your car.

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

Good morning and thank you for the replies, StefanL38, johnwasser, slipstick, and TomGeorge - I'll attempt to clarify everything you pointed out. I tend to give people information overload (not so great at parties...), so I was trying to pare it down and perhaps left too much mystery. This is for school. It's an RC kart that previously operated with four independent motors, but now just has two rigid front drive wheels and casters in the rear.

Here is a visual for reference. I hid all the unnecessary components, but know that the front wheels are rigid for a reason:

Here is an image of the wiring schematic which includes the Aruino Uno being employed:

And this is the radio controller we're using. I think they're typically used for RC planes and it's probably overkill for this project, but it's what I was provided:

Toggle vs. joystick: I called it a toggle because when I hear joystick I think of one single stick that does everything, as with the Atari and NES of my youth. Being as this has two, I was referring to just the stick on the right being used for left/right controls. I'll be happy to change my lingo, if it would help.

Skid steering is actually easy enough to explain that I'll skip the drawing: think of a tank. To turn right, the right tread (or wheels) rotate backward while the left tread (or wheels) rotate forward. It's sloppy (hence the "skid"), but can achieve a 0 degree turning radius. As it happens, it was too sloppy for the weight and length of the vehicle, and there was no reason to have 0 degree radius, so we went to two wheels.

So the front drive/steer wheels are rigid. Presently, they still operate as they did with skid steering (effectively slamming the brakes on one side every time I want to make even the most minor correction). So I'd like to be able to make more minor adjustments while going over bumpy terrain by, yes, just reducing the rpms on the side of the direction I'm wanting to turn by just a few volts, or all the way to 0, if necessary, to have it pivot on the stopped wheel.

I'm sorry, but I don't know what principle the toggle/joystick on the right (for left/right control) operates on, but I would assume a potentiometer, rheostat(?), or the like, as you said, Stefan.

johnwasser, someone else pointed to that line of code in a previous thread when I was working on a different problem. How might that bit of code, as it is, physically manifest itself in the way the kart operates? Thanks for pointing it out.

Stefan, I appreciate clarity, too. I'll be sure to update that "MotorRight_Pin" designation.

OK the inner working principle of the transmiter-sticks" is no longer of interest because the connection between transmitter and receiver works reliably and has nothing to do with the programming.

The arduino receives standard servo-signals from the receiver.

The picture shows an Arduino Uno. But its a non-fotographic picture.What is the real microcontroller that you are using?
If you don't know the name take a real-photographic picture of the microcontroller.
I estimate it will take the same amount of time to analyse the existing code and to modify it as writing a new code from scratch.

New writing from scratch has the advantage that you will learn step by step and do the development in stages.

The code that you have posted. Is this your attempt to adapt the existing code to the new steering-principle or the existing code for the old steering-principle?

best regards Stefan

Thank you again, Stefan. Noted. If you're looking for a model number, it might be 94v-0. But here are some pictures:

I'd be happy to write new code with the right guidance. The existing code was for the old steering principle, but it appears he removed any references to the now-removed, motorized rear wheels thinking this would still work. And it does... but poorly.

Forgive me, but I do need to step out for a few hours. I'll follow up with you and this thread later.

very normal to have a non-digital life.

Ah very good pictures
A classical Arduino Uno with a seeed-studio I2C-baseshield.

OK so a first step could be writing a testprogram that just does serial prints to the serial monitor with the received RC-signals

I looked up the datasheet of the MDDS30 DC-motordriver
https://www.robotshop.com/media/files/pdf/smartdriveduo-smart-dual-channel-30a-motor-driver-datasheet.pdf

If this is really the mortordriver-device you are using it even offers a direct RC-signal input !

What do you think. Would controlling the motors directly from the RC-receiver be a good solution?

Do you have any additional functions over just driving both motors forward/reverse?

I think at least you should examine how the controller behaves in the different RC modes.

Reading the datasheet is really worth the time
The datasheet even contains links to GitHub with Example-codes

@All you newbees: reading the datasheet almost always gives a good insight into your device regardless what device it is.

The provided library offers a greatly simplified controlling of the driver.

So do you really have the MDDS30 double DC-motor-driver?

best regards Stefan

Yes, the MDDS30 is the driver we're working with. Didn't realize it came with its own RC receiver. Not sure if the previous engineer did. Does the method of coding work the same? I looked at some examples it linked to, and my untrained eyes wouldn't know if there was a difference.

I think at least you should examine how the controller behaves in the different RC modes.

What do you mean by this? The driver's native RC receiver vs the Arduino?

Regardless, I think I'd like to just stick with the Arduino since it's already outfitted for it.

Looking over the MDDS30 specs currently...

The MDDS30 has not an RC-receiver.
The MDDS30 has inputs where you "feed-in" 50 Hz 1,5 milliseconds standard-RC-servo-signals to control the DC-motors.

This is possible leaving out the Arduino:
T8FB 2,4 GHz Transmitter --2,4GHz-radio-signal--->----- R8EF 2,4 Ghz receiver --50 Hz 1,5 millisecs-servo-signal-->----MDDS30-Inputs

This means you use two sticks on the 2,4 GHz transmitter to control left/right motor

With Arduino it looks like this
T8FB 2,4 GHz Transmitter --2,4GHz-radio-signal--->----- R8EF 2,4 Ghz receiver --50 Hz 1,5 millisecs-servo-signal-->----Arduino-Uno-->servo or analog or PWM or serial--->--MDDS30-Inputs

With Arduino offers to realise the control
one stick forward / reverse
one stick for left / right WHich I guess is more convenient.

Now inside the Arduino you can write a program that does all the details on its own.
or you can use a MDDS30-library that does the details.

To describe an mechanic analogon
I think you know what a paper-puncher is


Align some sheets of paper to the stop-edges press down the lever wholes punched at the right place and right distance. Very popular very , usual, very convenient.

Nobody will ever do it but you could do it the real hard way:
take a ruler and pen measure distancies mark where to cut the two wholes
take a small scissor ad with very tiny cuts cut out the wholes. Very inconvenient.

The manufacturer of the MDDS30 offers a library on github that makes life a bit easier.
The difference is not as big as in my paper-puncher-example but it is somehow a bit easier.

controlling the speed of the motors boils down to

smartDriveDuo30.control(speedLeft, speedRight);

The MDDS30 offers four ways how to control the motor
1.) servo-signal
2.) PWM /analog
3.) serial packetized
4.) serial simplified

1.) servo-signal
2.) PWM /analog
means you have to connect two wires between arduino and MDDS30

3.) serial packetized
4.) serial simplified
means a single wire is enough because all the information is transferred serial

when using the MDDS30-library you just specify the used method in the void setup()

best regards Stefan

@StefanL38 - that is a lot of information! So was reading the specs for the MDDS30. I've never been much for learning through text, though, so perhaps these details will make sense to me further down the road.

By the way, I realized I may have replied only to Stefan, previously, and accidentally cut @slipstick and @TomGeorge out of the loop by not 'at'ing them properly. The information you both requested is in post #6 - please have a look, if you care to. I should also say I think the term "differential drive" might mean more to you - it's very similar to skid steering (see here). Differential drive is what I'm after, but I'm not interested in the vehicle ever rotating about its center axis - just varying the speeds of the motors when turns and corrections are needed (see point #3 under the "Differential Drive" section of the link provided).

@johnwasser, I had asked in that same post about how the code error you pointed out might manifest itself. I've already changed that line of code to your suggestion and I'll take it for a run later today as I wonder if it might be related to a performance issue I've observed. Thank you, and I'll let you know how it develops.

I'm not sure what you exactly mean with that.
You are at the point to write an arduino program that

  • reads in three standard servo-signals from a rc-receiver
  • transforms the RC-servo-signal into "signals" that wil be understandable by the MDDS30 to adjust the forward/reverse rpm-speed of two DC-motors.

The MDDS30 offers three "languages" to talk to the MDDS30
50 Hz rectangular-pulses 1-2 milliseconds long (=standard servo-signal)

PWM

serial

with two "dialects"
packetized serial
simplified serial.

The manufacturer of the MDDS30 offers a "translator" that does all the details.
If you use the "translator" (=the library) it's enough to shout at the translator

leftspeed 50%, rightspeed 72% or any other combination of %-tage values for left/right speed and you are done.

As a real specific question:
did you find the link in the documentation that guides you to this library downloadable at Github?

best regards Stefan

I found the link and downloaded the files, yes. I'm having difficulty making sense of them, though. Where do pins 9, 10, and 11 from the antenna (as seen in my schematic) play into the code? And what does entering a single percentage value next to speedleft/speedright achieve? I'm looking for a range of speed change as the radio controller stick is moved.

From the MDDSPWMTest file:

  • Hardware Connection:
  • Arduino Uno MDDS30
  • GND ---------- GND
  • 4 ------------ IN1
  • 5 ------------ AN1
  • 6 ------------ AN2
  • 7 ------------ IN2

Are "IN" and "AN" input and antenna? I'm just guessing here.

Does the amount of voltage being used in the system ever play into the coding? Or is it all just a matter of percentages?

You have posted this schematic


This shows that three channels of the 2,4gHz receiver are connected to the Arduino IO-pins 9, 10 an 11

I was assuming that you did understand the code you have posted above. This seems not to be the case.

Your existing code is translating different transmitter-stick-positions into different speeds of the motor. And this code can be adapted to use the cytron-library which make programming easier.

These connections between receiver and Arduino IO-pins 9,10,11 can be reused.
But you seem to have no idea where in the code this is.
From your questions I want to ask you a question:
What was the most complex project you did in programming?

a) blinking an LED
b) making some LEDs blink in sequence
c) something much more complex than a) or b)

I think when I have a clear picture about your knowledge-level about programming I can write postings you do understand.

"the files" is a way too unprecise description of which files you meen.
add comments to that line of code you have questions about and then
post the complete file as a code-section

best regards Stefan

Hello, Stefan. I'll reiterate what I said in my original post that I am completely new to this world. Following a Youtube tutorial, I did blink an LED after I downloaded the Arduino software just to make sure everything was communicating... and that's it.

I understand very, very little of the code written by the now-absent engineer, other than spotting the 9, 10, and 11 pins that coordinate with those labeled on the outside of the Arduino. When I posted the code, I hoped it was just a matter of some adjustments to it to achieve what I wanted. I totally understand now that is not the case, so if you think I'm crazy for trying to cram months of training into the week that I have to finish this project, I'll understand. I'm a drafter/designer/welder who is also good with a soldering iron, but didn't expect to be working on something so foreign to me at this late stage of development.

"The files" is the entire zip folder you directed me to from the link you pointed out. I chose the MDDSPWMTest folder/file because it was the first one listed in the "Examples" folder of the library. I brought up pins 9, 10, and 11 because I figured they must need to be entered somewhere in this code. Is the MDDSPWMTest example coding as plug-and-play as you implied a few posts ago, or am I way out of my element here?

Hi schpuz,

just in case you do not yet know how to look up private messages.

I send you a private message.
So take a look at it an answer me there

best regards Stefan

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.