如果输入为HIGH,我写了这段代码来发送短信,你可以在其中看到,但问题是我有4个输入和延迟()是致命的,如果我需要做多个单一的话就非常错误一次一件事(我使用4个输入)。
所以我需要在void loop(),Send_SMS()和initia()中用millis()或其他东西来改变delay()。
有人可以帮助我,并提前感谢你。
const int DI = 2;
const int DT = 3;
const int DGP1 = 4;
const int DGP2 = 5;
int value1_old = 0;
int value2_old = 0;
int value3_old = 0;
int value4_old = 0;
unsigned long previousMillis = 0;
unsigned long interval=100;
#include<SoftwareSerial.h>
SoftwareSerial SIM900 (7, 8);
void setup() {
pinMode(DI, INPUT);
pinMode(DT, INPUT);
pinMode(DGP1, INPUT);
pinMode(DGP2, INPUT);
SIM900.begin(19200);
SIM900power();
delay(20000);
}
void SIM900power(){
digitalWrite(9 ,HIGH);
delay(1000);
digitalWrite(9 ,LOW);
delay(5000);
}
void initia(){
SIM900.print("AT+CMGF=1\r");
delay(100);
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
delay(100);
}
void Send_SMS(){
SIM900.println((char)26);
delay(100);
SIM900.println();
delay(100);
SIM900power();
}
void loop() {
int value1 = digitalRead (DI);
int value2 = digitalRead (DT);
int value3 = digitalRead (DGP1);
int value4 = digitalRead (DGP2);
if (value2 != value2_old && value2 == HIGH) {
initia();
SIM900.println("Station 85: Defaut electrique");
delay(100);
Send_SMS();
value2_old = value2;
}
if (value3 != value3_old && value3 == HIGH)
{
initia();
SIM900.println("Station 85: DefautGP1");
delay(100);
Send_SMS();
value3_old = value3;
}
if (value4 != value4_old && value4 == HIGH)
{
initia();
SIM900.println("Station 85:DD>1000");
delay(100);
Send_SMS();
value4_old = value4;
}
value2_old = value2;
value3_old = value3;
value4_old = value4;
}
答案 0 :(得分:0)
您可以尝试使用isr_timer()函数中的代码:
if (changed2) {
initia();
SIM900.println("Station 85: Defaut electrique");
delay(100);
Send_SMS();
changed2 = false;
}
祝你好运
答案 1 :(得分:0)
正如mclopez指出的那样,提供一个好的答案更好,而不是只指出其他的缺点,所以......我们走了。
在我看来,ISR解决方案不是一个好的选择,因为ISR会阻止正常执行。使用中断的唯一可行实现是记录引脚更改,然后发送SMS。
然而,在我看来,这不是一个好的解决方案。对于这个问题,我要使用状态机发送短信;由于你有状态,你可以在做其他事情时等待过渡,比如检查按钮。
我不知道SIM900如何发送短信,因此我将您的工作流程在状态机中实施。我不确定这是最佳解决方案,特别是因为我不认为您每次都需要重新启动模块,但您可以稍后修改它。
现在,工作流程必须执行七个操作,每个操作后面都有一个等待。我在这里写它,所以看到每个动作都比较简单:
SIM900.print("AT+CMGF=1\r");
delay(100);
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
delay(100);
SIM900.println("Message you want");
delay(100);
SIM900.println((char)26);
delay(100);
SIM900.println();
delay(100);
digitalWrite(9 ,HIGH);
delay(1000);
digitalWrite(9 ,LOW);
delay(5000);
所以我们有8个状态:一个空闲状态(当你等待状态机启动时,命名为SIM_IDLE),然后是五个&#34; SEND&#34;状态(我将它们命名为SIM_SEND1..5)和两种状态以重置电源(名为SIM_POW1和SIM_POW2)。你通常处于闲置状态;当按下一个或多个按钮时,您切换到第一个发送,循环播放,然后重置电源并返回空闲状态。
按下按钮仅更改状态SIM_SEND3(当您实际发送消息时),因此每当按下按钮时都会设置布尔变量(在状态机执行期间也会检测到按下按钮)并且仅在此状态下重置在发送正确的消息后,状态。
现在,这是实现此目的的代码:
const uint8_t DI = 2;
const uint8_t DT = 3;
const uint8_t DGP1 = 4;
const uint8_t DGP2 = 5;
const uint8_t SIMPOW = 9;
uint8_t value1_old = 0;
uint8_t value2_old = 0;
uint8_t value3_old = 0;
uint8_t value4_old = 0;
boolean value1_changed = false;
boolean value2_changed = false;
boolean value3_changed = false;
boolean value4_changed = false;
/********************************/
// SIM STATES
#define SIM_IDLE 0
//SEND1: SIM900.print("AT+CMGF=1\r");delay(100);
#define SIM_SEND1 1
//SEND2: SIM900.println("AT + CMGS = \"+212xxxxxxx\"");delay(100);
#define SIM_SEND2 2
//SEND3: SIM900.println("Message you want");delay(100);
#define SIM_SEND3 3
//SEND4: SIM900.println((char)26);delay(100);
#define SIM_SEND4 4
//SEND5: SIM900.println();delay(100);
#define SIM_SEND5 5
//POW1: digitalWrite(SIMPOW,HIGH);delay(1000);
#define SIM_POW1 6
//POW2: digitalWrite(SIMPOW,LOW);delay(5000);
#define SIM_POW2 7
/********************************/
unsigned long previousMillis;
uint8_t currentSimState;
#include<SoftwareSerial.h>
SoftwareSerial SIM900 (7, 8);
void setup()
{
pinMode(DI, INPUT);
pinMode(DT, INPUT);
pinMode(DGP1, INPUT);
pinMode(DGP2, INPUT);
pinMode(SIMPOW, OUTPUT);
SIM900.begin(19200);
digitalWrite(SIMPOW,HIGH);
delay(1000);
digitalWrite(SIMPOW,LOW);
delay(25000);
currentSimState = -1; // Force a state transition
}
void loop()
{
uint8_t value1 = digitalRead (DI);
uint8_t value2 = digitalRead (DT);
uint8_t value3 = digitalRead (DGP1);
uint8_t value4 = digitalRead (DGP2);
unsigned long currentMillis = millis();
if (value2 != value2_old && value2 == HIGH)
value2_changed = true;
if (value3 != value3_old && value3 == HIGH)
value3_changed = true;
if (value4 != value4_old && value4 == HIGH)
value4_changed = true;
value1_old = value1;
value2_old = value2;
value3_old = value3;
value4_old = value4;
// Check if a state transition is needed
uint8_t newSimState = currentSimState;
switch (currentSimState)
{
case SIM_IDLE: // Start sending if a value changed
if ((value2_changed) || (value3_changed) || (value4_changed))
newSimState = SIM_SEND1;
break;
case SIM_SEND1: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND2;
break;
case SIM_SEND2: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND3;
break;
case SIM_SEND3: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND4;
break;
case SIM_SEND4: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND5;
break;
case SIM_SEND5: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_POW1;
break;
case SIM_POW1: // Wait 1000 ms
if ((currentMillis - previousMillis) >= 1000)
newSimState = SIM_POW2;
break;
case SIM_POW2: // Wait 1000 ms
if ((currentMillis - previousMillis) >= 1000)
newSimState = SIM_IDLE;
break;
default:
newSimState = SIM_IDLE;
break;
}
// If there was a transition, do the appropriate action
if (newSimState != currentSimState)
{
case SIM_IDLE:
// Do nothing
break;
case SIM_SEND1:
SIM900.print("AT+CMGF=1\r");
previousMillis = millis();
break;
case SIM_SEND2:
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
previousMillis = millis();
break;
case SIM_SEND3:
if (value2_changed)
{
SIM900.println("Station 85: Defaut electrique");
value2_changed = false;
}
else if (value3_changed)
{
SIM900.println("Station 85: DefautGP1");
value2_changed = false;
}
else if (value4_changed)
{
SIM900.println("Station 85:DD>1000");
value2_changed = false;
}
else
{
// Should never arrive here. Just in case, you
// can either abort the SMS sending if you can
// or send another message
}
previousMillis = millis();
break;
case SIM_SEND4:
SIM900.println((char)26);
previousMillis = millis();
break;
case SIM_SEND5:
SIM900.println();
previousMillis = millis();
break;
case SIM_POW1:
digitalWrite(SIMPOW,HIGH);
previousMillis = millis();
break;
case SIM_POW2:
digitalWrite(SIMPOW,LOW);
previousMillis = millis();
break;
}
}
// Advance state
currentSimState = newSimState;
}
看起来很复杂,但确实非常简单。循环由三个&#34;块&#34;。
组成第一个是按钮检查。如果按下任何按钮,则会设置相应的valueX_changed
标志。这是一个非常简单的部分,只需检查是否有任何按钮具有不同的状态,然后设置标志。
第二部分是检查状态转换。在此switch语句中,程序确定是否需要更改状态机的状态。如果状态为空闲时按下按钮,或者如果在发送SMS的过程中已经过了指定的时间,则会发生这种情况。
第三部分是状态变化时要执行的操作。因此,如果状态发生变化,请执行状态操作,这对于空闲状态没有任何作用,为SIM_SENDx状态发送一些内容并更改SIM_POWx状态的引脚。
只需注意:在设置中,您在正常工作流程中添加了20秒延迟而不是预先发送。如果您要删除此功能,只需从执行重置的设置中删除四行,然后在第一个开关中修改default
个案例即可设置newSimState = SIM_POW1;
而不是SIM_IDLE
。
此代码中可能存在小错误,因为我还没有对其进行测试,但它应该按照您的需要进行操作
答案 2 :(得分:0)
使用计时器库https://playground.arduino.cc/Code/Timer/。正如他们所说:
delay
方法的缺点是其他任何事情都无法进行delay
发生时。您无法更新显示或检查 例如按键。
因此,您可以使用:
代替delay
t.every(1000, doStuff);
要在触发功能的同时离开循环进行业务。
希望有帮助。
答案 3 :(得分:0)
不完全是原始问题的答案...
但是对于那些正在寻找不使用 delay()
来打印秒的简单解决方案的人来说:
if(millis() % 1000 == 0) {
Serial.println(millis());
}
很简单,不是吗?
答案 4 :(得分:-1)
当值溢出时,函数millis()
将失败。正如@CPU_Terminator所说,使用中断。有一些有用的Arduino库,例如Timer1。
修改即可。假设您想要做的是每100分钟发送一条短信,如果您的某些输入发生了变化,您可以使用这样的代码(我删除了一些对我来说似乎不太必要的延迟,如果我和#39再次添加它们;我错了):
#include <SoftwareSerial.h>
#include "TimerOne.h"
const int DI = 2;
const int DT = 3;
const int DGP1 = 4;
const int DGP2 = 5;
const long interval = 100000; // in microseconds
int value1 = 0;
int value2 = 0;
int value3 = 0;
int value4 = 0;
int value1_old = 0;
int value2_old = 0;
int value3_old = 0;
int value4_old = 0;
boolean changed1 = false;
boolean changed2 = false;
boolean changed3 = false;
boolean changed4 = false;
SoftwareSerial SIM900 (7, 8);
void SIM900power(){
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(9, LOW);
delay(5000);
}
void initia(){
SIM900.print("AT+CMGF=1\r");
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
}
void Send_SMS(){
SIM900.println((char)26);
SIM900.println();
delay(20);
SIM900power();
}
void isr_timer(){
if (changed2) {
initia();
SIM900.println("Station 85: Defaut electrique");
Send_SMS();
changed2 = false;
}
if (changed3) {
initia();
SIM900.println("Station 85: DefautGP1");
Send_SMS();
changed3 = false;
}
if (changed4) {
initia();
SIM900.println("Station 85:DD>1000");
Send_SMS();
changed4 = false;
}
}
void setup() {
pinMode(DI, INPUT);
pinMode(DT, INPUT);
pinMode(DGP1, INPUT);
pinMode(DGP2, INPUT);
SIM900.begin(19200);
SIM900power();
delay(20000);
Timer1.initialize(interval);
Timer1.attachInterrupt(isr_timer);
}
void loop() {
value1 = digitalRead (DI);
value2 = digitalRead (DT);
value3 = digitalRead (DGP1);
value4 = digitalRead (DGP2);
if (value1 != value1_old && value1 == HIGH) changed1 = true;
if (value2 != value2_old && value2 == HIGH) changed2 = true;
if (value3 != value3_old && value3 == HIGH) changed3 = true;
if (value4 != value4_old && value4 == HIGH) changed4 = true;
value1_old = value1;
value2_old = value2;
value3_old = value3;
value4_old = value4;
// Here the rest of your code
}
这样,函数isr_timer()
将每0.1秒执行一次。