【问题标题】:Brightness on digital output varies based on level input type数字输出的亮度因电平输入类型而异
【发布时间】:2014-07-05 19:59:11
【问题描述】:

基本上,我正在按照 BarGraph 中的教程代码获取 LED 条形图。我没有电位器,所以我想通过使用Processing 串行写入来模仿它,基于 Dimmer 中的调光器示例。我已将 sensorReading 值设置为处理应用程序的输入(将其网格更新为 1023 个元素),如下所示:

  int sensorReading;
  if (Serial.available()) {
      // Read the most recent byte (which will be from 0 to 1023):
      sensorReading = Serial.read();
  }

这会根据我在处理应用程序网格中的鼠标位置点亮 LED。然而,LED 非常暗淡。如果我更改将sensorReading 值设置为:

  int sensorReading = random(0, 1023);

然后 LED 会亮得多。由于 LED 都在数字输出引脚上,我认为它只会根据 sensorReading 值发送/关闭,而与亮度无关。我错过了什么?

这里是处理代码:

 // Dimmer - sends bytes over a serial port
 // by David A. Mellis
 //
 // This example code is in the public domain.

 import processing.serial.*;
 Serial port;

 void setup() {
     size(256, 150);

     println("Available serial ports:");
     println(Serial.list());

     // Uses the first port in this list (number 0). Change this to
     // select the port corresponding to your Arduino board. The last
     // parameter (for example, 9600) is the speed of the communication. It
     // has to correspond to the value passed to Serial.begin() in your
     // Arduino sketch.
     //port = new Serial(this, Serial.list()[0], 9600);

     // If you know the name of the port used by the Arduino board, you
     // can specify it directly like this.
     port = new Serial(this, "COM6", 9600);
 }

 void draw() {
     // Draw a gradient from black to white
     for (int i = 0; i < 1024; i++) {
         stroke(i);
         line(i, 0, i, 150);
     }

     // Write the current X-position of the mouse to the serial port as
     // a single byte.
     port.write(mouseX);
 }

这是 Arduino 代码:

// These constants won't change:
const int analogPin = A0;   // The pin that the potentiometer is attached to.
const int ledCount = 10;    // The number of LEDs in the bar graph.

int ledPins[] = {
  2, 3, 4, 5, 6, 7,8,9,10,11 };   // An array of pin numbers to which LEDs are attached.

void setup() {
    Serial.begin(9600);
    // Loop over the pin array and set them all to output:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
      pinMode(ledPins[thisLed], OUTPUT);
    }
}

void loop() {
    // Read the potentiometer:
    //   int sensorReading = random(0, 1023);
    //   delay(250);
    byte streamReading;
    if (Serial.available()) {
        // Read the most recent byte (which will be from 0 to 255):
        sensorReading = Serial.read();
    }
    //Serial.println(sensorReading);

    // Map the result to a range from 0 to the number of LEDs:
    int ledLevel = map(sensorReading, 0, 255, 0, ledCount);

    // Loop over the LED array:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
        // If the array element's index is less than ledLevel,
        // turn the pin for this element on:
        if (thisLed < ledLevel) {
            digitalWrite(ledPins[thisLed], HIGH);
        }
        // Turn off all pins higher than the ledLevel:
        else {
            digitalWrite(ledPins[thisLed], LOW);
        }
    }
}

【问题讨论】:

  • 你能粘贴你用来设置输出引脚的代码吗?事实上,看看你的loop() 的其余部分也会很有用......我有一个理论:)
  • @angelatlarge,完整的代码在这两个链接中。我要替换的代码是 readAnalog,因为我没有锅。

标签: arduino


【解决方案1】:

问题:您的处理代码是sending data constantly一直在向您的 Arduino 发送串行数据

setup()后直接调用,draw()函数不断 执行包含在其块中的代码行,直到 程序停止或调用 noLoop()。 draw() 被调用 自动,永远不应显式调用。

这会导致您的 Arduino 草图频繁更新 LED 开/关状态,并且考虑到您读取数据的方式,这将导致 LED 非常快速地闪烁。

解决方案: 最简单的解决方法是向 Arduino 或处理草图添加延迟。更好的解决方案是将处理代码修改为仅在值更改时发送数据;尽管请注意,由于鼠标值几乎不断变化,并且这些变化对于 Arduino 代码并不重要,但您仍然可能有很多不必要的闪烁。但是,如果您在 Arduino 代码中修复了串行读取功能,那么闪烁就不会成为问题。)

代码:修改您的处理代码以跟踪上次读数,并且仅在不同时更新:

int lastMouseX; 

void draw() {
 // draw a gradient from black to white ...

 int newMouseX = mouseX;
 if (newMouseX != lastMouseX) {
    lastMouseX = newMouseX
    // write the current X-position of the mouse to the serial port as
    // a single byte
    port.write(mouseX);
 }

其他问题:首先,如果您期望值 0-1024,则存在一个问题:Arduino 的 analogWrite() 函数需要一个字节 0-255。

其次,正如Martin Thompson 指出的那样,您可能正在从您的处理应用程序发送一个字符串,例如128,然后使用它的ASCII 值来设置强度。由于 09 的 ASCII 值在 48-57 范围内,因此您的强度相对较低。请注意,当包含超过一个字节的字符串(例如128)时,您仅使用一个字节来表示强度。所以你有两个选择:

  • 发送一个真正的二进制字节,而不是字符串。这就是您展示的调光器示例中所做的事情
  • 发送一个字符串,然后将其转换为其二进制表示。为此,您需要读取所有字符直到某个分隔符(例如 CR 或空格),收集它们,然后转换。

这段代码可能看起来像这样:

#include <stdlib.h>

int idxChar = 0;
#define BUFFER_SIZE 10
char strIntensity[BUFFER_SIZE];


...

while (Serial.available()) {
    // read the string representation of a byte
    // assuming bytes are separated by non-numeric characters
    // and never overflow
    char ch = Serial.read();
    if ( (ch >= '0') && (ch <= '9') ) {
        strIntensity[idxChar++] = ch;
    } else {
        strIntensity[idxChar] = 0;
        sensorReading = atoi(strIntensity);
        idxChar = 0;
    }
    if (idxChar>=BUFFER_SIZE-1) {
        // (need space for the null char at the end too
        // Buffer overflow.  Bail 
        idxChar = 0;
    }
}

【讨论】:

  • 我实际上并没有发送强度。 LED 只是根据 sensorReading 参数的值打开/关闭。我的困惑是为什么这两种方法都基于 sensorReading 点亮 LED,它们具有不同的强度。我正在为问题添加完整代码。
  • 处理代码中没有循环。但我在 Arduino 代码中不断循环(当然)。降低波特率会对此有所帮助吗?
  • 就是这样!我在 Arduino 代码中添加了延迟,它看起来不错:delay(17);
  • @wergeld 根据我的个人建议再次修改了答案。干杯!
  • 我将您的示例代码从处理移动到 Arduino 代码文件(当然是修改过的)。像魅力一样工作!
【解决方案2】:

// 读取最近的字节(从 0 到 1023)

字节从 0 到 255。它们(通常)代表 ASCII 字符集中的字符。

如果您希望读取 0 到 1023 之间的数字,则可能一次传输一个字符(即字符 1 后跟字符 0 将表示数字 10) - 在这种情况下,您有解析它们以将它们转换为可以按预期使用的数字。

parseInt 函数可能正是您所需要的 - a tutorial on reading ASCII integers can be found here

【讨论】:

  • 我将 arduino 代码中的预期值更改为 255。还是同样的问题。
  • 好的,我知道需要做什么,但不知道该怎么做。 parseInt 需要一个新的流类引用和一个要读取的流列表。对于新的流类,这段代码会是什么样子?
  • Serial 就是这样一个 Stream,所以你可以调用 Serial.parseInt() (据我所知) - 答案也更新了教程链接。
猜你喜欢
  • 2016-12-19
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
相关资源
最近更新 更多