Servo к attiny85 и(или) attiny13

Прошу прощения, и сам же разобрался.

Однако Microcore не принимает переменные в «delayMicroseconds (300+p*(2500/180));» утверждение. Поэтому при использовании Micocore в этом операторе необходимо указать постоянное значение, которое дает приемлемую скорость.

void pulseOut(uint8_t pin, uint8_t angle) {
  digitalWrite(pin, HIGH);
  uint16_t pause_angle = 300 + angle * 14;
  delayMicroseconds(pause_angle);
  digitalWrite(pin, LOW);
}

Ругается именно на angle в строке uint16_t pause_angle = 300 + angle * 14;

исправился, делэймикросек может работать только с константами или регистровыми переменными видимо

#define SERVO_PIN 3
volatile uint16_t angle;

void setup() {
  pinMode(3, OUTPUT);
}

void loop() {
  for (uint8_t pos = 0; pos < 180; pos++) {
    angle = 300 + pos * 14;  
    pulseOut(SERVO_PIN);
    delay(20);
  }
}

void pulseOut(uint8_t pin) {
  digitalWrite(pin, HIGH);
  for(int i = 1; i <= angle; i++)  delayMicroseconds(1);
  digitalWrite(pin, LOW);
}

Вы наверное хотели написать pulseOut(SERVO_PIN, angle);

Servo.h не работает в версии 16,5 MHZ

код рабочий

А вот если писать по мотивам вашей конструкции с передачей параметров, то выходной импульс получается в два раза уже

#define SERVO_PIN 3

void setup() {
  pinMode(3, OUTPUT);
}

void loop() {
  for (uint8_t pos = 0; pos < 180; pos++) {
    uint16_t angle = 300 + pos * 14;  
    pulseOut(SERVO_PIN, angle);
    delay(20);
  }
}

void pulseOut(uint8_t pin, uint16_t new_pos) {
  digitalWrite(pin, HIGH);
  for(uint16_t i = 1; i <= new_pos; i++)  delayMicroseconds(1);
  digitalWrite(pin, LOW);
}

Да, говорить о точности micros() не приходится, то-есть коэффициент придётся подбирать индивидуально, на моём экземпляре микрос идёт в 1.5 раза быстрее

// ATMEL                                ATtiny 25/45/85
//                                           +-\/-+
//             !RESET PCINT5 5/A0 (D 5) PB5 1|    |8  Vcc
//  XTAL1 CLKI !OC1B  PCINT3 3/A3 (D 3) PB3 2|    |7  PB2 (D 2) 2/A1 PCINT2 USCK SCK T0   INT0 SCL
//  XTAL2 CLKO  OC1B  PCINT4 4/A2 {D 4) PB4 3|    |6  PB1 (D 1) pwm1 PCINT1 MISO DO  OC0B AIN1
//                                      GND 4|    |5  PB0 (D 0) pwm0 PCINT0 MOSI DI  OC0A AIN0 SDA AREF
//                                           +----+

#define SERVO_PIN 3
volatile uint16_t angle;
int koeff = 500;
void setup() {
  pinMode(3, OUTPUT);
}

void loop() {

  angle = 1000;
  angle = angle + koeff;
  for (int i = 0; i < 100; i++) {
    pulseOut(SERVO_PIN);
    delay(20);
  }
  angle = 2000;
  angle = angle + koeff*2;
  for (int j = 0; j < 100; j++) {
    pulseOut(SERVO_PIN);
    delay(20);
  }
}

  void pulseOut(uint8_t pin) {
    digitalWrite(pin, HIGH);
    for (int i = 1; i <= angle; i++)  delayMicroseconds(1);
    digitalWrite(pin, LOW);
  }

А что мешает настроить таймер на нужную частоту и менять скважность через регистры ?

я перепробовал и PLL и RC …нет ребята всё не так…только кварц решит проблему

Объясните пожалуйста.

Нужно повернуть серву в 90 градусов при старте программы.

  for (uint8_t pos = 0; pos < 90; pos++) {
    uint16_t angle = 300 + pos * 14;  
    pulseOut(SERVO_PIN, angle);
    delay(20);
  }

Так?
Нет сейчас сервы под рукой для экспериментов.

Под Тини микрос 2500 единииц не принимает?

ставьте сразу на 90 градусов


Micro 9g Servo

void setup() {
  pinMode(3, OUTPUT);
  for (uint8_t pos = 0; pos < 20; pos++) {
    angle = 300 + pos * 14;
    pulseOut(SERVO_PIN);
    delay(20);
  }
}

pos—угол по линейке
60—180
50—160
40—130
30—110
20—80
10—50
5—40

я жеж выше сказал, что микросы укорочены в полтора раза, проверил на частотах 16.5 и 16 мегагерц хоть от PLL хоть от RC генератора, подгоняйте, при передаче значения 1500 микросекунд фактически имеем 1000 при передаче значения 3000 микросекунд фактически имеем 2000

Смотрим хидер библиотеки servo.h

#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
#define REFRESH_INTERVAL    20000     // minimum time to refresh servos in microseconds 

По умолчанию, при инициализации библиотека устанавливает серву в положение 90 градусов, значит нам надо выставлять импульс длиной 1500 микросекунд или 2250 циклов в процедуре задержки

И код:

// ATMEL                                ATtiny 25/45/85
//                                           +-\/-+
//             !RESET PCINT5 5/A0 (D 5) PB5 1|    |8  Vcc
//  XTAL1 CLKI !OC1B  PCINT3 3/A3 (D 3) PB3 2|    |7  PB2 (D 2) 2/A1 PCINT2 USCK SCK T0   INT0 SCL
//  XTAL2 CLKO  OC1B  PCINT4 4/A2 {D 4) PB4 3|    |6  PB1 (D 1) pwm1 PCINT1 MISO DO  OC0B AIN1
//                                      GND 4|    |5  PB0 (D 0) pwm0 PCINT0 MOSI DI  OC0A AIN0 SDA AREF
//                                           +----+

#define SERVO_PIN 3
#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
#define REFRESH_INTERVAL    20000     // minimum time to refresh servos in microseconds 

volatile uint16_t angle = 90;
volatile uint16_t s_tau = 2250;
volatile uint32_t old_millis;

void setup() {
  pinMode(3, OUTPUT);
  pulseOut(SERVO_PIN);
  delay(20);
  old_millis = millis();
}

// функция преобразования в константу задержки (получает значение в градусах угла поворота сервы)
uint16_t set_pulse(uint16_t pulse) {
  return map(pulse, 0, 180, 816, 3600);
}

// функция формирования импульса
void pulseOut(uint8_t pin) {
  digitalWrite(pin, HIGH);
  for (int i = 1; i <= s_tau; i++)  delayMicroseconds(1);
  digitalWrite(pin, LOW);
}


void loop() {
  if (millis() - old_millis >= 20) {
    pulseOut(SERVO_PIN);
    old_millis = millis();
  }
}

Тема была бы не до конца раскрыта без примера применения, здесь СВИП от 0 до 180 и обратно:

#define SERVO_PIN 3
#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
#define REFRESH_INTERVAL    20000     // minimum time to refresh servos in microseconds 

volatile uint16_t angle = 90;
volatile uint16_t s_tau = 2250;
volatile uint32_t old_millis;
volatile uint32_t old_ms;
bool sweep = false;

void setup() {
  pinMode(3, OUTPUT);
  pulseOut(SERVO_PIN);
  delay(20);
  old_millis = millis();
  old_ms = old_millis;
}

// функция преобразования в константу задержки (получает значение в градусах угла поворота сервы)
uint16_t set_pulse(uint16_t pulse) {
  return map(pulse, 0, 180, 816, 3600);
}

// функция формирования импульса
void pulseOut(uint8_t pin) {
  digitalWrite(pin, HIGH);
  for (int i = 1; i <= s_tau; i++)  delayMicroseconds(1);
  digitalWrite(pin, LOW);
}


void loop() {
   static uint16_t angle = 0;
   
   if (millis() - old_millis >= 20) {
    pulseOut(SERVO_PIN);
    old_millis = millis();
  }

  if(millis() - old_ms >= 50 && !sweep){
    angle++;
    if(angle > 180) sweep = true;
    s_tau = set_pulse(angle);
     old_ms = millis();
  }
  
    if(millis() - old_ms >= 50 && sweep){
    angle--;
    if(angle == 0) sweep = false;
    s_tau = set_pulse(angle);
     old_ms = millis();
  }
}


Дак что происходит с Тинькой при delayMicroseconds(3600) ? Для чего цикл из микросекунд?

проблема в передаче этого числа, не знаю как это сделать

Вот это поворот…

ошибка показана тут

История, леденящая кровь, воистину:

ну так это в моём коде и сделано, только без посторонней помощи )))