首页 文章

同时读写arduino

提问于
浏览
2

我有一种情况,我从传感器(附加到arduino)读取值,这些值存储在mysql数据库中,然后显示在网页上 . 同时从网页读取中继值,存储在mysql上,然后写入arduino . 我可以单独做,但不能同时做 . 我附上了一些代码来展示我想要完成的事情 . 我认为它与串行可用性有关

/*----( 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';
  }
}

任何建议都会很受欢迎??

1 回答

  • 1

    “同时”做几件事的关键是理解Arduino只有一个核心 . 因此它只会一步一步地处理东西 . 现在假设您要“同时”执行三个函数“action1()”,“action2()”和“action3()” . 为了实现这一点,您必须确保

    • 所有动作都可以尽快执行,最好是亚毫秒

    • 没有人"blocks"

    然后通过将它们连续地连续实现所需的效果

    void loop() {
        action1();
        action2();
        action3();
    }
    

    这是“合作多任务处理”的基本思想 . 因此,没有一个动作必须利用delay()或阻塞等待 . 例如

    while(Serial.available() == 0);
    

    是一个阻塞等待,必须避免 . 如果任何动作是一组冗长且涉及的计算,事情会变得更复杂 . 假设action1()需要1秒来处理 . 然后必须将action1()拆分为足够快的执行部分 . 在“状态机”的帮助下,这些碎片仍然可以保存在action1()中 . 例如

    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;
    }
    

    当然这只是基本原则 . 在“真实”实现中,您可以根据需要改变它 .

    另一个经常需要的东西是有一个主循环,它做一些东西和一个更高频率的“循环”,做一些其他的东西 . 这通常通过所谓的定时器中断来执行 . 这更先进,但通常也更有效 . 中断的棘手之处在于它们往往更难以调试 . 我在博客中有一些记录的例子 .

    blinking several LEDs with different frequencies. VU Meter experiment (scroll down!)

相关问题