Go Down

Topic: run through 3 different programs with one button (Read 195 times) previous topic - next topic

SKELLA83

Hi

This is my first post on the forums. I do try to find the information out myself and learn as I go but I'm pretty much stuck at the moment.

I'm very new to coding for the Arduino but do a lot of php programming and I think I'm in php mode when trying to do if else statements, while loops, switch's etc and not quite sure if what im doing is correct.


Let me start by explaining what I want to do. I have built tried and tested an ac light flicker circuit. that works great. I have programmed 3 different modes that I want to be able to access with the push of a button. I left the coding for the flicker circuit out for now and concentrated on making 3 different modes that output their program names to an LCD. that all works fine as expected. I press a button and it will scroll through the different programs.


now this is where I get stuck, I have tried various different statements, if, where etc to loop through a very basic sequence. in this case I tried it with a blinking led with 3 different speed modes. First I was using delays and could not break out of a while loop. I did some more research and changed to milli and still could not break out. Looking at  my code below what is the best possible way for me to 'load in' my different programs? I would like to be able to use this on other projects so its not specific to my blinking led's or the actual; flicker circuit code but pretty much for anything.

so heres my code so far :

Code: [Select]
// include the library code:
#include <LiquidCrystal.h>


// LCD to pin number
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
const byte buttonPin = 7;            // pin button is connected
int buttonPushCounter = 0;           // counter for the number of button presses
boolean buttonState = LOW;           // current state of the button
boolean lastButtonState = LOW;       // previous state of the button
int led = 8;                         // pin LED is connected to


LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  Serial.begin(9600);
 
  lcd.begin(16, 2);                        // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("4WARD THEME WORX"); // load up screen text line 1
  lcd.setCursor(0, 1);
  lcd.print("LIGHT FLICKER V1"); // load up screen text line 2
 
  pinMode(buttonPin, INPUT);
  pinMode(led, OUTPUT);
}

void loop()
{
 
  buttonState = digitalRead(buttonPin);  // read the pushbutton input pin:
 
if (buttonState != lastButtonState)   // compare the buttonState to its previous state
  {
    if (buttonState == HIGH)
    {
      buttonPushCounter++;  // add one to counter
      lcd.clear(); 
      if (buttonPushCounter > 3) // if counter is over 3 reset the counter to 1 to show Program 1 and not load up text
                                 
      {
        buttonPushCounter = 1;
      }
     
      Serial.println(buttonPushCounter);

      if (buttonPushCounter == 1){
       
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P1 - FLICKER");
          }     
      else if (buttonPushCounter == 2){
           lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P2 - FLICKER");
      }
      else if (buttonPushCounter == 3){
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P3 - FLICKER");
      }
      else {
         lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("NO PROGRAM");
      }
    }
     lastButtonState = buttonState; // save the current state as the last state, for next time through the loop

}}



now what is the best way for me to insert my code like below :

Code: [Select]
if (buttonPushCounter == 1){
       
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P1 - FLICKER");

         
// INSERT CODE HERE //
   
          }     
      else if (buttonPushCounter == 2){
           lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P2 - FLICKER");


//INSERT CODE HERE //


      }
 else if (buttonPushCounter == 3){
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P3 - FLICKER");

//INSERT CODE HERE //

      }



And so on but be able to break out of each program and move on to the next each time the button is pressed?

Any ideas, guidance or help would be very much appreciated.

J-M-L

Are you getting rid of bouncing in hardware ?

(then you need to remember which program is "activated' and keep looping and testing the buttons. If what you do in your if/else is long then you won't  come back often to test if the button is pressed... system will feel slow to react )
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Idahowalker

#2
Dec 10, 2018, 03:48 am Last Edit: Dec 10, 2018, 03:50 am by Idahowalker
Code: [Select]

if (digitalRead(buttonPin))   
  {
      buttonPushCounter++;  // add one to counter
}
if (buttonPushCounter == 1)   
  {
      DoTheOneThing;
}
elif (buttonPushCounter == 2)   
  {
      DoTheTwoThing;
}
if (buttonPushCounter >= 3)
{
buttonPushCounter =0;
}

Or somthing like that.


SKELLA83

Are you getting rid of bouncing in hardware ?

(then you need to remember which program is "activated' and keep looping and testing the buttons. If what you do in your if/else is long then you won't  come back often to test if the button is pressed... system will feel slow to react )
I wasn't but I have now added some debounce code in there. I looked at various ways some using interrupts but the way I did it seemed pretty simple I just checked the status of the button 3 times with a small delay between each check

Code: [Select]
buttonState1 = digitalRead(buttonPin);
 delay(1);
 buttonState2 = digitalRead(buttonPin);  
 delay(1);
 buttonState3 = digitalRead(buttonPin);

 if ( (buttonState1 == buttonState2) && (buttonState1 == buttonState3) )
 {
if (buttonState1 != lastButtonState)   // compare the buttonState to its previous state
  {
    if (buttonState1 == HIGH)
    {
      buttonPushCounter++;  // add one to counter
      lcd.clear();  
      if (buttonPushCounter > 3) // if counter is over 3 reset the counter to 1 to show Program 1 and not load up text
                                
      {
        buttonPushCounter = 1;
      }
    
    }
    }
    }
    
    Program(); // run selected program based on button count
        
    lastButtonState = buttonState1; // save the current state as the last state, for next time through the loop

}



there maybe a better way of doing this but im still learning.


I did however manage to get my button to scroll through my 3 programs. I basically striped down the code and created functions for each program and everything worked nice. So I moved on to my next part of the project and that was implementing my code for the flicker programs. The program works well and does exactly what I want it to do. I will eventually make 3 variations of this program but for now I seem to be back to square one because now my button does not get detected to go to the next program. i'm not 100% sure why but I think because the whole sequence of the program is around 1min long the for loop inside the 'PowerSurge' function is running I can not break out of it. I have tried adding an if statement in ther and break the loop if the digitalRead(buttonPin) == HIGH but no joy. here is the new code :

Code: [Select]

#include <avr/pgmspace.h> // required for storing flicker dimmer levels table in PROGMEM
#include <LiquidCrystal.h> // required for LCD display
#define ON HIGH // define flicker outport ON
#define OFF LOW // define flicker outport OFF

const uint8_t OUTPORT1 = 13; // Pin out for Dimmer Gate
// Add more channel port defs here for multiple chanels.
const uint8_t STATPORT = 3;  // used for checking zero crossing on dimmer
const uint8_t REPEATS = 8; // used for dimmer

const uint8_t CHANNEL_1_TABLE[] PROGMEM =
  {
// had to remove lighting sequence as message exceeded maximum allowed length
  };

// Add more channel tables here, if desired. All must be the same length.

#define SIZE_TABLE ((uint16_t)(sizeof CHANNEL_1_TABLE / sizeof CHANNEL_1_TABLE[ 0 ] ))

volatile uint8_t isr_flag;
uint16_t table_index;
uint8_t half_cycle, brightness;
uint8_t table_1_value;
// Add more channel table value vars here.

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 6, d7 = 2; // LCD to pin number
const byte buttonPin = 7;            // pin button is connected
int buttonPushCounter = 0;           // counter for the number of button presses
boolean buttonState1 = LOW;          // current state of the button
boolean buttonState2 = LOW;          // current state of the button check 2
boolean buttonState3 = LOW;          // current state of the button check 3
boolean lastButtonState = LOW;       // previous state of the button
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void isr1()

  {
  isr_flag = 1U;
  }

void setup() {
 
  lcd.begin(16, 2);     // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("4WARD THEME WORX"); // load up screen text line 1
  lcd.setCursor(0, 1);
  lcd.print("LIGHT FLICKER V1"); // load up screen text line 2
  pinMode(buttonPin, INPUT);
  pinMode( STATPORT, INPUT ); // The input port detects power line zero-crossing for dimmer
  pinMode( OUTPORT1, OUTPUT );
  // Add more channel outputs here.

  digitalWrite( OUTPORT1, OFF );
  // Add more channel resets here.

  // set up zero crossing interrupt
  attachInterrupt( 1, isr1, RISING );
  interrupts();
}

// Wait for line zero crossing

void sync()

  {
  // wait until zero crossing detected (flag gets set)
  while (!isr_flag)
    ;

  // reset the flag
  isr_flag = 0U;

  // cancel all output drive
  digitalWrite( OUTPORT1, OFF );
  // Add more channel resets here.

  // wait for zero-cross end (pin to go low)
  while (digitalRead( STATPORT ))
    ;
  }

void loop()
{
 // do some swith debounce0
 
 buttonState1 = digitalRead(buttonPin);
 delay(1);
 buttonState2 = digitalRead(buttonPin);  
 delay(1);
 buttonState3 = digitalRead(buttonPin);

 if ( (buttonState1 == buttonState2) && (buttonState1 == buttonState3) )
 {
if (buttonState1 != lastButtonState)   // compare the buttonState to its previous state
  {
    if (buttonState1 == HIGH)
    {
      buttonPushCounter++;  // add one to counter
      lcd.clear();  
      if (buttonPushCounter > 3) // if counter is over 3 reset the counter to 1 to show Program 1 and not load up text
                                
      {
        buttonPushCounter = 1;
      }
    
    }
    }
    }
    
    Program(); // run selected program based on button count
        
    lastButtonState = buttonState1; // save the current state as the last state, for next time through the loop

}

//set up our programs

void Program(){
   if (buttonPushCounter == 1){    
      P1(); // Program 1
      }      
      else if (buttonPushCounter == 2){
      P2(); // Program 2
      }
      else if (buttonPushCounter == 3){
      P3();    // Program 3
      }
}
void P1(){ // program 1
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P1 - POWER SURGE");
          PowerSurge();          
}

void P2(){ // program 2
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P2 - HAUNTED");
          Haunted();
}

void P3(){ // program 3  
          lcd.setCursor(0, 0);
          lcd.print("4WARD THEME WORX");
          lcd.setCursor(0, 1);
          lcd.print("P3 - GENERATOR");
          Generator();
}


void PowerSurge()  {
  // Table loop
  for (table_index = 0; table_index < SIZE_TABLE; ++table_index)
    {
    table_1_value = pgm_read_byte(CHANNEL_1_TABLE + table_index);
    // Add more channel table value loads here.
    // All use same table index.

    // Number of power line half-cycles loop
    for (half_cycle = 0; half_cycle < REPEATS; ++half_cycle)   // repeat 'N' half-cycles
      {
      // wait for line zero-cross
      sync();

      // Trigger loop
      for (brightness = 15; brightness > 0; --brightness )   // 15 = bright, 0 = off
        {
        // Process channel trigger
        if (table_1_value == brightness)
          digitalWrite( OUTPORT1, ON );
        // Add more channel trigger processing here.

        delayMicroseconds( 500 );       // waste time (usec)
        }
      }  
    }
  
  }
  

 
 void Haunted(){
  
 }

 void Generator(){
  
 }




I'm really stuck on this at the moment so really appreciate any help

Go Up