C# 同时读写arduino
我有一种情况,我从传感器(连接到arduino)读取值,该值存储在mysql数据库中,然后显示在网页上。同时,中继值从网页读取,存储在mysql上,然后写入arduino。我可以分别做,但不能同时做。我附加了一些代码来展示我试图完成的任务。我认为这与串行可用性有关C# 同时读写arduino,c#,arduino,C#,Arduino,我有一种情况,我从传感器(连接到arduino)读取值,该值存储在mysql数据库中,然后显示在网页上。同时,中继值从网页读取,存储在mysql上,然后写入arduino。我可以分别做,但不能同时做。我附加了一些代码来展示我试图完成的任务。我认为这与串行可用性有关 /*----( SETUP: RUNS ONCE )----*/ void setup() { Serial.begin(115200); sensors.begin(); //Get DS18B20 temperat
/*----( SETUP: RUNS ONCE )----*/
void setup() {
Serial.begin(115200);
sensors.begin(); //Get DS18B20 temperatures
sensors.setResolution(probe1, 10); //set resolution to 10bit
sensors.setResolution(probe2, 10); //set resolution to 10bit
Wire.begin(); // Start the Wire (I2C communications)
RTC.begin(); // Start the RTC Chip
digitalWrite(Relay_1, RELAY_OFF); //Relays
digitalWrite(Relay_2, RELAY_OFF);
pinMode(Relay_1, OUTPUT); //Set relays as outputs
pinMode(Relay_2, OUTPUT);
}
/*--(end setup )---*/
/****** LOOP: RUNS CONSTANTLY ******/
void loop() {
ReadSensors();
delay(1000);
ReadRelays();
}
/****** Read Sensors ******/
void ReadSensors()
{
DateTime now = RTC.now(); //Get time from RTC
photolevel = analogRead(photopin); //Read light level
sensors.requestTemperatures();
dallas1 = sensors.getTempC(probe1);
dallas2 = sensors.getTempC(probe2);
dtostrf(photolevel, 1, 0, photo1);
dtostrf(dallas1, 1, 2, temp1);
dtostrf(dallas2, 1, 2, temp2);
String tempAsString1 = String(photo1);
String tempAsString2 = String(temp1);
String tempAsString3 = String(temp2);
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(" ");
Serial.println(tempAsString1 + " " + tempAsString2 + " " + tempAsString3);
Serial.flush();
}
void ReadRelays()
{
Serial.flush();
// Read all serial data available, as fast as possible
while(Serial.available() > 0)
{
char inChar = Serial.read();
if(inChar == SOP)
{
index = 0;
inData[index] = '\0';
started = true;
ended = false;
}
else if(inChar == EOP)
{
ended = true;
break;
}
else
{
if(index < 79)
{
inData[index] = inChar;
index++;
inData[index] = '\0';
}
}
}
if(started && ended)
{
// The end of packet marker arrived. Process the packet
if (strlen(inData) > 0)
{
char *token = strtok(inData, ",");
if(token)
{
index = 0;
array[index] = atoi(token);
while (token = strtok(NULL, ","))
{
array[index++] = atoi(token);
}
}
}
Serial.println(array[0]);
Serial.println(array[1]);
// Reset for the next packet
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
}
/*---(安装程序:运行一次)----*/
无效设置(){
序列号开始(115200);
sensors.begin();//获取DS18B20温度
sensors.setResolution(probe1,10);//将分辨率设置为10位
sensors.setResolution(probe2,10);//将分辨率设置为10位
Wire.begin();//启动导线(I2C通信)
RTC.begin();//启动RTC芯片
数字写入(继电器1,继电器关闭);//继电器
数字写入(继电器2,继电器断开);
pinMode(继电器_1,输出);//将继电器设置为输出
引脚模式(继电器2,输出);
}
/*--(结束设置)---*/
/******循环:持续运行******/
void循环(){
读取传感器();
延迟(1000);
ReadRelays();
}
/******读取传感器******/
void ReadSensors()
{
DateTime now=RTC.now();//从RTC获取时间
photolevel=analogRead(photopin);//读取光照级别
传感器。请求温度();
dallas1=传感器。getTempC(probe1);
dallas2=传感器。getTempC(probe2);
dtostrf(光电平,1,0,光电平1);
DTOSTF(达拉斯1、1、2、1);
DTOSTF(达拉斯2,1,2,2);
字符串tempAsString1=字符串(照片1);
字符串tempAsString2=字符串(temp1);
字符串tempAsString3=字符串(temp2);
Serial.print(now.year(),DEC);
序列号。打印(“/”);
Serial.print(now.month(),DEC);
序列号。打印(“/”);
Serial.print(now.day(),DEC);
连续打印(“”);
Serial.print(now.hour(),DEC);
序列号。打印(“:”);
Serial.print(now.minute(),DEC);
连续打印(“”);
Serial.println(tempAsString1+“”+tempAsString2+“”+tempAsString3);
Serial.flush();
}
void ReadRelays()
{
Serial.flush();
//尽可能快地读取所有可用的串行数据
while(Serial.available()>0)
{
char inChar=Serial.read();
如果(英寸=SOP)
{
指数=0;
inData[索引]='\0';
开始=真;
结束=假;
}
否则如果(英寸==EOP)
{
结束=真;
打破
}
其他的
{
如果(指数<79)
{
inData[指数]=英寸;
索引++;
inData[索引]='\0';
}
}
}
如果(开始和结束)
{
//数据包结束标记已到达。请处理数据包
如果(strlen(inData)>0)
{
char*token=strtok(inData,“,”);
如果(令牌)
{
指数=0;
数组[索引]=atoi(令牌);
while(token=strtok(NULL,“”,“”)
{
数组[index++]=atoi(令牌);
}
}
}
Serial.println(数组[0]);
Serial.println(数组[1]);
//为下一个数据包重置
开始=错误;
结束=假;
指数=0;
inData[索引]='\0';
}
}
如果您有任何建议,我们将不胜感激。同时做几件事的关键是要了解Arduino只有一个核心。因此,它只能一步一步地处理材料。现在,假设您希望同时执行三个函数“action1()”、“action2()”和“action3()”。为了实现这一点,您必须确保
void loop() {
action1();
action2();
action3();
}
这是“协作多任务处理”的基本思想。因此,任何操作都不能使用delay()或阻塞等待
while(Serial.available() == 0);
void action1() {
static uint8_t state = 0;
switch (state) {
case 1: sub_action1_1(); break;
case 2: sub_action1_2(); break;
case 3: sub_action1_2(); break;
default: state = 0; return;
}
++state;
}
是一种阻塞等待,必须避免。如果任何操作是一组冗长且复杂的计算,事情就会变得更加复杂。比如说,action1()需要1s来处理。然后action1()必须被分割成执行速度足够快的部分。在“状态机”的帮助下,这些部分仍然可以保存在action1()中。例如
while(Serial.available() == 0);
void action1() {
static uint8_t state = 0;
switch (state) {
case 1: sub_action1_1(); break;
case 2: sub_action1_2(); break;
case 3: sub_action1_2(); break;
default: state = 0; return;
}
++state;
}
当然,子操作必须执行得足够快。另一个经常遇到的问题是如何在不阻塞的情况下等待。这是通过存储所需的延迟来实现的。例如
void action1() {
static uint8_t state = 0;
static unsigned long start_millis = 0;
switch (state) {
case 1: sub_action(); break;
case 2: // this starts the delay
start_millis = millis();
break;
case 3: // this checks if the delay has elapsed
if (millis() - start_millis < 1000) {
// if it did not yet elapse ensure that the state will not progress to the next step
return;
}
// if the delay has elapsed proceed to next state
break;
case 4: next_sub_action(); break;
default: state = 0; return;
}
++state;
}
void action1(){
静态uint8_t状态=0;
静态无符号长起始\u毫秒=0;
开关(状态){
案例1:子动作();中断;
案例2://这将启动延迟
开始_millis=millis();
打破
案例3://检查延迟是否已过
如果(毫秒()-开始_毫秒<1000){
//如果该状态尚未消失,请确保该状态不会进入下一步
返回;
}
//如果延迟已过,则转至下一个状态
打破
案例4:下一个动作();中断;
默认值:state=0;返回;
}
++国家;
}
当然,这只是基本原则。在“真实”的实现中,您可以根据需要改变这一点
另一个经常需要的东西是有一个主循环,做一些事情和一个更高频率的“循环”“这还可以做其他事情。这通常通过所谓的定时器中断来执行。这更先进,但通常也更有效。中断的棘手之处在于,它们往往更难调试。在我的博客中,我有一些记录在案的例子
您不能同时做两件事-只有一个核心。执行乒乓球是在两个动作之间进行的。描述您认为此代码不起作用的原因。您尚未描述问题的症状。如果我运行当前代码,则只有ReadSensors可以工作。也就是说,传感器的读数显示在串行监视器中,而不是python脚本中的值,python脚本将值读取到arduino(ReadRelay)中。如果我将ReadSensors注释掉,则为ReadRelays wor