Всем привет. Нужна помощь со стабилизацией скорости моторчика. Имеется магнитофон орель 101, полностью отремонтировал, поставил новую головку и провёл профилактику и настройку всех узлов. Пишет и воспроизводит шикарно. Но детонации составляют около 0,5 процентов. Хотел бы их как то уменьшить. Для этой задачи решил собрать управление на базе ардуины. Управление мотором будет шим сигналом. Считывать скорость будем оптическим датчиком с маховика тон вала. На маховик надену насадку с 3 стойками, которая перекрывает датчик (то есть вызывает прерывание на мк). МК по каждому прерыванию получает пройденное время от стойки до стойки, затем сравнивает текущее время прохождения с заданным (задаётся потенциометром). Написал два варианта изменения скорости. В первом просто прибавляем/убаляем частоту шим на 1 при каждом прерывании, во втором рассчитываем конкретно, на сколько нужно изменить шим. Пока в сам магнитофон не вставлял систему, экспериментировал на моторчике (есть мощный моторчик от старого советского плеера, на него просто приклеил сверху полоску из картона для вращения вокруг датчика). Обороты не быстрые, датчик успевает нормально реагировать. Но вот стабилизация пока не очень. В первом варианте скорость вращения немного плавает, во втором сильно. Может у кого то будут идее по улучшению? Скетч, схему и фото предполагаемой насадки на маховик прилагаю.
// Пины
#define PIN_Tachometer 2 // Пин датчика скорости
#define PIN_SpeedMotor 3 // Пин управления мотором
#define PIN_SpeedController A0 // Пин подстроечного резистора для установки скорости
// Настройки
#define maxTimeRisk 100 // Максимальное время прохожения между рисками
#define minMototPWM 50 //
#define maxMototPWM 150 //
// Для ускорение АЦП
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// Переменные
unsigned long timeOld = 0; // Предыдущее время срабатывания прерывания
unsigned long timeRisk = 0; // Время прохождения от риски до риски
unsigned long timeReferenceRisk = 35; // Заданная скорость резистором
uint8_t signalToTheMotor = 100; // Выдаваемый сигнал на управление мотором
bool canUpdateSpeed = false;
void updateTime()
{
timeRisk = millis() - timeOld;
timeOld = millis();
canUpdateSpeed = true;
}
void setup()
{
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
TCCR2B = 0b00000001; // x1
TCCR2A = 0b00000001; // fast pwm
pinMode(PIN_Tachometer, INPUT);
pinMode(PIN_SpeedMotor, OUTPUT);
pinMode(PIN_SpeedController, INPUT);
Serial.begin(115200);
analogWrite(PIN_SpeedMotor, signalToTheMotor);
attachInterrupt(digitalPinToInterrupt(PIN_Tachometer), updateTime, FALLING);
// Убрать
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
digitalWrite(A1, HIGH);
digitalWrite(A2, LOW);
digitalWrite(A3, HIGH);
}
void loop()
{
timeReferenceRisk = map(analogRead(PIN_SpeedController), 0, 1023, 0, maxTimeRisk);
if (canUpdateSpeed)
{
updateSpeed_v1();
//updateSpeed_v2();
canUpdateSpeed = false;
// Лог
Serial.print(timeRisk);
Serial.print(F("/"));
Serial.println(timeReferenceRisk);
}
}
void updateSpeed_v1()
{
if (timeRisk > timeReferenceRisk && signalToTheMotor < maxMototPWM)
signalToTheMotor++;
else if (timeRisk < timeReferenceRisk && signalToTheMotor > minMototPWM)
signalToTheMotor--;
analogWrite(PIN_SpeedMotor, signalToTheMotor);
}
void updateSpeed_v2()
{
signalToTheMotor = signalToTheMotor / timeRisk * timeReferenceRisk;
if (signalToTheMotor < maxMototPWM)
signalToTheMotor = maxMototPWM;
else if (signalToTheMotor > minMototPWM)
signalToTheMotor = minMototPWM;
analogWrite(PIN_SpeedMotor, signalToTheMotor);
}