Go Down

Topic: Connecting Processing with Arduino and WS2812B (Read 522 times) previous topic - next topic

A7243618X

Hello,

I was making driver for WS2812B reacting to music. My first idea was "autonomic driver with screen and knobs" but then I find out that Arduino is too weak for very complicated programs and even don't have enough memory to store setting in EEPROM.  
So I want to create driver that downloading array with pixels from PC. I modified  this project and after two days of failures it works.
I have 75 LED with more than 120Hz refresh rate and I send 5bytes from MSGEQ5 to processing.

I have few question:
How can I improve my code?
In some places code look very weird (for example line 32 in processing file).
How can I connect two processing apps (I don't want to interface slowing down communication).

Code in processing file is doing rainbow.
I'm using Arduino Nano

Sorry for my bad English.

Arduino
Code: [Select]
#include "FastLED.h"

#define NUM_LEDS 75
#define LED_DATA_PIN 6
#define NUM_BYTES (NUM_LEDS*3) // 3 colors 

#define BRIGHTNESS 100

byte MESSAGE_PREAMBLE[] = { 211, 10, 137};
uint8_t PREAMBLE_LENGTH = 3;
uint8_t current_preamble_position = 0;

uint8_t led_counter = 0;
uint8_t byte_counter = 0;

CRGB leds[NUM_LEDS];
byte buffer[NUM_BYTES]; // buffer for pixels


//for MSGEQ5
int STROBE_PIN = 4;
int RESET_PIN = 2;
int EQIN_PIN = A0;
int bandValues[5];
int bandNo;

void readMSGEQ5()
{
  digitalWrite(RESET_PIN, HIGH);
  digitalWrite(RESET_PIN, LOW);
  delayMicroseconds(75);
 
  for (bandNo = 0; bandNo < 5; bandNo++)
  {
    digitalWrite(STROBE_PIN, LOW);
    delayMicroseconds(40);
    bandValues[bandNo] = analogRead(EQIN_PIN);
    digitalWrite(STROBE_PIN, HIGH);
    delayMicroseconds(40);
  }
}

void setup()
{
  pinMode(RESET_PIN, OUTPUT);//for MSGEQ5
  pinMode(STROBE_PIN, OUTPUT);


  Serial.begin(1000000); // Maximal speed
  FastLED.clear(true);
  FastLED.addLeds<WS2811, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);

 
  for(;;)
  {
   
    while (current_preamble_position < PREAMBLE_LENGTH) // waiting for preamble and sending data from MSGEQ5
    {
      if (Serial.available() > 0)
      {
        if (Serial.read() == MESSAGE_PREAMBLE[current_preamble_position])
        {
          current_preamble_position++;
        }
        else
        {
          current_preamble_position = 0;
        }
      }else
      {
        Serial.write(10);//send that i'm ready to recive, MSGEQ5 never give values smaller than 60
        Serial.write(bandValues[0]/4);// send data from MSGEQ5
        Serial.write(bandValues[1]/4);
        Serial.write(bandValues[2]/4);
        Serial.write(bandValues[3]/4);
        Serial.write(bandValues[4]/4);
       }
    }
    current_preamble_position = 0;
    Serial.readBytes(buffer, NUM_BYTES);//receiving array

    while (byte_counter < NUM_BYTES)
    {
      leds[led_counter++] = CRGB(buffer[byte_counter++], buffer[byte_counter++], buffer[byte_counter++]);
    }

    FastLED.show();
   
    readMSGEQ5();

    byte_counter = 0;
    led_counter = 0;
  }
}

void loop()
{
}


Processing
Code: [Select]
import processing.serial.*;

Serial port;
byte preamble[]= new byte[3];
byte out[]  = new byte[225];
int in[]  = new int[6];

int j=0;//for rainbow
int w=0;

void setup(){
  String portName = Serial.list()[0];
  port = new Serial(this, portName, 1000000);
 
  preamble[0]=(byte)211;
  preamble[1]=(byte)10;
  preamble[2]=(byte)137;
}


void draw() {
 
  for(int a=0;a<4;)//to have more FPS than window
  {

    in[0]=port.read();
    in[1]=port.read();
    in[2]=port.read();
    in[3]=port.read();
    in[4]=port.read();
    in[5]=port.read();
    print( in[0]);// I don't know why it must by here, but without it it's not working
        if(in[0]==10)
        {
          a++;
          colorMode(HSB, 1440);// Setting to HSB to make easy rainbow, 1440 is for better aquracy
          if(j==1440)
          {
              j=0;
          }
          j++;
 
          for(int i=0; i<75; i++)
          {
             w=i+j;
             if(i+j>1440)
             {
                 w=w-1440;
             }
             out[(i*3)]=(byte)(red(color(w, 1440, 1440))/5.8);
             out[(i*3)+1]=(byte)(green(color(w, 1440, 1440))/5.8);
             out[(i*3)+2]=(byte)(blue(color(w, 1440, 1440))/5.8);
          }
         
          if(port != null) // sending array
          {
              port.write(preamble);
              port.write(out);
          }
          port.clear();
    }
  }
 println(frameRate);
}

PaulS

Quote
How can I connect two processing apps
That is a question for the Processing forum, not the Arduino forum.

Code: [Select]
        Serial.write(bandValues[0]/4);// send data from MSGEQ5
        Serial.write(bandValues[1]/4);
        Serial.write(bandValues[2]/4);
        Serial.write(bandValues[3]/4);
        Serial.write(bandValues[4]/4);

Serial.write() takes a byte argument, not an int. I don't know what your upper limit is, but it is possible that you are going to lose data.

Code: [Select]
    Serial.readBytes(buffer, NUM_BYTES);//receiving array
The number of bytes actually read may not be the same as the number of bytes requested.

You should NOT be reading serial data in draw(). You should NOT be reading serial data without making sure that there IS data to read.

The art of getting good answers lies in asking good questions.

A7243618X

Thanks for quick answer.

Maximum value of bandValues[0] is 1023, so there is no problem.

I tried serialEvent() function, but now processing isn't sending anything.  I don't know what I'm doing wrong.

Arduino
Code: [Select]
#include "FastLED.h"

#define NUM_LEDS 75
#define LED_DATA_PIN 6
#define NUM_BYTES (NUM_LEDS*3) // 3 colors 

#define BRIGHTNESS 100

byte MESSAGE_PREAMBLE[] = { 211, 10, 137};
uint8_t PREAMBLE_LENGTH = 3;
uint8_t current_preamble_position = 0;

uint8_t led_counter = 0;
uint8_t byte_counter = 0;

CRGB leds[NUM_LEDS];
byte buffer[NUM_BYTES]; // buffer for pixels


//for MSGEQ5
int STROBE_PIN = 4;
int RESET_PIN = 2;
int EQIN_PIN = A0;
int bandValues[5];
int bandNo;

void readMSGEQ5()
{
  digitalWrite(RESET_PIN, HIGH);
  digitalWrite(RESET_PIN, LOW);
  delayMicroseconds(75);
 
  for (bandNo = 0; bandNo < 5; bandNo++)
  {
    digitalWrite(STROBE_PIN, LOW);
    delayMicroseconds(40);
    bandValues[bandNo] = analogRead(EQIN_PIN);
    digitalWrite(STROBE_PIN, HIGH);
    delayMicroseconds(40);
  }
}

void setup()
{
  pinMode(RESET_PIN, OUTPUT);//for MSGEQ5
  pinMode(STROBE_PIN, OUTPUT);


  Serial.begin(1000000); // Maximal speed
  FastLED.clear(true);
  FastLED.addLeds<WS2811, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);

 
  for(;;)
  {
   
    while (current_preamble_position < PREAMBLE_LENGTH) // waiting for preamble and sending data from MSGEQ5
    {
      if (Serial.available() > 0)
      {
        if (Serial.read() == MESSAGE_PREAMBLE[current_preamble_position])
        {
          current_preamble_position++;
        }
        else
        {
          current_preamble_position = 0;
        }
      }else
      {
       
        Serial.write(bandValues[0]/4);// send data from MSGEQ5
        Serial.write(bandValues[1]/4);
        Serial.write(bandValues[2]/4);
        Serial.write(bandValues[3]/4);
        Serial.write(bandValues[4]/4);
        Serial.write(10);//send that i'm ready to recive, MSGEQ5 never give values smaller than 60
       }
    }
    current_preamble_position = 0;
    Serial.readBytes(buffer, NUM_BYTES);//receiving array

    while (byte_counter < NUM_BYTES)
    {
      leds[led_counter++] = CRGB(buffer[byte_counter++], buffer[byte_counter++], buffer[byte_counter++]);
    }

    FastLED.show();
   
    readMSGEQ5();

    byte_counter = 0;
    led_counter = 0;
  }
}

void loop()
{
}


Processing
Code: [Select]
import processing.serial.*;

Serial port;
byte preamble[]= new byte[3];
byte out[]  = new byte[225];
byte in[]  = new byte[6];

int sendNext=1;

int j=0;//for rainbow
int w=0;

void setup(){
  String portName = Serial.list()[0];
  port = new Serial(this, portName, 1000000);
 
  port.bufferUntil(10);
 
  preamble[0]=(byte)211;
  preamble[1]=(byte)10;
  preamble[2]=(byte)137;
}


void draw() {
 
  for(int a=0;a<1;)//to have more FPS than window
  {
        if(sendNext==1)
        {
         
          a++;
          colorMode(HSB, 1440);// Setting to HSB to make easy rainbow, 1440 is for better aquracy
          if(j==1440)
          {
              j=0;
          }
          j++;
 
          for(int i=0; i<75; i++)
          {
             w=i+j;
             if(i+j>1440)
             {
                 w=w-1440;
             }
             out[(i*3)]=(byte)(red(color(w, 1440, 1440))/5.8);
             out[(i*3)+1]=(byte)(green(color(w, 1440, 1440))/5.8);
             out[(i*3)+2]=(byte)(blue(color(w, 1440, 1440))/5.8);
          }
         
          if(port != null) // sending array
          {
              port.write(preamble);
              port.write(out);
          }
          sendNext=0;
       }
  }
 println(frameRate);
}

void serialEvent( Serial port) {
       sendNext=1;
       in=port.readBytesUntil(10);
       
}

A7243618X

I improved my code. Now it's working. The reason that I have problem with code in post above must be because I never program in java before.

Now program is sending reconnection message every 2 second and is checking if correct data were recived.

But I can't set baudrate to 2000000 bits per second.

Arduino
Code: [Select]
#include "FastLED.h"

#define NUM_LEDS 75
#define LED_DATA_PIN 6
#define NUM_BYTES (NUM_LEDS*3) // 3 colors 

#define BRIGHTNESS 100

byte MESSAGE_PREAMBLE[] = { 211, 10, 137};
uint8_t PREAMBLE_LENGTH = 3;
uint8_t current_preamble_position = 0;

uint8_t led_counter = 0;
uint8_t byte_counter = 0;

CRGB leds[NUM_LEDS];
byte buffer[NUM_BYTES+1]; // buffer for pixels and end char


//for MSGEQ5
int STROBE_PIN = 4;
int RESET_PIN = 2;
int EQIN_PIN = A0;
int bandValues[5];
int bandNo;

long int lastConnectionTime=0;

void readMSGEQ5()
{
  digitalWrite(RESET_PIN, HIGH);
  digitalWrite(RESET_PIN, LOW);
  delayMicroseconds(75);
 
  for (bandNo = 0; bandNo < 5; bandNo++)
  {
    digitalWrite(STROBE_PIN, LOW);
    delayMicroseconds(40);
    bandValues[bandNo] = analogRead(EQIN_PIN);
    digitalWrite(STROBE_PIN, HIGH);
    delayMicroseconds(40);
  }
}

void setup()
{
  pinMode(RESET_PIN, OUTPUT);//for MSGEQ5
  pinMode(STROBE_PIN, OUTPUT);


  Serial.begin(1000000); // Maximal speed
  FastLED.clear(true);
  FastLED.addLeds<WS2811, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);

  readMSGEQ5();
 
  for(;;)
  {
   
    while (current_preamble_position < PREAMBLE_LENGTH) // waiting for preamble and sending data from MSGEQ5
    {
      if (Serial.available() > 0)
      {
        if (Serial.read() == MESSAGE_PREAMBLE[current_preamble_position])
        {
          current_preamble_position++;
        }
        else
        {
          current_preamble_position = 0;
        }
      }else
      {
        if(millis()-lastConnectionTime>2000)
        {
          lastConnectionTime=millis();
          Serial.write(9);
          Serial.write(bandValues[0]/4);// send data from MSGEQ5
          Serial.write(bandValues[1]/4);
          Serial.write(bandValues[2]/4);
          Serial.write(bandValues[3]/4);
          Serial.write(bandValues[4]/4);
          Serial.write(10);//send that i'm ready to recive, MSGEQ5 never give values smaller than 60
        }
       }
    }
    current_preamble_position = 0;
    Serial.readBytes(buffer, NUM_BYTES+1);//receiving array

    while (byte_counter < NUM_BYTES)
    {
      leds[led_counter++] = CRGB(buffer[byte_counter++], buffer[byte_counter++], buffer[byte_counter++]);
    }

    if(buffer[NUM_BYTES]=='>')// showing only correct frames, checking if last char is endchar
      FastLED.show();
   
    readMSGEQ5();
    lastConnectionTime=millis();

    byte_counter = 0;
    led_counter = 0;
    Serial.write(9);
    Serial.write(bandValues[0]/4);// send data from MSGEQ5
    Serial.write(bandValues[1]/4);
    Serial.write(bandValues[2]/4);
    Serial.write(bandValues[3]/4);
    Serial.write(bandValues[4]/4);
    Serial.write(10);//send that i'm ready to recive, MSGEQ5 never give values smaller than 60
  }
}

void loop()
{
}


Processing
Code: [Select]
import processing.serial.*;

Serial port;
byte preamble[]= new byte[3];
byte out[]  = new byte[226];
byte in[];

int j=0;//for rainbow
int w=0;

void setup(){
  String portName = Serial.list()[0];
  port = new Serial(this, portName, 1000000);
 
  port.bufferUntil(10);
 
  preamble[0]=(byte)211;
  preamble[1]=(byte)10;
  preamble[2]=(byte)137;
  out[225]='>';
}


void draw() {
 
 println(frameRate);
}

void serialEvent(Serial port)
{
  in = port.readBytesUntil(10);
  if(in.length==7)// cheking  if I recived everything
  if(in[0]==9&&in[6]==10)
        println(in);
  port.write(preamble);
  port.write(out); // Issue data to Arduino
 
  //making new frame
  colorMode(HSB, 1440);// Setting to HSB to make easy rainbow, 1440 is for better accuracy
  if(j==1440)
  {
      j=0;
  }
  j++;
 
  for(int i=0; i<75; i++)
  {
      w=i+j;
      if(i+j>1440)
      {
           w=w-1440;
      }
      out[(i*3)]=(byte)(red(color(w, 1440, 1440))/5.8);
      out[(i*3)+1]=(byte)(green(color(w, 1440, 1440))/5.8);
      out[(i*3)+2]=(byte)(blue(color(w, 1440, 1440))/5.8);
  }
}

Go Up