Arduino Uno Avoidance Robot: One of two motors not working - arduino

I'm trying to code an Arduino avoidance robot as a learning project. When I run the following code only one motor (the left one) works. If I comment out the if statement that uses the checkDistance() function and just loop the forward() function both motors work fine. I'm using an Adafruit Motorshield v1.2, and I believe this is the motor: Link. I've tried powering directly through USB, and also through external power supply (4 x AAs), and have the same issue. Any pointers would be appreciated. Thank you!
#include <AFMotor.h>
#define trigPin 3
#define echoPin 2
AF_DCMotor left_motor(2, MOTOR12_64KHZ); // create motor #1, 64KHz pwm
AF_DCMotor right_motor(1, MOTOR12_64KHZ); // motor #2\
int maxDistance = 30;
//int minDistance = 0;
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
left_motor.setSpeed(255);
right_motor.setSpeed(255);
}
void forward(int delayTime) {
left_motor.run(FORWARD);
right_motor.run(FORWARD);
delay(delayTime);
}
void backward(int delayTime) {
left_motor.run(BACKWARD);
right_motor.run(BACKWARD);
delay(delayTime);
}
void stop(int delayTime) {
left_motor.run(RELEASE);
right_motor.run(RELEASE);
delay(delayTime);
}
void right(int delayTime) {
left_motor.run(FORWARD);
right_motor.run(BACKWARD);
delay(delayTime);
}
void left(int delayTime) {
left_motor.run(BACKWARD);
right_motor.run(FORWARD);
delay(delayTime);
}
int checkDistance(){
long duration, distance;
/* The following trigPin/echoPin cycle is used to determine the
distance of the nearest object by bouncing soundwaves off of it. */
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
//Calculate the distance (in cm) based on the speed of sound.
distance = duration/59.1;
return distance;
}
void loop() {
int currentDistance = checkDistance();
Serial.print(currentDistance);
if (currentDistance >= maxDistance){
Serial.println(" cm. No immediate obstacles detected. Moving forward.");
forward(2000);
stop(1000);
}
else {
Serial.println(" cm. Obstacle detected. Changing direction.");
right(1500);
stop(1000);
}
}

If I were trying to debug this, I would first test each of the motor functions without any logic check from the sensor. (e.g. do both wheels turn and in the correct direction when left, right, backward, etc are called just from loop()). That will give confidence that it is not a wiring or other hardware problem. If they don't work then sorting that out give you a place to start.
If they do work, then it must be the values with the sensor, right? How did you determine the maxDistancevalue? If it is too high then this line:
if (currentDistance >= maxDistance){
may never evaluate to true. You have some log statements in there so you have some sense of the value of currentDistance. Does it seem to be reflecting accurate values when you place objects at varying distances from the sensor?
Anyway... some thoughts.

Related

Stop getting values from arduino after some time

I have a strange problem, I have Arduino UNO/MEGA and I need to get Gyro sensors's data and I want to see the data in the serial monitor. Seems like a simple task, I wrote a simple C program which collects data from Arduino through serial monitor I can see the data. Everything is working for few minutes and after that, it stops.
This code is supposed to calculate a distance travelled in a line using encoder (PID algorithm implemented using Gyroscope data for straight motion) after reaching desired position, machine takes a U-Turn.
It stop for a second after taking the U-Turn and then starts straight motion again. The problem I'm facing is that the gyroscope readings stop randomly while machine taking the turn. Due to this, the machine keeps rotating about that point without stopping.
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
float timeStep = 0.01, yaw=0;
const int motor11=6;//LEFT MOTOR FW
const int motor12=7;//LEFT MOTOR BK
const int motor1pwm=3;
const int motor21=8;//RIGHT MOTOR FW
const int motor22=9;//RIGHT MOTOR BK
const int motor2pwm=5;
int flag1 = 0;
int thres1=120;//PWM Values
int thres2=120;
void setup()
{
Serial.begin(115200);
// Initialize MPU6050
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
mpu.calibrateGyro();
mpu.setThreshold(1);
pinMode(motor11, OUTPUT);
pinMode(motor12, OUTPUT);
pinMode(motor1pwm, OUTPUT);
pinMode(motor21, OUTPUT);
pinMode(motor22, OUTPUT);
pinMode(motor2pwm, OUTPUT);
}
void loop()
{
Vector norm=mpu.readNormalizeGyro();
yaw=yaw+norm.ZAxis*timeStep;
if(flag1 == 0){
straight();
}
if(flag1 == 2){
taketurn();
}
}
void straight()
{
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, thres1);
digitalWrite(motor21, HIGH);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, thres2);
delay(8000);
flag1 = 2;
}
void taketurn()
{
float setPoint = yaw - 500;
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, 120);
digitalWrite(motor21, LOW);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, 120);
while(true)
{
Vector norm = mpu.readNormalizeGyro();
yaw = yaw + norm.ZAxis * timeStep;
Serial.print("Turning Yaw= ");
Serial.println(yaw);
if(setPoint >= yaw) {
digitalWrite(motor11, LOW);
digitalWrite(motor12, LOW);
analogWrite(motor1pwm, thres2);
digitalWrite(motor21, LOW);
digitalWrite(motor22, LOW);
analogWrite(motor2pwm, thres1);
delay(2000);
break;
}
}
flag1 = 0;
}
The serial monitor just stops displaying the reading. This does not happen every time, and it is very random. I want to get proper and continuous data. Is it a logical problem or a board problem?
Normally a random crash would indicate possibly unhandled interrupts or memory overwrite, but looking at your code and it being an Arduino program, it's unlikely to be either. I don't see any divide ops either, so you are not dividing by zero. The two possible things I see is that a) you have a "while (true)" without exit, so surely that could get you into trouble, and b) perhaps your delay functions are called with a very large value unexpectedly, and the MCU is actually just delaying a long time.

How to stop pwm after generate few pulse in Arduino?

I'm trying to generate pulse from Arduino to driver motor stepper 5 phase.
The driver only needs pulse to make motor stepper work. My problem is when I'm using code like this
for(int i=0; i <= 125; i++)
{
//analogWrite(13,125);
digitalWrite(13, HIGH);
delayMicroseconds(300);
digitalWrite(13, LOW);
delayMicroseconds(300);
}
digitalWrite(13,LOW);
delay(3000);
Stepper motor can work perfectly, but after more than 10 rotation,
the angle of the motor did not return to the original place. Can we use pwm in Arduino like that? So after generating 5000 pulses using pwm, we stop the pwm?
try this code:
#include <TimerOne.h>
const byte CLOCKOUT = 11;
volatile byte counter=0;
void setup() {
Timer1.initialize(15); //Every 15 microseconds change the state of the pin in the wave function giving a period of 30 microseconds
Timer1.attachInterrupt(Onda);
pinMode (CLOCKOUT, OUTPUT);
digitalWrite(CLOCKOUT,HIGH);
}
void loop() {
if (counter>=6000){ //With 6000 changes you should achieve the amount of pulses you need
Timer1.stop(); //Here I create the dead time, which must be in HIGH
PORTB = B00001000;
counter=0;
delayMicroseconds(50);
Timer1.resume();
}
}
void Onda(){
PORTB ^= B00001000; //Change pin status
counter+=1;
}
I just cant not eliminate the jitter. If you find a solution let me know

Arduino IR Sensors Not Calling Functions

With this code written in the Arduino IDE I used to be able to call functions based on which Infrared sensor detected an object(right, left, or both). I altered the code a little bit lately but I've continued to make sure it wasn't missing any key components which made it work in the first place. I'm not sure if it's an error in my program or hardware but now, no matter what sensor detects an object, my robot just turns slightly to the left.
//Include Servo Library
#include <Servo.h>
//Define Pins for the Sensors and LEDs
#define LsensorPin 8
#define RsensorPin 5
#define LeftTransPin 7
#define RightTransPin 6
I'm using continuous rotation servos so using 0's and 180's is how I would control them at full speed. I checked the numbers over and over but they don't seem to be the problem.
//Constants for driving servo
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //0 Speed
//Name the Servos for Left and Right Motor
Servo LMotor;
Servo RMotor;
The following 2 functions, when called, transmit an infrared signal through the transmitters. I do not think this is related to the problem because the sensors still detect objects, but my robot just doesn't respond the way I want it to.
//Take Reading from Left IR Sensor
void LeftIRled(){
for(int i=0;i<=384;i++){
digitalWrite(LeftTransPin, HIGH);
delayMicroseconds(13);
digitalWrite(LeftTransPin, LOW);
delayMicroseconds(13);
}
}
//Take Reading from Right IR Sensor
void RightIRled(){
for(int i=0;i<=384;i++){
digitalWrite(RightTransPin, HIGH);
delayMicroseconds(13);
digitalWrite(RightTransPin, LOW);
delayMicroseconds(13);
}
}
These functions control the direction in which the robot moves. I've checked it many times but this could possibly be one of the problems. They basically just control the spin of each individual servo with the previously declared variables.
//Controlling Servo Directions with Functions
void Forward(){
RMotor.write(RForward);
LMotor.write(LForward);
}
void Backup(){
RMotor.write(RBackward);
LMotor.write(LBackward);
}
void Stop(){
RMotor.write(RNeutral);
LMotor.write(LNeutral);
}
void Left(){
RMotor.write(RForward);
LMotor.write(LNeutral);
}
void Right(){
RMotor.write(RNeutral);
LMotor.write(LForward);
}
//Declare INPUT and OUTPUT for each Pin connected
//to Arduino Uno and set them to LOW
void setup(){
pinMode(LeftTransPin, OUTPUT);
digitalWrite(LeftTransPin, LOW);
pinMode(RightTransPin, OUTPUT);
digitalWrite(RightTransPin, LOW);
//drive forward
LMotor.attach(9);
RMotor.attach(10);
Forward();
}
Although I can't pinpoint the problem I believe it has something to do with the loop function. It is here that I transmit the infrared signal, receive it, and then call various functions which control the movement of the robot.
void loop(){
/*Drive forward until you reach an obstacle on either the
right side, left side, or both together(something in front of
you). If the left sensor goes low, he turns right, if the right
sensor goes low, he turns left. if both turn on at the same time
he stops, backs up, and turns right till he is out of danger
*/
int lstate;
int rstate;
LeftIRled();
lstate = digitalRead(LsensorPin);
delay(50);
RightIRled();
rstate = digitalRead(RsensorPin);
delay(50);
if (lstate == LOW && rstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Stop();
delay(100);
Right();
delay(500);
}
else if (lstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Right();
delay(500);
}
else if (rstate == LOW)
{
Stop();
delay(100);
Backup();
delay(1000);
Left();
delay(500);
}
else
{
Forward();
}
}
Any help or advice is greatly appreciated!

Arduino HC-SR04 NewPing Code Not Working

I was getting to know this ultrasonic detector with a simple code. All I was looking for was an output (my LED) to light up whenever the detector sensed an object within so many centimetres.
However the LED remains lit and the serial monitor just keeps spitting out the value '0.00cm'
I would appreciate any help, thanks.
(I do apologise if there is a very simple error I have overlooked)
#include <NewPing.h>
int TriggerPIN = 2;
int EchoPIN = 3;
int LEDPIN = 7;
void setup()
{
Serial.begin(9600);
//That started the distance monitor
pinMode(LEDPIN, OUTPUT);
pinMode(TriggerPIN, OUTPUT);
pinMode(EchoPIN, INPUT);
}
void loop()
{
float Distance, Duration;
digitalWrite(TriggerPIN, LOW);//These three blink the distance LED
delayMicroseconds(2);
digitalWrite(TriggerPIN, HIGH);
delayMicroseconds(10);
digitalWrite(TriggerPIN, LOW);
Duration = pulseIn(EchoPIN, HIGH); //Listening and waiting for wave
Distance = (Duration*0.034/2);//Converting the reported number to CM
if (Distance > 50)
{
digitalWrite(LEDPIN,LOW);
}
else
{
digitalWrite(LEDPIN,HIGH);
}
Serial.print(Distance);Serial.print("cm");
Serial.println(" ");
delay(200);
}
A couple of things to try:
Change the serial print to display 'Duration', to see if the problem lies in the centimetre conversion.
If this is not the problem:
(Assuming you are using the NewPing 1.7 library, as found here. )
The NewPing library has a built in 'Ping' function, along with distance conversion.
Try replacing the start of your code with this:
#include <NewPing.h>
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 200 // Maximum distance to ping for (cm). Up to ~450cm
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
You do not need to then set the Trigger and Echo pins as outputs in your setup.
In your main loop, use these methods to get time and distance in microsecs and centimetres:
unsigned int pingTime = sonar.ping(); //Gets the ping time in microseconds.
Serial.print(sonar.convert_cm(pingTime)); // Convert ping time in cm, serial out.
I hope this helps.

Arduino - Using interrupts freezes processing and serial output?

So, the interrupts seem to work insofar as "interrupting" when an event happens. My only problem is that I the interrupts will occur 2-3 times and everything essentially stops (Serial out, everything).
I was programming the board to output serially a calculated distance based on the output of the HC-SR04 distance IC. The distances are calculated accurately but, like I said earlier, everything seems to freeze. Below is both the code and an image of the serial monitor.
#define TRIGPIN 4
#define ECHOPIN 3
#define RED 2
#define GREEN 13
#define INTNUM 1 //interrupt pin 1 is digital pin 3 on the duemilanove
#define PULSE 10 //microseconds
#define CYCLETIME 50 //milliseconds
void ledWrite(int), trigPulse(), getTime();
int millisNow, millisPrev = 0;
int microsPrev;
boolean isHigh = false;
void setup() {
Serial.begin (9600);
pinMode(TRIGPIN, OUTPUT);
pinMode(ECHOPIN, INPUT);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
attachInterrupt(INTNUM, getTime, CHANGE);
}
void loop() {
trigPulse();
// some other code while waiting on HC-SR04 to interrupt us when echo goes HIGH
}
void trigPulse(){
if( (millisNow = millis()) - millisPrev >= CYCLETIME){ //sufficient cycle time
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(PULSE);
digitalWrite(TRIGPIN, LOW);
millisPrev = millisNow; //reset clock
}
return;
}
void ledWrite(int dTime){
int distance = dTime/58.2;
if (distance < 4) {
digitalWrite(RED,HIGH);
digitalWrite(GREEN,LOW);
}
else {
digitalWrite(RED,LOW);
digitalWrite(GREEN,HIGH);
}
if (distance >= 200 || distance <= 0){
Serial.println("Out of range");
}
else {
Serial.print(distance);
Serial.println(" cm");
}
}
void getTime(){
int timeNow = micros();
Serial.println("Interrupted");
if(isHigh == false){
microsPrev = timeNow; //get time now, pin LOW->HIGH
isHigh = true;
Serial.println("Returning ..");
return;
}
else { //pin HIGH->lOW
ledWrite(timeNow - microsPrev);
isHigh = false;
microsPrev = micros();
Serial.println("Returning ..");
return;
}
return;
}
I know this is an old thread, but I just came by it having my own problems. The problem here is that you cannot use:
Serial.Print()
Within an interrupt service routine. The reason that the Serial.Print() doesn't work within an ISR is that it uses interrupts to pull the characters out of the serial buffer, but interrupts of a certain level are masked within the ISR. What basically happens is that the arduino throws out all other interrupts that are of a lower priority, which Serial.Read() falls into.
It is documented in a number of places: link1, link2, link3
I think you are getting interrupt while you are already processing interrupt. You should try disabling the interrupt as soon as you are in interrupt function and re-enable it again when you are done processing just before return. Hence I would advice to have just one return so that you don't have to repeat code of enabling interrupt. Also make sure the function which you are calling inside your interrupt code do not re-enable the interrupt. It may happen that the function micros() or any of the Serial function are re-enabling the interrupt.
I would suggest instead of calling function directly in you interrupt code try using some flags and set/reset in interrupt and use these flags in main loop to call your regular function.

Resources