SoftwareServo fail to manage 2 servos

Hi,

I'm trying to control 2 servos with an ATTiny85 (IO 3 & 4). I face a problem with my program or with the ATTiny85 or with the SoftwareServo lib or with the servos.

The problem is that one servo is doing what he want, not what I say :frowning:

  • No problem with the servos, I can switch them, the problem is switch from servos
  • No problem with the ATTiny, same code on Arduino = same pb
  • Don't think it can come from the lib, google don't find similar problems
  • It can only comes from my code... but after many rewrites, I don't find solutions...

Here is my code (for Arduino) :

//#include <TinyWireS.h>
#include <SoftwareServo.h>

//
// Define hardware
//
#define SERVO_H_PIN 3
byte SERVO_H_LIMITS[2] = {0, 180}; // set limitations (min/max: 0->180)

#define SERVO_V_PIN 4
byte SERVO_V_LIMITS[2] = {80, 100}; // set limitations (min/max: 0->180)

#define SERVO_MIN_STEP 1
#define SERVO_MAX_STEP 10

#define LED_LASER_PIN 13

//
// Define software
//
#define I2C_Address 7

SoftwareServo servo_h;
float servo_h_position = SERVO_H_LIMITS[0];
float servo_h_target = (SERVO_H_LIMITS[1] - SERVO_H_LIMITS[0]) / 2;

SoftwareServo servo_v;
float servo_v_position = SERVO_V_LIMITS[0];
float servo_v_target = (SERVO_V_LIMITS[1] - SERVO_V_LIMITS[0]) / 2;

void setup() {
  delay(100);

  // Attach pins
  pinMode(LED_LASER_PIN, OUTPUT);

  servo_h.attach(SERVO_H_PIN);
  servo_v.attach(SERVO_V_PIN);

  // Init pins
  servo_h.write(servo_h_position);
  servo_v.write(servo_v_position);
  for(byte i=0;i<10;i++) {
    SoftwareServo::refresh();
    delay(20);
  }
  
  // Init I2C
  //TinyWireS.begin(I2C_Address);      // Begin I2C Communication
  //TinyWireS.onRequest(onRequestCallback);         // When requested, call function transmit()

  // Init is over
  blinkLed(LED_LASER_PIN, 4, 1500);
}

void loop() {
  if(servo_h_position != servo_h_target || servo_v_position != servo_v_target) {
    if(servo_h_position != servo_h_target) {
      int diff = abs(servo_h_target - servo_h_position);
      byte stepSize = min(diff, SERVO_MIN_STEP) * (servo_h_target - servo_h_position) / diff;
      servo_h_position += stepSize;
      
      servo_h.write(servo_h_position);
    }

    if(servo_v_position != servo_v_target) {
      int diff = abs(servo_v_target - servo_v_position);
      byte stepSize = min(diff, SERVO_MIN_STEP) * (servo_v_target - servo_v_position) / diff;
      servo_v_position += stepSize;
      
      servo_v.write(servo_v_position);
    }
  }
  SoftwareServo::refresh();
  delay(20);
}

void onRequestCallback() {

}

//
// Action methods
//
void blinkLed(byte ledPin, byte nbTimes, int duration) {
  int waitTime = duration / (nbTimes * 2);
  for(byte i=0; i < nbTimes; i++) {
    digitalWrite(ledPin, HIGH);
    delay(waitTime);
    digitalWrite(ledPin, LOW);
    delay(waitTime);
  }
}

Do you find anything strange ? Did you already face a problem with SoftwareServo lib and many Servos ?

I really need some help on this topic !

Thanks :slight_smile:

pirquessa:
The problem is that one servo is doing what he want, not what I say :frowning:

How can we possibly know what the problem is based on your description?

What sort of servo movement did you expect?

What servo movement did you observe?

I suggest making a simple test program to sweep the servos.

Thx for your answer, here is my hardware:

2 micro servos, one for tilt, one for pan (the one at the bottom is missing in the picture).

In my program the servo should take a position (defined as SERVO_X_LIMITS) during the "setup" and in the loop method it must try to reach the target position (90°) step by step (SERVO_MIN_STEP).

Everything fine during the first seconds, then one of the servo become crazy and force to try to reach a position behind the minimum... The other one stay in the good position.

I'll try to make a video tonight and make simpler tests.

Here, I would like to know if someone can make some tests with 2 servos & the SoftwareServo lib, just to be sure the problem is coming from me/my code/my hardware and not the lib.

I'm fine ! Here was the problem:

SoftwareServo servo_h;
float servo_h_position = SERVO_H_LIMITS[0];
float servo_h_target = (SERVO_H_LIMITS[1] - SERVO_H_LIMITS[0]) / 2;

SoftwareServo servo_v;
float servo_v_position = SERVO_V_LIMITS[0];
float servo_v_target = (SERVO_V_LIMITS[1] - SERVO_V_LIMITS[0]) / 2;

I just have to learn how to compute a middle ... :frowning: