我正在使用Arduino IDE和langauge (C)编写一个Raspberry Pi Pico程序。我有一个项目,使用16x2液晶显示器和按钮来控制它的背光。按钮和其他一切都正常工作,我的问题是,每次我按下开关,背光闪烁,需要按下它的随机时间来保持或关闭,我建议由于反弹。我想清除RP2040的ICSR寄存器中的22位,以便在从中断返回之前清除中断缓冲区中的任何挂起的内容。m0plus (第87页,或页面底部的86页)
到目前为止我的代码是:
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include "hardware/regs/m0plus.h"
//#include <pico/stdlib.h>
//#include <hardware/pwm.h>
Adafruit_BMP280 bmp; //I2C
hd44780_I2Cexp lcd(0x27, 16, 2);
const uint16_t AirValue = 1023;
const uint16_t WaterValue = 660; //measured fully submerged in water
const uint16_t DarkValue = 0;
const uint16_t LightValue = 1023;
uint16_t soilMoisture;
uint16_t soilMoisturePercent;
uint16_t lightIntensity;
uint16_t lightIntensityPercent;
volatile bool lcdBacklightStatus = false;
byte pressureChar[] = { 0b01000, 0b11110, 0b11100, 0b01000, 0b00011, 0b01111, 0b00000, 0b11110
};
byte moistureChar[] = { 0b00000, 0b00100, 0b01110, 0b11111, 0b11111, 0b11111, 0b01110, 0b00000
};
byte lightIntensityChar[] = { 0b00000, 0b01110, 0b10001, 0b11011, 0b10101, 0b01110, 0b01110, 0b00100
};
byte temperatureChar[] = { 0b01000, 0b10111, 0b10100, 0b11111, 0b11100, 0b11100, 0b11100, 0b01000
};
byte separatorWall[] = { 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010
};
byte degreeChar[] = { 0b00111, 0b00101, 0b00111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000
};
void backlight();
void setup() {
lcd.begin(0x27, 16, 2);
lcd.createChar(0, pressureChar);
lcd.createChar(1, moistureChar);
lcd.createChar(2, lightIntensityChar);
lcd.createChar(3, temperatureChar);
lcd.createChar(4, separatorWall);
lcd.createChar(5, degreeChar);
lcd.home();
pinMode(26, INPUT); //soilMoisture
pinMode(27, INPUT); //lightIntensity
pinMode(17, INPUT); //button
attachInterrupt(digitalPinToInterrupt(17), backlight, RISING);
//Serial.begin(9600);
bmp.begin(0x76);
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
lcd.clear();
lcd.backlight(); //lcd.noBacklight();
lcd.setCursor(1,0);
lcd.print("Plant Station");
lcd.setCursor(6,1);
lcd.print("V0.8");
delay(2000);
lcd.noBacklight();
lcd.clear();
lcd.setCursor(0,0);
lcd.write(byte(3));
lcd.setCursor(10,0);
lcd.write(byte(2));
lcd.setCursor(0,1);
lcd.write(byte(0));
lcd.setCursor(10,1);
lcd.write(byte(1));
lcd.setCursor(7,0);
lcd.write(byte(5));
lcd.setCursor(8,0);
lcd.print("C");
lcd.setCursor(15,0);
lcd.print("%");
lcd.setCursor(6,1);
lcd.print("hPa");
lcd.setCursor(15,1);
lcd.print("%");
}
void loop() {
soilMoisture = analogRead(26);
soilMoisturePercent = map(soilMoisture, AirValue, WaterValue, 0, 100);
lightIntensity = analogRead(27);
lightIntensityPercent = map(lightIntensity, DarkValue, LightValue, 0, 100);
if(soilMoisturePercent >= 100) soilMoisturePercent = 100;
else if(soilMoisturePercent <= 0) soilMoisturePercent = 0;
if(lightIntensityPercent >= 100) lightIntensityPercent = 100;
else if(lightIntensityPercent <= 0) lightIntensityPercent = 0;
//Serial.print("Moisture: ");
//Serial.println(soilMoisture);
//Serial.print("Percentage: ");
//Serial.println(soilMoisturePercent);
//Serial.print("LightIntensity: ");
//Serial.println(lightIntensity);
//Serial.print(soilMoisture);
//Serial.println(soilMoisturePercent);
//BANNED CURSOR POSITIONS: 0,0 9,0 0,1 9,1 6,0 14,0 7,0 15,0 5,1 15,1
lcd.setCursor(3,0);
lcd.print(bmp.readTemperature(),1);
lcd.setCursor(2,1);
lcd.print(((bmp.readPressure()/100)),0);
if(soilMoisturePercent < 10) {
lcd.setCursor(13,1);
lcd.print(" ");
lcd.print(soilMoisturePercent);
} else if(soilMoisturePercent < 100) {
lcd.setCursor(13,1);
lcd.print(soilMoisturePercent);
} else {
lcd.setCursor(12,1);
lcd.print(soilMoisturePercent);
}
if(lightIntensityPercent < 10) {
lcd.setCursor(13,0);
lcd.print(" ");
lcd.print(lightIntensityPercent);
} else if(lightIntensityPercent < 100) {
lcd.setCursor(13,0);
lcd.print(lightIntensityPercent);
} else {
lcd.setCursor(12,0);
lcd.print(lightIntensityPercent);
}
delay(60000);
}
void backlight() {
//noInterrupts();
detachInterrupt(digitalPinToInterrupt(17));
if(lcdBacklightStatus == true) {
lcd.noBacklight();
} else if(lcdBacklightStatus == false) {
lcd.backlight();
}
delayMicroseconds(500000);
//interrupts();
attachInterrupt(digitalPinToInterrupt(17), backlight, RISING);
lcdBacklightStatus = !lcdBacklightStatus;
//want to clear ICSR register here i guess
}我可能还不够清楚,如果是这样的话,英语不是我的主要语言。
发布于 2022-10-22 23:00:13
@stark成了我的英雄,我删除了整个中断部分,以及主循环结束时长达60秒的延迟。然后添加了下面的代码,现在当按钮被按下1秒时,lcd背光切换,感应器仍然每60秒检查一次。仍然不知道如何处理注册表来揭穿,所以帖子仍然是开放的。
for(int i = 0; i < 600; i++) {
if(digitalRead(17) == 1) trueCount++;
if(trueCount == 10) {
lcdBacklightStatus = !lcdBacklightStatus;
trueCount = 0;
}
if(lcdBacklightStatus == false) {
lcd.noBacklight();
} else if(lcdBacklightStatus == true) {
lcd.backlight();
}
delay(100);
}编辑:
我根据状态机的概念重写了我的整个代码。现在它运行得完美无缺,但我仍然想知道如何处理RP2040芯片上的中断,所以非常感谢您给出的好答案!
代码:
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
Adafruit_BMP280 bmp;
hd44780_I2Cexp lcd(0x27, 16, 2);
const uint8_t moistureSensorPin = 26;
const uint8_t lightSensorPin = 27;
const uint8_t buttonPin = 17;
const uint16_t moistureSensorInterval = 60000;
const uint16_t lightSensorInterval = 60000;
const uint16_t temperatureSensorInterval = 60000;
const uint16_t pressureSensorInterval = 60000;
const uint16_t buttonInterval = 500;
const uint16_t lcdUpdateInterval = 60000;
const uint32_t backlightDuration = 300000;
const uint16_t AirValue = 1023;
const uint16_t WaterValue = 660;
const uint16_t DarkValue = 0;
const uint16_t LightValue = 1023;
uint16_t soilMoisture;
uint16_t soilMoisturePercent;
uint16_t lightIntensity;
uint16_t lightIntensityPercent;
float temperature;
uint32_t pressure;
byte soilMoist = LOW;
byte soilHalfMoist = LOW;
byte soilDry = LOW;
byte buttonState = LOW;
byte lcdBacklightStatus = LOW;
byte buttonPreviouslyPressed = LOW;
uint32_t currentMillis = 0;
uint32_t previousMoistureSensorMillis = 60000;
uint32_t previousLightSensorMillis = 60000;
uint32_t previousTemperatureMillis = 60000;
uint32_t previousPressureMillis = 60000;
uint32_t previousButtonMillis = 0;
uint32_t previousLCDMillis = 0;
byte pressureChar[] = { 0b01000, 0b11110, 0b11100, 0b01000, 0b00011, 0b01111, 0b00000, 0b11110
};
byte moistureChar[] = { 0b00000, 0b00100, 0b01110, 0b11111, 0b11111, 0b11111, 0b01110, 0b00000
};
byte halfMoistureChar[] = { 0b00000, 0b00100, 0b01010, 0b10001, 0b11111, 0b11111, 0b01110, 0b00000
};
byte emptyMoistureChar[] = { 0b00000, 0b00100, 0b01010, 0b10001, 0b10001, 0b10001, 0b01110, 0b00000
};
byte lightIntensityChar[] = { 0b00000, 0b01110, 0b10001, 0b11011, 0b10101, 0b01110, 0b01110, 0b00100
};
byte temperatureChar[] = { 0b01000, 0b10111, 0b10100, 0b11111, 0b11100, 0b11100, 0b11100, 0b01000
};
byte separatorWall[] = { 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010
};
byte degreeChar[] = { 0b00111, 0b00101, 0b00111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000
};
byte painChar[] = { 0b00000, 0b00000, 0b11011, 0b11011, 0b00000, 0b01110, 0b10001, 0b00000
};
void setup() {
pinMode(moistureSensorPin, INPUT);
pinMode(lightSensorPin, INPUT);
pinMode(buttonPin, INPUT);
bmp.begin(0x76);
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
lcd.begin(0x27, 16, 2);
lcd.createChar(0, pressureChar);
lcd.createChar(1, painChar);
lcd.createChar(2, lightIntensityChar);
lcd.createChar(3, temperatureChar);
lcd.createChar(4, moistureChar);
lcd.createChar(5, halfMoistureChar);
lcd.createChar(6, emptyMoistureChar);
lcd.createChar(7, degreeChar);
lcd.home();
lcd.clear();
lcd.backlight(); //lcd.noBacklight();
lcd.setCursor(1,0);
lcd.print("Plant Station");
lcd.setCursor(6,1);
lcd.print("V1.0");
delay(2000);
lcd.noBacklight();
lcd.clear();
lcd.setCursor(0,0);
lcd.write(byte(3));
lcd.setCursor(10,0);
lcd.write(byte(2));
lcd.setCursor(0,1);
lcd.write(byte(0));
lcd.setCursor(10,1);
lcd.write(byte(4));
lcd.setCursor(7,0);
lcd.write(byte(7));
lcd.setCursor(8,0);
lcd.print("C");
lcd.setCursor(15,0);
lcd.print("%");
lcd.setCursor(6,1);
lcd.print("hPa");
lcd.setCursor(15,1);
lcd.print("%");
}
void loop() {
currentMillis = millis();
readMoistureSensor();
readLightSensor();
readTemperature();
readPressure();
readButtonState();
updateBacklight();
updateLCD();
}
void readMoistureSensor() {
if(currentMillis - previousMoistureSensorMillis >= moistureSensorInterval) {
soilMoisture = analogRead(26);
soilMoisturePercent = map(soilMoisture, AirValue, WaterValue, 0, 100);
if(soilMoisturePercent >= 100) soilMoisturePercent = 100;
else if(soilMoisturePercent <= 0) soilMoisturePercent = 0;
previousMoistureSensorMillis += moistureSensorInterval;
}
}
void readLightSensor() {
if(currentMillis - previousLightSensorMillis >= lightSensorInterval) {
lightIntensity = analogRead(27);
lightIntensityPercent = map(lightIntensity, DarkValue, LightValue, 0, 100);
if(lightIntensityPercent >= 100) lightIntensityPercent = 100;
else if(lightIntensityPercent <= 0) lightIntensityPercent = 0;
previousLightSensorMillis += lightSensorInterval;
}
}
void readTemperature() {
if(currentMillis - previousTemperatureMillis >= temperatureSensorInterval) {
temperature = bmp.readTemperature();
previousTemperatureMillis += temperatureSensorInterval;
}
}
void readPressure() {
if(currentMillis - previousPressureMillis >= pressureSensorInterval) {
pressure = (bmp.readPressure()/100);
previousPressureMillis += pressureSensorInterval;
}
}
void readButtonState() {
if(currentMillis - previousButtonMillis >= buttonInterval) {
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH) {
lcdBacklightStatus = !lcdBacklightStatus;
}
previousButtonMillis += buttonInterval;
}
}
void updateBacklight() {
if(lcdBacklightStatus == HIGH) {
lcd.backlight();
} else {
lcd.noBacklight();
}
}
void updateLCD() {
if(currentMillis - previousLCDMillis >= lcdUpdateInterval) {
if(soilMoisturePercent >= 50) {
lcd.setCursor(10,1);
lcd.write(byte(4));
} else if(soilMoisturePercent >= 25) {
lcd.setCursor(10,1);
lcd.write(byte(5));
} else {
lcd.setCursor(10,1);
lcd.write(byte(6));
}
if(pressure > 1007) {
lcd.setCursor(0,1);
lcd.write(byte(0));
} else {
lcd.setCursor(0,1);
lcd.write(byte(1));
}
lcd.setCursor(3,0);
lcd.print(temperature,1);
lcd.setCursor(2,1);
lcd.print(pressure);
if(soilMoisturePercent < 10) {
lcd.setCursor(13,1);
lcd.print(" ");
lcd.print(soilMoisturePercent);
} else if(soilMoisturePercent < 100) {
lcd.setCursor(13,1);
lcd.print(soilMoisturePercent);
} else {
lcd.setCursor(12,1);
lcd.print(soilMoisturePercent);
}
if(lightIntensityPercent < 10) {
lcd.setCursor(13,0);
lcd.print(" ");
lcd.print(lightIntensityPercent);
} else if(lightIntensityPercent < 100) {
lcd.setCursor(13,0);
lcd.print(lightIntensityPercent);
} else {
lcd.setCursor(12,0);
lcd.print(lightIntensityPercent);
}
previousLCDMillis += lcdUpdateInterval;
}
}发布于 2022-10-23 17:13:52
RP2040没有一个打开按钮的功能,您只需将其写到某个寄存器的某个位置即可打开。
您将不得不执行多个数字读数,并使用一个定时功能,如millis(),以检测什么时候按钮已按住或释放了足够长的时间。您可以使用Pololu中的按钮,按钮库来完成该操作,或者将其代码作为参考来阅读,这样您就可以了解如何实现自己的删除。
您还可以考虑使用PIO状态机读取按钮,并只向主CPU发送新闻/发布事件。
发布于 2022-10-27 04:24:08
在示例代码中,LCD初始化存在一些问题。begin()的API是
begin(cols, rows, [dotsize]);其中dotsize是可选的,但用于在5x8或5x10字体大小之间进行选择。你很幸运,用过的东西能起作用:
lcd.begin(0x27, 16, 2);这会将列设置为39列,将行设置为16 (这不是正确的几何形状),并根据库代码的工作方式,使用2表示点大小(这不是有效的参数),最后将字体大小设置为5x10。但由于该字体大小仅适用于单行显示,因此默认为5x8字体。
此外,您还应该考虑使用自动配置构造函数,因此不需要指定i2c地址。有关详细信息,请参阅所包含的文档。类似于API文档和wiki,获得关于hd44780_I2Cexp i/o类的更多文档。
https://stackoverflow.com/questions/74167514
复制相似问题