Different modes in single sketch

I have few functionalities in the below sketch and now I want to switch between the functionalities if pin 2 is connected to GND pin once the code is executed completely then the mode1 should change to mode2. Note that I would like to use the same pins for both modes for different actions. For example PIN 2 in mode1 as input but PIN 2 in mode2 as output.

Please help me how to achieve this in a single sketch with atmega328P.

// Define pins

// for mode1
const int button_Pin = 2;     // Push-to-make switch input
const int sensor_Pin = 3;  
const int relay1_Pin = 4;
const int relay2_Pin = 5; 

// for mode2
const int sensor2_Pin = 2;  
const int relay3_Pin = 4;
const int relay4_Pin = 5; 

bool relayActive = false;
bool mode1 =true;

void setup() {
  pinMode(button_Pin, INPUT_PULLUP);
  pinMode(sensor_Pin, INPUT_PULLUP);
  pinMode(relay1_Pin, OUTPUT);
  pinMode(relay2_Pin, OUTPUT);

  digitalWrite(relay1_Pin, HIGH)
  digitalWrite(relay2_Pin, HIGH)
}

void loop() {
  
  sensorState = digitalRead(sensor_Pin) == LOW;
  buttonState = digitalRead(button_Pin);

  if (buttonState == LOW) {
    buttonPressed = !buttonPressed;
    if (buttonPressed) {
      relayActive = true;
    } 
  }
  lastButtonState = buttonState;

  if (!sensor1State) {
    turnOffRelays();
    relayActive = false;
  }

  if (relayActive) {
    handleRelayActions();
  }
 }
 
void turnOffRelays() {
  digitalWrite(relay1_Pin, HIGH);
  digitalWrite(relay2_Pin, HIGH);
}

void handleRelayActions() {
  if (!sensorState) {
    turnOffRelays();
  }
  else {
    digitalWrite(relay1_Pin, LOW);
	mode1 = false;
	function2();
}

void function2(){
  if (!mode1){
    if(sensor2_Pin == LOW){
     digitalWrite(relay3_Pin, LOW);
	 digitalWrite(relay4_Pin, LOW);
}
  }
}

Is this the same problem as your previous topic ?

You could do something like this:

int mode;
bool newMode;

void setup() {
  Serial.begin(115200);
  // Do set up which is the same for all modes and only needs to be done once in here
  // ...
  mode = 0; // or set it to whatever mode value you want
  newMode = true; // to force setup for mode to be done
}

void loop() {
  switch (mode) {
    case 0:
      if (newMode) {
        setupForMode0();
        newMode = false;
      }
      loopForMode0();
      break;
    case 1:
      if (newMode) {
        setupForMode1();
        newMode = false;
      }
      loopForMode1();
      break;
    // add more cases if you want more modes
    default:
      Serial.println("Invalid mode");
      delay(1000); // to stop serial monitor filling up quickly
  }
}

void setupForMode0() {
  // Write setup code for mode 0 here
}

void setupForMode1() {
  // Write setup code for mode 1 here
}

void loopForMode0() {
  // Write loop code for mode 0 here
  // The code in here can change the value of mode when you want to switch modes
  // If the value of mode is changed in here it must also set newMode = true;
}

void loopForMode1() {
  // Write loop code for mode 1 here
  // The code in here can change the value of mode when you want to switch modes
  // If the value of mode is changed in here it must also set newMode = true;
}

What is your problem? read the state of the pin and switch the mode accordingly.

3 Likes

If this is possible, depends on your connected HW.

Hello chandu-mca06

Consider this sketch as frame work for your project.

//https://forum.arduino.cc/t/different-modes-in-single-sketch/1336242
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Different modes in single sketch"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum OnOff {Off, On};
// make variables
uint32_t currentMillis = millis();
constexpr uint8_t ButtonPin{A0};

// make structures
//-----------------------------------------
struct BUTTON
{
  uint8_t buttonPin;
  uint16_t stateOld;
  uint16_t selector;
  uint32_t interval;
  uint32_t now;
  void make ()
  {
    pinMode(buttonPin, INPUT_PULLUP);
    stateOld = digitalRead(buttonPin) ? Off : On;
  }

  uint16_t getButton(uint32_t currentMillis)
  {
    if (currentMillis - now >= interval == Expired)
    {
      now = currentMillis;
      uint8_t stateNew = digitalRead(buttonPin) ? Off : On;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        if (stateNew == On) selector = selector ? Off : On;
      }
    }
    return selector;
  }
};
BUTTON pushbutton {ButtonPin, Off, Off, 20, 0};
//-----------------------------------------
// make user tasks
//-----------------------------------------
void loopOne()
{
  Serial.println(__func__);
  delay(500); //for test purposes only and must be deleted
}

void loopTwo()
{
  Serial.println(__func__);
  delay(500); // for test purposes only and must be deleted
}

void (*looping[])(void) {
  loopOne, loopTwo
};
//-----------------------------------------
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  for (uint8_t n = 0; n < 32; n++) Serial.println("");
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  pushbutton.make();
  delay(2000);
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();
  looping[pushbutton.getButton(currentMillis)]();
}
//------

Have a nice day and enjoy coding in C++.

Here's @paulpaulson's sketch with the delays removed. I can confirm proper operation on the UNO Arduino board.

//https://forum.arduino.cc/t/different-modes-in-single-sketch/1336242
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Different modes in single sketch"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum OnOff {Off, On};
// make variables
uint32_t currentMillis = millis();
constexpr uint8_t ButtonPin{A0};

// make structures
//-----------------------------------------
struct BUTTON
{
  uint8_t buttonPin;
  uint16_t stateOld;
  uint16_t selector;
  uint32_t interval;
  uint32_t now;
  void make ()
  {
    pinMode(buttonPin, INPUT_PULLUP);
    stateOld = digitalRead(buttonPin) ? Off : On;
  }

  uint16_t getButton(uint32_t currentMillis)
  {
    if (currentMillis - now >= interval == Expired)
    {
      now = currentMillis;
      uint8_t stateNew = digitalRead(buttonPin) ? Off : On;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        if (stateNew == On) selector = selector ? Off : On;
      }
    }
    return selector;
  }
};

BUTTON pushbutton {ButtonPin, Off, Off, 20, 0};
//-----------------------------------------
// make user tasks
//-----------------------------------------

int lastPrinted = -1;   // not for long

void loopOne()
{
  if (lastPrinted == 1) return;  // already said

  lastPrinted = 1;

  Serial.print("now looping ");
  Serial.println(__func__);
//  delay(500); //for test purposes only and must be deleted
}

void loopTwo()
{
  if (lastPrinted == 2) return;  // already said

  lastPrinted = 2;

  Serial.print("now looping ");
  Serial.println(__func__);
//  delay(500); // for test purposes only and must be deleted
}

void (*looping[])(void) {
  loopOne, loopTwo
};

//-----------------------------------------
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  for (uint8_t n = 0; n < 32; n++) Serial.println("");
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  pushbutton.make();
  delay(777);
  Serial.println(" =-> and off we go\n");
}

void loop()
{
  currentMillis = millis();

# define theHeart 7
  heartBeat(theHeart, currentMillis);
  
  looping[pushbutton.getButton(currentMillis)]();
}

I wired in the heart beat, which works well in the absence of those delays.

But... I ask what is going on here? I thought the semicolon was stray, but removing it makes an syntax error, and I don't (yet) understand its roll in the dispatch:

void (*looping[])(void) {
  loopOne, loopTwo
};

a7

Hello alto777

This is caused by the automatic code alignment by using CTRL T.

Origin:

void (*looping[])(void) {loopOne, loopTwo};

yes I tried but still no luck

If you tried - please show your code

Its very long back. I dont have that code now.

@paulpaulson - nevermind, I figured it out. It isn't a function, it's an initialized array of function pointers.

a7

1 Like

Thanks for your reply. I didn't see different setups fro different loops. For example for the loop1 setup should be different and for the loop2 setup should be different as i am going to use same pins for different purposes. I have a question on Hardware part.

For example, in setup1 I use pin2 as input and in setup2, the pin2 might be output.

So howcome same pin can use as input in mode1 and as output in mode2??

I've not read all the posts since my previous post, but did
you look at my post #3? That has different setups. Maybe you could use part of that code?

Sure will try and let you know. BTW I am trying to use arduino reset functionality in the sketch. This code is working only in atmega8 microcontroller but not in atmega328 and attiny2313 chips.

#include <avr/wdt.h>

void resetMicrocontroller() {
  wdt_enable(WDTO_15MS);  // Enable the watchdog timer to reset in 15ms
  while (true) {
    // Wait for the watchdog to reset the system
  }
}

void waitAndReset() {
  const unsigned long fiveMinutes = 5UL * 60 * 1000;  // 5 minutes in milliseconds
  unsigned long startTime = millis();

  while (millis() - startTime < fiveMinutes) {
    // Do nothing, just wait
    delay(1000); // Avoid WDT issues; adjust if WDT is enabled
  }
  resetMicrocontroller();  // Reset the microcontroller
}

Gotta ask why. This is not normally necessary and it raises questions about what you are actually trying to accomplish.

a7

Maybe this will help

It would have been better if you had continued your previous topic rather than starting a new one

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.