0

作为一个简单的自动化项目的一部分,我试图通过串行端口控制一些 LED。我无法使以下代码工作

int pin =0;
int state = 0;

void setup() {
    Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {
    // send data only when you receive data:
    if (Serial.available() > 0) {
        // read the incoming byte:
        if(Serial.read() == 'S' && Serial.read() == 'S') {
            // Command to set the pin
            pin  = Serial.read() - 65;
            state = Serial.read() - '0';
            Serial.print("Set State Command received");
            // Set the Pin
            pinMode(pin, OUTPUT);          
            digitalWrite(pin, state == 0? LOW:HIGH);
        }
    }
}

我正在将“SSN1”从我的 python 程序发送到 Arduino 串行端口进行测试,但没有任何反应(我在引脚 13 上连接了一个 LED)

SS -  Set State Command
N  - (pin no) + 'A'  - Pin number 13
1  - State ( 0 = LOW, 1= HIGH)
4

4 回答 4

2

您想等到4 个串行字节在串行缓冲区上累积。

void loop() {
    // polls the serial buffer
    while (Serial.available() < 4);
    if (Serial.read() == 'S' && Serial.read() == 'S') {
       char type = Serial.read();
       char pin = Serial.read() - 65;
       // do something with the results
    }
}

请注意,您可能希望在输入之间实现某种填充(例如添加固定长度的空格),因为串行缓冲区可能会丢失一个字节或溢出,这可能会导致意外结果。此外,有些人会抱怨这个while (Serial.available() < 4)命令,因为计算机科学家受过训练,认为“轮询 = 糟糕!”,但对于 Arduino,它没有任何区别,因为它只运行一个任务。

顺便说一句,您也可以对串行数据使用中断,但这超出了此响应的范围。

于 2013-04-23T11:56:17.623 回答
1

实际上,我也一直在努力争取类似的权利。由于串行通信遇到的问题(有时消息很慢并且分段发送,ACII 代码很难记住),我选择了不同的解决方案。基本上,我在发送到串行的消息中添加了一个标题“>”和一个尾部“<”,并且我使用 Arduino 代码将 >< 之间的消息视为命令。然后我使用 ATOI 将字符串转换为整数。在下面的代码中,您将看到我使用以下数字来让 Arduino 更改 pin2 和 pin13 的状态。以下是与此代码相关的命令:

1000< 将引脚 13 设为高电平,2000< 将引脚 13 设为低电平,3000< 将引脚 2 设为高电平,4000< 将引脚 2 设为低电平

因此,只需将 >< 之间的这些数字发送到序列号,它就可以工作了。 我也使用上面的方法来设置 PWM 速度,只需操作与接收到的消息相关的字符串。我没有在这个示例中包含 PWM 命令,而只包含与引脚 13 和引脚 2 相关的命令。我认为使用数字和字符串标识符来打开和关闭消息会更简单和安全。加载草图,打开串行监视器并发送 >1000<,您应该看到引脚 13 上的内部 LED 亮起,依此类推。如果您需要任何其他帮助,请告诉我。

char inData[10];
int index;
boolean started = false;
boolean ended = false;
String message = "I am ready!, Send your command....";

void setup(){
    Serial.begin(9600);
    Serial.println(message);
    pinMode (13, OUTPUT);
    pinMode (2, OUTPUT);
}

void loop()
{
    while(Serial.available() > 0)
    {
        char aChar = Serial.read();
        if(aChar == '>')
        {
            started = true;
            index = 0;
            inData[index] = '\0';
        }
        else if(aChar == '<')
        {
            ended = true;
        }
        else if(started)
        {
            inData[index] = aChar;
            index++;
            inData[index] = '\0';
        }
    }

    if(started && ended)
    {
        int inInt = atoi(inData);

        // set  pin 13 HIGH
        if (inInt < 1000)
        { 
            digitalWrite(13, HIGH);
        }
        //set pin 13 LOW
        else if (inInt < 2000)
        { 
            digitalWrite(13, LOW); 
        }
        //set  pin 2 HIGH
        else if (inInt < 3000)
        { 
            digitalWrite(2, HIGH);
        }
        //set il pin 2 LOW
        else if (inInt < 4000)
        { 
            digitalWrite(2, LOW);
        }

        started = false;
        ended = false;
        index = 0;
        inData[index] = '\0';
    }
}
于 2013-04-27T06:49:57.373 回答
0

查看 Arduino物理像素教程中的示例代码

const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Serial.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    if (incomingByte == 'H') {
      digitalWrite(ledPin, HIGH);
    } 
    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByte == 'L') {
      digitalWrite(ledPin, LOW);
    }
  }

验证您是否SSN1在串行监视器上看到通过。

于 2013-04-23T03:29:11.093 回答
0

我改进了我的代码,因为它看起来像这样

int pin =0;
int state = 0;

void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {

        // send data only when you receive data:
        if (Serial.available() > 3) { // I am using chunk of 4 characters/bytes as a command 
                // read the incoming byte:
                if(Serial.read() == 'S' && Serial.read() == 'S') {
                  // Command to set the pin
                  pin  = Serial.read() - 65;
                  state = Serial.read() - '0';
                  Serial.print("Set State Command received");
                  // Set the Pin
                  pinMode(pin, OUTPUT);          
                  digitalWrite(pin, state == 0? LOW:HIGH);
                }
                delay(50); 
        }
}

它非常适合我。由于循环的频率很高,Arduino 无法拾取字节进行连续读取。所以我们正在等待缓冲区中累积 4 个字节来读取那些(Arduino 的串行缓冲区是 64 个字节)。

于 2013-04-28T21:37:19.047 回答