Как перемещать сервопривод с помощью функции
В настоящее время я перемещаю сервопривод с одной стороны на другую, используя типичный цикл for, подобный этому:
int lightON = 180;
int lightOFF = 90;
if (buttonState == HIGH) {
digitalWrite(LED, HIGH);
for (pos1 = lightOFF; pos1 <= lightON; pos1 += 1) {
servo1.write(pos1);
delay(15);
}
digitalWrite(LED, LOW);
}
Это означало бы перемещение сервопривода в одну сторону, и если я снова нажму кнопку, сервопривод переместится в другую сторону.
if (buttonState == LOW) {
digitalWrite(LED, HIGH);
for (pos1 = lightON; pos1 >= lightOFF; pos1 -= 1) {
servo1.write(pos1);
delay(15);
}
digitalWrite(LED, LOW);
}
Дело в том, что у меня есть тот же самый код в 3 других сервоприводах, и я не хочу повторять один и тот же код с 2 разными переменными (pos и сервопривод) снова и снова, поэтому я попытался
void runServoLight(int pos, int light1, int light2, Servo servo, int state) {
if (state == 1) {
digitalWrite(LED, HIGH);
for (pos = light1; pos <= light2; pos += 1) {
servo.write(pos);
delay(15);
}
digitalWrite(LED, LOW);
} else if (state == 0) {
digitalWrite(LED, HIGH);
for (pos = light2; pos >= light1; pos -= 1) {
servo.write(pos);
delay(15);
}
digitalWrite(LED, LOW);
}
}
Теперь вместо запуска всего кода цикла for я запускаю только:
runServoLight(pos1, lightON, lightOFF, servo1, 1);
Проблема в том, что это, похоже, не работает, и я могу понять, почему, возможно, я неправильно пишу функцию, но я не совсем уверен. Я был бы очень признателен за некоторую помощь. Спасибо!
@Marcelo_M, 👍3
Обсуждение2 ответа
Вы написали:
void runServoLight( int pos, int light1, int light2, Servo servo, int state)
Здесь вы приводите список параметров, используемых функцией. В C++ параметры по умолчанию передаются по значению. Это означает, что при вызове функции аргументы, переданные в вызове, копируются в перечисленные здесь параметры, которые являются локальными переменными функции. Изменения этих параметров не будут распространяться на аргументы, предоставленные вызывающим.
Это может быть проблемой для объекта сервопривода
. Этот объект сохраняет некоторое
внутреннее состояние, в котором хранится память о текущей конфигурации
таймеров. Поскольку вы работаете с копией предоставленного объекта,
исходный объект не обновляется при работе с копией. Я не знаю
, приводит ли это к неправильному поведению вашей программы, но было бы безопаснее
передать объект Servo
по ссылке:
void runServoLight(
int pos, int light1, int light2, Servo &servo, int state)
Таким образом, объект не будет скопирован: вместо этого функция будет работать с исходным объектом, предоставленным вызывающим.
То же самое может относиться и к параметру pos. Самое первое, что функция делает с этим параметром, - это перезаписывает его. Тогда нет смысла получать это значение от вызывающего абонента. Вместо этого вы можете удалить параметр и создать локальную переменную с тем же именем:
void runServoLight(int light1, int light2, Servo &servo, int state) {
int pos; // локальная переменная
...
}
Если вы хотите, чтобы версия вызывающей переменной была обновлена, вы
можете передать ее по ссылке, как и объект Servo.
Однако более эффективно сохранить переменную локальной и заставить функцию
возвращать конечную позицию. Тогда вызов будет выглядеть следующим образом:
pos1 = runServoLight(lightON, lightOFF, servo1, 1);
Один последний момент, который не виден в показанных вами фрагментах: вы
выполняете обнаружение краев на кнопках? Обнаружение границ означает, что вы действуете
по изменению состояния кнопок, а не по самим состояниям.
Например, вы переходите от lightOFF
к Lightton
не тогда, когда состояние кнопки
ВЫСОКОЕ
, а когда оно становится ВЫСОКИМ
.
Это не решение, однако, путем рафторинга оно делает ваш скетч более удобным для обслуживания, так как дублированный код удаляется:
void runServoLight(int pos, int light1, int light2, Servo servo, int state)
{
if (state == 1) {
process(light1, light2, +1, servo);
}
else if (state == 0) {
process(light2, light1, -1, servo);
}
}
def process(int this_light, int other_light, int delta, Servo servo)
{
digitalWrite(LED, HIGH);
for (pos = this_light; pos >= other_light; pos += delta) {
servo.write(pos);
delay(15);
}
digitalWrite(LED, LOW);
}
Вместо целого числа состояния более понятно использовать перечисление и использовать оператор switch.
#include "Servo.h"
const int LED = 13;
enum EServoState { LEFT, RIGHT };
void runServoLight(int light1, int light2, Servo servo, EServoState state);
void setup()
{
}
void loop()
{
int light1 = 1;
int light2 = 2;
EServoState state;
Servo servo;
runServoLight(light1, light2, servo, state);
}
void runServoLight(int light1, int light2, Servo servo, EServoState state)
{
switch (state)
{
case LEFT:
process(light1, light2, +1, servo);
break;
case RIGHT:
process(light2, light1, -1, servo);
break;
//default:
// Handle program error
}
}
void process(int this_light, int other_light, int delta, Servo servo)
{
digitalWrite(LED, HIGH);
for (int pos = this_light; pos >= other_light; pos += delta)
{
servo.write(pos);
delay(15);
}
digitalWrite(LED, LOW);
}
- Как быстро и без задержки переместить сервопривод?
- Как добавить задержку, закрыть сервопривод и снова перейти к началу?
- Как остановить серводвигатель в текущем положении при использовании последовательного порта? Я хочу, чтобы он оставался в одном положении при получении «0».
- Когда я включаю сервопривод, он вращается сам по себе, прежде чем перейти в нужное положение и начать скетч.
- Функция управления сервоприводами
- Как закодировать светодиодные поворотники на умной машине
- Код, из-за которого серводвигатель не работает!
- Рефакторинг плохого дизайна?
В вашей функции
light1
должен быть ниже, чемlight2
. Похоже, вы их перепутали в звонке., @Mat