Author Topic: Beginner Servo  (Read 19213 times)

digiwimp

  • Newbie
  • *
  • Posts: 1
Beginner Servo
« on: November 11, 2013, 08:36:15 am »
Hi,

I've recently purchased the Digispark and I am trying to figure out how to control my servo (SG90)

So far I have soldered the servo to pin5, ran the LED test example program and installed the following libraries; digisparkSimpleServo and SoftwareServo.

Now I am a bit stuck, to start off with I just want to load a sketch that controls the servo from 0-180 degrees just to test it works. Could anyone help me with this?

My project is a wireless mechanical shutter release for my camera. I am trying to replicate this project http://handya.co.nz/post/43777800968/wireless-remote-for-fuji-x100-camera-or-leica, I have a wireless remote off ebay that uses a 2.5mm jack that I am hoping to plug into my digispark and control the servo to a certain angle when the remote is pressed. This is the pinout of the 2.5mm jack http://www.doc-diy.net/photo/eos_wired_remote/pinout.png

If anyone could offer me any advice that would be great, I'm learning Arduino as I go along from scratch and need to get this done before I go travelling next month to take some remote selfies :)

Cheers guys!

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Beginner Servo
« Reply #1 on: November 11, 2013, 04:01:10 pm »
Try this - which uses the SoftRcPulseOut library included with the Digispark version of the IDE


Code: [Select]
#include <SoftRcPulseOut.h>
SoftRcPulseOut servo1;

void setup()
{
  servo1.attach(5);
  servo1.setMaximumPulse(2200);
}

void loop {
servo1.write(0);
delay(5000);
servo1.write(180);
delay(5000);

}

« Last Edit: November 11, 2013, 07:26:24 pm by digistump »

Bluebie

  • Sr. Member
  • ****
  • Posts: 486
Re: Beginner Servo
« Reply #2 on: November 11, 2013, 04:05:43 pm »
SG90 is an analog servo I think, so it needs to get a pulse roughly 50 times per second. Sending the pulse too infrequently will cause it to turn more slowly and shakily. I couldn't be bothered testing it, but something like this should work:

Code: [Select]
#include <SimpleServo.h>

SimpleServo shutter;

void setup() {
  shutter.attach(5); // connect to pin 5
}

void press_shutter() {
  int angle = 0;
  boolean looping = true;
 
  // loop until we are done
  while (looping) {
    if (angle <= 180) {
      shutter.write(angle); // move from 0 to 180
    } else if (angle > 180) {
      shutter.write(180 - angle); // now move back to 0
    } else {
      // we are done, so return and exit this loop
      looping = false;
    }
   
    delay(1000 / 50); // update 50 times per second
    angle += 1; // rotate at 50 degrees per second (because of update frequency)
    // change to += 4 to go at 200 degrees per second, etc..
  }
}


void loop() {
  press_shutter();
  delay(2000); // wait 2 seconds before doing it again
}

does that help?

misterbisson

  • Newbie
  • *
  • Posts: 3
Re: Beginner Servo
« Reply #3 on: November 22, 2013, 10:06:35 pm »
At risk of hijacking somebody else's thread, but I have a very similar question.

I used the following code on Arduino Leonardo and Mini Pro to drive a servo for the same purpose:

https://github.com/misterbisson/shutterfingers/blob/915210b37c564f157328f6844b24b702e141f658/shutterfingers.ino

I've made changes for it to run on Digispark, but the servo (using SimpleServo, included with the IDE) is twitchy and doesn't hold position.

I've been trying to diagnose it with the following stupid simple modification of the classic blink sketch:

Code: [Select]
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */

#include <SoftRcPulseOut.h>
SoftRcPulseOut servo1;

//#include <SimpleServo.h>
//SimpleServo servo1;        // create servo object to control a servo

 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 1;

// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
  servo1.attach(0);
  servo1.setMaximumPulse(2200);

}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  servo1.write(30);
  delay(20);               // wait for a second
  SoftRcPulseOut::refresh(1);
  delay(2000);               // wait for a second

  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  servo1.write(130);
  delay(20);               // wait for a second
  SoftRcPulseOut::refresh(1);
  delay(2000);               // wait for a second
}

You can see that I've tested both SoftRcPulseOut.h and SimpleServo.h, though neither gives satisfactory results. SimpleServo.h moves the server, but not as much as I think it should to match the code. SoftRcPulseOut.h doesn't move the servo at all.

I've played with different pins. I started on 5, then read the notes about pin 5 being low power and moved to pin 0. The servo behaves the same on both pins.

The servo in question is the Sparkfun generic sub-micro (https://www.sparkfun.com/products/9065). I just re-loaded the old version of the Shutterfingers sketch on a Leonardo and the servo behaves correctly there, though I'm not claiming that tests the servo for all conditions. I don't have another servo to try with, otherwise I definitely would.

Have others seen this behavior?

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Beginner Servo
« Reply #4 on: November 23, 2013, 12:20:45 am »
This library might be worth trying - should just work on the Digispark: https://github.com/adafruit/Adafruit_SoftServo

RC Navy

  • Jr. Member
  • **
  • Posts: 54
  • When you like, even too much, it is not enough!
Re: Beginner Servo
« Reply #5 on: November 23, 2013, 01:47:41 am »
Hi misterbisson,

You are not using properly the <SoftRcPulseOut> library.
As reminded by Bluebie, most of the libraries for servo designed for ATtiny require to be refreshed periodically in the main loop (typically every 20 ms).
Thus, during your delay(2000) calls, the servo is not refreshed and can not reach the target angle: it is  slow and shaky.
In <SoftRcPulseOut>, refresh() refreshes internally the servo pulse every 20 ms: you shall invoke it during long temporization and you cannot use delay() which is a blocking function. You shall use millis() instead.
Code: [Select]
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */

#include <SoftRcPulseOut.h>
SoftRcPulseOut servo1;

 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 1;

// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
  servo1.attach(0);
  servo1.setMaximumPulse(2200);

}

// the loop routine runs over and over again forever:
void loop() {
uint32_t StartMs;

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  servo1.write(30);
  /* Refresh pos during 2 sec */
  StartMs=millis();
  while(millis() - StartMs < 2000UL)
  {
    SoftRcPulseOut::refresh(); //without argument, refresh occurs every 20 ms (internal to the lib)
  }

  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  servo1.write(130);
  /* Refresh pos during 2 sec */
  StartMs=millis();
  while(millis() - StartMs < 2000UL)
  {
    SoftRcPulseOut::refresh(); //without argument, refresh occurs every 20 ms (internal to the lib)
  }
}

Instead of millis(), you can also check the return value of refresh(), it returns 1 when the refresh is done. As refresh is performed every 20 ms, you can use a counter to count the 20ms occurences needed to make you delay. This is another improvement of the SoftwareServo library (SoftRcPulseOut lib is highly based on SoftwareServo lib)
Code: [Select]
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */

#include <SoftRcPulseOut.h>
SoftRcPulseOut servo1;

#define REFRESH_NB_FOR_DELAY(MsToWait)  ((MsToWait)/20UL)
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 1;

// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
  servo1.attach(0);
  servo1.setMaximumPulse(2200);

}

// the loop routine runs over and over again forever:
void loop() {
uint16_t Needed20msRefreshNb;

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  servo1.write(30);
  /* Refresh pos during 2 sec */
  Needed20msRefreshNb=REFRESH_NB_FOR_DELAY(2000UL);
  do{
    while(!SoftRcPulseOut::refresh()); //without argument, refresh occurs every 20 ms (internal to the lib), returns 1 once refresh performed
    Needed20msRefreshNb--;
  }while(Needed20msRefreshNb);

  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  servo1.write(130);
  /* Refresh pos during 2 sec */
  Needed20msRefreshNb=REFRESH_NB_FOR_DELAY(2000UL);
  do{
    while(!SoftRcPulseOut::refresh()); //without argument, refresh occurs every 20 ms (internal to the lib), returns 1 once refresh performed
    Needed20msRefreshNb--;
  }while(Needed20msRefreshNb);
}

Both sketches tested OK with my Digispark and a Futaba S3003 servo.
« Last Edit: November 23, 2013, 02:08:57 am by RC Navy »

misterbisson

  • Newbie
  • *
  • Posts: 3
Re: Beginner Servo
« Reply #6 on: November 23, 2013, 09:09:56 am »
Thank you for your replies.

I'm ashamed to say that this may have come down to a wiring/soldering fault. I should have seen it earlier, but when these suggestions didn't yield different results I unsoldered everything and started again from scratch. Now it's working and all I can say is that I should have tried that earlier.

Again, thank you.

misterbisson

  • Newbie
  • *
  • Posts: 3
Re: Beginner Servo
« Reply #7 on: November 23, 2013, 08:26:54 pm »
One last followup...

The fully working code is available here:
https://github.com/misterbisson/shutterfingers

The schematic:
https://github.com/misterbisson/shutterfingers/blob/master/hardware/v2/shutterfingers.png
https://github.com/misterbisson/shutterfingers/blob/master/hardware/v2/shutterfingers.fzz
(the schematic isn't entirely correct: the switch should pull EN low on the regulator, rather than be inline with the power, but the regulator isn't available in Fritzing, so...)

And parts list:
https://github.com/misterbisson/shutterfingers/blob/master/hardware/v2/README.md

I'll post pictures of the assembled unit on my blog when that's complete.