Toggle button and distance toggle

i am working on a script that will get a motor to run or stop based on a distance and if a button is pressed.

I am still in the beginning but i am getting stuck at the step of toggling the button (adding the distance stuff later)

for now i want to push the button let the motor run forward.. push the button again make the motor stop. (will try to add the rest of the functionality later myself)

i have looked at multiple posts already but can't figure it out.. is amost if the

if (but1==LOW) doesn;t register

//motor constants
const int forwardPin = 12;
const int backwardPin = 13;
const int delayTime = 500;

//button constants
const int but1pin =2;


int but1;
int buttonState = 1;


unsigned long currentMillis; // Store current millis().
unsigned long previousMillis; // store last measured millis().


void setup() {
  Serial.begin(9600);
  Serial.println("Started!");
  Serial.println("");
  
  //motor setup
  pinMode (forwardPin, OUTPUT);
  pinMode (backwardPin, OUTPUT);
  
  // button setup
  pinMode(but1pin, INPUT);
 
}


void loop() {
  currentMillis = millis();
  but1= digitalRead(but1pin);
  
  if(currentMillis - previousMillis > 25){ // Millis timer fuction, to get little bugs out while measuring. the 25 value stands for the delay, do not go below 25.
    if((but1== LOW) && buttonState ==1){
      buttonState==0;
  	}
    else if((but1==HIGH)&& buttonState==0){
      buttonState==1;
    }
    delay(100);
    
    if(buttonState == 2){
      MotorForward();
    }
    if(buttonState == 1){
      MotorBackward();
    }
    if(buttonState == 0){
      MotorStop();
    } 
    Serial.println(but1);
    Serial.println(buttonState);
  }
}

void MotorForward(){
  digitalWrite(forwardPin,HIGH);
  digitalWrite(backwardPin,LOW);
   Serial.println("Forward");
}

void MotorBackward(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,HIGH);
  Serial.println("backward");
}

void MotorStop(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,LOW);
  Serial.println("stop");
}

In your code, where can buttonState get a value of 2? Where is a line that will set it to 2?

Review. '=' is for assignment, '==' is a test for equality;

      buttonState==0;  // this statement deos nothing
  	}
    else if((but1==HIGH)&& buttonState==0){
      buttonState==1;  // this statement does nothing

Also and FWIW, spaces are allowed! And can make reading code more pleasenter.
      buttonState == 0;  // this statement deos nothing
  	}
    else if (but1 == HIGH && buttonState == 0) {
      buttonState == 1;  // this statement does nothing

Use the IDE AutoFormat tool until you are typing code in good format automatically.

a7

1 Like

doesn't but1 become HIGH as soon as you release it

several more issues with your code that haven't been mentioned

buttons are typically connected between the pin and ground, the pin configured as INPUT_PULLUP to use the internal pullup resistor which pulls the pin HIGH and when pressed, the button pulls the pin LOW.

look this over

const int ForwardPin  = 12;     // Capitalize Constants
const int BackwardPin = 13;
const int But1Pin     = 2;

byte but1State;

enum { Stop1, Forward, Stop2, Reverse };
int mode = Stop1;

// -----------------------------------------------------------------------------
void loop ()
{
    byte but1 = digitalRead (But1Pin);
    if (but1State != but1)  {               // change
        but1State = but1;
        delay (20);                         // debounce

        if (but1 == LOW)  {                 // pressed
            mode++;
            if (Reverse < mode)
                mode = Stop1;

            Serial.print   ("mode ");
            Serial.println (mode);

            switch (mode)  {
            case Stop1:
            case Stop2:
                motorStop ();
                break;

            case Forward:
                motorForward ();
                break;

            case Reverse:
                motorBackward ();
                break;
            }
        }
    }
}

void motorForward (){
    digitalWrite (ForwardPin,HIGH);
    digitalWrite (BackwardPin,LOW);
    Serial.println ("Forward");
}

void motorBackward (){
    digitalWrite (ForwardPin,LOW);
    digitalWrite (BackwardPin,HIGH);
    Serial.println ("backward");
}

void motorStop (){
    digitalWrite (ForwardPin,LOW);
    digitalWrite (BackwardPin,LOW);
    Serial.println ("stop");
}

void setup ()
{
    Serial.begin (9600);
    Serial.println ("Started!");

    pinMode (ForwardPin,  OUTPUT);
    pinMode (BackwardPin, OUTPUT);
    pinMode (But1Pin,     INPUT_PULLUP);
    but1State = digitalRead (But1Pin);
}
1 Like

i want to add that later depending on distance

Iā€™d suggest you check the code for one of the numerous button library such as Button in easyRun or OneButton or Toggle or EasyButton or Bounce2, ...

That will make your coding effort easier

1 Like

How do you have the button wired? Do you have a pull-down resistor? Or is your button pin floating when the button isn't pressed?

It's easier to do it like @gcjr suggested and use the internal pull-ups.

Hi @arnoalkmaar

welcome to the arduino-forum.
Well done to post your code as a code-section in your first posting.

Here is one of many libraries that offer functionality to use a momentary push-button as a toggle-switch

Toggle.h by David Lloyd
You can install this library with the library-manager of the arduino-IDE

You can find this library also on GitHub

The library has some examples included.
There is one example-code with filename Use_Button_As_Toggle.ino

The following WOKWI-simulation is based on this example with some additional comments

Code of the WokSim

/***********************************************
  USE A MOMENTARY PUSHBUTTON AS A TOGGLE SWITCH:
  The button is connected from input pin to GND.
  INPUT_PULLUP and debouncing are pre-configured.
  The built in LED changes state as configured.
  **********************************************/

#include <Toggle.h> // does what the name says: include the code that is inside the file Toggle.h AND the file Toggle.cpp

const byte buttonPin = 2;
const byte ledPin = LED_BUILTIN;
byte actualButtonState;
boolean lastButtonState;

Toggle button(buttonPin);

void setup() {
  Serial.begin(115200);        // 115200 is the modern standard baudrate
  Serial.println("Setup-Start");
  button.begin(buttonPin);     // create the button-"object"
  button.setToggleState(0);    // set initial state 0 or 1
  button.setToggleTrigger(0);  // set trigger onPress: 0, or onRelease: 1

  pinMode(ledPin, OUTPUT);
}

void loop() {
  // this line must be called at high frequency = at least 100 times per second. 
  // Avoid using delay() whenever you want a QUICK reaction on a button-press
  button.poll();  // function-call with the code to read-in the button-state
  actualButtonState = button.toggle(); 
  digitalWrite(ledPin, actualButtonState);
  printButtonStateOnlyOnce();
}


void printButtonStateOnlyOnce() {
  // does what the function name says
  if (lastButtonState != actualButtonState) {
    if (actualButtonState == HIGH) {
      Serial.println("Button is in ON-state now");
    }
    else {
      Serial.println("Button is in OFF-state now");
    }
    lastButtonState = actualButtonState; // update lastButtonState => print only once per state-change
  }
  // exits without printing if lastButtonState and actualButtonState have the same value
  // the if-condition if (lastButtonState != actualButtonState) checks for UN-equalitiy 
  // the "!=" is the UN-equal-operator
  // in words: if value of variable lastButtonState is unequal to value of variable actualButtonState
}

If you want to learn about the details how this works you could read the
Toggle.h and the Toggle.cpp-file.
Though my expectation is : more or less hard to understand code

I have written this push-button to toggle-switch functionality myself

WokSim-Code

/* explanation of the most important details:

  realising a functionality where using a momentary push-button
  acts as a toogle-switch
  push       => activated  push again => DE-activated
  push again => activated  push again => DE-activated
  etc. etc. ...
  This needs quite some code. This code is well organised in MULTIPLE functions
  where each function is a senseful SUB-program

  This is the reason why function loop looks super-short:

  void loop () {
  activationMode = GetToggleSwitchState(); // must be executed all the time
  }

  Huh that's all? No. Of course there is more (below function loop)
*/


#define ProjectName "Toggle Button demonstration"

// define IO-states for inputs with pull-up-resistors
// pull-up-resistors invert the logig
#define unPressed HIGH
#define pressed   LOW

const byte    OnBoard_LED = 13;
const byte ToggleButtonPin = 4;

boolean activationMode;
boolean last_activationMode;


void setup() {
  Serial.begin(115200); // adjust baudrate in the serial monitor to match the number
  Serial.println( F("Setup-Start") );
  Serial.println("Click the button to switch on/off the Onboard-LED");

  pinMode (OnBoard_LED, OUTPUT);  // used for indicating logging active or not
  digitalWrite(OnBoard_LED, LOW);
  // wire button between IO-pin and GND
  // Pull-up-resistor inverts the logic
  // unpressed: IO-pin detects HIGH
  // pressed:   IO-Pin detects LOW
  pinMode(ToggleButtonPin, INPUT_PULLUP);
}


void loop () {
  activationMode = GetToggleSwitchState(); // must be executed all the time

  if (activationMode != last_activationMode) {
    digitalWrite(OnBoard_LED,activationMode);
    last_activationMode = activationMode;
  }
}


bool GetToggleSwitchState() {
  // "static" makes variables persistant over function calls
  static bool toggleState     = false;
  static bool lastToggleState = false;

  static byte buttonStateOld = unPressed;
  static unsigned long buttonScanStarted  =  0;
  unsigned long buttonDebounceTime = 50;
  static unsigned long buttonDebounceTimer;

  byte buttonStateNew;

  if ( TimePeriodIsOver(buttonDebounceTimer, buttonDebounceTime) ) {
    // if more time than buttonDebounceTime has passed by
    // this means let pass by some time until
    // bouncing of the button is over
    buttonStateNew = digitalRead(ToggleButtonPin);

    if (buttonStateNew != buttonStateOld) {
      // if button-state has changed
      buttonStateOld = buttonStateNew;
      if (buttonStateNew == unPressed) {
        // if button is released
        toggleState = !toggleState; // toggle state-variable
      } // the attention-mark is the NOT operator
    }   // which simply inverts the boolean state
  }     // !true  = false   NOT true  is false
  //       !false = true    NOT false is true
  return toggleState;
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

last but not least here is a link to a tutorial that explains how buttons can be wired and what disadvantages / advantages the different ways have

1 Like

i really like the solution of @gcjr with the states.

So i got that working and i added my distance sensor..

what i am making is a wall that will rotate into the room..
So you push the button and the wall will move (if distance = 0 or something) and stops when it hits 200 (for example) then when you push the button again it will move back until the sensor is 0 again.


i have the code working that it will go forward when the distance is smaller then 30, and it will reverse when the distance is > then 200.. but it keeps moving even when the distance is bigger then 200... i don;t understand why the state doesn't change



//motor constants
const int forwardPin = 12;
const int backwardPin = 13;
const int delayTime = 500;

//button 
const int but1pin =2;
int but1;
byte but1State;
enum { Stop1, Forward, Stop2, Reverse };
int mode = Stop1;

//pingsensor
const int pingPin = 7;


//millis
unsigned long currentMillis; // Store current millis().
unsigned long previousMillis; // store last measured millis().


void setup() {
  Serial.begin(9600);
  Serial.println("Started!");
  Serial.println("");
  
  //motor setup
  pinMode (forwardPin, OUTPUT);
  pinMode (backwardPin, OUTPUT);
  
  // button setup
  pinMode(but1pin, INPUT_PULLUP);
 
}


void loop() {
  currentMillis = millis();
  
  //read button
  byte but1= digitalRead(but1pin);
  
  
              
  
  if(currentMillis - previousMillis > 25){ // Millis timer fuction, to get little bugs out while measuring. the 25 value stands for the delay, do not go below 25.
    
    
    //pingsensor
    long duration, cm;
    
    // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
    // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
    pinMode(pingPin, OUTPUT);
    digitalWrite(pingPin, LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(pingPin, LOW);

    // The same pin is used to read the signal from the PING))): a HIGH pulse
    // whose duration is the time (in microseconds) from the sending of the ping
    // to the reception of its echo off of an object.
    pinMode(pingPin, INPUT);
    duration = pulseIn(pingPin, HIGH);

    // convert the time into a distance
    cm = microsecondsToCentimeters(duration);
    
    //testing if it is registering
    if (mode == Forward){
      Serial.print(cm);
      Serial.print("cm");
      Serial.println();
      Serial.print	("mode ");
      Serial.print(mode);
    }

    delay(100);
    
        
    //button
    if (but1State !=but1) {
      but1State = but1;
      delay(20);
      
      if (cm >= 200 && mode == Forward){
        mode = Stop2;
      }
      
      if (cm <= 50 && mode == Reverse){
        mode = Stop1;
      }
      
      if (but1 == LOW) {
        if (cm <= 30){
          mode = Forward;
        }
        if (cm >= 180){
          mode = Reverse;
        }
        
        //mode++;
      	//if (Reverse < mode)
      	//  mode = Stop1;
        
        Serial.print	("mode ");
        Serial.println (mode);
        
        switch (mode) {
        case Stop1:
        case Stop2:
          MotorStop();
          break;
         
        case Forward:
          MotorForward();
          break;
          
        case Reverse:
          MotorBackward();
          break;
          
        }  
      }    
    }
  }
}


//distance sensor
long microsecondsToCentimeters(long microseconds) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the object we
  // take half of the distance travelled.
  return microseconds / 29 / 2;
}


//motor states
void MotorForward(){
  digitalWrite(forwardPin,HIGH);
  digitalWrite(backwardPin,LOW);
  Serial.println("Forward");
}

void MotorBackward(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,HIGH);
  Serial.println("Reverse");
}

void MotorStop(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,LOW);
  Serial.println("stop");
}




you can move the switch statement that drives the motor out from inside the condition the tests for a button press so that it's independent.

with the switch statement independent of the button press, the mode can be changed independently, also depending on the distance measurement.

the tests for distances should NOT be under the condition for a button press.

don't understand the need to delay using millis(). just add a delay (25) at the bottom of loop()

doesn't that sensor have separate pins for ping and echo?

if (cm >= 200 && mode == Forward){
        mode = Stop2;
      }
      
      if (cm <= 50 && mode == Reverse){
        mode = Stop1;
      }

i had this code above

  if (but1State !=but1) {
      but1State = but1;
      delay(20);

this first but that didn't work either..

the millis.. is something i found as best practise i am new at this so if it is not needed i will use the delay.
there are two kinds of Ping sensors one with the seperate pins and on combined. the combined one is more accurate they say.

i started with the sensor more then 200 away.. so it went into reverse but as you can see i am smaller then 50 but it didn;t change states

There is no way around really understanding what a code does
if you want to modify it successfullly

the reason is this:

// is only executed in case the above most outside if-condition is true

Your code with additional comments that point on this problem

//motor constants
const int forwardPin = 12;
const int backwardPin = 13;
const int delayTime = 500;

//button 
const int but1pin =2;
int but1;
byte but1State;
enum { Stop1, Forward, Stop2, Reverse };
int mode = Stop1;

//pingsensor
const int pingPin = 7;


//millis
unsigned long currentMillis; // Store current millis().
unsigned long previousMillis; // store last measured millis().


void setup() {
  Serial.begin(9600);
  Serial.println("Started!");
  Serial.println("");
  
  //motor setup
  pinMode (forwardPin, OUTPUT);
  pinMode (backwardPin, OUTPUT);
  
  // button setup
  pinMode(but1pin, INPUT_PULLUP);
 
}


void loop() {
  currentMillis = millis();
  
  //read button
  byte but1= digitalRead(but1pin);

  if(currentMillis - previousMillis > 25){ // Millis timer fuction, to get little bugs out while measuring. the 25 value stands for the delay, do not go below 25.
    //pingsensor
    long duration, cm;
    
    // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
    // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
    pinMode(pingPin, OUTPUT);
    digitalWrite(pingPin, LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(pingPin, LOW);

    // The same pin is used to read the signal from the PING))): a HIGH pulse
    // whose duration is the time (in microseconds) from the sending of the ping
    // to the reception of its echo off of an object.
    pinMode(pingPin, INPUT);
    duration = pulseIn(pingPin, HIGH);

    // convert the time into a distance
    cm = microsecondsToCentimeters(duration);
    
    //testing if it is registering
    if (mode == Forward){
      Serial.print(cm);
      Serial.print("cm");
      Serial.println();
      Serial.print  ("mode ");
      Serial.print(mode);
    }

    delay(100);
    
        
    //button
    if (but1State !=but1) { // most outside if-condition 
      but1State = but1;
      delay(20);
      // is only executed in case the above-if-condition is true
      if (cm >= 200 && mode == Forward){
        mode = Stop2;
      }
      
      // is only executed in case the above most outside if-condition is true
      if (cm <= 50 && mode == Reverse){
        mode = Stop1;
      }
      
      // is only executed in case the above most outside if-condition is true
      if (but1 == LOW) {
        if (cm <= 30){
          mode = Forward;
        }
      // is only executed in case the above most outside if-condition is true
        if (cm >= 180){
          mode = Reverse;
        }
        
        //mode++;
        //if (Reverse < mode)
        //  mode = Stop1;
        
        Serial.print  ("mode ");
        Serial.println (mode);
        
      // is only executed in case the above most outside if-condition is true
        switch (mode) {
        case Stop1:
        case Stop2:
          MotorStop();
          break;
         
        case Forward:
          MotorForward();
          break;
          
        case Reverse:
          MotorBackward();
          break;
          
        }  
      }    
    }
  }
}


//distance sensor
long microsecondsToCentimeters(long microseconds) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the object we
  // take half of the distance travelled.
  return microseconds / 29 / 2;
}


//motor states
void MotorForward(){
  digitalWrite(forwardPin,HIGH);
  digitalWrite(backwardPin,LOW);
  Serial.println("Forward");
}

void MotorBackward(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,HIGH);
  Serial.println("Reverse");
}

void MotorStop(){
  digitalWrite(forwardPin,LOW);
  digitalWrite(backwardPin,LOW);
  Serial.println("stop");
}

please look this over

const int forwardPin    = 12;  // motor direction pins
const int backwardPin   = 13;

const int but1pin       = 2;   // button
const int pingPin       = 7;   // pingsensor

int but1State;

const char *ModeStr [] = { " Stop1", " Forward", " Stop2", " Reverse" };
enum { Stop1, Forward, Stop2, Reverse };
int mode = Stop1;

// -----------------------------------------------------------------------------
void loop ()
{
    // process button press
    byte but1= digitalRead(but1pin);
    if (but1State != but1) {         // change
        but1State  = but1;
        delay(20);                  // debounce

        Serial.println ("press");

        if (LOW == but1)  {
            mode++;
            if (Reverse < mode)
                mode = Stop1;
        }
    }

    // process distance measurement
    int cm = getCm ();

    Serial.print   ("  cm ");
    Serial.print   (cm);

    if (cm >= 200 && mode == Forward)  {
        mode = Stop2;
        Serial.println (ModeStr [mode]);
    }

    if (cm <= 50 && mode == Reverse) {
        mode = Stop1;
        Serial.print (ModeStr [mode]);
    }
    Serial.println ();

    // process mode
    switch (mode) {
    case Stop1:
    case Stop2:
        MotorStop();
        break;

    case Forward:
        MotorForward();
        break;

    case Reverse:
        MotorBackward();
        break;
    }

    delay (500);
}

// -----------------------------------------------------------------------------
//distance sensor
long microsecondsToCentimeters(long microseconds) {
    // The ping travels out and back, so to find the distance of the object we
    // take half of the distance travelled.
    return microseconds / 29 / 2;
}

int
getCm ()
{

    // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
    // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
    pinMode            (pingPin, OUTPUT);
    digitalWrite       (pingPin, LOW);
    digitalWrite       (pingPin, HIGH);
    delayMicroseconds  (5);

    pinMode            (pingPin, INPUT);
    long duration = pulseIn (pingPin, HIGH);

    return microsecondsToCentimeters (duration);
}

// -----------------------------------------------------------------------------
//motor states
void MotorForward(){
    digitalWrite(forwardPin,HIGH);
    digitalWrite(backwardPin,LOW);
    Serial.println("Forward");
}

void MotorBackward(){
    digitalWrite(forwardPin,LOW);
    digitalWrite(backwardPin,HIGH);
    Serial.println("Reverse");
}

void MotorStop(){
    digitalWrite(forwardPin,LOW);
    digitalWrite(backwardPin,LOW);
    Serial.println("stop");
}

// -----------------------------------------------------------------------------
void setup() {
    Serial.begin(9600);
    Serial.println("Started!");
    Serial.println("");

    //motor setup
    pinMode (forwardPin, OUTPUT);
    pinMode (backwardPin, OUTPUT);

    // button setup
    pinMode(but1pin, INPUT_PULLUP);
    but1State = (but1pin);

}

important - remove or reduce the 1/2 second delay before testing

@arnoalkmaar - how did you get your dog to sit in exactly the same spot and exactly the same pose for the two photos?

a7

1 Like

do you mean for the 3D renderings ?

the same way i painted the wall so quickly

1 Like

Well I already figured out it was exactly 24 hours later with no changes to the weather.

a7

Thank this works very nice and i love how you program in blocks so to say, very clear and understandable..

i added a light so green when stop so you can press the button red when moving.
and i placed an if statement in the getCm. i don't want the PING to be sending signals all the time.. it only needs to do it when moving.. no need to send signals when it is in a stop.

const int forwardPin    = 12;  // motor direction pins
const int backwardPin   = 13;

const int but1pin       = 2;   // button
const int pingPin       = 7;   // pingsensor

int but1State;

const char *ModeStr [] = { " Stop1", " Forward", " Stop2", " Reverse" };
enum { Stop1, Forward, Stop2, Reverse };
int mode = Stop1;

//LED
int redPin= 9;
int greenPin = 10;
int bluePin = 11;



// -----------------------------------------------------------------------------
void loop ()
{
    // process button press
    byte but1= digitalRead(but1pin);
    if (but1State != but1) {         // change
        but1State  = but1;
        delay(20);                  // debounce

        Serial.println ("press");
      
          
      
        if (LOW == but1)  {
            mode++;
            if (Reverse < mode)
                mode = Stop1;
        }
    }

    // process distance measurement
    int cm = getCm ();

    Serial.print   ("  cm ");
    Serial.print   (cm);

    if (cm >= 200 && mode == Forward)  {
        mode = Stop2;
        Serial.println (ModeStr [mode]);
    }

    if (cm <= 50 && mode == Reverse) {
        mode = Stop1;
        Serial.print (ModeStr [mode]);
    }
    Serial.println ();

    // process mode
    switch (mode) {
    case Stop1:
    case Stop2:
        MotorStop();
        break;

    case Forward:
        MotorForward();
        break;

    case Reverse:
        MotorBackward();
        break;
    }

    //delay (500);
}

// -----------------------------------------------------------------------------
//distance sensor
long microsecondsToCentimeters(long microseconds) {
    // The ping travels out and back, so to find the distance of the object we
    // take half of the distance travelled.
    return microseconds / 29 / 2;
}

int
getCm ()
{
  if(mode == Forward || mode == Reverse) {
    // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
    // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
    pinMode            (pingPin, OUTPUT);
    digitalWrite       (pingPin, LOW);
    digitalWrite       (pingPin, HIGH);
    delayMicroseconds  (5);

    pinMode            (pingPin, INPUT);
    long duration = pulseIn (pingPin, HIGH);

    return microsecondsToCentimeters (duration);
  }
}

// -----------------------------------------------------------------------------
//motor states
void MotorForward(){
    digitalWrite(forwardPin,HIGH);
    digitalWrite(backwardPin,LOW);
  	setColorLED(0,0,255);
    Serial.println("Forward");
}

void MotorBackward(){
    digitalWrite(forwardPin,LOW);
    digitalWrite(backwardPin,HIGH);
  	setColorLED(0,0,255);
    Serial.println("Reverse");
}

void MotorStop(){
    digitalWrite(forwardPin,LOW);
    digitalWrite(backwardPin,LOW);
  	setColorLED(255,0,0);
    Serial.println("stop");
}


void setColorLED(int red, int green, int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
}

// -----------------------------------------------------------------------------
void setup() {
    Serial.begin(9600);
    Serial.println("Started!");
    Serial.println("");

    //motor setup
    pinMode (forwardPin, OUTPUT);
    pinMode (backwardPin, OUTPUT);

    // button setup
    pinMode(but1pin, INPUT_PULLUP);
    but1State = (but1pin);
	
  	// LED setup
  	pinMode(redPin, OUTPUT);
  	pinMode(greenPin, OUTPUT);
  	pinMode(bluePin, OUTPUT);
}

what i want to impliment next is that the motor slowly starts to move and slowly comes to a stop.. i need to add a motor contol i think like the L298N, but there is not such a module in tinkercad.. how do i resolve this.

i also want to add (but will try that myself first) that if the distance is between the low and high stop and it is the same distance within a time frame that it will stop moving something is blocking it and i dont want to motor to burn down or the wheel spinning on the floor..

i have added the int.


//obstruction
int LastDistance = 0;
int delayCount =0;

then after the distance check in //process distance measurement i added

if (cm >= 51 && cm <=199 && (mode == Stop1 || mode == Stop2)) {
        mode++;
        Serial.print (ModeStr [mode]);
    }
  
  
  	Serial.println ();
  
  	// obstruction
    delayCount++;
    if (delayCount >= 50){
      if (mode == Reverse || mode == Forward){
        if ( cm == LastDistance){
          if ( mode == Reverse){
            mode = Stop1;
          }
          else{
            mode = Stop2;
          }
        }
      }
      LastDistance = cm;
      delayCount = 0;
    }

this does work but is this a desent code..
so when it is blocked and it stops when you push the button it first goes back where it came from..
and it only checks it when it is moving state
so the code works but i am not sure it is a good code.
i added the delay because it could be that the distance sensor isn;t accurate and could give the same values in the following loop (if you know what i mean)