Как управлять несколькими серводвигателями одновременно с помощью протопотока с помощью платы ШИМ I2C PCA9685?
Я пытаюсь использовать протопоточность для управления двумя (и, в конечном счете, четырьмя) серводвигателями по I2C с помощью платы PCA9685 PWM.
Для начала я просто пытаюсь запустить два двигателя назад и четвертый одновременно.
Вот код, который я использую:
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#include <protothreads.h>
#define SERVOMIN 150
#define SERVOMAX 600
#define USMIN 600
#define USMAX 2400
#define SERVO_FREQ 50
int servo1 = 0;
int servo2 = 4;
//////////////////////// T H R E A D 1 /////////////////////////
pt ptServo1;
int Servo1Thread(struct pt* pt){
PT_BEGIN(pt);
for(;;){
for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
pwm.writeMicroseconds(servo1, microsec);
}
PT_SLEEP(pt, 500);
for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
pwm.writeMicroseconds(servo1, microsec);
}
PT_SLEEP(pt, 500);
}
PT_END(pt);
}
//////////////////////// T H R E A D 2 /////////////////////////
pt ptServo2;
int Servo2Thread(struct pt* pt){
PT_BEGIN(pt);
for(;;){
for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
pwm.writeMicroseconds(servo2, microsec);
}
PT_SLEEP(pt, 500);
for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
pwm.writeMicroseconds(servo2, microsec);
}
PT_SLEEP(pt, 500);
}
PT_END(pt);
}
////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
PT_INIT(&ptServo1);
PT_INIT(&ptServo2);
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
}
void loop() {
PT_SCHEDULE(Servo1Thread(&ptServo1));
PT_SCHEDULE(Servo2Thread(&ptServo2));
}
Я замечаю, что сервопривод 1 поворачивается на -90 и останавливается. Когда он остановился, сервопривод 2 поворачивается до -90, а затем останавливается....затем сервопривод 1 поворачивается на +90 и останавливается, и так далее. Они не делают уборку одновременно.
Любая помощь будет очень признательна!
Спасибо тебе,
H
@H. M, 👍2
1 ответ
Не зная подробно Protothread: скорее всего, он обрабатывает обмен потоками во время PT_SLEEP ()
, который вы выполняете только после одной "развертки" (одного из внутренних циклов for), не давая никакой возможности переключиться на другой поток.
Кроме того, таким образом, у вас нет никаких задержек во внутренних циклах for, поэтому они выполняются очень быстро. Быстрее, чем двигатель действительно может следовать. Это означает, что сервопривод просто перемещается в конечное положение так быстро, как только может, а цикл for практически бесполезен. Вам нужна задержка внутри внутренних петель for для замедления сигнала.
Пожалуйста, попробуйте что-нибудь вроде этого:
pt ptServo1;
int Servo1Thread(struct pt* pt){
PT_BEGIN(pt);
for(;;){
for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
pwm.writeMicroseconds(servo1, microsec);
PT_SLEEP(pt, 50);
}
PT_SLEEP(pt, 500);
for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
pwm.writeMicroseconds(servo1, microsec);
PT_SLEEP(pt, 50);
}
PT_SLEEP(pt, 500);
}
PT_END(pt);
}
Измените время сна во внутреннем цикле в соответствии с требуемой скоростью развертки.
- Как заставить сервопривод вращаться на угол больше 180°
- 6 + 1 двигательей подключенных к arduino uno?
- Почему сервопривод вращается на 360 градусов?
- Как Arduino Uno может поддерживать до 12 сервоприводов, если у него всего 6 цифровых выводов ШИМ?
- Контакты ШИМ серводвигателей, Arduino Uno
- Как запитать 6 серводвигателей от батареи для создания робота-манипулятора?
- Как повторить код
- Серво не двигается
Спасибо вам за ваш ответ! Любопытно, что как только я добавляю PT_SLEEP(pt,50) внутри цикла for, как вы предложили, ничего не происходит. Двигатели не двигаются при all...is возможно ли, что протопоточность не работает с I2c, возможно?, @H. M
Возможно, вам придется значительно сократить время сна (до этого вы не регистрировались, вы записываете диапазон микросекунд от 600 до 2400 с шагом 1) или увеличить размер шага с 1 до большего числа. При текущей настройке может потребоваться слишком много времени, чтобы заметить движение, @chrisl