Using PWM to control a servo

You can use the PWM output, or more technically PPM (Pulse Position Modulation) - to control a servo.

Let’s start with connecting a servo:

We will use port 11, as typically we would use one of PWM-capable pins for servo control, there are alternatives though.

Starting code below:

#include <Arduino.h>
#include <Servo.h>

Servo myservo;
void setup(){
  myservo.attach(11);
}

void loop(){
  for(uint16_t i = 0; i <= 180 i++){
    myservo.write(i);
    delay(20);
  }
  for(uint16_t i = 180; i >= 0 i--){
    myservo.write(i);
    delay(20);
  }
  delay(1000);
}

Let’s try to build, and… whoops! Most likely the code has failed to build due to unavailable libraries:

Luckily PlatformIO makes it ieasy for us to solve the issue, let’s try to do what they suggest and use the search on their website: https://platformio.org/lib/search?query=header:Servo.h.

Usually it’s worthy checking out most downloaded libraries first:

If you go to the “Installation” tab you should see the recommended way to add the library as a dependency to your project.

Let’s open up platformio.ini and add it:

Right under framework = arduino let’s paste the following:

lib_deps =
    arduino-libraries/Servo @ ^1.1.8

Let’s try again to build, upload and verify. Now the servo should be moving from 0 to 180 degress and then down from 180 to 0.

TASK: Servo action after a button press

Let’s try to build a simple logic with the servo that will:

  • set up an interrupt for a button press
  • move the servo quickly to 100 degrees
  • hold for 3 seconds
  • move the servo slowly to 140 degrees
  • hold for 1 second
  • move the servo quickly back to 0 degrees The imagined use case is that you are opening something up based on a button press.

Suggestions:

  • if you just set the servo to given angle it’s reaction could be too dynamic, let’s try to use loops to make the movement with a manageable speed.
  • rather than using three separate loops, you could write a single function that would move the servo from given angle to given angle, with a specific speed,

Using digital gpio to control a stepper motor

It is also possible to use plain digital GPIO to control a stepper motor via an external driver.

Please connect the stepper motor driver to the Arduino:

  • IN1 - GPIO 11
  • IN2 - GPIO 10
  • IN3 - GPIO 9
  • IN4 - GPIO 8
  • 5V - 5V
  • GND - GND

And let’s try the starting code:

#include <Arduino.h>
#include <Stepper.h>
const int stepsPerRev = 200;
Stepper myStepper(stepsPerRev, 8, 9, 10, 11);

void setup(){
  myStepper.setSpeed(50);
}

void loop(){
  myStepper.step(stepsPerRev / 100);
}

Using PWM to control a buzzer

PWM can also be used to generate simple, square wave tones and emit sounds with a buzzer.

You can just connect it to any of the PWM capable pins and ground:

Starting code would be as simple as this:

#include <Arduino.h>
#define BUZZER_PIN 9
void setup(){
  pinMode(BUZZER_PIN, OUTPUT);
}

void loop(){
  tone(BUZZER_PIN, 440, 100);
  delay(1000);
}

Ultrasonic distance measurement

Let’s try to use an ultrasonic distance measurement module. It works on a simple principle of sending and ultrasound signal and waiting for it to bounce back.

To connect it to your board you need to attach power (5V & GND) and two digital signals - TRIG and ECHO. Any digital pins can be used.

Example wiring on a diagram:

To work with the sensor you will need a proper library. A quick search on platformio would bring up: https://platformio.org/lib/show/1507/Ultrasonic

Let’s try to add that library to your project (edit platformio.ini) and try a basic example.

#include <Arduino.h>
#include <Ultrasonic.h>

Ultrasonic ultrasonic(12, 13);

void setup() {
  Serial.begin(9600);
  ultrasonic.setTimeout(40000UL);
}

void loop() {
  Serial.print("Distance [cm]: ");
  Serial.println(ultrasonic.read());
  delay(1000);
}

Let’s try to build, upload & verify the serial output.

TASK: Lowering the sensor timeout for robustness

Important note - observe what happens when there is nothing in front of the sensor - how long it takes for the code to timeout practically blocking the code from moving with any other work.

If you have an use-case that doesn’t really require full sensor range (typically up to 200cm), but you only care if there is something close to the sensor - you can address that issue setting the timeout lower.

Let’s try to modify

TASK: build a complete parking sensor solution

Now you should have all the tools required to build a fully functional parking sensor.

Let’s try to implement the following:

  • ultrasonic sensor with distance measurement in the range of 0-50cm
  • a few LEDs displaying the measured distance
  • buzzer that will change its tone and period between beeps when the object gets closer

Next steps

Now let’s continue to work with digital I2C bus and an OLED screen