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