Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果我的按钮A)刚刚按下,B)按下,C)刚刚松开,我如何调用三个不同的函数?_C++_Arduino - Fatal编程技术网

C++ 如果我的按钮A)刚刚按下,B)按下,C)刚刚松开,我如何调用三个不同的函数?

C++ 如果我的按钮A)刚刚按下,B)按下,C)刚刚松开,我如何调用三个不同的函数?,c++,arduino,C++,Arduino,我正在写一个Arduino程序来控制一个朋友的角色扮演用的微型枪。我需要编写一个程序,当按下按钮时,电机从0上升到给定值(现在让我们说“analogWrite(output_pin,200)”),然后以该转速循环,直到按钮被释放,此时它需要下降到零 当我尝试将ramping放入一个循环时,它并没有完成代码。我 我需要在C++代码中为ARDUNO按钮这样的东西。(我用“延迟”功能尝试过类似的事情,但没有效果) 以下是按下按钮时仅以一种速度运行电机的当前代码 const int button1 =4

我正在写一个Arduino程序来控制一个朋友的角色扮演用的微型枪。我需要编写一个程序,当按下按钮时,电机从0上升到给定值(现在让我们说“analogWrite(output_pin,200)”),然后以该转速循环,直到按钮被释放,此时它需要下降到零

当我尝试将ramping放入一个循环时,它并没有完成代码。我

我需要在C++代码中为ARDUNO按钮这样的东西。(我用“延迟”功能尝试过类似的事情,但没有效果)

以下是按下按钮时仅以一种速度运行电机的当前代码

const int button1 =4;
int BUTTONstate1 = 0;

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(button1, INPUT);
}

void loop()
{
  //set button to read
  BUTTONstate1 = digitalRead(button1);
  //if button is pressed
  if (BUTTONstate1 == HIGH)
  {
    //run current through motor
    digitalWrite(2, LOW); 
    digitalWrite(3, HIGH);
    //set speed
    //Rampup 
    analogWrite(9,200);
  }
  else 
  {
    digitalWrite(2, LOW); 
    digitalWrite(3, LOW);
  }
}
这是电路的虚拟环境


我建议使用中断,它在Arduino参考资料中有很好的记录:

最有用的是“参数”和“示例代码”部分。我认为您应该准备两种方法,并在上升和下降触发器的输入(按钮)引脚上附加中断

确保按钮引脚可用于中断(仅在Arduino UNO/NANO引脚2和3上)

我认为它应该与此类似(我还没有测试过):

#在2中定义按钮;//可用于中断的引脚
#定义输出引脚9;
#定义powerPinA 3;
#定义powerpinb4;
bool running=false;
int currentSpeed=0;
void buttonUp()
{
数字写入(powerPinA,低电平);
数字写入(powerPinB,低电平);
运行=错误;
}
void buttonDown()
{
数字写入(powerPinA,低电平);
数字写入(powerPinB,高);
运行=真;
}
无效设置()
{
引脚模式(输出引脚,输出);
pinMode(电源pina,输出);
pinMode(电源pinb,输出);
pinMode(按钮输入,输入);
连接中断(数字插销至中断(中断插销)、按钮、提升);
连接中断(数字插针插入(中断插针)、按钮关闭、下降);
}
void循环()
{
延迟(1);
if(运行和当前速度<200)
电流速度+=20;
如果(!running&¤tSpeed>0),则为else
电流速度-=20;
模拟写入(输出引脚、电流速度);
}

您可以使用中断来处理按下/释放、设置值以及处理循环中的上升/下降

请记住,您还应取消按钮的抖动

下面是一些伪代码:

const byte maxLevel = 200;  // some example values (max 255)
const int rampDelay = 5;

volatile byte targetLevel = 0;
byte currentLevel = 0;

// ...

ISR for Button {    // Could be in one ore two ISR's

    if pressed
        targetLevel = maxLevel;
        // possible other calls

    if released
        targetLevel = 0;
        // possible other calls
}

void loop()
{
    if (currentLevel < targetLevel) {
        SetLevel(++currentLevel);
    }
    else if (currentLevel > targetLevel) {
        SetLevel(--currentLevel);
    }
    // if currentLevel == targetLevel nothing changes

    // if your device is battery powered you could even put the mcu
    // to sleep when both levels are zero (and wake up from the ISR)
    // no need for constantly polling the button when using ISR

    delay(rampDelay);
}
常量字节maxLevel=200;//一些示例值(最大255) 常数int rampDelay=5; 易失性字节targetLevel=0; 字节currentLevel=0; // ... 按钮{//的ISR可能在一个或两个ISR中 受压 targetLevel=maxLevel; //可能的其他电话 如果释放 targetLevel=0; //可能的其他电话 } void循环() { 如果(当前级别<目标级别){ 设置电平(++currentLevel); } else if(当前级别>目标级别){ SetLevel(--currentLevel); } //如果currentLevel==targetLevel,则无任何更改 //如果您的设备由电池供电,您甚至可以将mcu //在两个级别均为零时睡眠(并从ISR中醒来) //使用ISR时无需不断轮询按钮 延迟(rampDelay); }
如果在电机全速运行之前松开按钮,也会立即开始减速。

以下是一个不依赖任何中断的示例。只需读取按钮并记住变量中的状态,记住变量中最后一步的时间,以检查millis()(已编译但未测试)

int按钮pin=5;
int lastButtonState=高;
无符号长步长;
无符号整数步长时间=10;//10毫秒步。设置为任何你想要的。
int模拟引脚=3;
int模拟级别=0;
int maxLevel=200;
步长=10;
无效设置(){
pinMode(按钮输入,输入\上拉);//按下时读数为低
}
void循环(){
int buttonState=digitalRead(buttonPin);
如果(buttonState!=lastButtonState){
//按钮刚换了!
如果(按钮状态==低){
//刚刚被催促
analogLevel=0;//启动爬升
lastRampStep=millis();//请注意我们执行此步骤的时间
}否则{
//按钮刚松开。
//不知道你想在这里发生什么
}
}
否则如果(按钮状态==低){
//按住按钮,直到达到最大水平
if(模拟电平<最大电平){
如果(毫秒()-lastRampStep>=stepTime){
analogLevel+=模拟步长;
lastRampStep=millis();
}
}
}否则{
//释放按钮时(高)缓降:
如果(模拟级别>0){
如果(毫秒()-lastRampStep>=stepTime){
analogLevel-=模拟步长;
lastRampStep=millis();
}
}
}
模拟写入(模拟引脚、模拟电平);
lastButtonState=按钮状态;
}

谢谢!我用我原来的方法来确定按钮是否被按下。但是interrupt和if语句工作得很好,当我集成它并意识到delay使用ms而不是s时,你会得到很多关于中断的答案。人类按下按钮永远不需要中断。请看状态更改示例。你会像那样做的。唯一的区别是,你会做不同的事情,这取决于大头针是高还是低。没有volatile修饰符,两个字节的变量(没有原子性)——就我所见,它甚至不需要int,字节就足以存储0或200@KIIV这是一些快速的伪代码来显示算法。但是你对volatile和原子性的看法是正确的。两者都很重要-我更新了代码。
#define buttonPin 2; // pin usable for interrupt
#define outputPin 9;
#define powerPinA 3;
#define powerPinB 4;  
bool running = false;
int currentSpeed = 0;

void buttonUp()
{
  digitalWrite(powerPinA, LOW); 
  digitalWrite(powerPinB, LOW);
  running = false;
}

void buttonDown()
{
  digitalWrite(powerPinA, LOW); 
  digitalWrite(powerPinB, HIGH);
  running = true;
}

void setup()
{
  pinMode(outputPin, OUTPUT);
  pinMode(powerPinA, OUTPUT);
  pinMode(powerPinB, OUTPUT);
  pinMode(buttonPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), buttonUp, RAISING);
  attachInterrupt(digitalPinToInterrupt(interruptPin), buttonDown, FALLING);
}

void loop()
{
  delay(1);
  if (running && currentSpeed < 200)
    currentSpeed += 20;
  else if (!running && currentSpeed > 0)
    currentSpeed -= 20;

  analogWrite(outputPin, currentSpeed);
}
const byte maxLevel = 200;  // some example values (max 255)
const int rampDelay = 5;

volatile byte targetLevel = 0;
byte currentLevel = 0;

// ...

ISR for Button {    // Could be in one ore two ISR's

    if pressed
        targetLevel = maxLevel;
        // possible other calls

    if released
        targetLevel = 0;
        // possible other calls
}

void loop()
{
    if (currentLevel < targetLevel) {
        SetLevel(++currentLevel);
    }
    else if (currentLevel > targetLevel) {
        SetLevel(--currentLevel);
    }
    // if currentLevel == targetLevel nothing changes

    // if your device is battery powered you could even put the mcu
    // to sleep when both levels are zero (and wake up from the ISR)
    // no need for constantly polling the button when using ISR

    delay(rampDelay);
}
int buttonPin = 5;
int lastButtonState = HIGH;

unsigned long lastRampStep;
unsigned int stepTime = 10;  //  10ms steps.  Set to whatever you want.  

int analogPin = 3;
int analogLevel = 0;
int maxLevel = 200;
int analogStepSize = 10;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);  // will read LOW when pressed    
}

void loop() {

  int buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    //  The button just changed!
    if (buttonState == LOW) {
      //  was just now pressed
      analogLevel = 0; // start ramp up
      lastRampStep = millis();  // note the time that we took this step
    } else {
      //  Button just released.
      // not sure what you want to happen here
    }
  }
  else if (buttonState == LOW) {
    // While button is held ramp until we reach the max level
    if(analogLevel < maxLevel){
      if(millis() - lastRampStep >= stepTime){
        analogLevel += analogStepSize;
        lastRampStep = millis();
      }
    }
  } else {
    // While button is released (HIGH) ramp back down:
    if(analogLevel > 0){
      if(millis() - lastRampStep >= stepTime){
        analogLevel -= analogStepSize;
        lastRampStep = millis();
      }
    }
  }
  analogWrite(analogPin, analogLevel);
  lastButtonState = buttonState;
}