Reading digital and analog input simultaneously

Hello,

I’m currently working on a project for my final year of school. I am making an autonomous electric car that avoids obstacles using an ultrasonic sensor and also is able to detect metal. When turned on, the car will drive forwards, whilst detecting for metal and using the ultrasonic sensor to detect what’s in front of it. If an object comes within 30 centimetres, a servo will turn the front wheels 90 degrees and reverse back to avoid the obstacle. If metal is detected by the metal detector (using a digital input from an LED on the metal detector circuit) the car will stop and a buzzer will sound to signal that metal has been found. After 5 seconds the car will continue.

At the moment i have made two seperate codes (for each input), one for just the metal detector and the car, and one for the the ultrasonic sensor, servo, and car.
For the metal detector:

byte relayPin=2;
byte detectorPin=7; 
byte buz=4;
byte gLED=5;
byte rLED=3;
bool metalDetected;


void setup() {
  // put your setup code here, to run once:
pinMode(rLED, OUTPUT);
pinMode(gLED, OUTPUT); 
pinMode(buz, OUTPUT);
pinMode(relayPin, OUTPUT);
//we'll assume the detector is active low and needs a pullup
//detector pin normally high, goes low when detects something
pinMode(detectorPin, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly: 
  metalDetected=digitalRead(detectorPin);
  if (metalDetected==LOW) //not detected, assuming active low
  {
  digitalWrite(relayPin, HIGH); //drive the car
  digitalWrite(rLED, HIGH); // turn red LED on
  }
  else //it's HIGH, metal is detected
  { 
  digitalWrite(rLED, LOW); //turns red LED off 
  digitalWrite(relayPin, LOW); //stop the car
  digitalWrite(buz, HIGH); //buzzer will turn on
  digitalWrite(gLED, HIGH); //green LED turns on 
  delay(5000); //wait for 5 seconds 
  digitalWrite(buz, LOW); //turn off buzzer
  digitalWrite(gLED, LOW); //turn the green LED off

  }
}

And the servo and ultrasonic:

#include <Servo.h> 
#define trigPin 12 // define the pins of your sensor
#define echoPin 13 
#define rled 10 
#define gled 9
#define Servopin 11
Servo servo; 


void setup() {
  Serial.begin(9600); // begin serial communitication  
   pinMode(trigPin, OUTPUT);// set the trig pin to output (Send sound waves)
  pinMode(echoPin, INPUT);// set the echo pin to input (recieve sound waves)
  pinMode(rled, OUTPUT);
  pinMode(gled, OUTPUT);
  servo.attach(Servopin);
  

  
}
 void loop() {

   long duration, distance; // start the scan
  digitalWrite(trigPin, LOW);  
  delayMicroseconds(2); // delays are required for a succesful sensor operation.
  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //this delay is required as well!
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;// convert the distance to centimeters.
  if (distance < 30)/*if there's an obstacle 30 centimers, ahead, do the following: */ 
  {   
   Serial.println ("Close Obstacle detected!" );
Serial.println ("Obstacle Details:");
Serial.print ("Distance From Robot is " );
Serial.print ( distance);
Serial.print ( " CM!");// print out the distance in centimeters.

Serial.println (" The obstacle is declared a threat due to close distance. ");
Serial.println (" Turning !");
    servo.write(90);
    digitalWrite(rled, HIGH);
    delay(100);
    digitalWrite(gled, LOW);
    //ADD REVERSE DC MOTOR

}
  else {
   servo.write(0);
   Serial.println ("No obstacle detected. going forward");
   delay (15);
   digitalWrite(gled, HIGH);
   delay(100);
   digitalWrite(rled, LOW);
   //ADD FORWARD DC MOTOR 
  }
  
 
}

By the way, I will be using an l293d driver in place of the relay.

I want to incorporate the two codes but i’m unsure how to do it to allow simultaneous reading of both inputs. Would it be easier to use two arduino’s for each task or is there a way to incorporate the codes in such way that the arduino can read inputs from the sensor and detector at the same time?

Many thanks :slight_smile:

You can't do two things at exactly the same time but you can your code so that they will be done one after another so fast that it will seem like they were done at the same time. So you definitely don't need two Arduinos and I think it will be easier with one because you don't need to worry about communication between the two.

The trick is to write your code so that it's non-blocking. An example of blocking code is the delay(100) in your second sketch. For that 100 milliseconds the code is just sitting there at the delay. If the detector passes over the metal during that delay it will not be triggered. Depending on the range of the sensor, speed of the car, and size of the metal that may or may not be a problem but it's actually quite easy to write code without the use of delay. The key is to write your code so that the loop function is constantly running. If you need to wait for a specific amount of time or do something for a specific amount of time then you set a timestamp and then keep comparing millis() to the timestamp until the interval has passed. This technique is demonstrated at File > Examples > 02.Digital > BlinkWithoutDelay and the associated tutorial page: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay This is a very important skill to learn that is useful for just about any Arduino project so take some time to understand it.

In the case of the code you have posted I'm not sure that it is actually necessary to do any timed actions. Instead of turning for a fixed 100 ms you could turn until the ultrasonic sensor no longer detects an obstruction, then continue forward until another obstruction is detected.

As for the 5000 ms delay when metal is detected, you could get away with leaving that in. I find that whenever I write blocking code I end up having to rewrite the code later because it's interfering with a new feature I want to add. An example would be adding a button you can push to restart the car before the end of the 5 seconds. delay() will prevent the Arduino from detecting the button being pushed but if you had written a non-blocking delay using millis() in the BlinkWithoutDelay style then the Arduino could continue to poll the button pin during that 5000 ms.

Thanks for your advise! I'll do some research into the millis() coding and see how I go. If I were to copy the loop of my first sketch, would it not matter if i placed it before or after the second sketch's loop?

If I were to copy the loop of my first sketch, would it not matter if i placed it before or after the second sketch’s loop?

You can only have one loop() function in your program

Sorry, I mean inside the loop, but before or after the second sketch's main task, if that makes sense.

If you copy the code into loop() then it will be executed in the order in which you read it. However, you will need to eliminate any substantial delay()s unless they don't matter to both programs.

Ok thanks, i'll give it a go. :)