如何使用Arduino实现继电器开关的用户可调时序?

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

我正在开发一个 Arduino 项目来管理继电器开关的时序,该项目由 4 个继电器、3 个按钮和一个 7 段显示器组成。虽然我已经完成了设置,但我正在努力设计一个系统,用户可以使用三个按钮和 7 段显示器来调整继电器的开/关持续时间。下面是我的代码:


#define CLK 2
#define DIO 3
TM1637Display display(CLK, DIO);

int relayPins[] = {4, 5, 6, 7};
int onTimes[] = {2000, 4000, 5000, 3000};
int offTimes[] = {1000, 2000, 1000, 3000};

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW);
  }
  display.setBrightness(0x0f);
}

void loop() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(relayPins[i], HIGH);
    for (int j = onTimes[i] / 1000; j > 0; j--) {
      display.showNumberDec(j, false, 2, 0);
      delay(1000);
    }
    digitalWrite(relayPins[i], LOW);
    for (int j = offTimes[i] / 1000; j > 0; j--) {
      display.showNumberDec(j, false, 2, 0);
      delay(1000);
    }
  }
}

我需要帮助实现一种机制,用户可以使用按钮和显示屏调整每个继电器的开/关持续时间。我该如何修改这段代码来实现这一目标?

在尝试修改用户可调时序的变量时,我最初尝试集成其他函数来读取按钮的状态并相应地更新 onTimes[] 和 offTimes[] 数组。然而,我在将按钮输入与每个继电器的时间间隔正确同步方面遇到了困难。具体来说,我努力根据用户输入有效地更新定时变量,同时确保平稳的继电器操作和显示更新。我期望成功实现一个系统,用户可以使用按钮交互式地调整计时持续时间,并观察 7 段显示屏上反映的变化

arduino embedded
1个回答
0
投票

为了使 Arduino“大循环”框架有效工作,您应该将设计分解为单独的非阻塞状态机。当然,如果您希望能够同时处理中继切换和用户交互,您应该避免阻塞

delay()
调用。

事实上,您现有的实现无论如何都会被破坏,因为它按顺序执行每个继电器的开-关-切换,因此每个继电器的关闭时间将是其他三个继电器的开+关时间的总和。

如果您按如下方式更改

loop()
功能:

void loop() 
{
  relay_statemachine() ;
  ui_statemachine() ;
}

然后,同时运行所有四个继电器开关周期并且不阻塞(即总是立即返回,以便

relay_statemachine()
可以运行)的
ui_statemachine()
实现可能如下所示:

void relay_statemachine()
{
  static struct
  {
    int state ;     // current relay state
    int timestamp ; // time of last relay state change
  } relay[] = { 0 } ;

  // Current time
  unsigned long now = millis() ;
  
  // For each realy
  for( int r = 0; r < 4; r++ )
  {
    // If relay is off...
    if( relay[r].state == LOW )
    {
      // ... if it is time to switch ...
      if( now - relay[r].timestamp > offTimes[r] )
      {
         // ... change state and timestamp it
        relay[r].state = HIGH ;
        relay[r].timestamp = now ;
      }
    }
    else // ... else relay is on...
    {
      // ... if it is time to switch ...
      if( now - relay[r].timestamp > onTimes[r] )
      {
         // ... change state and timestamp it
        relay[r].state = LOW ;
        relay[r].timestamp = now ;
      }
    }

    // Assert current relay state.
    digitalWrite (relayPins[r], relay[r].state ) ;
  }
}

然后,您可以类似地将

ui_statemachine()
实现为状态机(没有延迟或阻塞),其中触发器是按钮事件(不要忘记需要去抖)。您尚未定义 UI 将如何工作,但我建议:

  • 按钮 A - 循环选择功能:
    1. 继电器 1 开启时间(显示 1.1)
    2. 继电器1断开时间(显示1.0)
    3. 继电器 2 开启时间(显示 2.1)
    4. 继电器2断开时间(显示2.0)
    5. 继电器 3 开启时间(显示 3.1)
    6. 继电器3断开时间(显示3.0)
    7. 继电器 4 开启时间(显示 4.1)
    8. 继电器4断开时间(显示4.0)
  • 按钮 B - 当前所选功能的增量时间(显示时间)
  • 按钮 C - 当前所选功能的递减时间(显示时间)
© www.soinside.com 2019 - 2024. All rights reserved.