Help: Reading digital pins goes crazy

Hi, I'm having trouble with me code below where the digital pins/program goes crazy as soon as I activate the LedMoon function.

I'm trying to write a program to control 2 DMX lights using the Tinker DMX library.

All is working fine until I add the second light in the function LedMoon(). If I add this function, reading the same button and pot states as the function MartinMania() the LCD goes crazy and the program eventuall resets itself.... Why???

I cannot seem to find the error here, cuz i do basically the same as in the MartinMania function. perhaps I'm missing something here?

I just assume that I can use the same buttons in different functios to read the digital state, I don't see why that cannot be done right?

All code is build around a simpe menu which you can see below.

Can anyone see why it goes wrong?

Below part of my code... I've deleted some lines but you get the essentials....

#include <DmxSimple.h  
#include <LiquidCrystal.h>             

byte arrow[8] = {
  B00000,
  B01000,
  B01100,
  B01110,
  B01111,
  B01110,
  B01100,
  B01000,
};

LiquidCrystal lcd(12, 11, 8, 7, 6, 5);    

int PanValue = 0;                        
int TiltValue = 0;                        
int Intensity = 0;                        
int ColorValue = 0;                      
int GoboValue = 0;                        
int MacroValue = 250;                     
int LedColorValue = 10;                   

int NextValue = 0;

int inputPin1 = 9;                        
int inputPin2 = 4;                        
int inputPin3 = 10;                       
int inputPin4 = 2;                        
int inputPin5 = 0;                        

int pin1 = 0;                             
int pin2 = 0;                             
int pin3 = 0;                             
Int pin4 = 0;
int pin5 = 0;                             

int PanValuePrev = 0;                     
int TiltValuePrev = 0;                   
int IntensityPrev = 0;                   


void setup() {
  DmxSimple.maxChannel(20);              
  
  lcd.createChar(0, arrow);
  
  lcd.begin(20, 4);                      
  
  // Setup the first menu
  lcd.setCursor(0, 0); lcd.print("     Main Menu      ");
  lcd.setCursor(1, 1); lcd.print("Martin Mania       ");
  lcd.setCursor(1, 2); lcd.print("LED Moon           ");
  
  pinMode(inputPin1, INPUT);              
  pinMode(inputPin2, INPUT);              
  pinMode(inputPin3, INPUT);              
  pinMode(inputPin4, INPUT);              
  pinMode(inputPin5, INPUT);              
  
  digitalWrite(inputPin1, HIGH);          // pushbutton HIGH so u dont need pullup resistor
  digitalWrite(inputPin2, HIGH);          
  digitalWrite(inputPin3, HIGH);          
  digitalWrite(inputPin4, HIGH);          
  digitalWrite(inputPin5, HIGH);         
}

void loop(){
  Selection();
}

//***************************************************************************************************************

void Selection(){
  pin1 = digitalRead(inputPin1);    
  pin2 = digitalRead(inputPin2);
  pin4 = digitalRead(inputPin4);
  delay(300); 
  if (pin2 == LOW && NextValue <= 2){NextValue++;}
  if (pin1 == LOW && NextValue >= 0){NextValue--;}
    switch(NextValue){
      case 1 :  lcd.setCursor (0, 1); lcd.write(0);
                lcd.setCursor (0, 2); lcd.print(" ");
                if (pin4 == LOW){MartinMania();} break;
      case 2 :  lcd.setCursor (0, 1); lcd.print(" "); 
                lcd.setCursor (0, 2); lcd.write(0);
                if (pin4 == LOW){LedMoon();} break;
    }
}

//***************************************************************************************************************

void MainMenu(){
  lcd.clear();
  lcd.setCursor(0, 0); lcd.print("     Main Menu      ");
  lcd.setCursor(1, 1); lcd.print("Martin Mania       ");
  lcd.setCursor(1, 2); lcd.print("LED Moon           ");
}

//***************************************************************************************************************

void MartinMania() {
  pin5 = digitalRead(inputPin5);
  lcd.clear();
  lcd.setCursor(4, 0); lcd.print("Martin Mania");              
  lcd.setCursor(0, 1); lcd.print("Wit                 ");     
  lcd.setCursor(0, 2); lcd.print("Open                ");    
  lcd.setCursor(0, 3); lcd.print("No Macros running   ");  
  while (pin5 != LOW){
    pin5 = digitalRead(inputPin5);
        
    // Left - Right orientation section
    PanValue = map(analogRead(A0),0, 1023, 0, 254); 
    // Make sure the potvalue reading is stable by adding an slight tollerance 
    if ((PanValue > PanValuePrev + 4) || (PanValue < PanValuePrev - 4)) {
      PanValuePrev = PanValue;
      DmxSimple.write(5, PanValue);         // Write Output to DMX Channel 5
   }
  
  pin1 = digitalRead(inputPin1);           // Set val to wait for button press
  pin2 = digitalRead(inputPin2);           // Set val to wait for button press
  pin3 = digitalRead(inputPin3);           // Set val to wait for button press
  pin4 = digitalRead(inputPin4); 
  
  if (pin1 == LOW) {                       // Only when button is pressed do the following:
    ColorValue = ColorValue + 6;           // Add 6 to select the next color
    if (ColorValue == 204){                  // Last color is at value 204, so when this is reached
      ColorValue = 0;                       // Set value back to 0 when loop starts again
    }
    lcd.setCursor(0, 1);
    switch(ColorValue) {
      case 0   : lcd.print("Wit                 "); break;
      case 6   : lcd.print("Wit/Blauw           "); break;
      case 12  : lcd.print("Blauw               "); break;
      case 18  : lcd.print("Blauw/Oranje        "); break;
      case 24  : lcd.print("Oranje              "); break;

      Etc etc etc....


    }
    delay(100);                              // Delay for the button press to finish properly
  }
  if (pin4 == LOW){
    DmxSimple.write(3, ColorValue);          // Sent color to DMX channel 3
  }
  MainMenu();
  loop();
}

//***************************************************************************************************************

void LedMoon(){

  pin5 = digitalRead(inputPin5);
  
  lcd.clear();
  lcd.setCursor(0, 0); lcd.print("      Led Moon      ");
  lcd.setCursor(0, 1); lcd.print("No Light            ");
  lcd.setCursor(0, 2); lcd.print("No Sequence         ");
  
  while (pin5 != LOW){
    pin5 = digitalRead(inputPin5);
    
    // Light intensity section
    Intensity = map(analogRead(A2), 0, 1023, 254, 0);  
    // Make sure the potvalue reading is stable by adding an slight tollerance 
    if ((Intensity > IntensityPrev + 4) || (Intensity < IntensityPrev - 4)) {
      IntensityPrev = Intensity; 
      DmxSimple.write(19, Intensity);        // Write Output to DMX Channel 2
    }
    DmxSimple.write(11, 45);
    
    pin1 = digitalRead(inputPin1);           // Set val to wait for button press
    pin2 = digitalRead(inputPin2);           // Set val to wait for button press
    pin3 = digitalRead(inputPin3);           // Set val to wait for button press
    pin4 = digitalRead(inputPin4);           // Set val to wait for button press
    
    if (pin1 == LOW) {                       // Only when button is pressed do the following:
      LedColorValue = LedColorValue + 6;     // Add 6 to select the next color
      if (LedColorValue >= 45){              // Last color is at value 204, so when this is reached
        LedColorValue = 10;                  // Set value back to 0 when loop starts again
      }
      lcd.setCursor(0, 1);
      switch(LedColorValue) {
        case 16  : lcd.print("Rood                "); break;
        case 22  : lcd.print("Groen               "); break;
        case 28  : lcd.print("Blauw               "); break;
        case 34  : lcd.print("Geel                "); break;
        case 40  : lcd.print("Paars               "); break;
        case 46  : lcd.print("Azury               "); break;
        case 52  : lcd.print("All Colors          "); break;  
      }
    delay(100);                              // Delay for the button press to finish properly
    }
    if (pin4 == LOW){
      DmxSimple.write(11, LedColorValue);          // Sent color to DMX channel 3
    }

  }
  MainMenu();
  loop();  

}

Edit: Code posted incorrectly. Please use the # icon in future. AWOL.

Directly calling "loop" from another function is a Bad Thing.

Aren't you ending up in a circular thing there?

loop() calls Selection() which calls MartinMania() which calls loop()
or
loop() calls Selection() which calls LedMoon() which calls loop()

Don't do that. Don't mess with the loop :slight_smile:

Ah ok, the Arduino doesn't like that does it? :roll_eyes:

Cool, that probably explains why it goes crazy then. Will try and fix that and let you know if it did the trick....

Thanks for the tip!!

The arduino likes it just fine - I'm just not sure you're ending up in loop() quite when you think you are. Can you guarantee you're not ending up in an infinite recursion and overflowing the stack?

I think you are right, Now looking at the code again makes me realize it doesnt go back to loop() as I thought it would be....I just overlooked it and looked for something else going wrong and missed the loop() one..... Oops....

Every time a function gets called, a small amount of memory is used to store information on how to return from the function. If you keep calling functions, these small amounts add up and will overflow in memory and your functions never returning doesn't help either. It's like in your dream you fall into another dream, then in that dream you fall into another dream and deeper and deeper until you can not return to reality any more (Sorry I was watching total recall last night, twice).

Hmmm, ok, I've tried solving that issue but still not very successful...here is what I did .....

  • No more LOOP(); reference anymore in the function
  • in LOOP(); I'm not calling the function Selection any longer

So this is what the code in the LOOP() looks like now...

void loop(){
  pin1 = digitalRead(inputPin1);    
  pin2 = digitalRead(inputPin2);
  pin4 = digitalRead(inputPin4);
  delay(100); 
  if (pin2 == LOW && NextValue <= 2){NextValue++;}
  if (pin1 == LOW && NextValue >= 0){NextValue--;}
  switch(NextValue){
      case 1 :  lcd.setCursor (0, 1); lcd.write(0);
                lcd.setCursor (0, 2); lcd.print(" ");
                break;
      case 2 :  lcd.setCursor (0, 1); lcd.print(" "); 
                lcd.setCursor (0, 2); lcd.write(0);
                break;
    }
    if (pin4 == LOW && NextValue == 1){MartinMania();}
    if (pin4 == LOW && NextValue == 2){LedMoon();}
}

I think this should work right? It will return properly in the loop and continue with the reading of the button states for the main menu... please correct me if I'm wrong.

However, I can already tell you that it still doesn't work, so I did some more investigation and found that the problem might have to do with the Tinker.it DmxSimple.h library.

I'm setting the max channels as described in the in their tutorial of the available functions to 20..... DmxSimple.maxChannel(20);

However, when I remove this setting of the max channel my code works fine until I press the ENTER button after selecting and sending the DmxSimple.write to a DMX channel, then it goes all crazy again.

As soon as you include the DmxSimple.h library and your program starts running it sends data to DMX constantly. Some DMX lights also need that, so that's probably why this is set in the DMX library.

Did some more testing and found that you can set the DmxSimple.maxChannel also to 0, this doesn't sent any data to the DMX. So, when I set DmxSimple.maxChannel(0); in my code and for instance set DmxSimple.maxChannel(20); again just before I do a DmxSimple.write my program works perfectly... problem solved you would think... but it doesn't work because some DMX lights need to get some data every so many milliseconds.

So, if you agree that my adjusted code in the LOOP() is now correct, could it be that there is an issue with the DmxSimple Library??
I would find it strange if it is, cause that would mean more people would have an issue... I'm only controlling 2 lights at max 20 channels in total...

Hope someone can dig into this.... thanks so far for the tips, much appreciated!!

You don't have a case for NextValue == 0 or -1 - is this deliberate?

Yes, only when NextValue is 1 or 2 I want something to happen...

Did some more digging...read something about Timer 2 of the Arduino which is used in the DmxSimple.h library that could perhaps cause the issue... not sure yet... grrrrrr

Btw, changed that also last night... I know what you are saying here, cuz NextValue can also become 3 or -1, and I don't need those values... so it reads now...

  if (pin2 == LOW && NextValue < 2){NextValue++;}
  if (pin1 == LOW && NextValue > 0){NextValue--;}

Anyway, that still doesn't solve my issue... :frowning: