Loop function messes up code! OSC, DMX, Ethernet

Hi all

I am using the following code to control via OSC some DMX controllers. I also use the Ethernet shield and it works until I use the following code.

So in the code I want to send a number that defines the Mode (manual, automatic/mood color, all close, all open). It is possible to choose mode 0 (all close), then mode 1 (manual color from my Processing interface), however when I go to mode 2, everything gets messed up. I can't choose any other mode, and everything sort of stuck!!!! It seems like the RGB[3] array does not reset to 0 and keeps counting on. How can I stop it?

Am I doing something wrong? I believe the problem is somewhere in the loop() function.

Please have a look (I have sort of included just the basic stuff). Cheers!

(Using Arduino 0.22 IDE, Z_OSC library, and DMXSimple)

#include <SPI.h>
#include <Ethernet.h> // version IDE 0022
#include <Z_OSC.h>
#include <DmxSimple.h>

#define RED_CH_1 1
#define GRN_CH_1 2
#define BLU_CH_1 3
#define ALPHA_CH_1 4

#define RED_CH_2 5
#define GRN_CH_2 6
#define BLU_CH_2 7
#define ALPHA_CH_2 8

#define RED_CH_3 9
#define GRN_CH_3 10
#define BLU_CH_3 11
#define ALPHA_CH_3 12

float RGB[3];

int DMX_dir = 2;
int LED2 = 8;
int LED3 = 7;
int mode, finalRed1, finalGreen1, finalBlue1, red1, green1, blue1, red2, green2, blue2, 
red3, green3, blue3, redMood1, greenMood1, blueMood1, redMood2, greenMood2, blueMood2, 
redMood3, greenMood3, blueMood3, alpha1, alpha2, alpha3 = 0;

byte myMac[] = { 
  0x90, 0xA2, 0xDA, 0x00, 0x54, 0x94 };
byte myIp[]  = { 
  141,163,187,151 };
int  serverPort  = 10000;

Z_OSCServer server;
Z_OSCMessage *rcvMes;

void setup(){ 
  Serial.begin(19200);
  Ethernet.begin(myMac ,myIp); 
  server.sockOpen(serverPort);

  pinMode(DMX_dir, OUTPUT);    
  pinMode(LED2, OUTPUT);       
  digitalWrite(DMX_dir, LOW);  // Set direction pin of trasnsceiver to Tx.
  DmxSimple.usePin(2);
  
  for (int i=0; i<3;i++){
    RGB[i] = 0; 
  }
}

void loop(){
  if(server.available()){
    rcvMes=server.getMessage();
    logMessage();
  }

  switch (mode){
  case 0:
    RGB[0] = 0;
    RGB[1] = 0;
    RGB[2] = 0;
    finalRed1 = 0;
    finalGreen1 = 0;
    finalBlue1 = 0;
    break;

  case 1:
    RGB[0] = 0;
    RGB[1] = 0;
    RGB[2] = 0;
    finalRed1 = red1;
    finalGreen1 = green1;
    finalBlue1 = blue1;
    break;

  case 2:
    for (float x=0;x<PI;x=x+0.00001){
      RGB[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led

      //        for(int i=0;i<3;i++){
      //          if(RGB[i]<1){
      //            delay(100);
      //          }
      //          if(RGB[i]<5){
      //            delay(50);
      //          }
      //          if(RGB[i]<10){
      //            delay(10);
      //          }
      //          if(RGB[i]<100){
      //            delay(5);
      //          }
    }
    finalRed1 = int (RGB[0]);
    finalGreen1 = int (RGB[1]);
    finalBlue1 = int (RGB[2]);
    //delay(1);
    break;

  }

  digitalWrite(LED2, HIGH);
  DmxSimple.write(RED_CH_1, finalRed1);
  DmxSimple.write(GRN_CH_1, finalGreen1);
  DmxSimple.write(BLU_CH_1, finalBlue1);
  delay(5);
}

void logMessage(){
  uint16_t i;
  byte *ip = rcvMes->getIpAddress();
  long int intValue;
  float floatValue;
  int rcvRed1, rcvGreen1, rcvBlue1, rcvAlpha1;
  char *stringValue;
  int rcvMode;

  for(i=0 ; i<rcvMes->getArgsNum(); i++){
    switch( rcvMes->getTypeTag(i) ){
    case 'i':        
      intValue = rcvMes->getInteger32(i);
      String modemsg = "/mode/";
      String red1msg = "/red1/";
      String green1msg = "/green1/";
      String blue1msg = "/blue1/";  

      if (modemsg==rcvMes->getZ_OSCAddress()){
        rcvMode = rcvMes->getInteger32(0);
        Serial.print("Mode: ");
        Serial.println(rcvMode);
        mode = rcvMode;
      }
      if (red1msg==rcvMes->getZ_OSCAddress()){
        rcvRed1 = rcvMes->getInteger32(0);
        Serial.print("red1: ");
        Serial.println(rcvRed1);
        red1 = rcvRed1;
      }
      if (green1msg==rcvMes->getZ_OSCAddress()){
        rcvGreen1 = rcvMes->getInteger32(0);
        Serial.print("green1: ");
        Serial.println(rcvGreen1);
        green1 = rcvGreen1;
      }
      if (blue1msg==rcvMes->getZ_OSCAddress()){
        rcvBlue1 = rcvMes->getInteger32(0);
        Serial.print("blue1: ");
        Serial.println(rcvBlue1);
        blue1 = rcvBlue1;
      }

If you put each { on a new line, and use Tools + Auto Format (and delete commented out code), you have:

    for (float x=0;x<PI;x=x+0.00001)
    {
      RGB[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led

      //        for(int i=0;i<3;i++){
    }

Looping a bazillion times to calculate one trio of values doesn't appear to make much sense.

It is supposed to be calculated constantly as this is the Auto/Mood function for the color - that means that it changes constantly randomly for the red, green, and blue to create this light effect.

Therefore, this needs to run continuously but ONLY when Mode 2 is selected. This keeps running even if I then change to Mode 0 or 1, which is weird because I set static values for RGB[3] which is 0.

The code you posted is incomplete. The { and } are not in matched pairs. Those that are present do not line up.

So as I suggested, and put each { on its own line. Use Tools + Auto Format to properly indent the code. And, post code that will compile. Otherwise, we can't help you.

Once you go to mode 2 and hit that for loop it is going to take a very long time to count up to PI by 0.00001 steps. So you're goingt o be hung in that for loop for a very long time. You could either ditch the for loop and take advantage of the fact that the loop() function is being called over and over or you could add something to that for loop that does a check of a button or whatever that will let you break out of it.

Otherwise, as written, you're stuck waiting for it to count all the way up to PI which will take a little more than 300,000 turns of that for loop.

Ok, so I checked the code - just two "{" missing, so sorry about that. If you want I can make a version that you set the Mode from the Serial Command Line.

Delta_G suggested to "ditch the for loop", however this is the function that I want the program to do. What are other alternatives? How can I simulate this?

Thanks.

(mood code was taken from here > http://www.instructables.com/id/Mood-Lamp-with-Arduino/?ALLSTEPS)

#include <SPI.h>
#include <Ethernet.h> // version IDE 0022
#include <Z_OSC.h>
#include <DmxSimple.h>

#define RED_CH_1 1
#define GRN_CH_1 2
#define BLU_CH_1 3
#define ALPHA_CH_1 4

float RGB[3];

int DMX_dir = 2;
int LED2 = 8;
int LED3 = 7;
int mode, finalRed1, finalGreen1, finalBlue1, red1, green1, blue1, redMood1, greenMood1, blueMood1 = 0;

byte myMac[] = { 
  //set your ethernet mac address
  0x90, 0xA2, 0xDA, 0x00, 0x54, 0x94 };
byte myIp[]  = { 
  //set your ip address
  141,163,187,151 };
int  serverPort  = 10000;

Z_OSCServer server;
Z_OSCMessage *rcvMes;

void setup(){ 
  Serial.begin(19200);
  Ethernet.begin(myMac ,myIp); 
  server.sockOpen(serverPort);

  pinMode(DMX_dir, OUTPUT);    
  pinMode(LED2, OUTPUT);       
  digitalWrite(DMX_dir, LOW);  // Set direction pin of trasnsceiver to Tx.
  DmxSimple.usePin(2);

  for (int i=0; i<3;i++){
    RGB[i] = 0; 
  }
}

void loop(){
  if(server.available()){
    rcvMes=server.getMessage();
    logMessage();
  }

  switch (mode){
  case 0:
    RGB[0] = 0;
    RGB[1] = 0;
    RGB[2] = 0;
    finalRed1 = 0;
    finalGreen1 = 0;
    finalBlue1 = 0;
    break;

  case 1:
    RGB[0] = 0;
    RGB[1] = 0;
    RGB[2] = 0;
    finalRed1 = red1;
    finalGreen1 = green1;
    finalBlue1 = blue1;
    break;

  case 2:
    for (float x=0;x<PI;x=x+0.00001){
      RGB[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led
    }
    finalRed1 = int (RGB[0]);
    finalGreen1 = int (RGB[1]);
    finalBlue1 = int (RGB[2]);
    //delay(1);
    break;
  }

  digitalWrite(LED2, HIGH);
  DmxSimple.write(RED_CH_1, finalRed1);
  DmxSimple.write(GRN_CH_1, finalGreen1);
  DmxSimple.write(BLU_CH_1, finalBlue1);
  delay(5);
}

void logMessage(){
  uint16_t i;
  byte *ip = rcvMes->getIpAddress();
  long int intValue;
  float floatValue;
  int rcvRed1, rcvGreen1, rcvBlue1, rcvAlpha1;
  char *stringValue;
  int rcvMode;

  for(i=0 ; i<rcvMes->getArgsNum(); i++){
    switch( rcvMes->getTypeTag(i) ){
    case 'i':        
      intValue = rcvMes->getInteger32(i);
      String modemsg = "/mode/";
      String red1msg = "/red1/";
      String green1msg = "/green1/";
      String blue1msg = "/blue1/";  

      if (modemsg==rcvMes->getZ_OSCAddress()){
        rcvMode = rcvMes->getInteger32(0);
        Serial.print("Mode: ");
        Serial.println(rcvMode);
        mode = rcvMode;
      }
      if (red1msg==rcvMes->getZ_OSCAddress()){
        rcvRed1 = rcvMes->getInteger32(0);
        Serial.print("red1: ");
        Serial.println(rcvRed1);
        red1 = rcvRed1;
      }
      if (green1msg==rcvMes->getZ_OSCAddress()){
        rcvGreen1 = rcvMes->getInteger32(0);
        Serial.print("green1: ");
        Serial.println(rcvGreen1);
        green1 = rcvGreen1;
      }
      if (blue1msg==rcvMes->getZ_OSCAddress()){
        rcvBlue1 = rcvMes->getInteger32(0);
        Serial.print("blue1: ");
        Serial.println(rcvBlue1);
        blue1 = rcvBlue1;
      }
      break;
    }
  }
}

Update

Changed the switch function to while and if. Still no way to escape the for loop. I am sure there is a way that you can exit this.

Any thoughts?

Still no way to escape the for loop. I am sure there is a way that you can exit this.

break

Hi again,

I have tried to use break but it does not escape the loop If I use the incremental variable that it is inside the loop it works (when the RGB[0] reaches a specific level).

However this is not any useful, as I want to control this for loop from outside, i.e. via OSC. When I change the variable to mode (which is the control variable that I want to use), nothing appears in the Serial print.....it is like the for loop overpowers this command, therefore I can't accept it to stop the for loop

Here is the part of the code:

case 2:
    for (float x=0;x<PI;x=x+0.00001){
      RGB[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led

      Serial.println(RGB[0]);
      
      //If the mode (control variable via OSC) is 1, break the for loop - however this does not work
      //If I use both the mode and the RGB[O] variables, does not work either
      //It only breaks when I use the RGB[0], which is within the for loop - not useful in my case

      if(mode == 1 && RGB[0] > 254.){
        break;
        //delay(10);
      }
    }
    break;
case 2:
    for (float x=0;x<PI;x=x+0.00001){
      RGB[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led

      Serial.println(RGB[0]);
      
      //If the mode (control variable via OSC) is 1, break the for loop - however this does not work
      //If I use both the mode and the RGB[O] variables, does not work either
      //It only breaks when I use the RGB[0], which is within the for loop - not useful in my case

      if(mode == 1 && RGB[0] > 254.){

mode will never be 2 in this case statement.

When are you going to do as you are told and put the { on a new line?

Your for loop still iterates 300,000 times accomplishing zip.

PaulS,

Either you are saying something that I can't understand, or that I am trying to do something that you don't understand.

You say that mode variable will never be 2, however this is not a problem, as I see the variable changing in my Serial Monitor with no problem. The problem is when it goes to 2, and the for loop starts running.

You say that I should do as I was told, and that is put a { in a new line. First, I don't know which { you mean, and second of all, I don't see how this affects anything. Again the problem is stopping the for loop.

Then you say that my loop iterates 300,000 times. Exactly, I need this to iterate continuously to achieve this effect. And again, it is this iteration that I want to exit when I receive an incoming signal.

Thanks for your comments, but still I have a problem I can't fix.

You say that mode variable will never be 2, however this is not a problem,

You've arrived in a case that requires "mode" to be 2, then you're testing it to see if it is 1.
As PaulS quite rightly said, that is not going to happen, even if he spelled 1 wrong.

Alright, got cha!

So, just to inform you that if I wait for a couple of minutes, the mode variable changes back to 1, 0 or whatever. Which means that the only problem is that I can't escape the for loop instantly - I have to wait.

I don't know if there is a workaround that I don't see.

Best.

LB

Which means that the only problem is that I can't escape the for loop instantly - I have to wait.

No, you can escape the loop whenever you want. The problem is that the loop you have does nothing but waste time. While you are spinning in that for loop, wasting time, only interrupts happen.

You REALLY need to explain the purpose of that waste of time loop.

Check this post:

And also see it practice here:

So the loop needs to keep running to change the color continuously.

Merci.

So the loop needs to keep running to change the color continuously.

Yes, but show me where your loop applies the new values to the LEDs.

What the for loop does, is to create an incremental float that is stored into RGB1 (RGB1[0] is the red value of the LED). I then pass this RGB1[0] to a second variable named finalRed1 within the same for loop like this:

  • finalRed1 = int (RGB1[0]);*
    Then I use the following code to pass this value to the DMX output in the main loop() function
  • digitalWrite(LED2, HIGH);*
  • DmxSimple.write(RED_CH_1, finalRed1);*
  • DmxSimple.write(GRN_CH_1, finalGreen1);*
  • DmxSimple.write(BLU_CH_1, finalBlue1);*
  • delay(5);*
    Ok, so here I changed almost everything just to demonstrate the loop problem. I also got rid all the dependancies, so you can run the example (I use 0.22 IDE). When you open the Serial Monitor enter 0/,1/,2/ or 3/ and hit enter. This will print the current case you selected. You will notice that this works fine, until you go to case 2. Then the program stucks - if you try to enter a new case value (i.e. to exit case 2), nothing happens because of the for loop.
    I seriously don't know a better way to demonstrate the problem. I hope someone can help.
    Thnx.
    ```
    *#define RED_CH_1 1
    #define GRN_CH_1 2
    #define BLU_CH_1 3

float RGB1[3];

int inbyte;
boolean stopLoop = true;
int serialNumber = 0;
unsigned long serialdata;

int DMX_dir = 2;
int LED2 = 8;
int LED3 = 7;
int mode, finalRed1, finalGreen1, finalBlue1,  red1, green1, blue1,
   redMood1, greenMood1, blueMood1 = 0;

void setup(){
 Serial.begin(9600);

for (int i=0; i<3;i++)
 {
   RGB1[i] = 0;
 }
}

void loop(){
 Serial.read();
 getSerial();
 Serial.println(serialdata);

switch (serialdata)
 {
 case 0:
   Serial.println("Case 0");
   stopLoop = true;
   RGB1[0], RGB1[1], RGB1[2] = 0.;
   finalRed1, finalGreen1, finalBlue1 = 0;
   break;

case 1:
   Serial.println("Case 1");
   stopLoop = true;
   RGB1[0], RGB1[1], RGB1[2] = 0.;
   finalRed1 = red1;
   finalGreen1 = green1;
   finalBlue1 = blue1;
   break;

case 2:
   Serial.println("Case 2");
   stopLoop = false;
   for (float x=0;x<PI;x=x+0.00001)
   {
     RGB1[0] = 255abs(sin(x(180/PI)));           // calculate the brightness for the red led
     RGB1[1] = 255abs(sin((x+PI/3)(180/PI)));    // calculate the brightness for the green led
     RGB1[2] = 255abs(sin((x+(2PI)/3)*(180/PI)));// calculate the brightness for the blue led
   
     for(int i=0;i<3;i++){
       if(RGB1[i]<1){
         delay(100);
       }
       if(RGB1[i]<5){
         delay(50);
       }
       if(RGB1[i]<10){
         delay(10);
       }
       if(RGB1[i]<100){
         delay(5);
       }
     }

if(serialdata == 0 || serialdata == 1 || serialdata == 3)
     {
       break;
       //delay(10);
     }

finalRed1 = int (RGB1[0]);
     finalGreen1 = int (RGB1[1]);
     finalBlue1 = int (RGB1[2]);
     delay(1);
   }
   break;

case 3:
   Serial.println("Case 3");
   stopLoop = true;
   RGB1[0], RGB1[1], RGB1[2] = 0.;
   finalRed1, finalGreen1, finalBlue1 = 255;
   break;
 }
 Serial.println(finalRed1);
 delay(5);
}

long getSerial()
{
 serialdata = 0;
 while (inbyte != '/')
 {
   inbyte = Serial.read();
   if (inbyte > 0 && inbyte != '/')
   {
     serialdata = serialdata * 10 + inbyte - '0';
   }
 }
 inbyte = 0;
 return serialdata;
}*
```

RGB1[0], RGB1[1], RGB1[2] = 0.;

No, sorry.
That doesn't do what you think.

RGB1[0] = RGB1[1] = RGB1[2] = 0.;

Alright - although I don't think the problem is there - I have corrected it.

Same thing...loop is stuck...

#define RED_CH_1 1
#define GRN_CH_1 2
#define BLU_CH_1 3

float RGB1[3];

int inbyte;
boolean stopLoop = true;
int serialNumber = 0;
unsigned long serialdata;

int DMX_dir = 2;
int LED2 = 8;
int LED3 = 7;
int mode, finalRed1, finalGreen1, finalBlue1,  red1, green1, blue1, 
    redMood1, greenMood1, blueMood1 = 0;

void setup(){ 
  Serial.begin(9600);

  for (int i=0; i<3;i++)
  {
    RGB1[i] = 0;
  }
}

void loop(){
  Serial.read();
  getSerial();
  Serial.println(serialdata);

  switch (serialdata)
  {
  case 0:
    Serial.println("Case 0");
    stopLoop = true;
    RGB1[0]=0.;
    RGB1[1]=0.;
    RGB1[2]=0.;
    finalRed1, finalGreen1, finalBlue1 = 0;
    break;

  case 1:
    Serial.println("Case 1");
    stopLoop = true;
    RGB1[0]=0.;
    RGB1[1]=0.;
    RGB1[2]=0.;
    finalRed1 = red1; 
    finalGreen1 = green1; 
    finalBlue1 = blue1;
    break;

  case 2:
    Serial.println("Case 2");
    stopLoop = false;
    for (float x=0;x<PI;x=x+0.00001)
    {
      RGB1[0] = 255*abs(sin(x*(180/PI)));           // calculate the brightness for the red led
      RGB1[1] = 255*abs(sin((x+PI/3)*(180/PI)));    // calculate the brightness for the green led
      RGB1[2] = 255*abs(sin((x+(2*PI)/3)*(180/PI)));// calculate the brightness for the blue led
    
      for(int i=0;i<3;i++){
        if(RGB1[i]<1){
          delay(100);
        }
        if(RGB1[i]<5){
          delay(50);
        }
        if(RGB1[i]<10){
          delay(10);
        }
        if(RGB1[i]<100){
          delay(5);
        }
      }

      if(serialdata == 0 || serialdata == 1 || serialdata == 3)
      {
        break;
        //delay(10);
      }

      finalRed1 = int (RGB1[0]);
      finalGreen1 = int (RGB1[1]);
      finalBlue1 = int (RGB1[2]);
      delay(1);
    }
    break;

  case 3:
    Serial.println("Case 3");
    stopLoop = true;
    RGB1[0]=0.;
    RGB1[1]=0.;
    RGB1[2]=0.;
    finalRed1, finalGreen1, finalBlue1 = 255;
    break;
  }
  Serial.println(finalRed1);
  delay(5);
}

long getSerial()
{
  serialdata = 0;
  while (inbyte != '/')
  {
    inbyte = Serial.read(); 
    if (inbyte > 0 && inbyte != '/')
    {
      serialdata = serialdata * 10 + inbyte - '0';
    }
  }
  inbyte = 0;
  return serialdata;
}
for(int i=0;i<3;i++){
        if(RGB1[i]<1){
          delay(100);
        }
        if(RGB1[i]<5){
          delay(50);
        }
        if(RGB1[i]<10){
          delay(10);
        }

This I really do not understand.
You still seem to have a massive loop that achieves nothing.