如何通过OSC消息使NeoPixels LED动画打开/关闭?

时间:2019-07-29 14:38:56

标签: arduino arduino-esp8266 osc

当前,我正在尝试弄清楚如何使用OSC控制我的Adafruit NeoPixels带。更具体地说,我正在使用TouchOSC从连接到NeoPixels的NodeMCU ESP8266微控制器通过WiFi发送/接收消息。

我下载了其他人编写的一些测试代码,这些代码侦听OSC消息以打开/关闭NodeMCU板上的微型LED。控制器收到消息后,会将消息发送回TouchOSC客户端,以告知指示灯是否点亮(这是一个切换按钮)。一切都很好。

我编写了一个简单的函数,可以对连接到NodeMCU板上的NeoPixel LED灯带进行动画处理。就其本身而言,这也可以很好地工作。

我一直在努力寻找一种方法来使我的函数[称为gwBlink()]在LED点亮时循环运行。

我已附上代码。有人可以告诉我我在做什么错吗?我将永远感谢您的帮助! :)

TouchOSC界面:
/**
 * Send and receive OSC messages between NodeMCU and another OSC speaking device.
 * Send Case: Press a physical button (connected to NodeMCU) and get informed about it on your smartphone screen
 * Receive Case: Switch an LED (connected to NodeMCU) on or off via Smartphone
 * Created by Fabian Fiess in November 2016
 * Inspired by Oscuino Library Examples, Make Magazine 12/2015
 */

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OSCMessage.h>                // for sending OSC messages
#include <OSCBundle.h>                 // for receiving OSC messages
#include <Adafruit_NeoPixel.h>

#define PIN 3

Adafruit_NeoPixel strip = Adafruit_NeoPixel(58, 3, NEO_GRB + NEO_KHZ800);

char ssid[] = "XXX";                 // your network SSID (name)
char pass[] = "XXX";              // your network password

// Button Input + LED Output
const int btnPin = 12;                 // D6 pin at NodeMCU
const int ledPin = 14;                 // D5 pin at NodeMCU
const int boardLed = LED_BUILTIN;      // Builtin LED

boolean btnChanged = false;
int btnVal = 1;  

WiFiUDP Udp;                           // A UDP instance to let us send and receive packets over UDP
const IPAddress destIp(192,168,0,10);   // remote IP of the target device (i.e. THE PHONE)
const unsigned int destPort = 12000;    // remote port of the target device where the NodeMCU sends OSC to
const unsigned int localPort = 10000;   // local port to listen for UDP packets at the NodeMCU (another device must send OSC messages to this port)

unsigned int ledState = 1;             // LOW means led is *on*

void setup() {
    strip.begin();
    strip.show();
    Serial.begin(115200);

    // Specify a static IP address for NodeMCU - only needeed for receiving messages)
    // If you erase this line, your ESP8266 will get a dynamic IP address
    WiFi.config(IPAddress(192,168,0,13),IPAddress(192,168,0,1), IPAddress(255,255,255,0)); 

    // Connect to WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    Serial.println("Starting UDP");
    Udp.begin(localPort);
    Serial.print("Local port: ");
    Serial.println(Udp.localPort());

    // btnInput + LED Output
    pinMode(btnPin, INPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(boardLed, OUTPUT); 
}

void loop() {
    receiveOSC();
    sendOSC();
}

void sendOSC(){
    // read btnInput and send OSC
    OSCMessage msgOut("/1/buttonListener");

    if(digitalRead(btnPin) != btnVal) {
        btnChanged = true;
        btnVal = digitalRead(btnPin);
    }

    if(btnChanged == true){
        btnChanged = false;
        digitalWrite(ledPin, btnVal);
        digitalWrite(boardLed, (btnVal + 1) % 2);    // strange, but for the builtin LED 0 means on, 1 means off
        Serial.print("Button: ");
        Serial.println(btnVal);
        msgOut.add(btnVal);
    }

    Udp.beginPacket(destIp, destPort);
    msgOut.send(Udp);
    Udp.endPacket();
    msgOut.empty();
    delay(100);
}

void receiveOSC(){
    OSCMessage msgIN;
    int size;
    if((size = Udp.parsePacket())>0){
        while(size--)
            msgIN.fill(Udp.read());
        if(!msgIN.hasError()){
            msgIN.route("/1/toggleLED",toggleOnOff);

        }
    }
}

void gwBlink() {
  // LED strip animation
  uint16_t i, j;
  for(i = 0; i < strip.numPixels(); i = i + 2) {
    strip.setPixelColor(i, 0, 182, 90);
  }
  for(j = 1; j < strip.numPixels(); j = j + 2) {
    strip.setPixelColor(j, 128, 128, 128);
  }
  strip.show();
  delay(100);

  for(i = 0; i < strip.numPixels(); i = i + 2) {
    strip.setPixelColor(i, 128, 128, 128);
  }

  for(j = 1; j < strip.numPixels(); j = j + 2) {
    strip.setPixelColor(j, 0, 182, 90);
  }
  strip.show();
  delay(100);
}

void toggleOnOff(OSCMessage &msg, int addrOffset){
  ledState = (boolean) msg.getFloat(0);

  digitalWrite(boardLed, (ledState + 1) % 2);   // Onboard LED works the wrong direction (1 = 0 bzw. 0 = 1)
  digitalWrite(ledPin, ledState);               // External LED

  if (ledState) {
    Serial.println("LED on");
    gwBlink();
  }
  else {
    Serial.println("LED off");
    strip.clear();
  }
  ledState = !ledState;                         // toggle the state from HIGH to LOW to HIGH to LOW ...
}

只要打开/关闭板上的小LED,此代码实际上就可以正常工作,但不会触发我的动画功能。

1 个答案:

答案 0 :(得分:1)

我只是与NeoPixels合作了很短的时间,但是在尝试同时使用它们和串行显示器时遇到了问题。一旦我禁用了串行命令( // Serial.begin(115200); ),它们就可以正常工作。文档中没有明确说明这一点,我是在一个线程中发现它的,在该线程中,Adafruit Admin引用使用串行,同时还尝试将NeoPixels更新为“痛苦”。

如果注释掉Serial.begin可以解决您的问题,那么我想您可以尝试:

*if (Serial.available()) {
int inByte = Serial.read();
Serial1.print(inByte, DEC);
}*

... idk,但值得尝试。