randomly choose between loops and execute them.

I’m building an interactive moodtoy for my gf. It’s my first more elaborate project and now I have totally hit the wall.

If I run all the loops separately they work fine but when I put them together all i get is a blinking rgbLED that don’t follow any of the set parameters for any of the loops.

Sorry for the long sketch but it is only when I run the full sketch that the problem(s?) appear.

Probably more than one error in my code but it’s my first more complex sketch so have patients plz :wink:

//LEDpins
const int redLED = 9;
const int greenLED = 10;
const int blueLED = 11;

//LED info
int redLevel = 0;
int greenLevel = 0;
int blueLevel = 0;
float counter = 0;
float pi = 3.14159;


//SENSORpins
const int HALL = 2;
const int BALL = 3;
const int LIGHT = 4;

//other ints
int randomValue = 0;
int brightness = 0;
int fadeAmount = 5;

void setup(){
//LEDpins
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(blueLED, OUTPUT);

//Sensors
pinMode(HALL, INPUT);
pinMode(BALL, INPUT);
pinMode(LIGHT, INPUT);
}

//Start loop
void loop() {
  while (true) {
    MOOD();
  }
}

//Set the mood to 1 out of 4
void MOOD() {
 
// chance % for the moods
 int MOOD = random(100);
  
  if (MOOD <=3) {
    ANGRY();
  }
  
  if (MOOD > 3 && MOOD <= 10) {
    CALM();
  }
  
  if (MOOD > 10 && MOOD <= 20) {
    PLAY();
  }
  else
  {
    blendColors();
  }
}


//Main mood, should run 3 times and then go back to MOOD() but havent found out how to make it work yet. 
//I thought Arduino should get stuck here due to no way out of loop but it doesn't execute it as in the code (just fast, random blink without the color change effekt).
void blendColors() {
 
   // code for blendColors here 
  counter = counter + 1;
redLevel = sin(counter/100)*1000;
greenLevel = sin(counter/100 + pi*2/3)*1000;
blueLevel = sin(counter/100 + pi*4/3)*1000;
redLevel = map(redLevel,-1000,1000,0,100);
greenLevel = map(greenLevel,-1000,1000,0,100);
blueLevel = map(blueLevel,-1000,1000,0,100);
analogWrite(redLED,redLevel);
analogWrite(greenLED,greenLevel);
analogWrite(blueLED,blueLevel);
delay(10); 


}

// Angry MOOD, loop redLED fade util simultaneous input from two sensors = back to MOOD()
void ANGRY() {
 // code for ANGRY here
   // set the brightness of pin RED:
  analogWrite(redLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

  if (digitalRead (BALL) == HIGH && digitalRead (LIGHT) == HIGH)
  {
    MOOD();
  }
}

// Same as ANGRY but with one sensor.
void CALM() {
  // code for CALM here
   analogWrite(greenLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

if (digitalRead (BALL) == HIGH)
{
    MOOD();
}
  }

//Same as green
void PLAY() 
{
  // code for PLAY here
  analogWrite(blueLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) 
  {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

if (digitalRead (HALL) == HIGH)
{
    MOOD();
  }
}

I’ve spent 2 days on google trying to find a solution but still learning and it’s hard to find stuff you don’t know what it’s called (i.e. functions etc).

Hopefully I haven’t F-ed it from line one…

For starters, this

//Start loop
void loop() {
  while (true) {
    MOOD();
  }
}

does this

//Start loop
void loop() {
    MOOD();
}

…minus doing some serial updating that you are probably not using.

So MOOD can call ANGRY and then ANGRY can call MOOD.

That's not going to end well.

I'd draw yourself a flow chart. Ensure you loop the last "block" to the start.
Maybe this will help you see why you have made something a bit off...

You also see to be using a lot of if and while loops where a for loop is probably more useful?

 // code for ANGRY here
   // set the brightness of pin RED:
  analogWrite(redLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
for (byte i=0; i<255; i+=fade_amount){
analogWrite(redLED,i);
delay(30);
}
for (byte i=255; i>0; i-=fade_amount){
analogWrite(redLED,i);
delay(30);
}

@ aarg
thx. I had help setting up the loops. Couldn't find out why he had put the true there but didn't dare remove it...

@AWOL
Is it better to send the mood loops to the beginning i.e. void loop()?

I need the code to pick new random mood when exiting a mood loop (angry, calm, play).

@Johnny010
I have a chart on paper for all the functions but since I'm new to the code part (the hardware I ave set up already) it's not perfect. This is a case of learn by doing.
I use what I (kinda) understand. If is more straight forward and easier for me to comprehend.

Also I'm trying to do as much code as possible without just copy/paste. I wanna learn not just add finished code.

I've read 3 books on Arduino (MAKE: Getting started with Arduino, Arduino projects for dummies and a native (swedish) book). It's quite a leap to build from scratch I have to say ^^

I’d advise against using the byte datatype in comparisons involving signed numbers.

@AWOL
Is it better to send the mood loops to the beginning i.e. void loop()?

Just use return - avoid recursion

Won’t return just rerun the same loop again or does it return to the first loop post setup?

I’ve made the changes (still using the If code for LED fade though) named here but I still just get a erraticly blinking rgbLED when I run the sketch in full.

I just can’t see why since the blendColors() runs perfectly by itself and as I understand the code that’s just about all the sketch runs as is (no way of breaking the blendColors loop).

What am I missing?

It runs just fine like this so somethings ought to be wrong in the excluded code:

//LEDpins
const int redLED = 9;
const int greenLED = 10;
const int blueLED = 11;

//LED info
int redLevel = 0;
int greenLevel = 0;
int blueLevel = 0;
float counter = 0;
float pi = 3.14159;


//SENSORpins
const int HALL = 2;
const int BALL = 3;
const int LIGHT = 4;

//other ints
int randomValue = 0;
int brightness = 0;
int fadeAmount = 5;

void setup(){
//LEDpins
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(blueLED, OUTPUT);

//Sensors
pinMode(HALL, INPUT);
pinMode(BALL, INPUT);
pinMode(LIGHT, INPUT);
}

//Start loop
void loop() {
/*MOOD();
  
}

//Set the mood to 1 out of 4
void MOOD() {
  int MOOD = random(100);
  
  if (MOOD <=3) {
    ANGRY();
  }
  
  if (MOOD > 3 && MOOD <= 10) {
    CALM();
  }
  
  if (MOOD > 10 && MOOD <= 20) {
    PLAY();
  }
  else
  {
    blendColors();
  }
}


//Main mood, should run 3 times and then go back to MOOD() but havent found out how to make it work yet. 
//I thought Arduino should get stuck here due to no way out of loop but it doesn't execute it as in the code (just fast, random blink without the color change effekt).
void blendColors() {
 
   // code for blendColors here 
 */ counter = counter + 1;
redLevel = sin(counter/100)*1000;
greenLevel = sin(counter/100 + pi*2/3)*1000;
blueLevel = sin(counter/100 + pi*4/3)*1000;
redLevel = map(redLevel,-1000,1000,0,100);
greenLevel = map(greenLevel,-1000,1000,0,100);
blueLevel = map(blueLevel,-1000,1000,0,100);
analogWrite(redLED,redLevel);
analogWrite(greenLED,greenLevel);
analogWrite(blueLED,blueLevel);
delay(5); 


}

// Angry MOOD, loop redLED fade util simultaneous input from two sensors = back to MOOD()
void ANGRY() {
 // code for ANGRY here
   // set the brightness of pin RED:
  analogWrite(redLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

  if (digitalRead (BALL) == HIGH && digitalRead (LIGHT) == HIGH)
  {
    loop();
  }
}

// Same as ANGRY but with one sensor.
void CALM() {
  // code for CALM here
   analogWrite(greenLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

if (digitalRead (BALL) == HIGH)
{
    loop();
}
  }

//Same as green
void PLAY() 
{
  // code for PLAY here
  analogWrite(blueLED, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) 
  {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);

if (digitalRead (HALL) == HIGH)
{
    loop();
  }
}
  1. Why do you limit the analog writes to less than 1/2 the range they can do?
redLevel = map(redLevel,-1000,1000,0,100);
greenLevel = map(greenLevel,-1000,1000,0,100);
blueLevel = map(blueLevel,-1000,1000,0,100);

As commented now, you have all the functions commented out, no way for them to run.

This is not a good way to do this:

if (digitalRead (HALL) == HIGH)
{
    loop();
  }

Instead, try this:

void loop(){
if (digitalRead(HALL) == HIGH){
// all the stuff in loop() now
}

The fade rgb code works with the other stuff commented out but as soon as I add it to the code the rgb goes bananas. I just can't figure out why.

void loop(){
if (digitalRead(HALL) == HIGH){
// all the stuff in loop() now
}

Been thinking of that but the code will get loong.

Might as well try it, can't get much worse then now.