首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >监控电压超过10秒

监控电压超过10秒
EN

Stack Overflow用户
提问于 2021-02-06 22:48:39
回答 1查看 79关注 0票数 0

我正在构建一个测量组件电压的程序。当电位低于1V时,振动电机将接通。

但我的问题是,如果电压低于1V持续10秒或更长时间,我希望Arduino打开电机。例如,如果电压水平低于1 V持续8秒,然后再次变为5 V以上,则电机不应启动。此外,电机应在振动3秒后关闭。我能满足第一个条件。但我不能关掉马达。

到目前为止,我的代码如下:

代码语言:javascript
运行
复制
int Pin = 2;
const float baselineVoltage = 200.0;
int belowBaselineVoltage = false;
unsigned long turnOnAt = 10000;
const unsigned long turnOnDelay = 10 * 1000;
    
void setup() {
  Serial.begin(9600);
  pinMode(Pin, OUTPUT);
}
    
void loop() {
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0);
  float voltage2 = voltage*(1023.0 / 5.0);
  Serial.println(voltage2);
  delay(1000);
  if (voltage2 < baselineVoltage) {
    if (belowBaselineVoltage == true) {
      if (millis() >= turnOnAt) {
        digitalWrite(2, HIGH);
      } else {
      } else {
        belowBaselineVoltage = true;
        turnOnAt = millis() + turnOnDelay;
      }
    } else {
      belowBaselineVoltage = false;
    }
  }
EN

回答 1

Stack Overflow用户

发布于 2021-02-07 01:28:43

状态机在嵌入式系统中非常流行。它使代码以可预测的方式运行,当您没有调试器来单步执行代码时,这是非常有价值的。

让我们定义一下你的状态。

  1. motor_off :电机关闭,读取电压,如果电压< 1V,则转到time_low_voltage
  2. motor_off关闭,读取电压,如果电压>= 1V,转到状态motor_off。在此状态下8秒后,go to motor_on state.
  3. motor_on:马达处于打开状态。3秒后,进入motor_off状态。

我们有一个要跟踪的数据项,一个状态何时发生变化的时间戳。

代码语言:javascript
运行
复制
// **********************************
// shaker motor related definitions

enum class shaker_state : char
{
    motor_off, 
    time_low_voltage,
    motor_on,
};

struct shaker_data_t
{
    shaker_state state;
    unsigned int timestamp;

    // you could add here a small buffer to hold a few previous values
    // of ADC readings to do a bit of filtering...  The median of 5 filter 
    // should work very well here.  It is not absolutely needed for now, 
    // but you should consider having some kind of filter.  The motor may 
    // introduce noise in the readings. We'll just keep the last reading for
    // now.

    unsigned int adc_value;
};

// constants are declared constexpr to save memory space.
constexpr unsigned int SHAKER_TIMEOUT_LOW_VOLTAGE = 8000;  // in milliseconds
constexpr unsigned int SHAKER_TIMEOUT_MOTOR_ON    = 3000;  // .idem. 

// Again to save memory, and allow for DAC related constants
// to be computed at compile-time.  
constexpr inline float adc_value_to_volts(unsigned int value)
{
    return value * (5.f / 1024.f);
}

constexpr inline unsigned int volts_to_adc_value(float tension)
{
    return unsigned int(tension * (1024.f / 5.f));
}

constexpr unsigned int SHAKER_ADC_THRESHOLD = volts_to_adc_value(1.f);

constexpr int SHAKER_MOTOR = 2;
constexpr int SHAKER_ADC   = A0;

// **********************************
// global data

shaker_data_t shaker;

// **********************************

static void shaker_control()
{
  // always read adc.
  shaker.adc_value = analogRead(SHAKER_ADC);

  switch (shaker.state)
  {
  default:           // in case of catastrophic error, turn motor OFF.
  case shaker_state::motor_off:
      digitalWrite(SHAKER_MOTOR, LOW);
      if (shaker.adc_value < SHAKER_ADC_THRESHOLD)
      {
          shaker.state     = shaker_state::time_low_voltage;      
          shaker.timestamp = (unsigned int)millis();
      }
      break;

  case shaker_state::time_low_voltage:
      digitalWrite(SHAKER_MOTOR, LOW);
      if (shaker.adc_value >= SHAKER_ADC_THRESHOLD)
      {
          shaker.state = shaker_state::motor_off;
      }
      else if ((unsigned int)millis() - shaker.timestamp >= SHAKER_TIMEOUT_LOW_VOLTAGE)
      {
          digitalWrite(SHAKER_MOTOR, HIGH);
          shaker.state     = shaker_state::motor_on;
          shaker.timestamp = (unsigned int)millis();
      }
      break;

  case shaker_state::motor_on:
      digitalWrite(SHAKER_MOTOR, HIGH);
      if ((unsigned int)millis() - shaker.timestamp >= SHAKER_TIMEOUT_MOTOR_ON)
      {
          digitalWrite(SHAKER_MOTOR, LOW);
          shaker.state     = shaker_state::motor_off;
          shaker.timestamp = (unsigned int)millis();
      }
      break;
  }
}

// **********************************

void setup() 
{
  Serial.begin(9600);

  digitalWrite(SHAKER_MOTOR, LOW);
  pinMode(SHAKER_MOTOR, OUTPUT);

  shaker.state     = shaker_state::motor_off;
  shaker.timestamp = (unsigned int)millis();
}
    
// **********************************

void loop() 
{
    // get temp and control moror.
    shaker_control();

    // shaker_control is very fast and never blocks, so you have plenty 
    // of extra time to blink LEDs, read switches, etc...
}

编辑

这里是一个简单的中值为5的滤波器,您可以添加它来滤除ADC读数中不需要的噪声。

代码语言:javascript
运行
复制
class median_of_5_filter
{
  public:
    void push(unsigned int value)
    {
        buffer_[next_] = value;
        if (++next_ >= 5)
            next_ = 0;
        compute();
    }

    unsigned int get() const 
    {
        return filtered_;
    }

  private:
    void compute()
    {
        // bubble sort, but only the first 3 elements

        unsigned int buf_copy[5] = { buffer_[0], buffer_[1], buffer_[2], 
                                     buffer_[3], buffer_[4] };

        for (unsigned char i = 0; i < 3; ++i)
        {
            auto min_index = i;
            auto min_value = buf_copy[i];
            for (unsigned char j = i + 1; j < 5; ++j)
            {
                if (buf_copy[j] < min_value)
                {
                    min_value = buf_copy[j];
                    min_index = j;
                }
            }
            if (i != min_index)
                swap(buf_copy[i], buf_copy[min_index]);
        }
        filtered_ = buf_copy[2];
    }

    static void swap(unsigned int& a, unsigned int& b)
    {
        auto t = a;
        a = b;
        b = t;
    }

  private:
    unsigned int filtered_  = 0;
    unsigned char next_     = 0; 
    unsigned int buffer_[5] = {};
};

要使用以下命令:

代码语言:javascript
运行
复制
struct shaker_data_t
{
    // ...
    median_of_5_filter adc_value;
};

// when reading ADC...
shaker.adc_value.push(analogRead(SHAKER_ADC));

// to get filtered adc reading 
if (shaker.adc_value.get() < SHAKER_ADC_THRESHOLD)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66078146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档