如何在switch语句中连续打印输出?

时间:2019-03-28 11:19:54

标签: c user-interface arduino switch-statement

我一直在尝试在switch语句条件内连续打印引脚3的PWM输出,但只打印一次。我可以连续在串行监视器中打印它直到遇到第二个条件吗?或使用while循环?还是其他?

这是我的代码,我也有一个具有类似功能的代码,但是如果不使用它,它仍然只打印一次

void loop() {
    // if there's any serial available, read it:
    while (Serial.available() > 0) {
        int InitVal = Serial.parseInt();
        int red = Serial.parseInt();

        switch(InitVal) {
            case 1:
                if (Serial.read() == '\n') {

                    analogWrite(redPin, red);
                    Serial.println(red);
                    Serial.write(red);

                }
                break;
            case 0:
                analogWrite(redPin, 0);
                Serial.println(0);
                Serial.write(0);
                break;
        }
    }
}

我打算将此阶段与GUI进行中间阶段。 GUI将ASCII发送到arduino,然后将输出值发送到GUI。 例子

1.GUI发送[1,123]:1 = switch语句的触发点; 123 = PWM值。

  1. Arduino接收指令,并打印出pwm值
  2. GUI接收并显示pwm值

修改后的代码:卡在最后一个while循环中,也许我可以在arduino中使用线程处理功能,以便最后一个while循环会得到满足/不满意?

void loop() {

  int InitVal = 0;
  // if there's any serial available, read it:
  while (Serial.available() > 0) {
    int InitVal = Serial.parseInt();
    int red = Serial.parseInt();

    switch(InitVal) {
      case 1:
        if (Serial.read() == '\n') {
           InitVal = 1;
          //analogWrite(redPin, red);
          //Serial.println(red);
         // Serial.write(red);
       }
        break;
      case 0:
        InitVal = 0;
        //analogWrite(redPin, 0);
        //Serial.println(0);
        //Serial.write(0);
        break;
       }

      if (InitVal) /* when enabled, blink leds */ {
        delay(20);
        while (InitVal == 1) /* loop forever */{

          Serial.println(red);
          Serial.write(red);
          delay(20);
        }

    }


    }
  } 

2 个答案:

答案 0 :(得分:0)

我放弃了Serial.parseInt()函数,删除了开关语句,然后按照@Arno Bozo建议在http://forum.arduino.cc/index.php?topic=396450.0上进行本教程的同时进行串行侦听 我想出了我想要的东西,这是代码

const int redPin = 3;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
boolean newData = false;

int InitVal = 0; // change to init value or red
int red = 0;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  // make the pins outputs:
  pinMode(redPin, OUTPUT);

}

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        One();
        newData = false;
    }
    else {
      Zero();

    }
}


 ///////////////////// ///////////////////// /////////////////////
void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

 ///////////////////// ///////////////////// /////////////////////

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    InitVal = atoi(strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    red = atoi(strtokIndx);     // convert this part to an integer

}


 ///////////////////// ///////////////////// /////////////////////
void One() {

  if (InitVal == 0){

    delay(20);
    Serial.println(0);
    delay(20);
  }      
 }
 ///////////////////// ///////////////////// /////////////////////
void Zero() {

  if (InitVal == 1){

    delay(20);
    Serial.println(red);
    delay(20);
  }      
 }

摘要中,代码的工作方式如下

1。在串行监视器中,发送此<1,123>:1 = switch语句的触发点; 123 = PWM值。

  1. Arduino接收指令,并打印出pwm值
  2. 如果您发送<0,123>,则会打印一次零

答案 1 :(得分:0)

我在这里发布了完善的代码。该体系结构可以重新用于串行处理。我已将它写为我遇到的人以及正在学习arduino的人的例子。

我对避免延误的方式进行了评论和解释。此处用于每1秒打印一次pwm的当前值,而不会延迟(1000)停止。

#include <Arduino.h>

// with schedule(f,i) , the function f() will be called every i ms
//   schedule(f,i)   lines are put in loop()  function
//   f is of type   void f(void)
#define schedule(f,i) {static unsigned long l=0;unsigned long c=millis();if((unsigned long)(c-l)>=i){l=c;f();}}

const int ledPin = 13;

void setup()   {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
}

boolean newCommandHasArrived=false, newParsedCommand=false;
String personalSerialBuffer="";   // char[] would be better; but String are so convenient
enum ECommand {ecmdNoPwm=0, ecmdPwm=1, ecmdBad=10 };
ECommand cmd=ecmdNoPwm;
int cmdArg=0;

boolean readSerialBuffer(String &personalSerialBuffer);
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg);
void executeCommand(ECommand acmd, int &acmdArg);
void printCurrentValue()  {Serial.println(String("cval:") + cmdArg);}


void loop() {
    // transfer serial buffer in personal buffer
    newCommandHasArrived = readSerialBuffer(personalSerialBuffer);

    if (newCommandHasArrived)   {
        newCommandHasArrived = false;
        newParsedCommand = parseCommand(personalSerialBuffer, cmd, cmdArg);
    }

    if (newParsedCommand)   {
        newParsedCommand = false;
        executeCommand(cmd, cmdArg);
    }

    // I print current value every 1000ms
    //delay(1000);    // you can often use delay without pb, but it is a bad usage
    // Here I provide you with a quick way to execute a task every 1000ms
    {
        const unsigned long  delayBetweenExecution=1000;
        static unsigned long lastTime=0;
        unsigned long current = millis();
        // note that C++ says that overflow on unsigned is well defined
        // it calculates modulo arithmetic
        if ((unsigned long)(millis() - lastTime) >= delayBetweenExecution)   {
            lastTime = current;
            Serial.println(String("cval:") + cmdArg);
        }
    }

    // We can make it shorter thanks to a macro:
    //   but you have to define a void function(void)  that uses only global variable
    //   because it has no argument :
    // void printCurrentValue()  {Serial.print(String("cval:") + cmdArg);}
    //schedule(printCurrentValue, 1000);
}



boolean readSerialBuffer(String &personalSerialBuffer)   {
    if (Serial.available() > 0) {
        personalSerialBuffer.concat(Serial.readString());
    }

    // the frame is considered finished, if it ends with \n
    if (personalSerialBuffer.endsWith("\n"))
        return true;
    else
        return false;
}

boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg)   {
    // format [ 1, 123]\n
    // I omit [  then I read first int : 1
    // Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
    int readCmd = apersonalSerialBuffer.substring(1).toInt();

    // conversion readCmd to acmd
    switch (readCmd)   {
    case 0:
        acmd = ecmdNoPwm;   break;
    case 1:
        acmd = ecmdPwm;   break;
    default:
        Serial.println(String("new command unknown: ") +
                       apersonalSerialBuffer);
        apersonalSerialBuffer = "";
        return false;
    }

    // find beginning of 2nd part, separated by ','
    int sepPos = apersonalSerialBuffer.indexOf(',');
    // no ',' : indexOf returns -1
    if (sepPos == -1)   {
        Serial.println(String("new command could not be parsed: ") +
                       apersonalSerialBuffer);
        apersonalSerialBuffer = "";
        return false;
    }
    // Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
    acmdArg = apersonalSerialBuffer.substring(sepPos+1).toInt();

    // All is fine
    // I have to reset buffer before leaving
    apersonalSerialBuffer = "";
    return true;
}

void executeCommand(ECommand acmd, int &acmdArg)   {
    switch(acmd)   {
    case ecmdNoPwm:
        // I erase acmdArg
        acmdArg = 0;
        analogWrite(ledPin, acmdArg);
        Serial.println("cmd no pwm");
        break;
    case ecmdPwm:
        analogWrite(ledPin, acmdArg);
        Serial.print("cmd pwm:");  Serial.println(acmdArg);
        break;
    default:
        analogWrite(ledPin, 0);
        Serial.println("Bad cmd");
    }
}