Stop getting values from arduino after some time - arduino

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.

Related

Arduino digital read is not working as expected

I have been using my Arduino to control motor polarity with a Cytron MD-10 motor driver shield, and I had it working.
Then when I came back to work it seemed as though the digital read pins were not differentiating between high and low voltage and one of the lights was powered on continuously.
The outputs function as set up with a continuous supply of measured 4.84 volts and then the switch is closed the voltage drops to 0 and the corresponding loop should be entered. Is my board fried?
Anything I should try?
const int outSwitch = 13;
const int inSwitch = 12;
const int pinPWM = 3;
const int pinDir = 2;
int lightOne = 11;
int lightTwo = 10;
static int Dir = 1;
static int cycleCounter = 0;
void setup() {
// Set Pin Out/Inputs:
pinMode(pinPWM, OUTPUT);
pinMode(pinDir, OUTPUT);
pinMode(outSwitch, INPUT);
pinMode(inSwitch, INPUT);
pinMode(lightOne, OUTPUT);
pinMode(lightTwo, OUTPUT);
analogWrite(pinPWM, LOW);
}
void loop() {
// Both read a low input value from the switch and then makes
// direction the opposite causing it to travel backwards:
if(digitalRead(inSwitch == LOW)){
analogWrite(pinPWM, HIGH);
digitalWrite(pinDir, Dir);
digitalWrite(lightOne, LOW);
digitalWrite(lightTwo, HIGH);
}
else if(digitalRead(outSwitch == LOW)){
analogWrite(pinPWM, HIGH);
digitalWrite(pinDir, -Dir);
digitalWrite(lightOne, LOW);
digitalWrite(lightTwo, HIGH);
}
}
Sma correctly identified the problem as a misplacement of the parentheses:
if (digitalRead(inSwitch == LOW)) // OOPS!
This compares inSwitch to LOW, which probably returns false. Since digitalRead expects an int, that false is converted to 0. So you do a read of pin 0. I don't think there is a pin 0, so you probably get an error. That return value is then implicitly compared to 0 in order to determine which branch of the if-statement to take.
The correct statement would look like this:
if (digitalRead(inSwitch) == LOW)
(Community Wiki because I'm just trying to provide a more detailed answer. I'm not trying to get rep for someone else's observation.)
What does analogWrite(pinPWM, HIGH); even mean? Missing a value (0-255), HIGH is not a valid value.

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 Uno Avoidance Robot: One of two motors not working

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.

Resources