attiny13 controlling a servo based on 2 digital input.

Hey

So, what i want to do is simple, An attiny13a connected to a servo and 2 digital input on two of its pin. The attiny moves the servo to a preset angle when a fixed pin is high, then when the pin is released, it returns to its preset starting place. If the other input is high, it does the same thing on the opposite side.

it would have been a pretty easy code on a nano, but the codes i saw online for attiny servo seem really complicated and hard to edit. How would i write a servo code for attiny?

not tried is personally but assuming the steps described here works (ie the led blink example there works) then you could try something like this to control the servo:

(code works for a sg90 servo on a UNO)

/*the sg90 accepts 3 command pulse width
  1ms - CCW movement
  1.5ms - return to center position
  2ms - CW movement
  minimum time between pulses/steps - 20ms
  Servo can rotate approximately 180 degrees end-to-end

  This example used delay() to demonstrate servo operation.

*/

uint8_t DirectionInputPin = 9; //change this to the ACTUAL pin being used!!!
uint8_t sg90ControlPin = 8; //change this to the ACTUAL pin being used!!!

uint8_t CCWpulseWidth = 1;  // milliseconds
uint8_t CWpulseWidth = 2;  // milliseconds
int millisbetweenSteps = 20; // milliseconds - or try larger values for slower steps

uint8_t numberOfSteps = 100;
uint8_t dir_req;

void move_servo(int Steps, uint8_t pulseWidth) {
  for (uint8_t n = 0; n < Steps; n++) {
    digitalWrite(sg90ControlPin, LOW);
    delay(millisbetweenSteps);
    digitalWrite(sg90ControlPin, HIGH);
    delay(pulseWidth);
  }
}

void setup() {

  Serial.begin(115200);

  pinMode(DirectionInputPin, INPUT_PULLUP);
  pinMode(sg90ControlPin, OUTPUT);
  digitalWrite(sg90ControlPin, HIGH); //reduces chances of jitter on powerup/reset
                                      //a 1k pullup resistor between sg90ControlPin and VCC would also help

  Serial.println("Starting Sg90 Demo");
  
  //abitrary delay
  delay(2000);

  //servo initialisation
  //move servo to center positon
  digitalWrite(sg90ControlPin, LOW);
  delay(20);
  digitalWrite(sg90ControlPin, HIGH);
  delayMicroseconds(1500);
  digitalWrite(sg90ControlPin, LOW);
  delay(20);
  //move servo fully CounterClockwise (approximately 90 steps)
  move_servo(90, CCWpulseWidth);
  
  //initialise direction flag
  dir_req = LOW;

  //abitrary delay
  delay(2000);
}

void loop() {
  
  if(digitalRead(DirectionInputPin) != dir_req){
    
    dir_req = digitalRead(DirectionInputPin);
    
    //move servo Clockwise
    if (dir_req == HIGH) {
      move_servo(numberOfSteps, CWpulseWidth);
    }
    //move servo Counter-Clockwise
    else {
      move_servo(numberOfSteps, CCWpulseWidth);
    }
    
  }
  
  delay(millisbetweenSteps);
}

hope that helps…

sherzaad:
not tried is personally but assuming the steps described here works (ie the led blink example there works) then you could try something like this to control the servo:

(code works for a sg90 servo on a UNO)

/*the sg90 accepts 3 command pulse width

1ms - CCW movement
  1.5ms - return to center position
  2ms - CW movement
  minimum time between pulses/steps - 20ms
  Servo can rotate approximately 180 degrees end-to-end

This example used delay() to demonstrate servo operation.

*/

uint8_t DirectionInputPin = 9; //change this to the ACTUAL pin being used!!!
uint8_t sg90ControlPin = 8; //change this to the ACTUAL pin being used!!!

uint8_t CCWpulseWidth = 1;  // milliseconds
uint8_t CWpulseWidth = 2;  // milliseconds
int millisbetweenSteps = 20; // milliseconds - or try larger values for slower steps

uint8_t numberOfSteps = 100;
uint8_t dir_req;

void move_servo(int Steps, uint8_t pulseWidth) {
  for (uint8_t n = 0; n < Steps; n++) {
    digitalWrite(sg90ControlPin, LOW);
    delay(millisbetweenSteps);
    digitalWrite(sg90ControlPin, HIGH);
    delay(pulseWidth);
  }
}

void setup() {

Serial.begin(115200);

pinMode(DirectionInputPin, INPUT_PULLUP);
  pinMode(sg90ControlPin, OUTPUT);
  digitalWrite(sg90ControlPin, HIGH); //reduces chances of jitter on powerup/reset
                                      //a 1k pullup resistor between sg90ControlPin and VCC would also help

Serial.println(“Starting Sg90 Demo”);
 
  //abitrary delay
  delay(2000);

//servo initialisation
  //move servo to center positon
  digitalWrite(sg90ControlPin, LOW);
  delay(20);
  digitalWrite(sg90ControlPin, HIGH);
  delayMicroseconds(1500);
  digitalWrite(sg90ControlPin, LOW);
  delay(20);
  //move servo fully CounterClockwise (approximately 90 steps)
  move_servo(90, CCWpulseWidth);
 
  //initialise direction flag
  dir_req = LOW;

//abitrary delay
  delay(2000);
}

void loop() {
 
  if(digitalRead(DirectionInputPin) != dir_req){
   
    dir_req = digitalRead(DirectionInputPin);
   
    //move servo Clockwise
    if (dir_req == HIGH) {
      move_servo(numberOfSteps, CWpulseWidth);
    }
    //move servo Counter-Clockwise
    else {
      move_servo(numberOfSteps, CCWpulseWidth);
    }
   
  }
 
  delay(millisbetweenSteps);
}




hope that helps....

this example here uses delay. as the servo is going to be controlled rapidly and without a pattern, its sure going to block the process…

Isnt it possible to use a stripped down servo library?

kaseftamjid: this example here uses delay. as the servo is going to be controlled rapidly and without a pattern, its sure going to block the process..

Isnt it possible to use a stripped down servo library?

you always have the option to use millis()/micros()...

I'll let YOU read up on using the ATtiny13a timer(s) and/or mod the example provided! ;)

sherzaad:
you always have the option to use millis()/micros()…

I’ll let YOU read up on using the ATtiny13a timer(s) and/or mod the example provided! :wink:

i did read the code. But I would prefer using a library as I want to implement a bit more functionality later on. Libraries hurts my eyes less…

anyway, i did find this GitHub - fri000/Servo8Bit: Servo library for the ATtiny45 and the ATtiny85 I did check, and if i set the attinies internal clock at 8mhz, this should work, right?

This video from the github page you posted says Yes, this should work. https://www.youtube.com/watch?v=UvY2BeQav8k

#include <avr/io.h>
#include <Servo8bit.h>
void setup() {
  Servo8bit myServo;
  myServo.attach(1); //attach the servo to pin PB1
  
  DDRB &= ~(1 << DDB3);    //set PB3 as input
 
  DDRB &= ~(1 << DDB4);    //set PB4 as input
  //the inputs i need to use, switch from low to high, so i decided to use physical pulldown resistors
  //PORTB |= (1 << PORTB3);  //activate internal pull-up resistor for PB3
  //PORTB |= (1 << PORTB4);  //activate internal pull-up resistor for PB4


}

void loop() {//this is the part im having trouble figuring 
  if(PB3 == LOW && PB4 == LOW){  //no input, hold servo in 100
    myServo.write(100);
  }
  else if(PB3 == HIGH && PB4 == LOW){ //pb3 high, move servo to 40
    myServo.write(40);
  }
  else if(PB3 == LOW && PB4 == HIGH){ //pb4 high, move servo to 140
    myServo.write(140);
  }
}

this code is obviously wrong. But i put it together just to show what im actually trying to do.

  1. How do you address a pin while using port manipulation? “(PB3 == HIGH && PB4 == LOW)” in this part?
    2.The example code provided with servo8bit
#include "Servo8Bit.h"
 
int main()
{
    Servo8Bit myServo;  //create a servo object.
                        //a maximum of five servo objects can be created 
 
    myServo.attach(1);  //attach the servo to pin PB1
 
    //sweep the servo
    while(1)
    {
        for(int pos = 0; pos < 180; pos++)  // goes from 0 degrees to 180 degrees
        {                                   // in steps of 1 degree
            myServo.write(pos);             // tell servo to go to position in variable 'pos'
            delay(15);                      // waits 15ms for the servo to reach the position
        }
 
        for(int pos = 180; pos > 1; pos--)  // goes from 180 degrees to 0 degrees
        {
            myServo.write(pos);             // tell servo to go to position in variable 'pos'
            delay(15);                      // waits 15ms for the servo to reach the position
        }
    }
}

seems to be a bit different, so would the functions work the same way in my code?

PB3 is a macro defined as 3.

You can check the pin state like this using the AvrLibC macros.

(PINB & (1<<PB3))

tf68:
PB3 is a macro defined as 3.

You can check the pin state like this using the AvrLibC macros.

(PINB & (1<<PB3))

Im really bad at coding, could you please explain?

as i already know the angles i want the servo to be on, cant i just calculate the pulses and send them? but how would i do that?

My question has vastly shifted from this topic. Thus i have decided to open another topic.