Имеется dc мотор с энкодером на датчиках холла . С помощью потенциометра управляю мотором- лево, право, стоп. С энкодера снимаю показания. При нажатии кнопки Save сохраняю в память данные с энкодера. При нажатии кнопки Go мотор движется в сохранённое положение. Сейчас с направлением движения в сохранённое положение всё нормально (при разных комбинациях сохранённых значений и текущего положения направление движения правильное), а вот останавливаться не хочет - проскакивает. В чём ошибка.
03 | potX = analogRead(potXPin); |
04 | if (potX >= 465 && potX <= 565) |
06 | analogWrite(speedXPin, 0); |
10 | fspeedX = map(potX, 465, 0, 10, 255); |
11 | digitalWrite(DirX1, HIGH); |
12 | digitalWrite(DirX2, LOW); |
13 | analogWrite(speedXPin, fspeedX); |
17 | bspeedX = map(potX, 565, 1023, 10, 255); |
18 | digitalWrite(DirX1, HIGH); |
19 | digitalWrite(DirX2, LOW); |
20 | analogWrite(speedXPin, fspeedX); |
23 | attachInterrupt(0, UpdateRotation, FALLING); |
24 | /////////////////////////////////// сохраняю положение |
25 | if (buttonStateSave == HIGH) { |
27 | EEPROM.write(10, posA); |
29 | ///////////////////////////////// движение в сохранённое положение |
30 | if (buttonStateGo == HIGH) { |
32 | valueA = EEPROM.read(10); |
35 | digitalWrite(DirX1, HIGH); |
36 | digitalWrite(DirX2, LOW); |
37 | analogWrite(speedXPin, 100); |
39 | else if (valueA > Rotor) |
41 | digitalWrite(DirX1, LOW); |
42 | digitalWrite(DirX2, HIGH); |
43 | analogWrite(speedXPin, 100); |
45 | else if ( (abs(valueA) - abs( Rotor)) == 0) |
47 | analogWrite(speedXPin, 0); |
51 | void UpdateRotation() { |
Что - то сам быстро разобрался. Но при минимальных скоростях останавливается чётко в сохранённом положении, а при средних начинаются проскоки , наверно из-за инерции ротора и редуктора. Прийдётся изучать PID регулятор, до этого с PID никогда не сталкивался.
01
// параметры ПИД-регулятора
02
#define Kp 1.0 // коэффициент усиления
03
#define Ki 0.015 // коэффициент интегрирования
04
#define Kd 0.005 // коэффициент дифференцирования
05
#define Tt 2500L // постоянная времени, совпадает с интервалом опроса датчика
06
07
byte
PID_control(
int
settemp,
int
currenttemp)
08
{
09
static
int
last_error;
10
static
long
I;
11
int
P = settemp - currenttemp;
12
long
D = (((settemp - currenttemp) - last_error) * 1000 / Tt);
13
last_error = settemp - currenttemp;
14
long
PID = Kp*P + Ki*I + Kd*D;
15
PID = constrain(PID, 0, 255);
16
if
(PID > 0 && PID < 255) I = I + ((settemp - currenttemp) * Tt) / 1000;
17
return
PID;
18
}
Спасибо maksim за подсказку. Изучаю тему. Пока понял, что заставить пид регулятор работать довольно геморррррррно. Буду пробовать.
По поводу своего кода рано обрадовался. При отрицательных значениях valueA мотор крутится не как надо
01
void
loop
() {
02
if
(inputModeX) {
03
potX = analogRead(potXPin);
04
if
(potX >= 465 && potX <= 565)
05
{
06
analogWrite(speedXPin, 0);
07
}
08
if
(potX < 465)
09
{
10
fspeedX = map(potX, 465, 0, 10, 255);
11
digitalWrite(DirX1, HIGH);
12
digitalWrite(DirX2, LOW);
13
analogWrite(speedXPin, fspeedX);
14
}
15
if
(potX > 565)
16
{
17
bspeedX = map(potX, 565, 1023, 10, 255);
18
digitalWrite(DirX1, HIGH);
19
digitalWrite(DirX2, LOW);
20
analogWrite(speedXPin, fspeedX);
21
}
22
}
23
attachInterrupt(0, UpdateRotation, FALLING);
24
25
if
(inputModeX == 0 && valueA == Rotor)
26
{
27
analogWrite(speedXPin, 0);
28
inputModeX = 1;
29
}
30
/////////////////////////////////// сохраняю положение
31
if
(buttonStateSave == HIGH) {
32
posA = Rotor;
33
EEPROM.write(10, posA);
34
}
35
///////////////////////////////// движение в сохранённое положение
36
if
(buttonStateGo == HIGH) {
37
inputModeX = 0;
38
valueA = EEPROM.read(10);
39
if
(valueA < Rotor)
40
{
41
digitalWrite(DirX1, HIGH);
42
digitalWrite(DirX2, LOW);
43
analogWrite(speedXPin, 20);
44
}
45
else
if
(valueA > Rotor)
46
{
47
digitalWrite(DirX1, LOW);
48
digitalWrite(DirX2, HIGH);
49
analogWrite(speedXPin, 20);
50
}
51
}
52
}
53
void
UpdateRotation() {
54
if
(digitalRead(B)) {
55
Rotor++;
56
}
57
else
{
58
Rotor--;
59
}
60
}
А уж рассчитать ПИД регулятор в вашей системе... Вы чего хотите ПИД регулировать момент? угловую скорость? положение ротора? В коде ПИД регулятора меня особо порадовал комментарий - постоянная времени, совпадает с интервалом опроса датчика
Ну что ж тут радостного? Данный код писался под температуту, а датчик опрашивался раз в 2,5 секунды. Сделать меньше проблемы не вижу. Можете предложить лучше?
Если слова
вам ни о чем не говорят, то расшифрую - регулировать нужно положение ротора.
Я представляю себе ситуацию так - периодически проверяется положение ротора по отношению к разнице между valueA и Rotor, когда разница приближается к 0 скорость вращения ротора должна плавно снижаться тоже до 0. Или я ошибаюсь?
Вы систему ТС рассмотрели. Что за датчик и как он работает? "Энкодер" - а где число импульсов на оборот? 2? или 3? А регулятор тока, а система подчиненного регулирования? В электроприводах с DSP время берут чаще всего от ШИМ прерывания. И за период ШИМ процессор должен обработать все вычисления для следующего шага. Кстати, нечто подобное (время от ШИМ) встречал и для Ардуино.
StrangerM, я не специалист, я из чайников, и получается разговор на разных языках. У меня есть ардуина, L293D драйвер, мотор-редуктор 12 вольт с энкодером (90 на оборот выходного вала) - всё. Да и первая попытка решить подобную задачу, при том что я не программист. В данном случае мне нужна понятно-доступная информация и направление в котором идти дальше. Теорию почитал. Кстати вот хорошая статья для чайников http://robot-develop.org/archives/2833 . Теперь нужно попытаться реализовать пид регулятор для моего случая. Мне на форуме много помогали и я всем отвечающим всегда благодарен.
Эх писал, писал - а регистрацию не обновил. Пропал текст. Больше уж не смогу. По крайней мере сейчас. Извините.
1
// параметры ПИД-регулятора
2
#define Kp 1.0 // коэффициент усиления
3
#define Ki 0.015 // коэффициент интегрирования
4
#define Kd 0.005 // коэффициент дифференцирования
Пожалуйста подскажите как рисчитывали эти коэффициенты
Да, тоже интересует как рассчитать эти коэффициенты.
Есть ещё вопрос. Телега на двух колёсах с энкодером в виде колёсика с дырочками (от старой мышки).
Пытаюсь таким энкодером считать угол вращения колёс (а затем расстояние), чтобы после движения робот вернулся в исходную точку. Т.о. когда сам задаю направление движения, я знаю, что с оптопары сигналы нужно суммировать при движении вперед и вычитать при движении назад. НО, откуда ни возьмись маленький комарик садится на телегу и нечаянно сдвигает в неопределенном направлении...! данные с энкодера посчитались неверно... т.к. направление задавал не я, а комарик...
вопрос. реально ли таким супер энкодером определить правильное напрвление вращения колеса?
не понятно как мышка при помощи одной оптопары на одно колесо понимает куда движется... т.е. без доп средств это же как-то делается?
похоже сам нашёл ответ на свой вопрос. в мышках какой-то ДВОЙНОЙ фототранзистор...
к сожалению я в электронике хуже разбираюсь, чем в программировании... подскажите кто знает какой-нибудь готовый модуль или схему на распространенных ДЕШЕВЫХ элементах, для подключения к ардуино. что-то на али один такой энкодер от 400рублей, что очень дорого. можно два обычных энкодера поставить по 65руб )))
Добавлено: что-то я напутал, не нашёл таких энкодеров на али... только одинарные. помогите найти двойной
1 отковыряй со старой шариковой мыши. 2 посмотри на али концевые датчикb для репрапа около 50рублей.
http://ru.aliexpress.com/item/Free-Shipping-Optical-Endstop-Light-Contro...