1

Currently I am attempting to figure out how to control my Adafruit NeoPixels strip using OSC. More specifically, I am using TouchOSC to send/receive messages over WiFi from my NodeMCU ESP8266 microcontroller, which is connected to my NeoPixels.

I have downloaded some test code that somebody else made that listens for OSC messages to toggle the tiny LED on the NodeMCU board on/off. When the controller receives the message, it sends the message back to the TouchOSC client to tell whether or not the light is on (it's a toggle button). This all works perfectly fine.

I've written a simple function that animates the NeoPixel LED strip connected to the NodeMCU board. On its own, this also works perfectly fine.

What I've been struggling with is to figure out a way to get my function [the one called gwBlink()] to run in a loop when the LED is toggled on.

I've attached the code. Could somebody tell me what I'm doing wrong?? I would be eternally grateful for any help!! :)

The TouchOSC interface:
/**
 * 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 ...
}

This code actually works fine as far as switching the little LED on the board on/off, but my animation function isn't triggered.

vj_njoy
  • 11
  • 2

1 Answers1

1

I have only been working with NeoPixels for a short time, but I had problems when trying to use them & serial monitor simultaneously. Once I disabled the serial command (//Serial.begin(115200);), they worked fine. The documentation doesn't plainly state this, I discovered it in a thread where an Adafruit Admin referred to using serial while trying to also update the NeoPixels as a "pain".

If commenting out Serial.begin fixes your problem, then I guess you can experiment with:

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

...idk, but it's worth trying.

nitewing76
  • 11
  • 1