Одновременная работа двух и более серво (класс sweeper)
- Войдите на сайт для отправки комментариев
Втр, 07/08/2018 - 09:09
Уважаемые опытные программисты . помогите пожалуйста разобраться начинающему. В программе для 2-х серво ( строка 84) пытаюсь менять угол 0 град. на 30 или 80 или любой другой и обе сервы отказываются видеть этот угол.Крутятся в 0 градусов и там зависаютю А при 0 град. всё работает.(при этом угол 180 можно изменять как угодно - проблем с ним нет) . Это известный скетч из инета. Извините что отнимаю время. (светодиоды меня не интересуют). Заранее благодарен за любую помощь.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <Servo.h>
class Flasher
{
// Переменные - члены класса
// Инициализируются при запуске
int ledPin; // номер пина со светодиодом
long OnTime; // время включения в миллисекундах
long OffTime; // время, когда светодиод выключен
// Текущее состояние
int ledState; // состояние ВКЛ/ВЫКЛ
unsigned long previousMillis; // последний момент смены состояния
// Конструктор создает экземпляр Flasher и инициализирует
// переменные-члены класса и состояние
public:
Flasher(int pin, long on, long off)
{
ledPin = pin;
pinMode(ledPin, OUTPUT);
OnTime = on;
OffTime = off;
ledState = LOW;
previousMillis = 0;
}
void Update()
{
// выясняем не настал ли момент сменить состояние светодиода
unsigned long currentMillis = millis(); // текущее время в миллисекундах
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // выключаем
previousMillis = currentMillis; // запоминаем момент времени
digitalWrite(ledPin, ledState); // реализуем новое состояние
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // выключаем
previousMillis = currentMillis ; // запоминаем момент времени
digitalWrite(ledPin, ledState); // реализуем новое состояние
}
}
};
class Sweeper
{
Servo servo; // сервопривод
int pos; // текущее положение сервы
int increment; // увеличиваем перемещение на каждом шаге
int updateInterval; // промежуток времени между обновлениями
unsigned long lastUpdate; // последнее обновление положения
public:
Sweeper(int interval)
{
updateInterval = interval;
increment = 1;
}
void Attach(int pin)
{
servo.attach(pin);
}
void Detach()
{
servo.detach();
}
void Update()
{
if((millis() - lastUpdate) > updateInterval) // время обновлять
{
lastUpdate = millis();
pos += increment;
servo.write(pos);
Serial.println(pos);
if ((pos >= 180) || (pos <= 0)) // конец вращения
{
// обратное направление
increment = -increment;
}
}
}
};
Flasher led1(11, 123, 400);
Flasher led2(12, 350, 350);
Flasher led3(13, 200, 222);
Sweeper sweeper1(15);
Sweeper sweeper2(25);
void setup()
{
Serial.begin(9600);
sweeper1.Attach(9);
sweeper2.Attach(10);
}
void loop()
{
sweeper1.Update();
sweeper2.Update();
led1.Update();
led2.Update();
led3.Update();
}
|
Вот здесь две сервы работают одновременно, управляемые через радиокакнал. Скетч крохотный, посмотрите почему там работают, а у Вас нет - http://arduino.ru/forum/apparatnye-voprosy/upravlenie-servoprivodami-dzhoistikom-cherez-radiomodul-rf-5v?page=2#comment-357613
У Вас положение сервы и направление движения определяется всего двумя переменными - pos и increment. Вывели бы их в монитор порта - всё бы сами поняли. В скетче даже остатки такой отладки есть (строка 83).
Вы забыли про начальную позицию. Вам, как я понял, нужно, чтобы серва вращалась не от нуля, а от какого-то другого положения, так? Вот Вы меняете в строке 84 ноль допустим на 30, инкремент у Вас единица. И Вы первый раз попадаете в метод update (считаем, что время обновлять наступило!). А чему же равно Pos? Нулю! А теперь просто пальцем по строчкам 80 - 88 пройдитесь. Pos увеличили на 1 (стало равно 1). 1 <= 30 - условие сработало, инкремент сменил знак. И в следующий раз единичку уже вычтут. Вот так оно у Вас около нуля и дёргается!
Можете добавить в класс два поля - откуда и докуда вращаться, передавайте ещё два значения в конструктор, в конструкторе присваивайте начальное значение переменной Pos и устанавливайте серву в эту позицию! И в условии (84) эти значения используйте.
Если позволяет устройство можно "конструктивно" проблему решить. Допустим Вам нужно вращение от 30 до 150. Вращайте от 0 до 120, закрепив соответствующим образом исполнительный механизм, а в скетче только меняете 180 на 120.
p.s. И не пишите так больше "известный скетч из интернета". :) Никому-то он не известный.
Спасибо большое . Сейчас буду пробовать )
Спасибо большое . Попробую разобраться )
Урааа!...Всё работает. Введение переменных с углами всёрешило. Я догадывался но не знал что pos принимает значение 0 по умолчанию. Спасибо Вам большое!...
Урааа!...Всё работает. Введение переменных с углами всёрешило. Я догадывался но не знал что pos принимает значение 0 по умолчанию. Спасибо Вам большое!...
В следующий раз, не догадывайтесь, а на дисплей выводите значения сомнительных переменных.
ок спасибо)
0
Прошу помощи. Я только начинаю знакомиться с программированием. Подскажите пожалуйста как прописать задержку для серво при выполнении Update2 но только в начале и только ОДИН раз т.е. задержка должна быть однократной при старте серво по Update2 (строка 102). Заранее признателен.
Вот скетч: (светодиоды пока не интересуют)
#include <Servo.h> class Flasher { // Переменные - члены класса // Инициализируются при запуске int ledPin; // номер пина со светодиодом long OnTime; // время включения в миллисекундах long OffTime; // время, когда светодиод выключен // Текущее состояние int ledState; // состояние ВКЛ/ВЫКЛ unsigned long previousMillis; // последний момент смены состояния // Конструктор создает экземпляр Flasher и инициализирует // переменные-члены класса и состояние public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // выясняем не настал ли момент сменить состояние светодиода unsigned long currentMillis = millis(); // текущее время в миллисекундах if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // выключаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } } }; class Sweeper { Servo servo; // сервопривод int pos =90; // текущее положение сервы const int pos_min =60; const int pos_max =100; int increment; // увеличиваем перемещение на каждом шаге int updateInterval; // промежуток времени между обновлениями unsigned long lastUpdate; // последнее обновление положения long OffTime; // время, когда сервопривод выключен boolean servoState; // состояние ВКЛ (true)/ВЫКЛ (false) public: Sweeper(int interval, long off) { updateInterval = interval; increment = 1; // шаг вращения OffTime = 500; //задаем время паузы между вращением servoState = true; // серво в режиме вращения } void Attach(int pin) { servo.attach(pin); } void Detach() { servo.detach(); } void Update1() { if((millis() - lastUpdate) > updateInterval) // время обновлять { lastUpdate = millis(); pos += increment; servo.write(pos); Serial.println(pos); if ((pos >= pos_max ) || (pos <= pos_min )) // конец вращения { // обратное направление increment = -increment; } } } void Update2() { unsigned long currentMillis = millis(); // текущее время в миллисекундах if(servoState && ((currentMillis - lastUpdate) > updateInterval)) // время обновлять { lastUpdate = currentMillis; pos += increment; servo.write(pos); Serial.println(pos); if ((pos >= pos_max) || (pos <= pos_min)) // конец вращения { increment = -increment; // обратное направление servoState=false; // выключаем режим вращения } } else if (!servoState && (currentMillis - lastUpdate >= OffTime)) { lastUpdate = millis(); // запоминаем момент времени servoState = true; // включаем режим вращения } } }; Flasher led1(3, 123, 400); Flasher led2(4, 350, 350); Flasher led3(5, 200, 222); Sweeper sweeper_forwLup(30, 0); Sweeper sweeper_forwLdown(30, 0); Sweeper sweeper_backwLup(30, 500);// время обновления - 30мс, пауза - 0,5 секунд Sweeper sweeper_backwLdown(30, 500);// время обновления - 30мс, пауза - 0,5 секунд void setup() { Serial.begin(9600); sweeper_forwLup.Attach(11); sweeper_forwLdown.Attach(12); sweeper_backwLup.Attach(7); sweeper_backwLdown.Attach(8); } void loop() { sweeper_forwLup.Update1(); sweeper_forwLdown.Update1(); sweeper_backwLup.Update2(); sweeper_backwLdown.Update2(); led1.Update(); led2.Update(); led3.Update(); }Этот скетч Вы сами не писали, а откуда-то взяли. Правильно? Или сами писали?
ПС: У Sweeper должно быть 3(три) состояния /*пауза / вращение вперед / вращение назад*/
спасибо за комплимент , но как же это сделать? Может быть у вас есть пример какого то скетча? Дело в том что мне некого спросить. Я учусь самостоятельно, учителей нет. Да еи ещё ...паузу я научился делать и в начале и в конце движения, но эти паузы повторяются так как входят в цикл вращения. А мне нужна ТОЛЬКО ОДНА пауза и только один раз в начале вращения ....вне цикла а как бы перед Update2. Не получается...
,
Этот скетч Вы сами не писали, а откуда-то взяли. Правильно? Или сами писали?
я взял за основу скетч из инета и доработал...
Ну в работе не проверял. Опять же сдавать скетч учителю не рекомендую. Сильная специфика.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown}; /* состояние ВЫКЛ/ по часовой/против*/ class Cl_Sweeper { protected: Servo servo; // сервопривод const int pos_min = 60; const int pos_max = 100; int pos = 90; // текущее положение сервы const byte step = 1; // шаг вращения byte pin; unsigned long stepTime; // промежуток времени между обновлениями unsigned long OffTime; // время, когда сервопривод выключен unsigned long past; // последнее обновление положения byte state; void stand(byte s) { state = s; past = mill; switch (s) { case pOFF: digitalWrite(pin, LOW); 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(pOFF); else { servo.write(pos); Serial.println(pos); } break; } } public: Cl_Sweeper(byte p, unsigned long t1, unsigned long t2): pin(p), stepTime(t1), OffTime(t2) {} 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); } }; //--------Компоновка-------------------------------------------------- Cl_Flasher led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper F_D(/*пин*/12,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper B_U(/*пин*/7,/*время обновления*/ 30,/*пауза*/ 500); Cl_Sweeper B_D(/*пин*/8,/*время обновления*/ 30,/*пауза*/ 500); //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4146 байт (13%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 369 байт (18%) динамической памяти, оставляя 1679 байт для локальных переменных. Максимум: 2048 байт. */Ну в работе не проверял. Опять же сдавать скетч учителю не рекомендую. Сильная специфика.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown}; /* состояние ВЫКЛ/ по часовой/против*/ class Cl_Sweeper { protected: Servo servo; // сервопривод const int pos_min = 60; const int pos_max = 100; int pos = 90; // текущее положение сервы const byte step = 1; // шаг вращения byte pin; unsigned long stepTime; // промежуток времени между обновлениями unsigned long OffTime; // время, когда сервопривод выключен unsigned long past; // последнее обновление положения byte state; void stand(byte s) { state = s; past = mill; switch (s) { case pOFF: digitalWrite(pin, LOW); 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(pOFF); else { servo.write(pos); Serial.println(pos); } break; } } public: Cl_Sweeper(byte p, unsigned long t1, unsigned long t2): pin(p), stepTime(t1), OffTime(t2) {} 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); } }; //--------Компоновка-------------------------------------------------- Cl_Flasher led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper F_D(/*пин*/12,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper B_U(/*пин*/7,/*время обновления*/ 30,/*пауза*/ 500); Cl_Sweeper B_D(/*пин*/8,/*время обновления*/ 30,/*пауза*/ 500); //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4146 байт (13%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 369 байт (18%) динамической памяти, оставляя 1679 байт для локальных переменных. Максимум: 2048 байт. */Огромное Вам спасибо!!!)
Сейчас буду разбираться с этим скетчем...)
Ну в работе не проверял. Опять же сдавать скетч учителю не рекомендую. Сильная специфика.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown}; /* состояние ВЫКЛ/ по часовой/против*/ class Cl_Sweeper { protected: Servo servo; // сервопривод const int pos_min = 60; const int pos_max = 100; int pos = 90; // текущее положение сервы const byte step = 1; // шаг вращения byte pin; unsigned long stepTime; // промежуток времени между обновлениями unsigned long OffTime; // время, когда сервопривод выключен unsigned long past; // последнее обновление положения byte state; void stand(byte s) { state = s; past = mill; switch (s) { case pOFF: digitalWrite(pin, LOW); 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(pOFF); else { servo.write(pos); Serial.println(pos); } break; } } public: Cl_Sweeper(byte p, unsigned long t1, unsigned long t2): pin(p), stepTime(t1), OffTime(t2) {} 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); } }; //--------Компоновка-------------------------------------------------- Cl_Flasher led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper F_D(/*пин*/12,/*время обновления*/ 30,/*пауза*/ 0); Cl_Sweeper B_U(/*пин*/7,/*время обновления*/ 30,/*пауза*/ 500); Cl_Sweeper B_D(/*пин*/8,/*время обновления*/ 30,/*пауза*/ 500); //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4146 байт (13%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 369 байт (18%) динамической памяти, оставляя 1679 байт для локальных переменных. Максимум: 2048 байт. */Ваш скетч прекрасно работает. Сервы вращаются как надо.....НО как же мне сделать паузу перед запуском одной из серво...именно ОДНОКРАТНУЮ паузу . В вашем скетче пауза опять таки входит в цикл и повторяется при каждом вращении....а мне нужна только одна пауза ...спасибо Вам.
kors,конечно в этом скетче у серв все идет по циклу пауза-поворот вперед-поворот назад-пауза-.. Все как и задкмано. Что бы правильно написать скетч надо прежде всего узнать что он должен делать. То есть зачем он и его работу. Опять же длительнось задержки до начала работы должна быть одинакова или же индивидуально для каждой.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown, pPause}; /* состояние ВЫКЛ/ по часовой/против/пауза*/ class Cl_Sweeper { protected: Servo servo; // сервопривод const int pos_min = 60; 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 led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*нач.пауза*/100,/*время обновления*/ 30,/*пауза*/100); Cl_Sweeper F_D(/*пин*/12,/*нач.пауза*/200,/*время обновления*/ 30,/*пауза*/100); Cl_Sweeper B_U(/*пин*/7,/*нач.пауза*/300,/*время обновления*/ 30,/*пауза*/ 500); Cl_Sweeper B_D(/*пин*/8,/*нач.пауза*/400,/*время обновления*/ 30,/*пауза*/ 500); //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4300 байт (13%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 385 байт (18%) динамической памяти, оставляя 1663 байт для локальных переменных. Максимум: 2048 байт. */ПС: Вы говорили что вы учитесь, а на деле вам нужен готовый скетч в котором вы даже не захотели разобраться.
kors,конечно в этом скетче у серв все идет по циклу пауза-поворот вперед-поворот назад-пауза-.. Все как и задкмано. Что бы правильно написать скетч надо прежде всего узнать что он должен делать. То есть зачем он и его работу. Опять же длительнось задержки до начала работы должна быть одинакова или же индивидуально для каждой.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown, pPause}; /* состояние ВЫКЛ/ по часовой/против/пауза*/ class Cl_Sweeper { protected: Servo servo; // сервопривод const int pos_min = 60; 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 led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*нач.пауза*/100,/*время обновления*/ 30,/*пауза*/100); Cl_Sweeper F_D(/*пин*/12,/*нач.пауза*/200,/*время обновления*/ 30,/*пауза*/100); Cl_Sweeper B_U(/*пин*/7,/*нач.пауза*/300,/*время обновления*/ 30,/*пауза*/ 500); Cl_Sweeper B_D(/*пин*/8,/*нач.пауза*/400,/*время обновления*/ 30,/*пауза*/ 500); //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4300 байт (13%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 385 байт (18%) динамической памяти, оставляя 1663 байт для локальных переменных. Максимум: 2048 байт. */ПС: Вы говорили что вы учитесь, а на деле вам нужен готовый скетч в котором вы даже не захотели разобраться.
нет мне интересно самому написать скетч. И Ваш скетч я разбирал 2 дня и вроде бы порнял. Только с однократной задержкой было неясно...И я действительно хочу во всём разобраться и понять. Поэтому и попросил пример - так легче учиться...просто до меня туго доходит...я на лету не схватываю...И кроме того всегда собираю схему а потом меняя параметры скетча смотрю как реагирует реальная схема....Спасибо Вам за помощь...Сейчас начну разбирать как Вы организовали задержку. Я очень ценю Вашу помощь. Извините что отнимаю время...
Простейший цифровой автомат. Представьте себе устройство по типу черного ящика. У него есть внутрений параметр состояние. Его работа это переход из одного состояния в другое по времени и внешнему воздействию. Понятно что состояние это просто переменная со значениями. Но что бы не усложнять жизнь используются перечисляемый тип . Цикл циклу пауза-поворот вперед-поворот назад-пауза это pOFF => pUp => pDown => pPause=> pUp => pDown => pPause Осталось это делать по заданым промежуткам.
да да я понимаю... в принципе мне удалось задать все эти параметры и в классе Sweeper... и паузу в начале и в конце вращения и направление начала вращения от pos min или от pos max ... НО конечно же автомат лучше...автомат великолепен!...
Простейший цифровой автомат. Представьте себе устройство по типу черного ящика. У него есть внутрений параметр состояние. Его работа это переход из одного состояния в другое по времени и внешнему воздействию. Понятно что состояние это просто переменная со значениями. Но что бы не усложнять жизнь используются перечисляемый тип . Цикл циклу пауза-поворот вперед-поворот назад-пауза это pOFF => pUp => pDown => pPause=> pUp => pDown => pPause Осталось это делать по заданым промежуткам.
Так значит автомату можно задавать неограниченное число переманных?...Очень круто )
в принципе мне удалось задать все эти параметры и в классе Sweeper... и паузу в начале и в конце вращения и направление начала вращения от pos min или от pos max ...только олнократная пауза не получалась... НО конечно же автомат лучше...автомат великолепен!...
Не переменных а состояний, а так же условия перехода из одного в другое.
ПС:#258
Простейший цифровой автомат. Представьте себе устройство по типу черного ящика. У него есть внутрений параметр состояние. Его работа это переход из одного состояния в другое по времени и внешнему воздействию. Понятно что состояние это просто переменная со значениями. Но что бы не усложнять жизнь используются перечисляемый тип . Цикл циклу пауза-поворот вперед-поворот назад-пауза это pOFF => pUp => pDown => pPause=> pUp => pDown => pPause Осталось это делать по заданым промежуткам.
Уррааа!!! Работает однократная пауза.. просто чудо!!!! Только серву с начальной паузой как то подёргивает иногда во време движения...сейчас переставлю другую (у меня их 12 штук))) (MG 996R)
СПАСИБО Вам ОГРОМНОЕ !!!
ага значит состояние мы в скетче менять програмно не можем...это не переменная...понятно
кстати дёрганье было изз за сервы ..другую не дёргает
ой нет...дёргало серву потому что я указал адрес этой сервы 5й пин и забыл снять с этого адреса светодиод)))
Не переменных а состояний, а так же условия перехода из одного в другое.
ПС:#258
значит теперь можно задать автомату состояние аналогового пина и заставить его работать по команде с этого пина?)
Не переменных а состояний, а так же условия перехода из одного в другое.
ПС:#258
это моя лаборатория)
простите за назойливость а можно ли указать автомату ещё одно состояние - угол поворота сервы?
простите за назойливость а можно ли указать автомату ещё одно состояние - угол поворота сервы?
это моя лаборатория)
такая лаборатория хорошая... а скетчи писать не умеешь.
А я вот умею - а лаборатории нет. По-моему. это несправедливо :)
ПС:https://youtu.be/K71ofRVvfL4
дело в том что я только 1 год назад начал заниматься электротехникой ...моей лаборатории ток и вообще только 2 месяца отроду...а программированием я занялся 2 недели назад первый раз...никогда рвньше ...а Вы я думаю сможете своими знаниями заработать гораздо больше чем стоит эта лаборатория )....знания - сила....и деньги)
ПС:https://youtu.be/K71ofRVvfL4
Вы знаете qwone, я полностью поддерживаю Ваши слова...мои знания по электротехнике мне тоже приходится постоянно поддерживать и апдэйтить...иначе они уходят...забывается всё быстро...а добыты они были огромным трудом...по 10 - 13 часов в день с формулами и кнмгами...и впереди ещё столько непознанного...
простите за назойливость а можно ли указать автомату ещё одно состояние - угол поворота сервы?
жаль...а не подскажите как ввести переменную с углом поворота в автомат..или ещё как нибудь но чтобы сохранились функции автомата. В классе Sweeper есть возможность менять угол поворота одной сервы независимо от другой через Update2 и соответственно pos max+20 (например)...а у автомата я пытался задать какой то run2 или state2 ...компилятор ругается...простите дилетанта...
знания - сила....и деньги)
Вы в курсе, что из поговорок "знание - сила" и "время - деньги" (в англоязычном варианте: "knowledge is power" и "time is money") лекго доказывается, что чем больше знаний, тем меньше денег?
знания - сила....и деньги)
Вы в курсе, что из поговорок "знание - сила" и "время - деньги" (в англоязычном варианте: "knowledge is power" и "time is money") лекго доказывается, что чем больше знаний, тем меньше денег?
нет я не знаю эту теорему) ...но согласен что коммерческие способности это тоже талант...и как правило люди с огромным багажом знаний и математическими способностями увы этим талантом не обладают...поэтому им нужно искать дельцов умеющих делать деньги из знаний...
нет я не знаю эту теорему) ...
Ну, я тут не зря упомянул англоязычность. Шутка родилась там и в доказательстве используется тот факт, что power - это ещё и мощность.
Ну а дальше просто: как известно из физики "время = работа / мощность". В соответсвии с поговорками, заменяем "время" на "деньги", а "мощность" на "знания", получаем "деньги = работа / знания", т.е. деньги обратно пропорциональны знаниям, о чём и шла речь :)
получаем "деньги = работа / знания", т.е. деньги обратно пропорциональны знаниям
и жизнь это полностью подтверждает... :)
прикольная подмена понятий)))...но это всего лишь шутка ...это не является доказательством)
..и я имел ввиду именно силу...force...а сила как известно всегда полностью определяется точкой приложения и направлением (кроме её модуля)...сила это векторная величина...в этом смысл моих слов...)
...да и ещё забыл упомянуть что в поговорке "money is a power...power is the money" слово power переводится как "власть" а не сила...
подтверждает когда человек плывёт по течению...нужны волевые усилия и некоторое самопожертвование...и знания принесут деньги...
согласен ... просто не знаю где копать...Вы мне и так очень помогли показав как работает автомат. Автомат это очень круто и он мне очень нравится. Я хотел бы изучить его поглубже. Но в инете нет инфы на эту тему. Поэтому я и попросил совета как организовать независимую работу двух серво по принципу автомата (он гораздо лучше класса Sweeper) так чтобы угол поворота pos min и pos max для каждой сервы был свой. В классе Sweeper это можно легко сделать прописав для каждой сервы свой Update (со своим pos max+30 например). А в автомате так прописать у меня не получается в Вашем скетче? Спасибо Вам.
/**/ unsigned long mill; //-------------------------------------- enum {sOFF = 0, sOn};/* состояние ВЫКЛ/ВКЛ*/ class Cl_Flasher { protected: byte pin; // номер пина со светодиодом unsigned long OnTime; // время включения в миллисекундах unsigned long OffTime; // время, когда светодиод выключен int state; 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 <Servo.h> enum {pOFF = 0, pUp, pDown, pPause}; /* состояние ВЫКЛ/ по часовой/против/пауза*/ class Cl_Sweeper { protected: Servo servo; // сервопривод int pos_min; int pos_max; 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, int mi, int ma): // <-- добавляем сюда pin(p), offTime(t1) , stepTime(t2), pauseTime(t3), pos_min(mi), pos_max(ma) {} // <-- добавляем сюда 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 led1(/*пин*/3,/*времяВКЛ*/123,/*времяВЫКЛ*/400); Cl_Flasher led2(/*пин*/4,/*времяВКЛ*/350,/*времяВЫКЛ*/350); Cl_Flasher led3(/*пин*/5,/*времяВКЛ*/200,/*времяВЫКЛ*/222); Cl_Sweeper F_U(/*пин*/11,/*нач.пауза*/100,/*время обновления*/ 30,/*пауза*/100,/*min*/10,/*max*/20);// <-- добавляем сюда Cl_Sweeper F_D(/*пин*/12,/*нач.пауза*/200,/*время обновления*/ 30,/*пауза*/100,/*min*/20,/*max*/30);// <-- добавляем сюда Cl_Sweeper B_U(/*пин*/7,/*нач.пауза*/300,/*время обновления*/ 30,/*пауза*/ 500,/*min*/40,/*max*/50);// <-- добавляем сюда Cl_Sweeper B_D(/*пин*/8,/*нач.пауза*/400,/*время обновления*/ 30,/*пауза*/ 500,/*min*/60,/*max*/100);// <-- добавляем сюда //--------------------------------- void setup() { led1.init(); led2.init(); led3.init(); F_U.init(); F_D.init(); B_U.init(); B_D.init(); } void loop() { mill = millis(); led1.run(); led2.run(); led3.run(); F_U.run(); F_D.run(); B_U.run(); B_D.run(); } /*Скетч использует 4310 байт (14%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 385 байт (18%) динамической памяти, оставляя 1663 байт для локальных переменных. Максимум: 2048 байт. *//Спасибо большое...я всё понял....блин когда не знаешь всё кажется просто неразрешимым а когда узнаёшь думаешь какой же я тупой)...А можно как то оплачивать Ваши уроки?.. А то мне неудобно как то приставать с вопросами забесплатно...а вопросов ещё очень много...
Так я не сильный специалист. И это больше хобби.
Так я не сильный специалист. И это больше хобби.
Для меня Вы очень сильный специалист...и многому можете научить...
Какой счет. Я же с Украины. Задавайте так вопросы. Смогу помогу. Да и другие на форуме тоже , если посчитают нужным.
Какой счет. Я же с Украины. Задавайте так вопросы. Смогу помогу. Да и другие на форуме тоже , если посчитают нужным.
так я тоже с Украины) Я в Одессе живу)...Спасибо за доброе отношение и я надеюсь что у меня будет возможность ..вобщем я добро не забываю)
qwone, подскажите пожалуйста есть ли возможность в Вашем скетче сделать так чтобы обе сервы по сигналу с аналогового или цифрового пина начали крутиться по совершенно другому заданному алгоритму...? какой нибудь run1 можно прописать?или это нужно создавать ещё один автомат?...но тогда как его прописать в скетче и как с ним связать аналоговый пин?...вобщем задача в том чтобы по сигналу сервы начали крутиться совсем по другим заданным парамеирам (как бы по другому автомату)...Спасибо Вам)
Ну для этого надо начинать с нуля и рисовать новый проект. Вспомните как в детстве решали задачу с неизвестным. Обозначим неизвестное за икс . Ну в данном случае 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(); } /**/