Arduino延迟替代方案

Arduino alternative for delays?

本文关键字:方案 延迟 Arduino      更新时间:2023-10-16

我想做的是同时运行2个交通信号灯(例如,北部和南方)。除了Millis之外,还有延迟的替代方案吗?我尝试使用blinkwithoutdelay,但作为新手,我非常复杂。

    digitalWrite(greenled, HIGH); //Green on for 1 seconds
    delay(greenDuration);
    digitalWrite(greenled, LOW); //Green off, yellow on for 1 seconds
    digitalWrite(yellowled, HIGH);
    delay(1000);
    digitalWrite(yellowled, LOW); //yellow off, red on for 1 seconds
    digitalWrite(redled, HIGH);
    delay(1000);
    digitalWrite(redled, LOW); //Red off

    digitalWrite(greenled2, HIGH); //Green on for 1 seconds
    delay(1000);
    digitalWrite(greenled2, LOW); //Green off, yellow on for 1 seconds
    digitalWrite(yellowled2, HIGH);
    delay(1000);
    digitalWrite(yellowled2, LOW); //yellow off, red on for 1 seconds
    digitalWrite(redled2, HIGH);
    delay(1000);
    digitalWrite(redled2, LOW); //Red off

完成代码:

int beam = 2;//Beam sensor
int greenled = 4;
int redled = 7;
int yellowled = 13;
int greenDuration =1000;    //normal time
int greenShortDuration = 1000;
int greenIncrement = 5000; //5 seconds
void setup() 
{
  // set the digital pin as output:
  pinMode(greenled, OUTPUT);  
  pinMode(redled, OUTPUT); 
  pinMode(greenled, OUTPUT); 
  pinMode(beam,INPUT); 
  Serial.begin(9600);
}
void loop()
{
            Serial.println("Status:low");
            digitalWrite(greenled, HIGH); //Green on for 5 seconds
            delay(greenDuration);
            digitalWrite(greenled, LOW); //Green off, yellow on for 2 seconds
            digitalWrite(yellowled, HIGH);
            delay(1000);
            digitalWrite(yellowled, LOW); //yellow off, red on for 5 seconds
            digitalWrite(redled, HIGH);
            delay(1000);
            digitalWrite(redled, LOW); //Red and Yellow off
    digitalWrite(greenled2, HIGH); //Green on for 1 seconds
    delay(1000);
    digitalWrite(greenled2, LOW); //Green off, yellow on for 1 seconds
    digitalWrite(yellowled2, HIGH);
    delay(1000);
    digitalWrite(yellowled2, LOW); //yellow off, red on for 1 seconds
    digitalWrite(redled2, HIGH);
    delay(1000);
    digitalWrite(redled2, LOW); //Red off
  if(digitalRead(beam)==HIGH){
    for(int i=1; i<=10; i++){
      Serial.println(i);
      while(i>=10){
          Serial.println("Motion Detected");
          greenDuration +=greenIncrement; //Add 5 seconds everytime
          Serial.println(greenDuration);
        break;
      }
      }
    }
         if(!digitalRead(beam)==HIGH){
        Serial.println("hey"); //indication of code is working
        greenDuration=greenShortDuration;
        return;
}
}

我试图使用blinkwithoutdelay,但作为新手,它非常复杂 为我使用它。

您必须更努力地:)

想象loop()不是"程序",而是任何时刻的描述。总的来说,它检测到既没有进行更改的时间,也没有新的pushbutton请求,因此循环立即退出。即使应该发生什么事情,任何新反应都不会花费任何时间,并且循环立即退出。

有一个简单的解决方案来解决给定的交通灯样本。

而不是调用延迟功能,您可以调用特殊延迟功能:

int globalFlagSomeonePressedBeam = false;  // store global if someone pushed the beam button
void delay_and_check_for_beam (int msDelay) {
    for (int i=0; i<msDelay; ++i) {
        if(digitalRead(beam)==HIGH){ // check beam button
            globalFlagSomeonePressedBeam = true; // store information
        }
        delay(1);
    }
}

在您延迟功能的呼叫之间,您设置了正确的灯(数字出口)检查globalflagsomeOnePressedBeam后,您需要将其设置回false

op。

解决方案
unsigned long curGoStopDuration, defGoStopDuration = 5000, maxGoStopDuration = 30000;
unsigned long currentMillis;
#pragma region SensorFields
int durationIncrement = 2500;
unsigned long greenPrevMillis;
float DetectionTime = 2500;
bool triggered;
#pragma endregion
enum LightState { Green, Yellow, Red };
class Stoplight
{
private:
    int greenLed, yellowLed, redLed;
    unsigned long previousMillis;
    float CurInterval;
    LightState state;
public:
    unsigned long GreenDuration = 5000;
    unsigned long RedDuration = 5000;
    int YellowDuration = 1000;
    Stoplight(int gLed, int yLed, int rLed) :greenLed(gLed), yellowLed(yLed), redLed(rLed)
    {
        pinMode(greenLed, OUTPUT);
        pinMode(redLed, OUTPUT);
        pinMode(yellowLed, OUTPUT);
    }
    void Loop()
    {
        if (currentMillis - previousMillis >= CurInterval)
        {
            previousMillis = currentMillis;
            //Transitions
            switch (state)          
            {
                case Green:             
                    ToYellow();
                    break;
                case Yellow:
                    ToRed();
                    break;
                case Red:
                    ToGreen();
                    break;
            }
        }
    }
    void ToGreen()
    {
        digitalWrite(redLed, LOW);
        digitalWrite(greenLed, HIGH);
        CurInterval = GreenDuration - YellowDuration;
        state = Green;
    }
    void ToYellow()
    {
        digitalWrite(greenLed, LOW);
        digitalWrite(yellowLed, HIGH);
        CurInterval = YellowDuration;
        state = Yellow;
    }
    void ToRed()
    {
        digitalWrite(yellowLed, LOW);
        digitalWrite(redLed, HIGH);
        CurInterval = RedDuration;
        state = Red;
    }
};
Stoplight SL_01(2, 3, 4), SL_02(5, 6, 7);
int beamSensor = 8;
void setup()
{
    //Set default values
    curGoStopDuration = defGoStopDuration;
    SL_01.ToGreen();
    SL_02.ToRed();
    pinMode(beamSensor, INPUT);
    Serial.begin(9600);
}
void loop()
{
    currentMillis = millis();
    Sensor();
    //Manipulate durations
    SL_01.GreenDuration = curGoStopDuration;
    SL_02.RedDuration = curGoStopDuration;
    SL_01.Loop();
    SL_02.Loop();
}
void Sensor()
{
    //If sensor detects something
    if (digitalRead(beamSensor) == HIGH)
    {
        if (!triggered)
        {
            greenPrevMillis = currentMillis;
            triggered = true;
        }
        if (currentMillis - greenPrevMillis >= DetectionTime)
        {
            if(curGoStopDuration < maxGoStopDuration)
                curGoStopDuration += durationIncrement; //Add seconds
            greenPrevMillis = currentMillis;
            Serial.print("Green light duration is now: ");
            Serial.println(curGoStopDuration);
        }
    }
    else  //No detection
    {
        curGoStopDuration = defGoStopDuration;
        triggered = false;
    }
}

您需要在光束上中断,快速,只需计数器,但是对于更精确的计数(clogine =))...这对我有用:

#define redPin1 40
#define yellowPin1 41
#define greenPin1 42
#define beamPin1 21
#define redDuration 1000
#define yellowDuration 1000
#define greenDuration 1000
#define durationIncrement 500
byte carCounter1 = 0;
byte state1 = 1;
void setup()
{
    pinMode(redPin1, OUTPUT);
    pinMode(yellowPin1, OUTPUT);
    pinMode(greenPin1, OUTPUT);
    pinMode(beamPin1, INPUT);
    attachInterrupt(digitalPinToInterrupt(beamPin1), beamCount1, RISING);
}
void beamCount1()
{
     carCounter1++;
}
void wait(long duration)
{
    int wait = 0;
    long last = millis();
    while (wait == 0)
    {
        long now = millis();
        if (now - last >= duration) { wait = 1;}
        else {}
    }
}
void redLight(byte redLightPin)
{
    digitalWrite(redLightPin, HIGH);
    wait(redDuration);
    state1 = 2;
}
void yellowLight1(byte redLightPin, byte yellowLightPin)
{
    digitalWrite(yellowLightPin, HIGH);
    wait(yellowDuration);
    digitalWrite(redLightPin, LOW);
    digitalWrite(yellowLightPin, LOW);
    state1 = 3;
}
void yellowLight2(byte yellowLightPin)
{
    digitalWrite(yellowLightPin, HIGH);
    wait(yellowDuration);
    digitalWrite(yellowLightPin, LOW);
    state1 = 1;
}
void greenLight(byte greenLightPin)
{
    digitalWrite(greenLightPin, HIGH);
    long incremented = greenDuration + (carCounter1 * durationIncrement);
    wait(incremented);
    digitalWrite(greenLightPin, LOW);
    carCounter1 = 0;
    state1 = 4;
}
void trafficLight(byte red, byte yellow, byte green)
{
    switch (state1){
    case 1: 
      redLight(red);
      break;
    case 2:
      yellowLight1(red, yellow);
      break;
    case 3:
      greenLight(green);
      break;
    case 4:
      yellowLight2(yellow);
      break;
    }
}
void loop()
{
    trafficLight(redPin1, yellowPin1, greenPin1);
}

否延迟,只需跟踪Millis的等待功能...如果您想要更精确,请计算每个灯所需的时间,然后将其从等待...

中删除