使用DIP开关进行伺服控制

我对Arduino和编程也很陌生。 我想使用DIP开关扫描伺服。目前,我使用4位DIP开关。对于每个开关,我想设置伺服必须运行的次数。例如,DIP开关的Pos 1说,扫描5次。 Pos 2说,扫了10次等。

我写了以下代码:

#include 

Servo myservo;  
int pos = 0; 
int count = 0;  //might need later
int runXTimes = 0;

#define S1 2
#define S2 3
#define S3 4
#define S4 5

int s1state = HIGH;
int s2state = HIGH;
int s3state = HIGH;
int s4state = HIGH;


void setup() {
   myservo.attach(9);
   pinMode(S1, INPUT_PULLUP);
   pinMode(S2, INPUT_PULLUP);
   pinMode(S3, INPUT_PULLUP);
   pinMode(S4, INPUT_PULLUP);
   pinMode(9, OUTPUT);
}

void loop() {

   s1state = digitalRead(S1);
   s2state = digitalRead(S2);
   s3state = digitalRead(S3);
   s4state = digitalRead(S4);


  //Servo control through Switch 1
   if (s1state == LOW) {    //read the input pin
      for (int runXTimes = 0; runXTimes < 5; runXTimes++) {   //Servo to     sweep for 5 times
         for (pos = 0; pos <= 80; pos += 1) //goes from 0 degrees to 80 degrees in steps of  degree

         {                                   
            myservo.write(pos);             //tell servo to go to position in variable 'pos'
            delay(5);
         }

         for(pos = 80; pos>=0; pos-=1)    //goes from 80 degrees to 0 degrees
         {                               
            myservo.write(pos);             //tell servo to go to position in variable 'pos'
            delay(5);
         }

      }

   }

  //Servo control through Switch 2. Used servo detach here
   else if (s2state == LOW) { //read the input pin
      for (int runXTimes = 0; runXTimes < 10; runXTimes++) { //Servo to sweep for 10 times
         for (pos = 0; pos <= 80; pos += 1) //goes from 0 degrees to 80 degrees in steps of  degree
         {                                  
            myservo.write(pos);             //tell servo to go to position in variable 'pos'
            delay(5); 
         }

         for(pos = 80; pos>=0; pos-=1)    //goes from 80 degrees to 0 degrees
         {                               
            myservo.write(pos);             //tell servo to go to position in variable 'pos'
            delay(5);  
         }

      }
      myservo.detach();
   }

  //Servo control through Switch 3
   else if (s3state == LOW) { //read the input pin
      for (pos = 0; pos <= 80; pos += 1) //goes from 0 degrees to 80 degrees in steps of  degree
      {                                 //
         myservo.write(pos);             //tell servo to go to position in variable 'pos'
         delay(5); 
      }

      for(pos = 80; pos>=0; pos-=1)    //goes from 80 degrees to 0 degrees
      {                               
         myservo.write(pos);             //tell servo to go to position in variable 'pos'
         delay(5);  
      }
   }

  //Servo control through Switch 4
   else if (s4state == LOW) { //read the input pin
      for (pos = 0; pos <= 80; pos += 1) //goes from 0 degrees to 80 degrees  in steps of  degree
      {                                 
         myservo.write(pos);             //tell servo to go to position in variable 'pos'

         delay(5); 
      }

      for(pos = 80; pos>=0; pos-=1)    //goes from 80 degrees to 0 degrees
      {                               
         myservo.write(pos);             //tell servo to go to position in variable 'pos'
         delay(5);  
      }

   }
}

上述代码发生的操作是: 1)通过开关1进行伺服控制 - 如果我立即开启(0)然后关闭(1),伺服扫描5次。更像是一个按钮开关。如果我再次打开和关闭(立即),我可以再次扫描5次。但是,如果我将开关置于1,则扫描不会在5次后停止 2)通过开关2进行伺服控制:如果我打开,伺服扫描10次并根据我的兴趣停止。但是,如果我再次将开关更改为0和1,则序列不会启动。事实上,没有其他开关工作。我需要关闭Arduino以重新运行程序。 3)通过开关3(=开关4)进行伺服控制:如果我的开关为1,则伺服扫描。如果我的开关为0,则伺服停止。

你能建议一下: 1)如何编写代码使我的伺服器只扫描设定的次数,即使开关始终处于1或每当我在0和1之间切换时? 2)我不想使用串行通信(或通常是PC)。是否可以连接7段或LCD以显示已完成或仍然保留的扫描次数。

先感谢您。

1

3 答案

这是基于想象力的,因为我现在无法自己测试,但可以随意询问是否有些不对劲。

int readswitch()
{
 int S1,S2,S3,S4;
 uint8_t data = 255;
 data |= digitalRead(S4)<<3;
 data |= digitalRead(S3)<<2;
 data |= digitalRead(S2)<<1;
 data |= digitalRead(S1)<<0;

  if (data==0b11111110) return 1; else
  if (data==0b11111101) return 2; else
  if (data==0b11111011) return 3; else
  if (data==0b11110111) return 4; else
  //add another condition here if you want
  return 0;
}

int laststate = 0;
int state = 0;
int rotation;

void setup()
{
  //setup here, including LCD initialization
  //..
  //..
  //..
}

void updateLCD(int x,int y)
{
  lcd.clear();
  //displaying pin status
  lcd.print("dip : ");
  lcd.print(x,DEC);
  lcd.print(" rot : ");
  lcd.print(y,DEC); 
}

void loop()
{
  state = readswitch();
  if (state!=laststate)
  {
    if (state == 1) 
    {
      rotation = 5;
      for (int i = 0; i< rotation; i++)
        {
         //update lcd
         updateLCD(state,(rotation-i));

         //.. servo rotation
         //..
        }
      //...
    } else

    if (state == 2) 
    {
      //do what you want here if switch 2 == LOW
      //...
    } else

    if (state == 3) //switch 1 == LOW
    {
      //do what you want here if switch 3 == LOW
      //...
    } else

    if (state == 4) //switch 1 == LOW
    {
      //do what you want here if switch 4 == LOW
      //...
    } 
  }
  laststate = state;

}

For more information about LCD, you can refer to this documentation

1
额外

如果你将扫描代码放在setup函数中,它将执行一次(因为setup()只调用一次),你会看到你所期望的。

但是,因为它在loop()函数中,它每次执行loop()函数时执行 - 这是loop()函数的要点。作为另一种选择,您可以设置无限循环或永久循环

for(;;)
   ;   //program hangs here forever

在loop()函数的末尾,以防止它返回并再次被调用。无论哪种方式,您都会看到对您编码的步骤进行单次传递。

0
额外

您的switch 2代码在末尾包含一个myservo.detach(),可防止任何其他服务器代码运行。

如果希望switch 1代码只执行一次,可以在块中添加myservo.detach()。

如果清除开关,您似乎也想要回收适当的次数。为此,当所有开关都打开时,您可能需要myservo.attach(9)。

或者,您可以通过向条件添加一次性标记来避免detach()和attach(),将其设置在条件内,并在开关清除时清除它。

例如:

   if (!s1state & !s2state & !s3state & !s4state) armed = 1;
   ...

   if (armed & s1state == LOW) {    //read the stored input pin value
       armed = 0;
       ...
0
额外