数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 286|回复: 24

[Arduino] 大佬看一下代码!为什么中断不执行?Arduino C++ 的PID恒温

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式
本帖最后由 sadfun 于 2025-8-1 17:21 编辑

Arduino C语言  PID恒温   通过18B20温度传感器,感应加热片的温度,控制MOS管 0~255的PWM
目前PID运行很好,我很满意,但是我想要用一个按钮调整温度,按下按钮没有反应,按钮接在11引脚和12引脚




         

代码如下:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PinChangeInterrupt.h>


LiquidCrystal_I2C mylcd(0x27,16,2);
volatile double kd;
volatile double ki;
volatile double kp;
volatile int setpint;
volatile long sumerror;
volatile long lasterror;
volatile int input;
volatile int output;
volatile long newerror;
volatile float t;
volatile int p;
OneWire oneWire_9(9);
DallasTemperature sensors_9(&oneWire_9);
DeviceAddress insideThermometer;


float ds18b20_9_getTemp(int w) {
  sensors_9.requestTemperatures();
  if(w==0) {
    return sensors_9.getTempC(insideThermometer);
  }
  else {
    return sensors_9.getTempF(insideThermometer);
  }
}


void attachPinInterrupt_fun_CHANGE_11() {
  setpint++;
}
//按下按钮,设置温度加1,就是这里的代码不生效
void attachPinInterrupt_fun_FALLING_12() {
  setpint = setpint - 1;
}
//按下按钮,设置温度减1,就是这里的代码不生效

void setup(){
  mylcd.init();
  mylcd.backlight();
  kd = 0.12;
  ki = 0.2;
  kp = 0.5;
  setpint = 40; //这个是当前设置的温度
  sumerror = 0;
  lasterror = 0;
  input = 10;
  output = 0;
  newerror = 0;
  t = 0;
  p = 0;
  mylcd.setCursor(1-1, 1-1);
  mylcd.print("T");
  mylcd.setCursor(2-1, 1-1);
  mylcd.print(":");
  mylcd.setCursor(8-1, 1-1);
  mylcd.print("C");
  mylcd.setCursor(1-1, 2-1);
  mylcd.print("SET");
  mylcd.setCursor(4-1, 2-1);
  mylcd.print(":");
  mylcd.setCursor(5-1, 2-1);
  mylcd.print(setpint);
  mylcd.setCursor(9-1, 2-1);
  mylcd.print("PWM");
  mylcd.setCursor(12-1, 2-1);
  mylcd.print(":");
  sensors_9.getAddress(insideThermometer, 0);
  sensors_9.setResolution(insideThermometer, 9);
  pinMode(6, OUTPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
}


void loop(){
  mylcd.setCursor(13-1, 2-1);
  mylcd.print(p);
  mylcd.setCursor(3-1, 1-1);
  mylcd.print(ds18b20_9_getTemp(0));
  t = ds18b20_9_getTemp(0);  //读取18B20温度传感器的值,并且赋值给 变量 t
  newerror = setpint - t;
  sumerror = sumerror + newerror;
  output = (kp * newerror + ki * sumerror) + kd * (lasterror - newerror);
  lasterror = newerror;
  p = output;
  if (p >= 255) {
    p = 255;


  }
  if (p <= 0) {
    p = 0;


  }
  analogWrite(6, p);  //接MOS管 接6号引脚
  attachPCINT(digitalPinToPCINT(11),attachPinInterrupt_fun_CHANGE_11,CHANGE);//按下按钮,设置温度加1,就是这里的代码不生效
  attachPCINT(digitalPinToPCINT(12),attachPinInterrupt_fun_FALLING_12,FALLING);//按下按钮,设置温度减1,就是这里的代码不生效


}





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
 楼主| 发表于 6 天前 | 显示全部楼层
保留一个楼层
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
@8139 大佬帮我看看啊~

打赏

参与人数 1家元 +6 收起 理由
8139 + 6 我不懂Arduino啊,哈哈

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
PID没看到库啊?
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层

没用库~纯算的~
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
sadfun 发表于 2025-8-1 16:57
@8139 大佬帮我看看啊~

大佬快点学!(你学起来肯定块),学会了在来教我!
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
问AI来的快
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
@t3486784401  大佬有时间帮我看看代码中断为什么不生效吗?
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
sadfun 发表于 2025-8-1 17:09
没用库~纯算的~

output = (kp * newerror + ki * sumerror) + kd * (lasterror - newerror);
就这一句就行了,PID我还真的没用过
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
人艰不拆了 发表于 2025-8-1 17:17
output = (kp * newerror + ki * sumerror) + kd * (lasterror - newerror);
就这一句就行了,PID我还真 ...

这个恒温真的无敌!我是一个菜鸟,第一次玩,温度保持好,不会波动
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层

没玩过~AI!
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
attachPCINT(digitalPinToPCINT(11),attachPinInterrupt_fun_CHANGE_11,CHANGE);//按下按钮,设置温度加1,就是这里的代码不生效
  attachPCINT(digitalPinToPCINT(12),attachPinInterrupt_fun_FALLING_12,FALLING);//按下按钮,设置温度减1,就是这里的代码不生效

应该放在loop里?
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
camell 发表于 2025-8-1 17:34
attachPCINT(digitalPinToPCINT(11),attachPinInterrupt_fun_CHANGE_11,CHANGE);//按下按钮,设置温度加1 ...

是在loop里的~
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
#include <PinChangeInterrupt.h>  你这个库  单独写个程序测试一下  或者看看里面的例程,用的应该不太对

打赏

参与人数 1家元 +6 收起 理由
sadfun + 6 熱心助人

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
最近也在搞C,调不通可以在屏幕合适位置显示 setpint 的值,这样就能看到随按键变化的情况
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
zhang_yy007 发表于 2025-8-1 17:44
#include   你这个库  单独写个程序测试一下  或者看看里面的例程,用的应该不太对 ...

我试一下~~~
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
本帖最后由 kpj001 于 2025-8-1 18:15 编辑

一次性设置都放setup里。

还有就这几句也没必要中断。

PID时需要调参数的,应该用串口绘图看一下这个过程。 https://www.bilibili.com/video/BV1AHufz1E13/   置顶评论有截图
回复 支持 反对

使用道具 举报

发表于 6 天前 来自手机浏览器 | 显示全部楼层
这是硬件中断还是软件中断,一般是硬件外部中断,放在setup,软件检测才放到循环了里
回复 支持 1 反对 0

使用道具 举报

发表于 6 天前 | 显示全部楼层
sadfun 发表于 2025-8-1 17:15
@t3486784401  大佬有时间帮我看看代码中断为什么不生效吗?

如果是 m328 的硬件 PCINT 的话,查看下 PCICR、PCMSK0~2 这四个寄存器。
要都开启了,才能响应相关中断;

如果是软中断的话,就是楼上说的,你得在 loop 里有循环查询调用,才会中断。

另外 attachPCINT 这种函数,怎么都该是放在 setup 里边单次调用的吧。
绑定好以后,有中断了直接后台跳转到中断函数
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 天前 | 显示全部楼层
t3486784401 发表于 2025-8-1 20:59
如果是 m328 的硬件 PCINT 的话,查看下 PCICR、PCMSK0~2 这四个寄存器。
要都开启了,才能响应相关中断 ...

感谢大佬解答
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-8-7 21:24 , Processed in 0.296401 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表