Servo without library and delays

Hello! I used this code, but I need such a thing without delays. I heard about millis(), but I don’t know how to use it here. Can someone help me? Thanks!

int servo = 9;
int angle;
int pwm;

void setup()
{
pinMode(servo, OUTPUT);
}

void loop ()
{
for (angle = 0; angle <= 180; angle += 50) {
servoPulse(servo, angle); }
for (angle = 180; angle >= 0; angle -= 50) {
servoPulse(servo, angle); }
}

void servoPulse (int servo, int angle)
{
pwm = angle * 9 + 500;
digitalWrite(servo, HIGH);
delayMicroseconds(pwm); //First delay
digitalWrite(servo, LOW);
delay(50); //Second delay
}

Why on earth would you? Just grab the servo library and you’re done!

A mixed approach using micros() for the HIGH part of the control pulse, and millis() for the LOW part, and add a dash of blink without delay concept, and you're done.

Or, more sensibly, use the library.

There are some cases, where you can not use the servo library. For example it doesn’t work with virtualwire. I stumbled up this while programming a receiver for a plane, using basic RF link. So, every like 50 millis I run a code, which sets the pin to high, waits some microseconds, and sets it low again. Here is the full receiver code.

unsigned long A=0;
unsigned long B=0;
unsigned long C=0;
int n=5;
int m=5;
int k=1;
#include <VirtualWire.h>                                                                                                                  int count;
void setup()
{
    Serial.begin(9600);	// Debugging only
    Serial.println("setup"); //Prints "Setup" to the serial monitor
    vw_set_rx_pin(12);       //Sets pin D12 as the RX Pin
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(3800);	     // Bits per sec
    vw_rx_start();       // Start the receiver PLL running
    pinMode(11, 1);
    pinMode(13, 1);
    pinMode(2, 1);
    pinMode(3, 1);
    pinMode(4, 1);

    

}

void loop()
{
  digitalWrite(11, 1);
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    if (vw_get_message(buf, &buflen)) // Non-blocking
     
    {
      digitalWrite(13, 1);
	int i;
	// Message with a good checksum received, dump it.
	
	for (i = 0; i < buflen; i++)
	{
            char c = (buf[i]);
        if(c == 'q'){n = 1;}
        if(c == 'w'){n = 2;}
        if(c == 'e'){n = 3;}
        if(c == 'r'){n = 4;}
        if(c == 't'){n = 5;}
        if(c == 'y'){n = 6;}
        if(c == 'u'){n = 7;}
        if(c == 'i'){n = 8;}
        if(c == 'o'){n = 9;}
        
        if(c == 'a'){m = 1;}
        if(c == 's'){m = 2;}
        if(c == 'd'){m = 3;}
        if(c == 'f'){m = 4;}
        if(c == 'g'){m = 5;}
        if(c == 'h'){m = 6;}
        if(c == 'j'){m = 7;}
        if(c == 'k'){m = 8;}
        if(c == 'l'){m = 9;}

        if(c == 'Q'){k = 1;}
        if(c == 'W'){k = 2;}
        if(c == 'E'){k = 3;}
        if(c == 'R'){k = 4;}
        if(c == 'T'){k = 5;}
        if(c == 'Y'){k = 6;}
        if(c == 'U'){k = 7;}
        if(c == 'I'){k = 8;}
        if(c == 'O'){k = 9;}
        
        
	}
        count++;
    Serial.print(n);
    Serial.print(",");
    Serial.print(m);
    Serial.print(",");
    Serial.print(k);
    Serial.println(",");
    digitalWrite(13, 0);
    C=A;
    }
    if((A-C)>500){k=1; n=5; m=5;}
    A=millis();
    if(A-B>=60){
      B=A;
      PORTD |= _BV(PD2);
      delayMicroseconds(600+(n*70));
      PORTD &= ~_BV(PD2);
      delayMicroseconds(100);
      PORTD |= _BV(PD3);
      delayMicroseconds(600+(m*70));
      PORTD &= ~_BV(PD3);
      delayMicroseconds(100);
      PORTD |= _BV(PD4);
      delayMicroseconds(600+(k*70));
      PORTD &= ~_BV(PD4);
      }
      
    }

True, both VirtualWire and Servo take over timer1. But I find fixing that with a delay() based solution a bit urgly... And other people have already fixed it, ServoTimer2 is an example of that :)

tried my best to make it easier to understand how to make a servo signal.
the given code works fine with servo name SG90.

i make this code because i wanted to understand servo signals and by using a library i could not understand it fully.

/* this code is for a servo to move from 0 to 180 degree and 180 to 0 degree back. it will repeat itself without any further instruction. we did not use any library
to understand fully how a servo operates. /
/
we are not using a library therefor we need to understand how a servo works.

  • it is quite like a transistor in which maximum voltage and ground is applied and still we need a signal at base to flow current.
    in servo ground is connected to brown/black wire and 5 volt or operating voltage is applied to power input pin which is red in our case.
    a servo needs a signal at is signal input point which is in range of 1000 micro to 2000 micro seconds range. frequency of that signal should be 50hz.
    in our servo case its range is 700-2450 micro seconds for 0-180 degree angle.
    again its a little complex.
    for example 0 degree signal will be something like 5 volts for 700 micro seconds and 0 volt for 19300.
    note: only HIGH part of signal wont operate servo. we have to send complete HIGH and LOW signal to make servo work.
    */

int servo = 8; //servo is connected to pin 8.

int highDelay = 700;

/* highDelay is the time in which we want to keep voltage high on pin 8 and this unit is in micro seconds*/

int lowDelay ;

/* lowDelay is the time in which want to keep voltage zero across pin 8 again this unit is going to be in micro seconds*/

int angle = 10;

/* angle 10 = our signal range (2450 - 700) for SG90 divided by 180 which is equal to 9.8 something that we make 10 as an integer. angle 10 = 1 degree of servo. */

int Loop = 20000;

/* 20000 micro seconds or 20 milli seconds is signal cycle or u can say total signal should be equal to 20 milli seconds including HIGH and LOW input.*/

void setup() { pinMode (servo, OUTPUT);}

void loop() {

highDelay = highDelay + angle; // increasing angle to move servo

digitalWrite(servo, HIGH);

/* we are making pulse width modulation of frequency 50hz and frequency of pwm pins of arduino is more than 490 hz. */

delayMicroseconds(highDelay);

/* keep servo signal HIGH for 700 micro seconds or 700+10= 710 or 710+10=20 or accordingly from 700 to 2450. */

lowDelay = Loop - highDelay ;

/* lowDelay is declared here because we want it be inversely proportional to highDelay. */

digitalWrite(servo, LOW);

delayMicroseconds(lowDelay);

/* keep signal LOW for 19300 or 19300-10=19290 or accordingly bcz complete cycle of signal of HIGH and LOW should always be 20000 micro seconds.*/

delay (10);

// this is a delay to control moving speed after a complete signal transmission.

if ( highDelay >= 2450 || highDelay <= 700 ) { angle = -angle ; }

//after reaching 180 degree we want to come back to 0 degree so angle should be reversed and vice versa.

}

Hi, welcome to the forum. As you might have notice, your post is virtual unreadable... That's because it lacks code-tags. Have a look at How to use the forum on how to fix that.

Next on topic, why on earth still go for a blocking delay() solution ???