1

I am a beginner in arduino and due to the lockdown I have been learning it by implementing it on tinkercad. I have made a simulation where I have attached :

  1. Servo Motor

  2. Ultrasonic Sensor

  3. Led Bulb

  4. LCD display

to an arduino uno 3

My AIM : When something falls under 30cm of the ultrasonic sensor, the servo motor starts from zero position and goes upto 180 degrees in a span of 20seconds and then goes back to its initial position. At the same time and led switches on for 20s and switches off when the motor returns back to its position. I was able to successfully implement this. But then I added an lcd to show the time i.e time is initialized at 0seconds and then goes to 20 seconds and when the motor resets. Time also resets.

I was able to make a timer on another simulation and I tried to run it in this one by placing the code correctly but I am not able to figure out how?

The present code I have written keeps blinking the led at an interval of one second and the servo moves very very slowly.

Any sort of help will be amazing.

This is my simulation, I have made it public, you may copy and simulate it if you have a tinkercad account. Even without an account you can see how it looks.

Here is the code: (Please ask if you want me to add comments some areas)

//library code for lcd
#include <LiquidCrystal.h>
//setting up pins
const int rs = 9, en = 8, d4 = 5, d5 = 4, d6 = 3, d7 = 2;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


unsigned long readTime=20; 



//servo motor
#include <Servo.h>
Servo servo_9;
int pos = 0;
//servo motor end

//ultrasonic sensor pin
const int pingPin = 12;

//lcd
signed short seconds;
char timeline[16];

void setup()
{
  
  servo_9.attach(13); //servo pin
  Serial.begin(9600);
  
  pinMode(11,OUTPUT);// led 
  
  //lcd initialize
  lcd.begin(16, 2);
  lcd.print("Time : ");

}

void loop()
{
  
  long duration, cm;
  //Ultrasonic start
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  cm = microsecondsToCentimeters(duration);

  // Print the distance
  Serial.print("Distance: ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  // ultrasonic end
  
  
  // the servo motor should activate when object is
  //less than 30cm close to the sensor
  
 if(cm < 30) {
   
  // sweep the servo from 0 to 180 degrees in steps
  // of 1 degrees
  for (pos = 0; pos <= 180; pos += 1) {
    
    // tell servo to go to position in variable 'pos'
    servo_9.write(pos); 

     //LCD TIMER START
    lcd.setCursor(0, 1);
    sprintf(timeline,"%0.2d secs", seconds);
    lcd.print(timeline);
    delay(1000);
    seconds++;


    //led buld switch on
    digitalWrite(11,HIGH);

    // wait 20ms for servo to reach the position
    delay(200);

    //switch of the bulb
    digitalWrite(11,LOW);

     
  }
   
  
  //moving servo back to zero
  for (pos = 180; pos >= 0; pos -= 1) {
      // tell servo to go to position in variable 'pos'
      servo_9.write(pos);
      // wait 20 ms for servo to reach the position
      delay(20); // Wait for 15 millisecond(s)
            }
  
    } //if end
 
  
  delay(100);


}//loop end


//FUNCTIONS 

long microsecondsToCentimeters(long microseconds) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}


4
  • 1
    This program spends most of its time executing delay(), which does no useful work. Study the Blink Without Delay Arduino tutorial and see if it answers your question. Jun 20, 2020 at 7:58
  • The servo moves with the speed you programmed it. (And there are delays between the moves. ) And don't think in "multiple processes". It's easier than that and you don't have an operating system on an uno. Jun 20, 2020 at 11:26
  • @EdgarBonet thank you. I will check it out
    – curse
    Jun 20, 2020 at 18:52
  • @DataFiddler ok sure. Thanks for the guidance !!
    – curse
    Jun 20, 2020 at 18:52

1 Answer 1

7

Think of an Arduino as a circus clown spinning plates. It has to spend very little time on any one plate, and then it can keep a lot of plates spinning, moving quickly from one to the next.

That's how "multi-tasking" works on a realtime device like an Arduino. You write a loop function that buzzes through a bunch of sub-tasks, spending a few microseconds on each one, and then repeats the process. Each plate (sub-task) gets a little bit of time on each pass, but only a little.

The delay() function is the death of that. If you're in a delay(), everything comes to a screeching halt. Your program stops checking for button presses, stops switching output pins to control your motors, etc. It's like the clown taking a coffee break. The plates start crashing to the ground.

You might get away with single-digit delays for things like timing changes in output state (and delayMicroseconds() is rarely a problem since those delays are so short), but a delay(1000) means everything comes to a screeching halt for a full second.

You need to refactor your code to get rid of calls to delay() with delay values of more than a few milliseconds. Do a search on "Arduino blink without delay" to figure out how.

Note that on a single core device with preemptive multi-tasking, the circus clown analogy still holds, but now the OS serves as the clown's manager. The OS schedules the clown's time, and tells it when to switch between plates. If the clown gets distracted by a particularly shiny plate and tries to spend too long on that plate, the OS forces the clown to switch plates. The OS also saves the clown's current state each time it switches away from a task, and restores that state when it returns to that task.

On A multi-core device with preemptive multi-tasking, the manager (OS) has a team of clowns (cores). Each clown (core) gets assigned to different plates (tasks), and all the clowns work at the same time (The cores run concurrently.) The OS has to make sure the clowns (cores) don't bump elbows (have conflicting access to the same memory or other resources.)

4
  • Thanks a lot for the answer. It clears a lot of things for me as I am new here and puts the functioning of arduino in a better perspective.
    – curse
    Jun 20, 2020 at 18:54
  • upvote for the best analogy of multitasking i have seen so far ... the spinning plate circus act may actually be something that almost everyone has seen
    – jsotola
    Jun 20, 2020 at 19:18
  • Best analogy I've heard for Arduino loops so far. I created an account over here to upvote it.. Jun 21, 2020 at 2:24
  • Thank you again. I was able to refactor my code to make it work after implementing the Arduino Work Without Delay Article
    – curse
    Jun 21, 2020 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.