[Solved]ATtiny 85 and servo library

Hi,my name is Ratto and I'm italian testers of ATtiny on arduino :) First excuse me for my english..... None of you ever run the lbrary Softwareservo or servo on ATtiny85? Tanks for reply...bye....

Ratto,

making the Servo library work with the ATtiny85 sounds like a rather improbable proposition: If I’m not confusing things completely, the ATtiny85 just has 2 8-bit timers and no 16-bit timer, but the Servo-library relies on having a 16-bit timer available.

Korman

Tanks for reply…
then I’m forced to write a new library or it is impossible for this hardware ?

I don’t think it’s impossible, though it will be hard. And furthermore, the big advantages of the Servo library - the fact that it can handle up to 8 servos at the same time - is lost on the ATtiny85. There aren’t really enough pins for one to attach that many servos.

When using the ATtiny with servos, I think one shouldn’t do it with the Servo library but generate the one or two needed pulses in the main loop. Before investing much work there, I would wait for specific requests and spend the time on more urgent migrations.

In case I misunderstood you and you need to do something with the ATtiny and Servos, let me know more about the specifics. I might be able to help you.

Korman

I would use two ATtiny85 on my brat to manage the upper limbs and head as her legs were controlling a Atmega328 I should send the number of degrees and their servant and a stop bit serial by SwSerial we did turn on the tiny ... thanks for your help:) Alessandro ...

This afternoon I tried to watch the libraries already …
you’re forced to by parire SwServo but I can not understand its functions …
Can you explain??
thanks …

#include <SoftwareServo.h>

SoftwareServo *SoftwareServo::first;

#define NO_ANGLE (0xff)

SoftwareServo::SoftwareServo() : pin(0),angle(NO_ANGLE),pulse0(0),min16(34),max16(150),next(0)
{}

void SoftwareServo::setMinimumPulse(uint16_t t)
{
    min16 = t/16;
}

void SoftwareServo::setMaximumPulse(uint16_t t)
{
    max16 = t/16;
}

uint8_t SoftwareServo::attach(int pinArg)
{
    pin = pinArg;
    angle = NO_ANGLE;
    pulse0 = 0;
    next = first;
    first = this;
    digitalWrite(pin,0);
    pinMode(pin,OUTPUT);
    return 1;
}

void SoftwareServo::detach()
{
    for ( SoftwareServo **p = &first; *p != 0; p = &((*p)->next) ) {
	if ( *p == this) {
	    *p = this->next;
	    this->next = 0;
	    return;
	}
    }
}

void SoftwareServo::write(int angleArg)
{
    if ( angleArg < 0) angleArg = 0;
    if ( angleArg > 180) angleArg = 180;
    angle = angleArg;
    // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true
    // That 64L on the end is the TCNT0 prescaler, it will need to change if the clock's prescaler changes,
    // but then there will likely be an overflow problem, so it will have to be handled by a human.
    pulse0 = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/64L;//This row in particulary I'dont understand 16L/180L(I think it's grades of servo) and 64L
}

uint8_t SoftwareServo::read()
{
    return angle;
}

uint8_t SoftwareServo::attached()
{
    for ( SoftwareServo *p = first; p != 0; p = p->next ) {
	if ( p == this) return 1;
    }
    return 0;
}

void SoftwareServo::refresh()
{
    uint8_t count = 0, i = 0;
    uint16_t base = 0;
    SoftwareServo *p;
    static unsigned long lastRefresh = 0;
    unsigned long m = millis();

    // if we haven't wrapped millis, and 20ms have not passed, then don't do anything
    if ( m >= lastRefresh && m < lastRefresh + 20) return;
    lastRefresh = m;

    for ( p = first; p != 0; p = p->next ) if ( p->pulse0) count++;
    if ( count == 0) return;

    // gather all the SoftwareServos in an array
    SoftwareServo *s[count];
    for ( p = first; p != 0; p = p->next ) if ( p->pulse0) s[i++] = p;

    // bubblesort the SoftwareServos by pulse time, ascending order
    for(;;) {
	uint8_t moved = 0;
	for ( i = 1; i < count; i++) {
	    if ( s[i]->pulse0 < s[i-1]->pulse0) {
		SoftwareServo *t = s[i];
		s[i] = s[i-1];
		s[i-1] = t;
		moved = 1;
	    }
	}
	if ( !moved) break;
    }

    // turn on all the pins
    // Note the timing error here... when you have many SoftwareServos going, the
    // ones at the front will get a pulse that is a few microseconds too long.
    // Figure about 4uS/SoftwareServo after them. This could be compensated, but I feel
    // it is within the margin of error of software SoftwareServos that could catch
    // an extra interrupt handler at any time.
    for ( i = 0; i < count; i++) digitalWrite( s[i]->pin, 1);

    uint8_t start = TCNT0;
    uint8_t now = start;
    uint8_t last = now;

    // Now wait for each pin's time in turn..
    for ( i = 0; i < count; i++) {
	uint16_t go = start + s[i]->pulse0;

	// loop until we reach or pass 'go' time
	for (;;) {
	    now = TCNT0;
	    if ( now < last) base += 256;
	    last = now;

	    if ( base+now > go) {
		digitalWrite( s[i]->pin,0);
		break;
	    }
	}
    }
}

Not solution ? :(

pulse0 = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/64L;

This calculate the length of the pulse for the servo in timer ticks. min16*16L*clockCyclesPerMicrosecond() : the minimum length of the pulse, usually 1000µs in processor cycles * 16. (max16-min16)(16L*clockCyclesPerMicrosecond()) : the range the servo can move. max16-min16 is 1000µs too. (max16-min16)(16L*clockCyclesPerMicrosecond())*angle/180L) : convert degrees into processor cycles*16 /64L : This part is to get from processor cycles*16 back down to the prescaler settings of the times to the number of timer ticks to use.

min16 usually are 1000µs, max16 2000µs and 1500µs are the middle position on the common servo. But depending on the make, these values can vary, most of the time min16 is even smaller and max16 bigger.

Korman

tanks for reply :) tonight I modify the library and test it.....

SoftwareServo library work on ATtiny 85 MCU
bye

Good to know. Did you need to modify anything?

I forgoted a row of code…
this code work :slight_smile:

#include <SoftwareServo.h>

SoftwareServo servo;

void setup()
{ 
  servo.attach(0);}

void loop() {
    int pos;
    for(pos = 0; pos < 180; pos += 1) { 
        servo.write(pos);              
        delay(50);                      
        SoftwareServo::refresh();//this row....
    } 
    for(pos = 180; pos>=1; pos-=1) {                                
        servo.write(pos);              
        delay(50);                      
        SoftwareServo::refresh();//This row....
    } 
}

ratto93: SoftwareServo library work on ATtiny 85 MCU bye

Hi,

I have been searching for someone who has used the servo library on the attiny85, Would you care to share a detailed description of how you modified it and post the code? I am trying to control a servo with the attiny85, and i would like to use the pulse in function and the servo library. Thanks in advance,

Jason

This is the code that I have used for my experiment

#include <SoftwareServo.h>

SoftwareServo servo;
int potpin = 0;  
int val;

void setup()
{
  
  servo.attach(0);

}

void loop()
{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180) 
  servo.write(val);                  // sets the servo position according to the scaled value 
  delay(15); 
  SoftwareServo::refresh();
}

I haven’t modify the library SoftwareServo :wink:
excuse me for my not good English ;):wink:

the software servo library is woking perfectly also with the ATtiny45...

A remark about using SoftwareServo.h. In case you get an error on WProgram.h while compiling, change inside SofwareServo.h the name WProgram.h into Arduino.h and it magically works!

Could you please tell me how to include the code in attiny45? I am trying to run the servo with attiny45. I know how the blink the led with attiny45. Are they similar?

I can´t get my servo to work, using the same code as posted before.

#include <SoftwareServo.h>

SoftwareServo servo;

void setup()
{ 
  servo.attach(0);}

void loop() {
    int pos;
    for(pos = 0; pos < 180; pos +=1) { 
        servo.write(pos);              
        delay(100);                      
        SoftwareServo::refresh();//this row....
    } 
    for(pos = 180; pos>=1; pos-=1) {                                
        servo.write(pos);              
        delay(100);                      
        SoftwareServo::refresh();//This row....
    } 
}

The servo turns when being upload. And also rotate half a time, but then it stops.

Here's an attiny servo dedicated library. Give it a go. http://www.cunningturtle.com/attiny4585-servo-library/