Buttons to set void

I'm working on making doctor a who k-9 project.
What I'm attempting to do is with the buttons on top have each one switch to that mode. (i.e. button 1 sets to "follow me {Cooler}" , button 2 sets to "autonomous {with ultrasonic}, button 3 sets to "remote" etc.)
Is difficult with the follow me mode because it combines GPS, Bluetooth (blynk) & a compass. So the code I'm trying to combine is-
a keypad code (to reduce wires and hopefully code)
-Arduino Playground - KeypadTutorial
And then the 5 follow me pages:

#define BLYNK_USE_DIRECT_CONNECT
// Imports
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
#include <Servo.h>
#include <SoftwareSerial.h>
#include <BlynkSimpleSerialBLE.h>
#include "./TinyGPS.h"                 // Use local version of this library
#include "./CoolerDefinitions.h"

// GPS
TinyGPS gps;

// Lid
Servo lidServo;
CoolerLid lidState = CLOSED;

// Master Enable
bool enabled = false;

//WidgetTerminal terminal(V3);

// Serial components
SoftwareSerial bluetoothSerial(BLUETOOTH_TX_PIN, BLUETOOTH_RX_PIN);
SoftwareSerial nss(GPS_TX_PIN, 255);            // TXD to digital pin 6

/* Compass */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

GeoLoc checkGPS() {
  Serial.println("Reading onboard GPS: ");
  bool newdata = false;
  unsigned long start = millis();
  while (millis() - start < GPS_UPDATE_INTERVAL) {
    if (feedgps())
      newdata = true;
  }
  if (newdata) {
    return gpsdump(gps);
  }

  GeoLoc coolerLoc;
  coolerLoc.lat = 0.0;
  coolerLoc.lon = 0.0;
  
  return coolerLoc;
}

// Get and process GPS data
GeoLoc gpsdump(TinyGPS &gps) {
  float flat, flon;
  unsigned long age;
  
  gps.f_get_position(&flat, &flon, &age);

  GeoLoc coolerLoc;
  coolerLoc.lat = flat;
  coolerLoc.lon = flon;

  Serial.print(coolerLoc.lat, 7); Serial.print(", "); Serial.println(coolerLoc.lon, 7);

  return coolerLoc;
}

// Feed data as it becomes available 
bool feedgps() {
  while (nss.available()) {
    if (gps.encode(nss.read()))
      return true;
  }
  return false;
}

// Lid Hook
BLYNK_WRITE(V0) {
  switch (lidState) {
    case OPENED:
      setServo(SERVO_LID_CLOSE);
      lidState = CLOSED;
      break;
    case CLOSED:
      setServo(SERVO_LID_OPEN);
      lidState = OPENED;
      break;
  }
}

// Killswitch Hook
BLYNK_WRITE(V1) {
  enabled = !enabled;
  
  //Stop the wheels
  stop();
}

// GPS Streaming Hook
BLYNK_WRITE(V2) {
  GpsParam gps(param);
  
  Serial.println("Received remote GPS: ");
  
  // Print 7 decimal places for Lat
  Serial.print(gps.getLat(), 7); Serial.print(", "); Serial.println(gps.getLon(), 7);

  GeoLoc phoneLoc;
  phoneLoc.lat = gps.getLat();
  phoneLoc.lon = gps.getLon();

  driveTo(phoneLoc, GPS_STREAM_TIMEOUT);
}

// Terminal Hook
BLYNK_WRITE(V3) {
  Serial.print("Received Text: ");
  Serial.println(param.asStr());

  String rawInput(param.asStr());
  int colonIndex;
  int commaIndex;
  
... SHORTENED TO MEET CHARACTER REQIREMENTS


void setServo(int pos) {
  lidServo.attach(SERVO_PIN);
  lidServo.write(pos);
  delay(2000);
  lidServo.detach();
}

void setSpeedMotorA(int speed) {
  digitalWrite(MOTOR_A_IN_1_PIN, LOW);
  digitalWrite(MOTOR_A_IN_2_PIN, HIGH);
  
  // set speed to 200 out of possible range 0~255
  analogWrite(MOTOR_A_EN_PIN, speed + MOTOR_A_OFFSET);
}

void setSpeedMotorB(int speed) {
  digitalWrite(MOTOR_B_IN_1_PIN, LOW);
  digitalWrite(MOTOR_B_IN_2_PIN, HIGH);
  
  // set speed to 200 out of possible range 0~255
  analogWrite(MOTOR_B_EN_PIN, speed + MOTOR_B_OFFSET);
}

void setSpeed(int speed)
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  setSpeedMotorA(speed);

  // turn on motor B
  setSpeedMotorB(speed);
}

void stop() {
  // now turn off motors
  digitalWrite(MOTOR_A_IN_1_PIN, LOW);
  digitalWrite(MOTOR_A_IN_2_PIN, LOW);  
  digitalWrite(MOTOR_B_IN_1_PIN, LOW);
  digitalWrite(MOTOR_B_IN_2_PIN, LOW);
}

void drive(int distance, float turn) {
  int fullSpeed = 230;
  int stopSpeed = 0;

  // drive to location
  int s = fullSpeed;
  if ( distance < 8 ) {
    int wouldBeSpeed = s - stopSpeed;
    wouldBeSpeed *= distance / 8.0f;
    s = stopSpeed + wouldBeSpeed;
  }
  
  int autoThrottle = constrain(s, stopSpeed, fullSpeed);
  autoThrottle = 230;

  float t = turn;
  while (t < -180) t += 360;
  while (t >  180) t -= 360;
  
  Serial.print("turn: ");
  Serial.println(t);
  Serial.print("original: ");
  Serial.println(turn);
  
  float t_modifier = (180.0 - abs(t)) / 180.0;
  float autoSteerA = 1;
  float autoSteerB = 1;

  if (t < 0) {
    autoSteerB = t_modifier;
  } else if (t > 0){
    autoSteerA = t_modifier;
  }

  Serial.print("steerA: "); Serial.println(autoSteerA);
  Serial.print("steerB: "); Serial.println(autoSteerB);

  int speedA = (int) (((float) autoThrottle) * autoSteerA);
  int speedB = (int) (((float) autoThrottle) * autoSteerB);
  
  setSpeedMotorA(speedA);
  setSpeedMotorB(speedB);
}

void driveTo(struct GeoLoc &loc, int timeout) {
  nss.listen();
  GeoLoc coolerLoc = checkGPS();
  bluetoothSerial.listen();

  if (coolerLoc.lat != 0 && coolerLoc.lon != 0 && enabled) {
    float d = 0;
    //Start move loop here
    do {
      nss.listen();
      coolerLoc = checkGPS();
      bluetoothSerial.listen();
      
      d = geoDistance(coolerLoc, loc);
      float t = geoBearing(coolerLoc, loc) - geoHeading();
      
      Serial.print("Distance: ");
      Serial.println(geoDistance(coolerLoc, loc));
    
      Serial.print("Bearing: ");
      Serial.println(geoBearing(coolerLoc, loc));

      Serial.print("heading: ");
      Serial.println(geoHeading());
      
      drive(d, t);
      timeout -= 1;
    } while (d > 3.0 && enabled && timeout>0);

    stop();
  }
}

void setupCompass() {
   /* Initialise the compass */
  if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
  
  /* Display some basic information on this sensor */
  displayCompassDetails();
}

void setup()
{
  // Compass
  setupCompass();

  // Motor pins
  pinMode(MOTOR_A_EN_PIN, OUTPUT);
  pinMode(MOTOR_B_EN_PIN, OUTPUT);
  pinMode(MOTOR_A_IN_1_PIN, OUTPUT);
  pinMode(MOTOR_A_IN_2_PIN, OUTPUT);
  pinMode(MOTOR_B_IN_1_PIN, OUTPUT);
  pinMode(MOTOR_B_IN_2_PIN, OUTPUT);
  
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  //Debugging via serial
  Serial.begin(4800);

  //GPS
  nss.begin(9600);

  //Bluetooth
  bluetoothSerial.begin(9600);
  Blynk.begin(bluetoothSerial, auth);
}

// Testing
void testDriveNorth() {
  float heading = geoHeading();
  int testDist = 10;
  Serial.println(heading);
  
  while(!(heading < 5 && heading > -5)) {
    drive(testDist, heading);
    heading = geoHeading();
    Serial.println(heading);
    delay(500);
  }
  
  stop();
}

void loop()
{
  Blynk.run();
}

And the wall avoidance code

And then I would also like to add a joystick from blynk for the remote mode which I haven't made yet, and also a stop mode,
and then a button for stopping any actions.

If anyone can help with combining these code to be called and looped (until unpowered or another button is pressed) when a button is pressed. Its been hard to find any info online because using the word Goto is a command and it is apparently told to be usually avoided. any info helps Thanks :slight_smile:

K-9 files.zip (549 KB)

You seem to have a lot more code than I would expect to see when you have a simple (is it simple?) question about a button.

Presumably you have been testing this carefully as you have developed it.

Where in the code you posted is the piece with the button that is causing a problem, and what does the program actually do and what do you want it to do that is different?

...R

PS. What is in the ZIP file? People don't like opening strange ZIP files.

I'm actually wondering how to switch between "Modes" using buttons, i have several different codes that would make the device do something different (remote mode, follow me mode [shown in example which is the hardest because its across a few pages], autonomous mode etc.) all i want it to do is as you press a button it goes to that mode(or void)
(and the zip just includes the Arduino files i want to include)

I'm actually wondering how to switch between "Modes" using buttons,

The simplistic way to do this is to put all of the code for each mode in its own function and call the function when required.

Put common code, such pinMode()s in setup() and declare of global variables for all of the modes at the top of the program.

Presumably you will need a way to get out of or between modes which implies that the code for each mode must be non blocking, ie no delay()s, no long for loops or while()s that hold up the reading of inputs to switch mode.

If you put the code to read buttons and switch mode in its own function then you can call it from anywhere.

Harrypph:
I'm actually wondering how to switch between "Modes" using buttons, i have several different codes that would make the device do something different (remote mode, follow me mode [shown in example which is the hardest because its across a few pages],

I don't know what you mean by "a few pages". I just see 304 lines of code in your Original Post. I had hoped you would point me at specific line numbers where the problem is.

One common way to switch between modes is to have a variable (let's call it selectedMode) which gets changed when you press a button. Maybe it could have the value 'F' for follow-me and 'R' for remote. then the different parts of your program can check that variable to see if they should be operating.

...R

Ok, im going to try and explain this as best as I can.
The 3 Images I've attached are 3 different sketches, Of which I want to combine into 1 where the keypad sketch controls which "mode" is active. All I want to know (which is the problem I'm asking about) is how am I to combine these and what code do I use to separate them to be called (or "activated") by a button being pressed

UKHeliBob:
The simplistic way to do this is to put all of the code for each mode in its own function and call the function when required.

when i try putting them into funtions it gives me this error-

exit status 1
a function-definition is not allowed here before '{' token
I feel like its because it has other funtions inside such as-
GeoLoc checkGPS() {
(which is what was highlighted with the error)

when i try putting them into funtions it gives me this error-

Which means that you did it wrong.

Post what you tried here but first read this before posting a programming question

#define BLYNK_USE_DIRECT_CONNECT

// Imports
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
#include <Servo.h>
#include <SoftwareSerial.h>
#include <BlynkSimpleSerialBLE.h>
#include "./TinyGPS.h"                 // Use local version of this library
#include "./CoolerDefinitions.h"

void funtion1()
{

// GPS
TinyGPS gps;

// Lid
Servo lidServo;
CoolerLid lidState = CLOSED;

// Master Enable
bool enabled = false;

//WidgetTerminal terminal(V3);

// Serial components
SoftwareSerial bluetoothSerial(BLUETOOTH_TX_PIN, BLUETOOTH_RX_PIN);
SoftwareSerial nss(GPS_TX_PIN, 255);            // TXD to digital pin 6

/* Compass */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

GeoLoc checkGPS() {
  Serial.println("Reading onboard GPS: ");
  bool newdata = false;
  unsigned long start = millis();
  while (millis() - start < GPS_UPDATE_INTERVAL) {
    if (feedgps())
      newdata = true;
  }
  if (newdata) {
    return gpsdump(gps);
  }
}

(Thats just the first section of code)
Error code- exit status 1
a function-definition is not allowed here before '{' token
i believe looking online said to set or call a function via setting that section in a void with a name such ad void funtion1()
{ ?

UKHeliBob:
The simplistic way to do this is to put all of the code for each mode in its own function and call the function when required.

Also, would it be easier to use an if statement or something like if button is pressed do the section of code until another button is pressed?

Harrypph:
Also, would it be easier to use an if statement or something like if button is pressed do the section of code until another button is pressed?

You could do it several ways. Will there be a button to enter each state or a single button that cycles through the states ?

Either way, using switch/case would allow only the code for the current state to run and the button testing could be in loop(). This would involve making the code for each state non blocking.