Одновременная работа двух и более серво (класс sweeper)

kors
Offline
Зарегистрирован: 07.08.2018

Уважаемый qwone помогите пожалуйста....я написал программу голосового управления с андроида и она прекрасно работает для светодиода (я имею ввиду не светодиоды автомата...я их отключил...а сторонний светодиод на каком то пине)...но скетч автомата почему то не реагирует на Serial  когда туда со смартфона приходит "1"....mp3 я временно отключил... Как правильно прописать это управление в скетче автомата?

Спасибо Вам) 

 unsigned long past;
    void stand(int s) {
      state = s;
      past = mill;
      switch (state) {
        case sOFF:
          digitalWrite(pin, LOW);
          break;
        case sOn:
          digitalWrite(pin, HIGH);
          break;
      }
    }
    
  public:
    Cl_Flasher(int p, unsigned long t1, unsigned long t2)
      : pin(p), OnTime(t1), OffTime(t2) {}
    void init() {
      pinMode(pin, OUTPUT);
      stand(sOFF);
    }
    void run() {
      if (state == sOFF && mill - past >= OffTime) stand(sOn);
      if (state == sOn && mill - past >= OnTime) stand(sOFF);
    }
};
//------------------------------------
 #include <SoftwareSerial.h>
 #include <DFPlayer_Mini_Mp3.h>

 #include <Servo.h>
enum {pOFF = 0, pUp, pDown, pPause}; /* состояние ВЫКЛ/ по часовой/против/пауза*/
class Cl_Sweeper {
  protected:
    Servo servo; // сервопривод

    const int pos_min = 80;
    const int pos_max = 100;
    int pos = 90; // текущее положение сервы
    const byte step = 1; // шаг вращения

    byte pin;
    unsigned long offTime; // время, когда сервопривод выключен
    unsigned long stepTime; // промежуток времени между обновлениями
    unsigned long pauseTime; // время, когда сервопривод паузе
    unsigned long past; // последнее обновление положения
    byte state;
    void stand(byte s) {
      state = s;
      past = mill;
      switch (s) {
        case pOFF:/*начальная пауза*/
          break;
        case pUp:/*прямо*/
          pos += step;
          if (pos > pos_max)stand(pDown);
          else {
            servo.write(pos);
            Serial.println(pos);
          }
          break;
        case pDown:/*обратно*/
          pos -= step;
          if (pos < pos_min)stand(pPause);
          else {
            servo.write(pos);
            Serial.println(pos);
          }
          break;
        case pPause:/*в паузе*/
          break;
      }
    }

  
   
  public:
    Cl_Sweeper(byte p, unsigned long t1, unsigned long t2, unsigned long t3):
      pin(p), offTime(t1) , stepTime(t2), pauseTime(t3) {}
    void init () {
      servo.attach(pin);
      stand(pOFF);
    }
    void run() {
      if (state == pOFF && mill - past >= offTime) stand(pUp);
      if (state == pUp && mill - past >= stepTime) stand(pUp);
      if (state == pDown && mill - past >= stepTime) stand(pDown);
      if (state == pPause && mill - past >= pauseTime) stand(pUp);
    }

   
};
//--------Компоновка--------------------------------------------------

Cl_Flasher led2(/*пин*/2,/*времяВКЛ*/350,/*времяВЫКЛ*/350);
Cl_Flasher led3(/*пин*/13,/*времяВКЛ*/200,/*времяВЫКЛ*/222);


Cl_Sweeper F_L_U(/*пин*/5,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/100);
Cl_Sweeper F_L_D(/*пин*/6,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/100);
Cl_Sweeper B_L_U(/*пин*/7,/*нач.пауза*/200,/*время обновления*/ 30,/*пауза*/ 100);
Cl_Sweeper B_L_D(/*пин*/8,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/ 100);

Cl_Sweeper F_R_U(/*пин*/9,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/100);
Cl_Sweeper F_R_D(/*пин*/10,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/100);
Cl_Sweeper B_R_U(/*пин*/11,/*нач.пауза*/200,/*время обновления*/30,/*пауза*/ 100);
Cl_Sweeper B_R_D(/*пин*/12,/*нач.пауза*/0,/*время обновления*/ 30,/*пауза*/ 100);
//---------------------------------
void setup() {

   Serial.begin(9600);
 // pinMode (inPin4, INPUT); 
 // pinMode (inPin3, INPUT);

  // Serial.begin (9600);
   // mp3_set_serial (Serial);    //set Serial for DFPlayer-mini mp3 module 
 // delay (100);
 // mp3_set_volume (5);

 

  
  
  led2.init();
  led3.init();

  F_L_U.init();
  F_L_D.init();
  B_L_U.init();
  B_L_D.init();
  
  F_R_U.init();
  F_R_D.init();
  B_R_U.init();
  B_R_D.init();
}


void loop() {

   if (Serial.available())
  {
    val = Serial.read();
    // При символе "1" включаем задержку
    if (val == '1')
    { 
       

    //  mp3_play (4); // Произрываем "mp3/0004.mp3"
   delay (8000);
    //mp3_play (3);
  // delay (2000);
    }
    // При символе "0" выключаем 
   // if ( val == '0')
   // {
   //   digitalWrite(LED, LOW);
   // }   
    
  };
   
 if (digitalRead(inPin4) ==LOW)
 {
   delay (500);
 //mp3_play (2);  // Произрываем "mp3/0002.mp3"
 delay (8000); 
// mp3_play (5);
 delay (2000);
 };

   if (digitalRead(inPin3) ==HIGH)
 {
   delay (1000);
 //mp3_play (6);  // Произрываем "mp3/0006.mp3"
 delay (8000); 
 //mp3_play (7);
 delay (4000);
   
 }
    
  mill = millis();
 
  
  

  F_L_U.run();
  F_L_D.run();
  B_L_U.run();
  B_L_D.run();

  F_R_U.run();
  F_R_D.run();
  B_R_U.run();
  B_R_D.run();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors. Вы что издеваетесь. Вот ответьте, почему машина не будет ехать, если ее по колеса забетонировать.

ПС:  Почаще используйте delay (8000); И тогда вам с МК можно завязать.

kors
Offline
Зарегистрирован: 07.08.2018

...так почему то как раз delay и не включается....я пробовал и без delay (я понимаю всю тяжесть это команды)... просто прописывал digital.Write на серво ...ни какой реакции....не видит ...

автомат прекрасно работает и с delay 8000...всё крутится...только не останавливается по сигналу со смартфона...

delay 8000 мне нужен был для mp3 ...он не успевал произнести фразу...

Вы знаете что интересно....иногда при в момент соединения с блютузом он видит "1" и останавливается...но чаще не видит

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors пишет:
delay 8000 мне нужен был для mp3 ...он не успевал произнести фразу...
Для этого нужен еще один автомат . А не delay() в loop-e

kors
Offline
Зарегистрирован: 07.08.2018

я понял попробую прописать ещё один автомат...спасибо

а как же быть с отсуцтвием реакции на сигнал с андроида (продолжает крутится в том же режиме)??

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors пишет:

я понял попробую прописать ещё один автомат...спасибо

а как же быть с отсуцтвием реакции на сигнал с андроида (продолжает крутится в том же режиме)??

А это скорее всего приколы с использованием  SoftwareSerial.h

kors
Offline
Зарегистрирован: 07.08.2018

....да да это точно...ноги оттуда растут....я попробую управлять серво без автомата (я думаю что вне автомата будет работать ) и отпишусь...сейчас схемку переделаю

 

да ...и ещё я столкнулся с тем что нужно как то дублировать пины RX и TX для одновременного управления со смартфона и работы mp3...

 

kors
Offline
Зарегистрирован: 07.08.2018

qwone пишет:

kors пишет:

я понял попробую прописать ещё один автомат...спасибо

а как же быть с отсуцтвием реакции на сигнал с андроида (продолжает крутится в том же режиме)??

А это скорее всего приколы с использованием  SoftwareSerial.h

не работает и вне автомата...со светодиодом работает ...переписываю скетч под серво - не работает...

kors
Offline
Зарегистрирован: 07.08.2018

работает всё наладил.....буду пытаться к автомату приспособить...

 

kors
Offline
Зарегистрирован: 07.08.2018

Здравствуйте Уважаемый qwone. Продолжаю постепенно разбираться в Вашими скетчами... Дело в том что управление с клавы или джойчтика мне не нужно ...(хочу чтобы моя система была полностью автоматической интерактивной и с голосовым управлением...определённый прогресс уже есть) поэтому стараюсь приспособить ваш скетч (тот что с клавы вперёд-назад влево-вправо) под сигналы с цифровых и аналоговых пинов. Я так понимаю что если прописать в команде if  вместо кнопок номера пинов то должно всё получиться...правильно?

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

Спасибо Вам)

 

kors
Offline
Зарегистрирован: 07.08.2018

qwone пишет:

Ну для этого надо начинать с нуля и рисовать новый проект. Вспомните как в детстве решали задачу с неизвестным. Обозначим неизвестное за икс . Ну в данном случае Unit по классу Cl_Unit 

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
class Cl_Unit {
  protected:
  public:
    void init() {}
    void run() {}
};
//---Компоновка-----------------------------
Cl_Unit Unit;
//---main-----------------------------
void setup() {
  Unit.init();
}


void loop() {
  mill = millis();
  Unit.run();
}
/**/

 

...я правильно понял что можно прописать несколько таких классов па разным переменным ? ...напримир 

class Cl_Unit1  с переменной(автоматом 1)  Cl_Unit1 Unit1

class Cl_Unit2  с переменной(автоматом 2)  Cl_Unit2 Unit2

class Cl_Unit3  с переменной(автоматом 3)  Cl_Unit3 Unit3

class Cl_Unit4  с переменной(автоматом 4)  Cl_Unit4 Unit4      и это и будут четыре разных автомата?

но как быть с millis ? Если автоматы работают по очереди то я так понимаю millis можна использовать одну а если например два автомата включить одновременно то тогда для каждого нажна своя millis ?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

kors, millis() - это часы.

Могут несколько человек одновременно пользоваться одними и теми же часами ? (например, часами на башне)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors пишет:
Конечно в идеале мне нужно прописать в скетче 3-4 автомата с разными алгоритмами движения и заставить их переключаться по сигналам с пинов...то есть есть сигнал на пине - останавливается один автомат и включается другой с другим алгоритмом....дальше приходит сигнал на другой пин - выключается второй автомат и включается третий и т.д
В этом что-то есть. Покупаете 10 телевизоров. Настраиваете на каждый канал. Не нравится один канал , выключаете один телевизор и включаете другой. 100% отличный ход. Или может у вас лучше будет 1 телевизор и вы будете переключать каналы не выключая его. Автомат это просто проигрыватель аглоритмов. с1- 10 состояния это 1 алгоритм ,11-20 второй и так далее. А millis это часы . У меня в начале loop один раз посмотрел на часы и записал значение в mill. А дальше просто все автоматы смотрят на это время.  Как вариант пусть каждый автомат напрямую смотрит на единственные часы millis.Больше других часов не надо.

kors
Offline
Зарегистрирован: 07.08.2018

понял... спасибо) а где прописаны эти состояния с 1 по 10 и с 11 по 20 ? ...я имею ввиду в скетче автомата как их эти состояния реализовать? путём задания классов с переменными...

class Cl_Unit1  с переменной-АЛГОРИТМОМ ДВИЖЕНИЯ 1)  Cl_Unit1 Unit1

class Cl_Unit2  с переменной- АЛГОРИТМОМ ДВИЖЕНИЯ 2)  Cl_Unit2 Unit2

class Cl_Unit3  с переменной-АЛГОРИТМОМ ДВИЖЕНИЯ 3)  Cl_Unit3 Unit3

class Cl_Unit4  с переменной- АЛГОРИТМОМ ДВИЖЕНИЯ 4)  Cl_Unit4 Unit4   

 ТАК БУДЕТ ПРАВИЛЬНО???

ИЛИ ЭТИ СОСТОЯНИЯ МОЖНО ПРОПИСАТЬ В ОДНОМ КЛАССЕ?

kors
Offline
Зарегистрирован: 07.08.2018

а я думал это отсчёт времени который ведётся каждым использующим врямя элементом программы для себя отдельно

sadman41
Offline
Зарегистрирован: 19.10.2016

Что такое "элемент программы" и зачем ему отсчет времени?

kors
Offline
Зарегистрирован: 07.08.2018

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Нет такого элемента программы, как мп3-плеер.

Переменная - это элемент. Или GOTO какое-нить. Время нужно людям, а элементам программы на него плевать - оно для них не имеет никакого значения.

bwn
Offline
Зарегистрирован: 25.08.2014

kors пишет:

..так вот я думал что так как каждый из этих элементов использует время по-своему то и отсчёт этого времени для каждого из них ведётся отдельно то есть не с момента включения всей программы а с момента запуска каждого из этих элементов отдельно

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors пишет:

понял... спасибо) а где прописаны эти состояния с 1 по 10 и с 11 по 20 ? ...я имею ввиду в скетче автомата как их эти состояния реализовать? путём задания классов с переменными...

Я обычно так оформляю

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
class Cl_Unit {
  protected:
    enum state_t {
      sNone //<- начальное состояние
      , s1, s2, s3, s4, s5, s6, s7, s8, s9, s10         //<- состояние от1 до 10
      , s11, s12, s13, s14, s15, s16, s17, s18, s19, s20 //<- состояние от 11 до 20
    } state;
  public:
    void init() {}
    void run() {}
};
//---Компоновка-----------------------------
Cl_Unit Unit;
//---main-----------------------------
void setup() {
  Unit.init();
}


void loop() {
  mill = millis();
  Unit.run();
}
/**/

 

kors
Offline
Зарегистрирован: 07.08.2018

ага значит при выполнении какой либо функции фиксируем вначале момент времени mill = millis() и эта функция ведёт отсчёт от данного момента....правильно? ..а дальше в программе в начале выполнения следующей функции опять фиксируем уже для этой другой  функции момент начала осчёта тем же самым  mill = millis() и эта другая функция ведёт отсчёт уже от  этого другого момента времени ..я правильно понимаю или нет???

Спасибо)

kors
Offline
Зарегистрирован: 07.08.2018

Спасибо Вам большое я понял....но как я понял это Вы задаёте автомату другие переменные(состояния)....а как же прописать ему переключение на эти другие переменные(состояния) или другой алгоритм движения по тем же самым переменным(состояниям)....это же прописывается в loop ...а там только один run ...и как же автомату указать что нужно начать выполнение другого run ???

bwn
Offline
Зарегистрирован: 25.08.2014

kors пишет:

ага значит при выполнении какой либо функции фиксируем вначале момент времени mill = millis() и эта функция ведёт отсчёт от данного момента....правильно? ..а дальше в программе в начале выполнения следующей функции опять фиксируем уже для этой другой  функции момент начала осчёта тем же самым  mill = millis() и эта другая функция ведёт отсчёт уже от  этого другого момента времени ..я правильно понимаю или нет???

Спасибо)

mill в каждой функции своя. Чтобы не плодить имена переменных нарекается как static unsigned long в функции.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kors, все явно написано в передыдущих скетчах. Если так не понятно, то поробуйте учебники что ли почитать.

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
class Cl_Unit {
  protected:
    enum state_t {
      sNone = 0 //<- начальное состояние
      , s1, s2, s3, s4, s5, s6, s7, s8, s9, s10         //<- состояние от1 до 10
      , s11, s12, s13, s14, s15, s16, s17, s18, s19, s20 //<- состояние от 11 до 20
    } state;
    unsigned long past;//<-- переменая времени когда был предыдущий переход
    const unsigned long time = 0.5; /*переходить через 1/2 сек*/
    void stand(state_t s) {
      state = s;
      past = mill;
      switch (state) {
        case sNone:
          break;
        case s1:
          break;
        case s2:
          break;
        case s3:
          break;
        case s10:
          break;
        case s11:
          break;
        case s12:
          break;
      }
    }
    bool is(state_t s) {
      return s == state && mill - past >= time;
    }
  public:
    void init() {
      stand(sNone);
    }
    void run() {
      if (is(s1)) stand(s2);
      if (is(s2)) stand(s3);
      if (is(s3)) stand(s1);
      if (is(s10)) stand(s11);
      if (is(s11)) stand(s12);
      if (is(s12)) stand(s10);
    }
    void stop() {
      stand(sNone);
    }
    void program1() {
      stand(s1);
    }
    void program2() {
      stand(s10);
    }
};
//---Компоновка-----------------------------
Cl_Unit Unit;
//---main-----------------------------
void setup() {
  Unit.init();
  Unit.program1();
}


void loop() {
  mill = millis();
  Unit.run();
}
/**/

 

kors
Offline
Зарегистрирован: 07.08.2018

Спасибо Вам)

kors
Offline
Зарегистрирован: 07.08.2018

qwone, огромное Вам спасибо !!) Кажется наконец то все пазлы сложились и я начал понимать КАК написать мой скетч...) Думаю все алгоритмы движения я смогу прописать) Единственное пока не понял как прописать переход с одного алгоритма движения к другому по сигналу с какого нибудь пина...постараюсь разобраться ..это кажется должно быть в Вашем скетче управления с кнопок...да??

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Два варианта.Внешний и внутрений. Внешний это как вы переключате программы. А внутрений - заводится номер пина внутрь класса и  так же как внешний. 

ПС:#4  или #6