伺服电机不会持续旋转,这与原始 Arduino 代码的意图不同

问题描述 投票:0回答:1

我想不停地循环移动伺服电机!怎么了?

#include <Adafruit_PWMServoDriver.h>
#include <Wire.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

int motors[] = {0, 1, 2, 3};
int degrees[] = {0, 0, 0, 0};

void setup() {
  Serial.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(50);
  pwm.setOscillatorFrequency(27000000); 
  
  for(int i=0; i<15; i++){
    pwm.setPWM(i, 0, 150);   
  }
  
  Serial.setTimeout(10);
}

void joystick_val(int pin){
  Serial.print(pin);
  Serial.print("   ");  
}

void Move_motor(int motor, int degree, int int_val){
  if(int_val <= 1){
    degree += 5;
    if(degree > 180) degree = 180;
        
    int pul = map(degree,0,180,150,600);
    pwm.setPWM(motor, 0, pul);
  }
  
  else if(int_val >= 4){
    degree -= 5;
    if(degree < 0) degree = 0;
        
    int pul = map(degree,0,180,150,600);
    pwm.setPWM(motor, 0, pul);
  }
  
}

void loop() { 

  //int e = Serial.parseInt();
  int analogPin[] = {analogRead(A0), analogRead(A1), analogRead(A2), analogRead(A3)};
  int int_Pin[] = { map(analogPin[0], 0, 1023, 0, 5),
                    map(analogPin[1], 0, 1023, 0, 5),
                    map(analogPin[2], 0, 1023, 0, 5),
                    map(analogPin[3], 0, 1023, 0, 5)
                  };
  int Pin_amount = sizeof(analogPin)-4;
  
  Move_motor(motors[0], degrees[0], map(analogPin[0], 0, 1023, 0, 5));
  Move_motor(motors[1], degrees[1], map(analogPin[1], 0, 1023, 0, 5));
  Move_motor(motors[2], degrees[2], map(analogPin[2], 0, 1023, 0, 5));
  Move_motor(motors[3], degrees[3], map(analogPin[3], 0, 1023, 0, 5));


  for(int j=0; j<Pin_amount; j++){
    Serial.print(map(analogPin[j], 0, 1023, 0, 5));
    Serial.print("   "); 
  }       
  
  Serial.println("");
}

原本,只要握住连接到电机的操纵杆,伺服电机就必须保持旋转,只有松开操纵杆才停止。然而,当摇杆移动时,伺服电机会在旋转一瞬间后停止,而不是连续旋转。

我尝试使用“for”循环,也尝试改变 PWM 的频率。我想要的是使代码功能相同,而无需编写四次 Move_motor 函数。预先感谢您。

c arduino servo
1个回答
0
投票
  1. 当您更改

    degree
    中的
    Move_motor
    时,它只会更改本地值。

  2. 它不会更改全局数组degrees

    ,因此当调用
    degree
    时,
    Move_motor
    的值是
    always 0。

  3. degree

     只会是 0 或 5

为了解决这个问题,我们

可以degrees

作为指针传递给
Move_motor

但是,有很多[不必要的]重复代码。

解决此问题的最佳方法是使用单个

struct

 数组,而不是使用相同值索引的多个数组。


这是一个重构版本。注释为:

#include <Adafruit_PWMServoDriver.h> #include <Wire.h> Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // per-motor control typedef struct mctl { int motidx; // motor index int apin; // AnalogRead port number int aval; // AnalogRead value int ival; // int of aval int degree; // current rotation int pul; // old motor pul value } mctl_t; #define NCTL 4 mctl_t controls[NCTL]; void setup(void) { Serial.begin(9600); pwm.begin(); pwm.setPWMFreq(50); pwm.setOscillatorFrequency(27000000); for (int i = 0; i < 15; i++) pwm.setPWM(i, 0, 150); Serial.setTimeout(10); int aport[] = { A0, A1, A2, A3 }; for (mctl_t mctl = &controls[0]; mctl < &controls[NCTL]; ++mctl) { int motidx = mctl - controls; mctl->motidx = motidx; mctl->aport = aport[motidx]; mctl->pul = 0x7FFFFFFFF; } } void joystick_val(int pin) { Serial.print(pin); Serial.print(" "); } void move_motor(mctl_t *mctl) { int degree = mctl->degree; int setflg = 0; int int_val = map(mctl->aval, 0, 1023, 0, 5), do { if (int_val <= 1) { degree += 5; setflg = 1; break; } if (int_val >= 4) { degree -= 5; setflg = 1; break; } // do nothing??? } while (0); if (degree > 180) degree = 180; if (degree < 0) degree = 0; do { if (! setflg) break; int pul = map(degree, 0, 180, 150, 600); // optional speedup: don't send value if hasn't changed since the last // time if (pul == mctl->pul) break; pwm.setPWM(mctl->motidx, 0, pul); // remember the value we just output mctl->pul = pul; } while (0); // save updated values mctl->degree = degree; mctl->ival = int_val; } void loop(void) { // grab all values quickly for (mctl_t mctl = &controls[0]; mctl < &controls[NCTL]; ++mctl) mctl->aval = AnalogRead(mctl->apin); // change all motor values for (mctl_t mctl = &controls[0]; mctl < &controls[NCTL]; ++mctl) move_motor(mctl); // show all values for (mctl_t mctl = &controls[0]; mctl < &controls[NCTL]; ++mctl) { Serial.print(mctl->ival); Serial.print(" "); } Serial.println(""); }
    
© www.soinside.com 2019 - 2024. All rights reserved.