How do I make an accurate 90 degree turn?

Hi, i'm a beginner using the keyestudio 4wd bt robot car and i've been struggling to get a consistent and accurate 90 degree turn. I've adapted the kit's ultrasonic avoiding code to be suited for a maze but when I run the code the turns are inconsistent and make it impossible to complete the maze. I've currently been trying to figure out a perfect turn based off the location of the nearest corner, but I haven't been having much success. Any other recommended changes would also be greatly appreciated. Also sorry about the lack of comments, it was a bit too messy keeping the old ones from the original tutorial, so I'll try respond to any questions about clarification as soon as I can. I also would love to remove all the display code if possible, however i'm not sure which parts are which.

unsigned char front[] = {0x00,0x00,0x00,0x00,0x00,0x24,0x12,0x09,0x12,0x24,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char left[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,0x44,0x28,0x10,0x44,0x28,0x10,0x00};
unsigned char right[] = {0x00,0x10,0x28,0x44,0x10,0x28,0x44,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char STOP01[] = {0x2E,0x2A,0x3A,0x00,0x02,0x3E,0x02,0x00,0x3E,0x22,0x3E,0x00,0x3E,0x0A,0x0E,0x00};
unsigned char clear[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
#define SCL_Pin  A5  //Set clock pin to A5
#define SDA_Pin  A4  //Set data pin to A4
#define ML_Ctrl 4     //define direction control pin of B motor
#define ML_PWM 5   //define PWM control pin of B motor
#define MR_Ctrl 2    //define direction control pin of A motor
#define MR_PWM 9   //define PWM control pin of A motor
#include "SR04.h"//define the library of ultrasonic sensor
#define TRIG_PIN 12// set the signal input of ultrasonic sensor to D12
#define ECHO_PIN 13//set the signal output of ultrasonic sensor to D13
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long distance,a1,a2,diaMeasurement,no_counter,HAngle,hozMeasurement;//define three distance
const int servopin = 10;//set the pin of servo to D10




void setup() {
 Serial.begin(9600);//open serial monitor and set baud rate to 9600
 pinMode(ML_Ctrl, OUTPUT);//set direction control pin of B motor to OUTPUT
 pinMode(ML_PWM, OUTPUT);//set PWM control pin of B motor to OUTPUT
 pinMode(MR_Ctrl, OUTPUT);//set direction control pin of A motor to OUTPUT


 pinMode(MR_PWM, OUTPUT);//set PWM control pin of A motor to OUTPUT
 servopulse(servopin,90);// the angle of servo is 90 degree
 delay(300);
 pinMode(SCL_Pin,OUTPUT);//  set clock pin to OUTPUT
 pinMode(SDA_Pin,OUTPUT);//set data pin to OUTPUT
 matrix_display(clear);// Clear the matrix display
}


void loop()
{
 avoid();//run the main program
}
void avoid()
{
 distance=sr04.Distance(); //obtain the value detected by ultrasonic sensor
 if((distance < 16)&&(distance > 0))//if the distance is greater than 0 and less than 20 
{
   car_Stop();//stop
   matrix_display(STOP01);   //show stop pattern
   delay(100);
   servopulse(servopin,185);//servo rotates to 185°
   servopulse(servopin,180);//correction due to error with rotation for unknown reason
   delay(500);
   a1=sr04.Distance();//measure the distance
   delay(100);
   servopulse(servopin,0);//rotate to 0 degree
   servopulse(servopin,0);//correction due to error with rotation for unknown reason
   servopulse(servopin,0);//correction due to error with rotation for unknown reason
   delay(500);
   a2=sr04.Distance();//measure the distance
   a1=round(a1 / 2);
   a2=round(a2 / 2);
   delay(100);
   if (a1 = a2);
   {
   while (a1 = a2)
    {
     car_back();
     delay(200);
     car_Stop();//stop
     matrix_display(STOP01);   //show stop pattern
     delay(100);
     servopulse(servopin,185);//servo rotates to 185°
     servopulse(servopin,180);//correction due to error with rotation for unknown
     delay(500);
     a1=sr04.Distance();//measure the distance
     delay(100);
     servopulse(servopin,0);//rotate to 0 degree
     servopulse(servopin,0);//correction due to error with rotation for unknown
     servopulse(servopin,0);//correction due to error with rotation for unknown
     delay(500);
     a2=sr04.Distance();//measure the distance
     a1=round(a1 / 2);
     a2=round(a2 / 2);
     car_back();
     delay(150);
   }
 }


if(a1 > a2)//if distance a1 is greater than a2
   {
     servopulse(servopin,90);//rotate to 0 degree
     servopulse(servopin,90);//rotate to 0 degree
     HAngle = 90;
     while (diaMeasurement < sr04.Distance()){
        HAngle = HAngle - 2;
        servopulse(servopin,HAngle);
        diaMeasurement = sr04.Distance() - 1;
        delay(1);
     }
     car_Stop();
     delay(100);
     while (hozMeasurement < sr04.Distance()){
        car_left();//turn left
        delay(1);
        no_counter = no_counter + 1;
        hozMeasurement = sr04.Distance() - 1;
     }
     car_left();//turn left
     servopulse(servopin,90);//servo rotates to 90 degree
     servopulse(servopin,90);//correction due to error with rotation for unknown reason
     delay(no_counter * 90 / HAngle - no_counter);
   }
   else//if the right distance is greater than the left
   {
     car_right();// turn right
     matrix_display(front);   //show forward pattern
     delay(200);
     servopulse(servopin,90);//servo rotates to 90 degree
     servopulse(servopin,90);//correction due to error with rotation for unknown reason
   }
 }
 else//otherwise
 {
   car_front();//go forward
   matrix_display(front);   // show forward pattern
 }
}
void servopulse(int servopin,int myangle)//the running angle of servo
{
 for(int i=0; i<30; i++)
 {
   int pulsewidth = (myangle*11)+500;
   digitalWrite(servopin,HIGH);
   delayMicroseconds(pulsewidth);
   digitalWrite(servopin,LOW);
   delay(20-pulsewidth/1000);
 } 
}


void car_front()//car goes forward
{
 digitalWrite(ML_Ctrl,HIGH);//set direction control pin of B motor to HIGH level
 analogWrite(ML_PWM,150);//set PWM control speed of B motor to 150
 digitalWrite(MR_Ctrl,HIGH);//set direction control pin of A motor to HIGH level
 analogWrite(MR_PWM,150);//set PWM control speed of A motor to 150
}
void car_back()//go back
{
 digitalWrite(ML_Ctrl,LOW);//set direction control pin of B motor to LOW
 analogWrite(ML_PWM,200);//set PWM control speed of B motor to 200
 digitalWrite(MR_Ctrl,LOW);//set direction control pin of A motor to LOW
 analogWrite(MR_PWM,200);//set PWM control speed of A motor to 200
}
void car_left()//car turns left
{
 digitalWrite(ML_Ctrl,LOW);//set direction control pin of B motor to LOW
 analogWrite(ML_PWM,225);//set PWM control speed of B motor to 200
 digitalWrite(MR_Ctrl,HIGH);//set direction control pin of A motor to HIGH
 analogWrite(MR_PWM,225);//set PWM control speed of A motor to 200
}
void car_right()//car turn rights
{
 digitalWrite(ML_Ctrl,HIGH);//set direction control pin of B motor to HIGH
 analogWrite(ML_PWM,210);//set PWM control speed of B motor to 200
 digitalWrite(MR_Ctrl,LOW);//set direction control pin of A motor to LOW
 analogWrite(MR_PWM,210);//set PWM control speed of A motor to 200
}
void car_Stop()//car stops
{
 digitalWrite(ML_Ctrl,LOW);
 analogWrite(ML_PWM,150);
 digitalWrite(MR_Ctrl,LOW);
 analogWrite(MR_PWM,150);
 delay(50);
 analogWrite(ML_PWM,0);//set PWM control speed of B motor to 0
 analogWrite(MR_PWM,0);//set PWM control speed of A motor to 0
}
//this function is used for dot matrix display
void matrix_display(unsigned char matrix_value[])
{
 IIC_start();  //the function to call the data transmission
 IIC_send(0xc0);  //Select address
 for(int i = 0;i < 16;i++) //Pattern data has 16 bytes
 {
   IIC_send(matrix_value[i]); //data to convey patterns
 }
 IIC_end();   //end the transmission of patterns data
 IIC_start();
 IIC_send(0x8A);  //display control, set pulse width to 4/16
 IIC_end();
}
//  the condition that data transmission starts 
void IIC_start()
{
 digitalWrite(SCL_Pin,HIGH);
 delayMicroseconds(3);
 digitalWrite(SDA_Pin,HIGH);
 delayMicroseconds(3);
 digitalWrite(SDA_Pin,LOW);
 delayMicroseconds(3);
}
// transmit data
void IIC_send(unsigned char send_data)
{
 for(char i = 0;i < 8;i++)  //Every character has 8 bits
 {
   digitalWrite(SCL_Pin,LOW);  //pull down the SCL_Pin to change the signal of SDA
   delayMicroseconds(3);
   if(send_data & 0x01)  //1 or 0 of byte  is used to set high and low level of SDA_Pin
   {
     digitalWrite(SDA_Pin,HIGH);
   }
   else
   {
     digitalWrite(SDA_Pin,LOW);
   }
   delayMicroseconds(3);
   digitalWrite(SCL_Pin,HIGH); //Pull up SCL_Pin to stop data transmission
   delayMicroseconds(3);
   send_data = send_data >> 1;  //Detect bit by bit, so move the data right by one bit
 }
}
//the sign that data transmission ends
void IIC_end()
{
 digitalWrite(SCL_Pin,LOW);
 delayMicroseconds(3);
 digitalWrite(SDA_Pin,LOW);
 delayMicroseconds(3);
 digitalWrite(SCL_Pin,HIGH);
 delayMicroseconds(3);
 digitalWrite(SDA_Pin,HIGH);
 delayMicroseconds(3);
}//*********************************************************

Mistake here.

2 Likes

Thank you, I might edit the post now and remove some of the other parts unnecessary to the problem to make it more legible.

Please don't. Post it in a new reply.

Worse. 2 mistakes now.

And please don't update previous posts. It's ok for spelling errors and broken links, things like that, but don't make changes that make later posts make no sense.

1 Like

Ah okay, i'll revert it, thanks for telling me about this.

If you have DC motors with no encoder, you will need to time the turns and use that timing data in your calculation for angle. If you are looking for methods of steering, here is a short simulation of the eight basic turning methods. Adding PWM to any of the turning methods will change the rate of turn.

1 Like

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