Управление приводом

V_Alex

Любая задача должна начинаться с техзадания. Оно как-бы было озвучено в первом пункте:

egor-mav:

Имеется привод (см. вложение), необходима схема управления приводом с трёх кнопок, желательно на avr. Принцип работы следующий…

Там было три кнопки, сейчас в схеме откуда-то появился переменный резистор. Еще в ТЗ не отображено, как должен вести себя мотор-редуктор при не нажатых кнопках - просто обесточиваться или удерживать текущее положение. Если первый вариант, то никакого контроллера там не нужно, можно оттолкнуться от этой схемы: rcopen.com/forum/f68/topic138133/36242 В вашем случае нарисованный на схеме регулятор не нужен, все подключается прямо к источнику питания. Концевики шунтируются управляющими кнопками крест-накрест, третья кнопка для медленного хода должна подключаться параллельно одной их первых двух, но последовательно со своим балластным резистором.

Dinotron
V_Alex:

Любая задача должна начинаться с техзадания.

Полностью согласен. Видимо тем и отличаются любители, что любят переобуваться по нескольку раз. 😃

V_Alex:

Концевики шунтируются управляющими кнопками крест-накрест, третья кнопка для медленного хода должна подключаться параллельно одной их первых двух, но последовательно со своим балластным резистором.

И никаких процессоров нафинг !

leons
V_Alex:

сейчас в схеме откуда-то появился переменный резистор

а как кнопка и резистор вчесте работать должны , я пробовал у них тупо конфликт , я так понял нужно две переменные к кнопке и к переменнику

V_Alex

Щас практически на каждом китайском сервотестере стоит переменник и батарея кнопок. В общем случае там организован цикл с частотой 50 Гц. Первыми опрашиваются кнопки и от них серва либо уходит в заданное крайнее положение, либо начинает елозить из края в край. Опрос канала АЦП на время нажатия кнопки должен блокироваться. Когда кнопки отпущены, доходит очередь до переменника. Для резвого и вменяемого распределения ресурсов такие вещи лучше писать на ассемблере. Для задачи автора темы достаточно чего-то совсем мелкого, типа тини13а.

Игорь555
egor-mav:

Управление приводом

Егор вот посмотри здесь ,правда там для сервы ,но может что то интересное для себя найдете там с права оглавление,есть и написанные программы под Пик контролер.
alex-exe.ru/radio/robotics/servo-pic/

egor-mav

Всем спасибо за советы, особенно Вам Дмитрий. Про Ардуино даже и не думал… Попробую на нем сделать.
Согласен, на концевиках проще всего, но моторчик в данном редукторе имеет хорошую инерцию, и после пары применений на схеме с концевиками, я этот редуктор скорей всего выкину.
Резистор вроде в ТЗ присутствовал всегда, см. вложение.
И не надо говорить, что я переобуваюсь… Хотя да, скорей всего я буду переобуваться, т.к. сам до конца не знаю что в итоге хочу получить, и я не только про привод…
Сам руковожу проектным отделом, самого бесят заказчики, которые дают невнятное ТЗ, а потом переобуваются в самый последний момент.

V_Alex
egor-mav:

Согласен, на концевиках проще всего, но моторчик в данном редукторе имеет хорошую инерцию, и после пары применений на схеме с концевиками, я этот редуктор скорей всего выкину.

Погуглите фразу “кулачок механизм”.

egor-mav

Все, стоп. Забыли про концевики и кулачковые механизмы… Это не наш метод, и не интересно… Пока электриком работал на них насмотрелся.
Буду делать на Ардуино. Сижу изучаю…

leons
egor-mav:

Все, стоп. Забыли про концевики и кулачковые механизмы… Это не наш метод, и не интересно… Пока электриком работал на них насмотрелся.
Буду делать на Ардуино. Сижу изучаю…

Вы только не исчезайте , всётаки будет интересен результат

Dinotron
egor-mav:

Буду делать на Ардуино. Сижу изучаю…

Хотите вместе поизвращаемся. 😃 Та китайская мандула с фото всё ещё в работе. И да. Больше чем ардуинку я к ней, видимо, не подключу.
P. S. У меня случай тяжелее. Она вот к чему прикручена. Сразу не бейте. Каждый сходит с ума по-своему. 😃 Там ещё и ROS распределённый а ардуинка нодой. Надо было его на помойку отпереть. Теперь жалко.

egor-mav

Что это? С одной стороны напоминает человеческий скелет… С другой - концептуальную вешалку

Dinotron

И то и другое верно. 😃 И вопрос хороший. Это нечто упрощённо подделывающее человеческую анатомию, из всякого мусора, но с компьютерами в башке и в заднице. Оно пластмассовое и гнётся. Ну бред короче, но забористый оказался. 😃

egor-mav

И снова обращаюсь к Вам за помощью, нужно проверить код… Двигаюсь конечно потихоньку, времени мало свободного, но все же двигаюсь…

Итак, решил начать с малого. Так сказать без всяких кнопок и прочего. Оставляю только мотор и потенциометр (так сказать код открытия):

int motorPin = 10; // мотор подключен к цифровому выводу 10
int analogPin = A0; // потенциометр подключен к аналоговому выходу А0
int val = 0; // переменная для хранения считанного значения с потенциометра

void setup() {

pinMode(motorPin, OUTPUT); // переключение вывода в режим “выход”

}

void loop() { // этот цикл выполняется бесконечное количество раз

val = analogRead(analogPin); // записываем в переменную показания с потенциометра

if (val<700) {
analogWrite(motorPin, 255); // если переменная меньше 700 включаем ШИМ на полную
}
if (val>700&&val<1000) {
analogWrite(motorPin, 150); // если переменная меньше от 700 до 1000 убавляем ШИМ на некоторое значение
}
if (val>1000) {
analogWrite(motorPin, 0); // если переменная меньше больше 1000 отрубаем ШИМ
}
}

Я в правильном направлении двигаюсь?

Dinotron

/В правильном.
Только учтите

/

{Analogread() Щупает от 0 до 1023,
А AnalogWrite() может вписать только до 255.}
/Constrain между ними поставьте. doc.arduino.ua/ru/prog/Constrain
И только если это по кругу как пони.
Ну для начала.
что я делаю/

7 days later
egor-mav

И снова здравствуйте, и снова нужна ваша помощь.
к предыдущему скетчу пытаюсь добавить кнопку:

int motorPin = 10; // мотор подключен к цифровому выводу 10
int analogPin = A0; // потенциометр подключен к аналоговому выходу А0
int buttom1Pin = 22; // кнопка подключен к входу 22
int val = 0; // переменная для хранения считанного значения с потенциометра
int openn = 0; // переменная для хранения считанного значения с потенциометра

void setup() {

pinMode(motorPin, OUTPUT); // переключение вывода в режим “выход”

}

void loop() { // этот цикл выполняется бесконечное количество раз

val = analogRead(analogPin); // записываем в переменную показания с потенциометра
if (digitalRead(buttom1Pin) == HIGH) {
do {
if (val<500) {
analogWrite(motorPin, 255); // если переменная меньше 700 включаем ШИМ на полную
}
if (val>500&&val<1000) {
analogWrite(motorPin, 150); // если переменная меньше от 700 до 1000 убавляем ШИМ на некоторое значение
}
if (val>1000) {
analogWrite(motorPin, 0); // если переменная меньше больше 1000 отрубаем ШИМ
}
}while (val>1000);
}
}

Но, при симуляции в протеусе происходит следующее:

  1. начальные параметры, кнопка не нажата, переменник в нуле, мотор не крутится;
  2. при нажатии кнопки начинает вращатся мотор с максимальной скоростью;
  3. начинаю “крутить” переменник, скорость мотора изменяется согласно алгоритма скетча;
  4. при достижении переменника 100%, мотор останавливается.
    Вроде все хорошо, но…
    Если я правильно понимаю свой скетч, то после всех этих действий, изменении положения резистора и повторного нажатия кнопки цикл (do-while) должен запустится заново, и мотор снова должен вращатся по алгоритму, но этого почему-то не происходит…
    В чем проблема?
22 days later
egor-mav

Не знаю, смотрит кто нибудь эту тему или нет…
Переделал предыдущий скетч теперь все работает.

int motorPin1 = 10; // мотор подключен к цифровому выводу 10
int motorPin2 = 11; // мотор подключен к цифровому выводу 11 (реверс)
int analogPin = A0; // потенциометр подключен к аналоговому выходу А0
int buttom1Pin = 22; // АЦЦ
int buttom2Pin = 23; // кнопка подключен к входу 22
int val = 0; // переменная для хранения считанного значения с потенциометра
int openn = 0; // переменная фиг знает для чего

void setup() {

pinMode(motorPin1, OUTPUT); // переключение вывода в режим “выход”
pinMode(motorPin2, OUTPUT); // переключение вывода в режим “выход”

}

void loop() { // этот цикл выполняется бесконечное количество раз
val = analogRead(analogPin);
if (digitalRead(buttom2Pin)==HIGH && val<500 && openn == 0) {
openn = 1;
}
if (digitalRead(buttom2Pin)==HIGH && val>500 && openn == 0) {
openn = 2;
}

if (openn == 1) {
if (val < 250) {
analogWrite(motorPin1, 255); // если переменная меньше 700 включаем ШИМ на полную
}
if (val>250 && val < 1000) {
analogWrite(motorPin1, 150); // если переменная меньше от 700 до 1000 убавляем ШИМ на некоторое значение
}
if (val > 1000) {
analogWrite(motorPin1, 0); // если переменная меньше больше 1000 отрубаем ШИМ
openn = 0;
}
}

if (openn == 2) {
if (val > 500) {
analogWrite(motorPin2, 255); // если переменная меньше 700 включаем ШИМ на полную
}
if (val > 100 && val < 500) {
analogWrite(motorPin2, 150); // если переменная меньше от 700 до 1000 убавляем ШИМ на некоторое значение
}
if (val < 100) {
analogWrite(motorPin2, 0); // если переменная меньше больше 1000 отрубаем ШИМ
openn = 0;
}
}
}

Но теперь появились другие проблемы и новые исходные данные. Но это уже совсем другая история 😁

10 days later
egor-mav

Продолжаю тему сам с собой 😁
В качестве контроллера выбрал Arduino Mega 2560 R3 (продавали в моем городе, не хотелось долго ждать с Али).
В качестве драйвера двигателя взята плата L298, спасибо за совет leons.
драйвер пока не пришел с алика, так что пока все тестирую в протеусе.

Схема которую собрал в протеусе (во вложении).
Далее код который написал:

// ----------------------------------------------------------------управления приводом
int motorPin1 = 24; // мотор подключен к цифровому выводу 10
int motorPin2 = 25; // мотор подключен к цифровому выводу 11 (реверс)
int motorPin3 = 10; // мотор подключен к цифровому выводу 10 (PWM)
int analogPin = A0; // потенциометр подключен к аналоговому выходу А0
int buttom1Pin = 22; // АЦЦ
int buttom2Pin = 23; // кнопка подключен к входу 23
int val = 0; // переменная для хранения считанного значения с потенциометра
int openn = 0; // переменная для хранения открытия по кнопке
int opennacc = 0; // переменная для хранения открытия по АСС

int led1 = 51;
int led2 = 52;
int led3 = 53;

unsigned long currentTime;
unsigned long loopTime;

//------------------------------------------------------------------------------------------------------

void setup() {
// ----------------------------------------------------------------управления приводом
pinMode(motorPin1, OUTPUT); // переключение вывода в режим “выход”
pinMode(motorPin2, OUTPUT); // переключение вывода в режим “выход”
pinMode(motorPin3, OUTPUT); // переключение вывода в режим “выход”
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);

currentTime = millis(); // считываем время, прошедшее с момента запуска программы
loopTime = currentTime;

//------------------------------------------------------------------------------------------------------

}

void loop() { // этот цикл выполняется бесконечное количество раз
// ----------------------------------------------------------------управления приводом
val = analogRead(analogPin);
currentTime = millis();

if (digitalRead(buttom1Pin) == HIGH && opennacc == 0 && currentTime >= (loopTime + 10000)) {
opennacc = 1;
loopTime = currentTime;
}

if (digitalRead(buttom1Pin) == LOW && currentTime >= (loopTime + 10000)) {
opennacc = 0;
loopTime = currentTime;
}

if (digitalRead(buttom2Pin) == HIGH && val < 500 && openn == 0 && opennacc == 2) {
openn = 1;
}

if (digitalRead(buttom2Pin) == HIGH && val > 500 && openn == 0 && opennacc == 2) {
openn = 2;
}

if (opennacc == 1) { // открытия привода по АСС
if (val < 700) {
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
analogWrite(motorPin3, 255); // если переменная меньше 250 включаем ШИМ на полную
}
if (val >= 700 && val <= 1000) {
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
analogWrite(motorPin3, 150); // если переменная меньше от 250 до 1000 убавляем ШИМ на некоторое значение
}
if (val > 1000) {
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
analogWrite(motorPin3, 0); // если переменная меньше больше 1000 отрубаем ШИМ
opennacc = 2; // открыт по АСС
}
}

if (opennacc == 0) { // Закрытие привода по АСС

if (val > 300) {
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
analogWrite(motorPin3, 255); // если переменная меньше 500 включаем ШИМ на полную
}
if (val >= 20 && val <= 300) {
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
analogWrite(motorPin3, 150); // если переменная от 100 до 500 убавляем ШИМ на некоторое значение
}
if (val < 20) {
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, LOW);
analogWrite(motorPin3, 0); // если переменная меньше больше 100 отрубаем ШИМ
opennacc = 0;
}
}

if (openn == 1 && opennacc == 2) { //Открытие привода по кнопке
if (val < 700) {
digitalWrite(motorPin1, HIGH);
analogWrite(motorPin3, 255); // если переменная меньше 250 включаем ШИМ на полную
}
if (val >= 700 && val <= 1000) {
digitalWrite(motorPin1, HIGH);
analogWrite(motorPin3, 150); // если переменная меньше от 250 до 1000 убавляем ШИМ на некоторое значение
}
if (val > 1000) {
digitalWrite(motorPin1, LOW);
analogWrite(motorPin3, 0); // если переменная меньше больше 1000 отрубаем ШИМ
openn = 0;
}
}

if (openn == 2) { // Закрытие привода по кнопке
if (val > 300) {
digitalWrite(motorPin2, HIGH);
analogWrite(motorPin3, 255); // если переменная больше 500 включаем ШИМ на полную
}
if (val >= 20 && val <= 300) {
digitalWrite(motorPin2, HIGH);
analogWrite(motorPin3, 150); // если переменная от 100 до 500 убавляем ШИМ на некоторое значение
}
if (val < 20) {
digitalWrite(motorPin2, LOW);
analogWrite(motorPin3, 0); // если переменная меньше меньше 100 отрубаем ШИМ
openn = 0;
}
}

//-------------------------индикация переменной opennacc временно
if (opennacc == 0){
digitalWrite(led1, HIGH);
}else {digitalWrite(led1, LOW);
}

if (opennacc == 1){
digitalWrite(led2, HIGH);
}else {digitalWrite(led2, LOW);
}

if (opennacc == 2){
digitalWrite(led3, HIGH);
}else {digitalWrite(led3, LOW);
}
}
//------------------------------------------------------------------------------------------------------

Вроде все работает… Если не сложно, оцените пожалуйста, может чего лишнего понаписал…

We-BEER
egor-mav:

Если не сложно, оцените пожалуйста, может чего лишнего понаписал…

Номера пинов принято указывать дефайнами, нет смысла хранить их в переменных.

#define MOTOR_PIN1 24; // мотор подключен к цифровому выводу 10
#define MOTOR_PIN2 25; // мотор подключен к цифровому выводу 11 (реверс)
...

соответственно в коде написать

...
pinMode(MOTOR_PIN1, OUTPUT); // переключение вывода в режим "выход"
...

я не большой специалист, но кажется такое:

  if (opennacc == 1) { // открытия привода по АСС
    if (val < 700) {
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin1, HIGH);
      analogWrite(motorPin3, 255); // если переменная меньше 250 включаем ШИМ на полную
    }
    if (val >= 700 && val <= 1000) {
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin1, HIGH);
      analogWrite(motorPin3, 150); // если переменная меньше от 250 до 1000 убавляем ШИМ на некоторое значение
    }
    if (val > 1000) {
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin1, LOW);
      analogWrite(motorPin3, 0); // если переменная меньше больше 1000 отрубаем ШИМ
      opennacc = 2; // открыт по АСС
    }
  }

можно упростить до такого:

  if (opennacc == 1) { // открытия привода по АСС
    digitalWrite(MOTOR_PIN1 HIGH);
    digitalWrite(MOTOR_PIN2, LOW);
    if (val < 700) analogWrite(MOTOR_PIN3, 255);                  // если переменная меньше 250 включаем ШИМ на полную
    if (val >= 700 && val <= 1000) analogWrite(MOTOR_PIN3, 150);  // если переменная меньше от 250 до 1000 убавляем ШИМ на некоторое значение
    if (val > 1000) {
      analogWrite(MOTOR_PIN3, 0);                                 // если переменная меньше больше 1000 отрубаем ШИМ
      digitalWrite(MOTOR_PIN1, LOW);
      opennacc = 2; // открыт по АСС
    }
  }

еще вам нужно будет бороться с дребезгом контактов, которого в протеусе нет, а в железе будет.

Обычно для обработки кнопок пишут отдельную функцию типа getBTN(), которая фильтрует дребезг и возвращает их состояние, а основная программа уже вызывает эту функцию и действует согласно её ответа. На истину не претендую, просто мысли 😃

egor-mav

ОГО! Спасибо большое за советы! Можно поподробнее насчет функции getBTN()?

We-BEER
egor-mav:

Можно поподробнее насчет функции getBTN()?

схематично как-то так:

void setup() {
  // начальные настройки
}

void loop() {
  // основной код
  switch (getBTN()) {
    case 0:
      // действия еcли ничего не нажато
      break;
    case 1:
      // действия еcли нажата кнопка 1
      break;
    case 2:
      // действия еcли нажата кнопка 2
      break;
  }
}

byte getBTN() {
  byte btn_state;
  // опрос кнопок и фильтрация дребезга
  return btn_state;
}

так можно отследить не только момент нажатия, но и удержание в нажатом состоянии и отпускание, если оно конечно нужно.

А для борьбы с дребезгом самое простое делать два опроса кнопки с небольшой задержкой, сравнивать результаты и фискировать нажатие только при их совпадении. Примеров в интернетах вагон arduinomaster.ru/…/ustranenie-drebezg-kontaktov-kn…