nefilim » 02 окт 2011, 14:47
так сколько нужно?
Grem » 02 окт 2011, 17:07
зачем вам ПИД-регулятор на частоте 1КГц?
Прикольно же
так сколько нужно?
Можно 490Гц и сделать.
Duhas » 02 окт 2011, 17:10
а лучше бы, имхо, поднять частоту ШИМ
nefilim » 03 окт 2011, 14:42
Вот исправленный код.
Не работает.
// spinMotor(),
int pinMotor1 = 8; // пин для подключения мотора
int pinMotor2 = 9; // пин для подключения мотора
int pinMotorSpeed = 10; // пин для подключения мотора (ШИМ) управление скоростью
// pid ()
float kP = 1.25;
float kI = .5;
float kD = .2;
int iMax = 100;
int iMin = 0;
volatile int error = 0;
volatile int lastError = 0;
volatile int sumError = 0;
int minSpeed = 100;
int maxSpeed = 255;
volatile int correct = 0;
// loop()
int potVal = 0; // значение потенциометра, полученное из Serial
int inTimeStep = 0; // количество шагов на которое нужно повернуть мотор (+ или - выбирает направление)
// encoder()
int interruptPin = 2; // номер порта для энкодеа (прерывания) А канал
int buttonDir = 3; // номер порта для энкодера (направление) Б канал
volatile int steping = 0; // текущее количество шагов энкодера
void setup() {
Serial.begin(9600);
// motor
pinMode(pinMotor1, OUTPUT); // инициализируем порт для мотора
pinMode(pinMotor2, OUTPUT); // инициализируем порт для мотора
pinMode(pinMotorSpeed, OUTPUT); // инициализируем порт для мотора (управление скоростью)
// encoder
pinMode(interruptPin, INPUT); // инициализируем порт для прерывания (энкодера) А канал
pinMode(buttonDir, INPUT); // инициализируем порт для энкодера (направление) Б канал
digitalWrite(interruptPin, HIGH); // включаем подтягивающий резистор
digitalWrite(buttonDir, HIGH); // включаем подтягивающий резистор
attachInterrupt(0, encoder, RISING); // инициализируем прерываение
MsTimer2::set(10, pid); // 10ms period Таймер вызываем PID
MsTimer2::start();
}
void loop() {
if (Serial.available()>0) potVal = readPotSerial();
spinMotor (correct);
}
// speedR - скорость вращения от 0 до 255 (положительное значение вращаем в одну сторону, отрицательное - в другую)
void spinMotor (int speedR) {
if (speedR > 0)
{
digitalWrite(pinMotor1,HIGH);
digitalWrite(pinMotor2,LOW);
}
else if (speedR < 0)
{
digitalWrite(pinMotor1,LOW);
digitalWrite(pinMotor2,HIGH);
speedR = speedR * -1;
}
int motorSpeed = map(speedR, 0, 1024, minSpeed, maxSpeed);
if (steping == potVal ) {
digitalWrite(pinMotor1,LOW);
digitalWrite(pinMotor2,LOW);
}
analogWrite(pinMotorSpeed, motorSpeed);
}
// основной алгоритм подсчета
// расчет скорости и направления движения двигателя (ПИД алгоритм)
void pid() {
error = steping - potVal;
correct = kP * error + kD * (error - lastError) + kI * (sumError);
lastError = error;
sumError += error;
if(sumError > iMax){
sumError = iMax;
}
else if(sumError < iMin){
sumError = iMin;
}
}
// читает значение с энкодера через прерывание и инкрементирует или декрементирует значение steping
void encoder() {
if (digitalRead(interruptPin) == digitalRead(buttonDir)) {
steping ++;
}
else {
steping --;
}
}
=DeaD= » 03 окт 2011, 15:04
Какая детальная информация. Тогда совет будет заключаться в "сделайте чтобы работало!".
PS: Я бы spinMotor(correct) внёс в pid()
nefilim » 04 окт 2011, 19:03
Ув. Антон. Я новичок. Мне очень сложно понять некоторые детали. К тому-же в ТАУ я вообще не разбираюсь. Поэтому пришел на форум за помощью.
Свой код я предоставил. Проблема как я понимаю в коэффициентах.
Не работает? Это значит тот -же результат. Дергает в разные стороны и не может стабилизироваться
=DeaD= » 04 окт 2011, 20:26
Ну и что мы тут сделаем с коэффициентами без реального железа? Как в целом настраивать регулятор - описано в статье, ссылку на которую я приводил. Угадать коэффициенты нереально, даже если представить, что проблема именно в них (кстати, почему вы так решили?)
В пределах скольки единиц колеблется? Какая частота колебаний? Почему minSpeed именно 100, а не 50 или 20?
Если снизить пропорциональную и интегральную часть и вообще убрать дифференциальную - что получится по колебаниям?