Sample code for tower pro SG90 servo?

Can someone help me out with sample code for the common Tower Pro SG90 servo?

I’m able to get the servo to move briefly when I plug this in:

`// April controlling a servo with PWM

// Configure hardware
// the servo used in this example have ~170 degrees of range. Each servo has three pins: power, ground, and pulse in
// The width of the pulse determines the position of the servo
// The servo expects a pulse every 20 to 30 ms
// 0.8 ms pulse -> fully counterclockwise
// 2.6 ms pulse -> fully clockwise
// set up PWM on both pins at a period of 20 ms, and initialize the duty cycle
hardware.pin7.configure(PWM_OUT, 0.5, 0.018);

server.log("Hardware Configured");
 
class servo extends InputPort
{
 
    name = "servo position"
    type = "number"
 
    function set(value) {
        hardware.pin7.write(0.04 + (value * 0.09));
        //server.log(format("%s set to %.2f", name, value));
    }
}`

I have to play with the values in the first line after PWM_OUT to get it to move.

I want the servo to move to a known 90 degree position when a button is pushed on a webpage (via agent code) and then slowly return -90 degrees to a reset position. If the user presses the button while it is returning, it will move to that same 90 degree position again (not 90+ current location). Does this make sense?

For starters I just need to get the servo moving properly.

Thanks,

John

Thanks everyone but I figured it out. FYI, the sample servo code in the Developer Documentation is broken. It builds, but throws errors when run.

Can you point us to where you found that documentation? That example is using very old code, and as you mention - isn’t going to work.

I figured it out on my own by going through various documentation here. No single source.

Here is the working code:
`
// Simple Servo Test Code
// Copyright © 2015 ManganLabs.com
//
// Moves servo from a defined start position (SERVO_MIN) to a target position (SERVO_MAX)
// then slowly decrements back to start position.
//
// Designed for use with TowerPro Micro Servo model SG90
// USE AT YOUR OWN RISK

const SERVO_MIN = 0.05 //duty cycle
const SERVO_MAX = 0.12

// Tweak the following two values to change how fast the servo returns to start position
const angleDecrement = 0.005 //Increase number, keeping lower than SERVO_MIN to adjust angle decrement
const sleepTime = 0.5 //Controls the delay between each return movement

servo <- hardware.pin7 //set to the signal pin that your servo is connected to

// Don’t Change anything Past Here
servo.configure(PWM_OUT, 0.02, SERVO_MIN)
server.log(“Device Online!”);

local position = 0.0 //write current position

function moveFast() {

servo.write(SERVO_MAX);
server.log("Servo Moved")

}

function returnSlow() {
local angle = SERVO_MAX

while (angle >= SERVO_MIN) {
    servo.write(angle)
    angle = angle-angleDecrement
    server.log(angle)
    imp.sleep(sleepTime)
}
servo.write(SERVO_MIN)  // make sure it goes exactly to home position
server.log(angle)

server.log("Returned To Home")

}

/* RUNTIME BEGINS HERE -------------------------------------------------------*/

moveFast()
imp.sleep(1.0)
returnSlow()`

Here is a simple video showing it in action (when clicking “Build and Run” from the IDE).

By the way, if anyone from Imp can help make my returnSlow() function work with a non-blocking loop (using imp.wakeup()), that would be greatly appreciated!

  • John

Here’s some non-blocking code to do what you want… I made it a bit more generic so you can set a Start, Stop, Delta (angleDecrement), and sleepTime. All of the parameters are optional, and the default values are setup to swing the servo from SERVO_MAX to SERVO_MIN. The function also takes an optional callback that will execute once the movement is complete:

`const SERVO_MIN = 0.05
const SERVO_MAX = 0.12

const DELTA = -0.005
const SLEEP = 0.5;

function moveServo(servo, current = SERVO_MAX, target = SERVO_MIN, delta = DELTA, sleepTime = 0.5, cb = null) {
// don’t allow delta 0, since it will never end + never move
if (delta == 0) {
servo.write(current);
return;
}

// if we're at or beyond the bounds, write the target value, then call cb
if ((delta <= 0 && current <= target) || (delta > 0 && current >= target)){
    servo.write(target);
    if (cb != null) cb();
    return;
}

// otherwise, write current value, and call moveServo with new currentValue:
servo.write(current);
imp.wakeup(sleepTime, function() { moveServo(servo, current+delta, target, delta, sleepTime, cb); });

}

// swing from max to min:
moveServo(servo, SERVO_MAX, SERVO_MIN, DELTA, SLEEP, function() {
server.log(“Done!”);
});`

Recursion (functions that call themselves) is really common pattern for asynchronous programming, but can sometimes take a while to wrap your head around… so let me know if you have any questions about how this works :slight_smile:

Thank you so much! Just implemented this code and it works perfectly! Really apprecaite the help. I will share my entire project once I’m close to done.