【问题标题】:How to continually print output inside a switch statement?如何在 switch 语句中连续打印输出?
【发布时间】:2019-03-28 11:19:54
【问题描述】:

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

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

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

    }


    }
  } 

【问题讨论】:

  • 输入中的逗号在哪里以及为什么需要它?
  • 如果你尝试过这个循环,它在哪里不能满足你的需求? Serial.available() 可以根据来自您设备的数据速率限制连续执行。这是你看到的吗?
  • @Lundin arduino.cc/en/Tutorial/ReadASCIIString 我目前正在关注本教程,使用 arduino 代码 Serial.parseInt() 函数来定位由非字母数字字符分隔的值。
  • @ryyker 我目前正在使用串行监视器发送 [1,123](csv 字符串)。我想要的是,如果满足案例 1 或 0,它会不断打印输出。在我的情况下,它只打印一次并再次等待另一个输入。因此,我需要不断地从 GUI 向 arduino 发送数据以便连续打印它?
  • 如我所说,如果串行队列中没有任何内容,serial.available() 将停止执行流程。作为测试,在循环底部放置一个 serial.write() 来模拟应该来自 Arduino 的内容。

标签: c user-interface arduino switch-statement


【解决方案1】:

我丢弃了 Serial.parseInt() 函数,删除了开关语句,并在遵循http://forum.arduino.cc/index.php?topic=396450.0 上的本教程时遵循@Arno Bozo 关于串行监听的建议 我想出了我想要的,这是代码

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 = switch 语句的触发点; 123 = PWM 值。

  1. Arduino 接收指令并打印出 pwm 值
  2. 如果您发送 它会打印一次零

【讨论】:

    【解决方案2】:

    我在这里发布了一个精炼的代码。该体系结构可以重复用于串行处理。我已经为我遇到的和正在使用 arduino 学习的人写了它作为示例。

    我已经做了 cmets 并解释了避免延迟的方法。此处用于每 1s 打印一次 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");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 2022-11-19
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多