Hi all, I’m new to Arduino and the forums.
My first project is a basic obstacle avoidance robot. I use an Uno with a motor shield, driving 2 DC motors that power the wheels. I also use a US sensor mounted on a servo to get distances (left, right and centre).
My first iteration, the robot did things in sequence, i.e. move forward, if an obstacle is too close, then scan left and right, turn, then go again. It worked all fine.
I wanted to make it scan and move at the same time. so I modified my code based on this one. It all works nicely, the robot scans at the same time that it moves, so it knows where to turn as soon as it has to. Sweet!
Here is the code I’m currently using.
#include <Servo.h>
#define runEvery(t) for (static typeof(t) _lasttime;(typeof(t))((typeof(t))millis() - _lasttime) > (t);_lasttime += (t))
Servo RadarServo;
// from 9V to 6V
const float MotorReduction = 0.66;
const int
PWM_L = 3, // motor 1 pins
DIR_L = 12,
BRA_L = 9,
CUR_L = A0,
PWM_R = 11, // motor 2 pins
DIR_R = 13,
BRA_R = 8,
CUR_R = A1,
USPin = A2, // ultrasonic sensor pin
TurnInterval = 500; // time spent turning / moving backwards
int MotorSpeed;
int rawDist;
int USpos = 82; // servo position to centre the US sensor
int USdir = 0; // 0 = going left, 1 = going right
int Ldist = 200; //distance left of robot
int Cdist = 200; //distance centre of robot
int Rdist = 200; //distance right of robot
int RobotDir = 0; // forward = 0 back = 1 left = 2 right = 3
int oldRobotDir = 0;
long oldTimer = 0;
int SweepSpeed = 40; //sweep speed ms
void setup(){
RadarServo.attach(4);
RadarServo.write(USpos);
pinMode(USPin,INPUT);
pinMode(PWM_L,OUTPUT);
pinMode(DIR_L,OUTPUT);
pinMode(BRA_L,OUTPUT);
pinMode(CUR_L,INPUT);
pinMode(PWM_R,OUTPUT);
pinMode(DIR_R,OUTPUT);
pinMode(BRA_R,OUTPUT);
pinMode(CUR_R,INPUT);
digitalWrite(BRA_L,LOW);
digitalWrite(DIR_L,LOW);
analogWrite(PWM_L,0);
digitalWrite(BRA_R,LOW);
digitalWrite(DIR_R,HIGH);
analogWrite(PWM_R,0);
Serial.begin(9600);
}
void loop(){
Scan();
Ping();
// Serial.println(rawDist);
if (USpos >= 0 && USpos <= 30){ // if sensor is to the far left we get left dist
Ldist = rawDist;
}
if (USpos >= 134 && USpos <= 164){ // if sensor is to the far right we get right dist
Rdist = rawDist;
}
if (USpos >= 67 && USpos <= 97){ // ... centre dist
Cdist = rawDist;
}
if (Cdist >= 20){ // front clear, go forward
RobotDir = 0;
}
else // need to turn
{
if (Ldist >= Rdist){
RobotDir = 2;
}
if (Ldist < Rdist){
RobotDir = 3;
}
if(Ldist <= 20 && Rdist <= 20 && Cdist <= 20){
RobotDir = 1;
}
}
// now move according to measures
//Serial.println(RobotDir);
unsigned long newTimer = millis(); //set a timer
if (RobotDir == 0 && RobotDir == oldRobotDir){
Serial.println(RobotDir);
MoveFor();
oldRobotDir = RobotDir;
}
if (RobotDir == 0 && RobotDir != oldRobotDir && newTimer - oldTimer > TurnInterval){
Serial.println(RobotDir);
MoveFor();
oldRobotDir = RobotDir;
oldTimer = newTimer;
}
if (RobotDir == 1 && RobotDir == oldRobotDir){
Serial.println(RobotDir);
MoveBack();
oldRobotDir = RobotDir;
}
if (RobotDir == 1 && RobotDir != oldRobotDir && newTimer - oldTimer > TurnInterval){
Serial.println(RobotDir);
MoveBack();
oldRobotDir = RobotDir;
oldTimer = newTimer;
}
if (RobotDir == 2 && RobotDir == oldRobotDir){
Serial.println(RobotDir);
MoveLeft();
oldRobotDir = RobotDir;
}
if (RobotDir == 2 && RobotDir != oldRobotDir && newTimer - oldTimer > TurnInterval){
Serial.println(RobotDir);
MoveLeft();
oldRobotDir = RobotDir;
oldTimer = newTimer;
}
if (RobotDir == 3 && RobotDir == oldRobotDir){
Serial.println(RobotDir);
MoveRight();
oldRobotDir = RobotDir;
}
if (RobotDir == 3 && RobotDir != oldRobotDir && newTimer - oldTimer > TurnInterval){
Serial.println(RobotDir);
MoveRight();
oldRobotDir = RobotDir;
oldTimer = newTimer;
}
}
void MoveFor(){
digitalWrite(DIR_L,LOW);
digitalWrite(DIR_R,HIGH);
analogWrite(PWM_L,150);
analogWrite(PWM_R,150);
}
void MoveBack(){
digitalWrite(DIR_L,HIGH);
digitalWrite(DIR_R,LOW);
analogWrite(PWM_L,150);
analogWrite(PWM_R,150);
}
void MoveLeft(){
digitalWrite(DIR_L,HIGH);
digitalWrite(DIR_R,HIGH);
analogWrite(PWM_L,90);
analogWrite(PWM_R,90);
}
void MoveRight(){
digitalWrite(DIR_L,LOW);
digitalWrite(DIR_R,LOW);
analogWrite(PWM_L,90);
analogWrite(PWM_R,90);
}
void Stop(){
analogWrite(PWM_L,0);
analogWrite(PWM_R,0);
}
void Scan(){
runEvery(4){
if(USpos > 3 && USdir == 0){
USpos = USpos - 1; // change direction to right
}
if(USpos <163 && USdir == 1){
USpos = USpos + 1; // change direction to right
}
}
if (USpos <= 3){
USdir = 1;
}
if(USpos >= 163){
USdir = 0;
}
RadarServo.write(USpos);
}
void Ping(){
runEvery(40){
rawDist = analogRead(USPin);
}
}
No my problem. The ultrasonic sensor seems quite sensitive, the readings fluctuate a LOT. So I’d like to average its readings. I managed to do that in the 1st iteration of the code, but now that the sweep/scan functions do not use delay(), I’m a bit lost.
It was easy to do before with a simple “for” loop inside the Scan function, but know I think it would have to be a loop in the loop()… I’m not really sure.
I would greatly appreciate any suggestions. Thanks!
Edit: added the code directly in the post, thanks wildbill.