同时读写arduino

时间:2013-07-04 00:49:11

标签: c# arduino

我有一种情况,我从传感器(附加到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 个答案:

答案 0 :(得分:1)

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

  1. 所有操作都可以尽快执行,最好是亚毫秒
  2. 其中没有一个“阻挡”
  3. 然后通过将它们连续地连续实现所需的效果

    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!)