SG90 servo unresponsive using ATTiny85 and SoftwareServo library

Hello all,

I am very inexperience in regards to coding (I'm learning...very slowly) so please forgive my ignorance. I'm trying to run a single servo with an ATTiny85 using the SoftwareServo library for a solar panel solar tracker system.

The sketch compiles and it seems to upload to the ATTiny (using an UNO as ISP) but the servo is completely unresponsive. I have verified that the servo works.

Here's the code:

#include <SoftwareServo.h>

 
SoftwareServo tracker;  // create servo object to control a servo 
int eastLDRPin = 3;  //Assign analogue pins
int westLDRPin = 4;
int eastLDR = 0;   //Create variables for the east and west sensor values
int westLDR = 0;
int error = 0;
int calibration = 204;  //Calibration offset to set error to zero when both sensors receive an equal amount of light
int trackerPos = 90;    //Create a variable to store the servo position
 
void setup() 
{ 
  tracker.attach(0);  // attaches the servo on pin 11 to the servo object
} 
 
 
void loop() 
{ 
  eastLDR = calibration + analogRead(eastLDRPin);    //Read the value of each of the east and west sensors
  westLDR = analogRead(westLDRPin);
  if(eastLDR<350 && westLDR<350)  //Check if both sensors detect very little light, night time
  {
    while(trackerPos<=160)  //Move the tracker all the way back to face east for sunrise
    {
      trackerPos++;
      tracker.write(trackerPos);
      delay(100);
    }
  }
  error = eastLDR - westLDR;          //Determine the difference between the two sensors.
  if(error>15)        //If the error is positive and greater than 15 then move the tracker in the east direction
  {
    if(trackerPos<=160)  //Check that the tracker is not at the end of its limit in the east direction
    {
      trackerPos++;
      tracker.write(trackerPos);  //Move the tracker to the east
    }
  }
  else if(error<-15)  //If the error is negative and less than -15 then move the tracker in the west direction
  {
    if(trackerPos>20)  //Check that the tracker is not at the end of its limit in the west direction
    {
      trackerPos--;
      tracker.write(trackerPos);  //Move the tracker to the west
    }
  }
  delay(100);
}

I connected everything as shown/described in this super jankey photo/diagram (haha):

Photo/diagram

Any assistance in the matter would be greatly appreciated.

First post and code posted using code tags. Karma++.
Shouln't there be a "tracker.begin…" in Setup?

Servos require an ampere or more each, and should be powered separately from the Arduino. Don't forget to connect the grounds.

Please post a complete, hand drawn wiring diagram.

Railroader:
First post and code posted using code tags. Karma++.
Shouln't there be a "tracker.begin…" in Setup?

Thanks, Railroader!

One would think there should be a, "tracker.begin" in setup but I used (basically) this same sketch on my UNO and it worked fine.

You need to call the refresh function often.

From SoftwareServo.h:

static void refresh();  // must be called at least every 50ms or so to keep servo alive.   you can call more often, it won't happen more than once every 20ms

See the example.

And you need to get rid of any delay() calls. Like the .h files says, refresh needs to called at least every 50msec.

Okey, fine. My ignorance.
According to #2, attach schematics. Pen and paper and a foto from straight above would be good.

I modified your code to get rid of delay()s and inserted the refresh call. Here are some tutorials on how to use millis() (and micros()) for timing.

Non-blocking timing tutorials:
Several things at a time.
Beginner's guide to millis().
Blink without delay().

Modified code. Not tested.

#include <SoftwareServo.h>


SoftwareServo tracker;  // create servo object to control a servo
int eastLDRPin = 3;  //Assign analogue pins
int westLDRPin = 4;
int eastLDR = 0;   //Create variables for the east and west sensor values
int westLDR = 0;
int error = 0;
int calibration = 204;  //Calibration offset to set error to zero when both sensors receive an equal amount of light
int trackerPos = 90;    //Create a variable to store the servo position

void setup()
{
   tracker.attach(0);  // attaches the servo on pin 11 to the servo object
}


void loop()
{
   // added non blocking timing so that the samples are taken at 10Hz
   // but the refresh call is done every time through loop()
   static unsigned long timer = 0;
   unsigned long interval = 100;
   if (millis() - timer >= interval)
   {
      timer = millis();
      eastLDR = calibration + analogRead(eastLDRPin);    //Read the value of each of the east and west sensors
      westLDR = analogRead(westLDRPin);
      if (eastLDR < 350 && westLDR < 350) //Check if both sensors detect very little light, night time
      {
         while (trackerPos <= 160) //Move the tracker all the way back to face east for sunrise
         {
            trackerPos++;
            tracker.write(trackerPos);
         }
      }
      error = eastLDR - westLDR;          //Determine the difference between the two sensors.
      if (error > 15)     //If the error is positive and greater than 15 then move the tracker in the east direction
      {
         if (trackerPos <= 160) //Check that the tracker is not at the end of its limit in the east direction
         {
            trackerPos++;
            tracker.write(trackerPos);  //Move the tracker to the east
         }
      }
      else if (error < -15) //If the error is negative and less than -15 then move the tracker in the west direction
      {
         if (trackerPos > 20) //Check that the tracker is not at the end of its limit in the west direction
         {
            trackerPos--;
            tracker.write(trackerPos);  //Move the tracker to the west
         }
      }
   }
   
   SoftwareServo::refresh();  //****** added in the refresh function ********
}

jremington:
Servos require an ampere or more each, and should be powered separately from the Arduino. Don't forget to connect the grounds.

Please post a complete, hand drawn wiring diagram.

I currently have the servo red lead powered by the 5V from an Arduino and the servo ground running to the GRND of the same arduino.

Fair warning: my hand drawn sketch is awful...but I did my best. haha:

Complete, hand-drawn wiring diagram

Railroader:
Okey, fine. My ignorance.
According to #2, attach schematics. Pen and paper and a foto from straight above would be good.

Coming right up!

schematics

Not sure how much help these photos will be since they're so awful but here they are;

It's impossible to see from the orientation of the photo below but the white wire runs to one terminal on each of the LDR's and the yellow and orange wires connected to the green breadboard are each going to the other terminals of their respective LDR's:

Schematic photo #1

It's difficult to tell from this photo but the resisters are plugged in between the pairs of wires on either end of the breadboard:

Schematic photo #2

Connetions to servo wires There is a wire connected to physical pin #4 that run to the 5V on an Arduino and a wire on connected to physical pin #8 that is connected to the same Arduino's GRND:

[Schematic photo #3/url]
](https://photos.app.goo.gl/x2aoNfAxxtxPpwjm8)

groundFungus:
I modified your code to get rid of delay()s and inserted the refresh call. Here are some tutorials on how to use millis() (and micros()) for timing.

Non-blocking timing tutorials:
Several things at a time.
Beginner's guide to millis().
Blink without delay().

Modified code. Not tested.

#include <SoftwareServo.h>

SoftwareServo tracker;  // create servo object to control a servo
int eastLDRPin = 3;  //Assign analogue pins
int westLDRPin = 4;
int eastLDR = 0;   //Create variables for the east and west sensor values
int westLDR = 0;
int error = 0;
int calibration = 204;  //Calibration offset to set error to zero when both sensors receive an equal amount of light
int trackerPos = 90;    //Create a variable to store the servo position

void setup()
{
  tracker.attach(0);  // attaches the servo on pin 11 to the servo object
}

void loop()
{
  // added non blocking timing so that the samples are taken at 10Hz
  // but the refresh call is done every time through loop()
  static unsigned long timer = 0;
  unsigned long interval = 100;
  if (millis() - timer >= interval)
  {
     timer = millis();
     eastLDR = calibration + analogRead(eastLDRPin);    //Read the value of each of the east and west sensors
     westLDR = analogRead(westLDRPin);
     if (eastLDR < 350 && westLDR < 350) //Check if both sensors detect very little light, night time
     {
        while (trackerPos <= 160) //Move the tracker all the way back to face east for sunrise
        {
           trackerPos++;
           tracker.write(trackerPos);
        }
     }
     error = eastLDR - westLDR;          //Determine the difference between the two sensors.
     if (error > 15)     //If the error is positive and greater than 15 then move the tracker in the east direction
     {
        if (trackerPos <= 160) //Check that the tracker is not at the end of its limit in the east direction
        {
           trackerPos++;
           tracker.write(trackerPos);  //Move the tracker to the east
        }
     }
     else if (error < -15) //If the error is negative and less than -15 then move the tracker in the west direction
     {
        if (trackerPos > 20) //Check that the tracker is not at the end of its limit in the west direction
        {
           trackerPos--;
           tracker.write(trackerPos);  //Move the tracker to the west
        }
     }
  }
 
  SoftwareServo::refresh();  //****** added in the refresh function ********
}

groundFungus, you're awesome-the servo's moving!

...not as it should, however. Here's a link to a video of what happens when it gets plugged in:

Tracker in action

When I reposition the tracker (or even shine a light on it), it does nothing.

uktenore:
I currently have the servo red lead powered by the 5V from an Arduino and the servo ground running to the GRND of the same arduino.

I think you need a 5 V power supply, not an Arduino!

A 4xAA battery pack works great with a servo. Sharing power with the Arduino, or expecting the 5V Arduino output to power a servo always leads to problems, including destruction of the Arduino, in the long run.