Use of Passive Buzzer blocks all the functions of my Robot Car

Hello,

I'm currently working on my first project, the SMARS Robot Car by Kevin Thomas. I didn't quite follow the instructions and used different components, so I'll describe it briefly in bullet points.

  • Arduino Uno Rev. 3
  • L293d Motor Shield on the Arduino Uno
  • 2x N20 mini geared motor
  • Ultrasonic sensor hc-sr04
  • Infrared sensor
  • JOY-IT Wireless Gamepad
  • Power supply with Amazon Basics battery
    Battery (button switch to turn on and off)
  • Passive buzzer (without resistance)

Everything works fine except for the passive buzzer. Whenever I press the buzzer (in my case with "SELECT"), nothing works. Neither the manual control works afterwards, nor the other programmed functions.

Unfortunately, I don't know whether there is an error in the code or whether it is the hardware. So I'll post my code and get back to you if I have any further questions. I would also like to add that I am an absolute beginner and apologize for individual errors in the forum. All my efforts have not helped and I could not find a similar topic to my problem.

I want the other buttons to work after I use the buzzer. Actually, I also intended to emit a sound when I press a button. But unfortunately my code seems to hang up.

#include <PS2X_lib.h>
#include <AFMotor.h>
#include <pitches.h>

#define PS2_DAT 9   // data
#define PS2_CMD 10  // command
#define PS2_SEL 2   // attention
#define PS2_CLK 13  // clock

PS2X ps2x;  // create PS2 Controller Class

int error = 0;  // for controller-connenction
byte type = 0;  // for controller-type

AF_DCMotor lmotor(1);  // left motor
AF_DCMotor rmotor(2);  // right motor

int echo = A1;     // echo pin connected to A1
int trigger = A2;  // trig pin connected to A2

long duration;        // variable for ultrasonic-sensor
int theDistance = 0;  // variable for ultrasonic-sensor

int keepDistance = 8;  // variable for ultrasonic-sensor

int infrared = A0;  // variable for infrared-sensor

int bobber = A5;  // variable for buzzer

int melody[] = {
  NOTE_C4, NOTE_C4,
  NOTE_D4, NOTE_C4, NOTE_F4,
  NOTE_E4, NOTE_C4, NOTE_C4,
  NOTE_D4, NOTE_C4, NOTE_G4,
  NOTE_F4, NOTE_C4, NOTE_C4,

  NOTE_C5, NOTE_A4, NOTE_F4,
  NOTE_E4, NOTE_D4, NOTE_AS4, NOTE_AS4,
  NOTE_A4, NOTE_F4, NOTE_G4,
  NOTE_F4
};

int durations[] = {
  4, 8,
  4, 4, 4,
  2, 4, 8,
  4, 4, 4,
  2, 4, 8,

  4, 4, 4,
  4, 4, 4, 8,
  4, 4, 4,
  2
};

//-------------------------------------------------- SETUP
void setup() {

  Serial.begin(9600);
  delay(400);  // time to startup, before configuring it

  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT);  // setup pins for PS2 Controller

  if (error == 0) {  // check for errors
    Serial.print("PS2 Controller successfully found and configured, B.O.B. is waiting :) -> ");
  } else {
    Serial.print("No PS2 Controller found, try again ");
    setup();
  }

  type = ps2x.readType();  // read type of Controller
  switch (type) {
    case 0:
      Serial.print("Unknown Controller type found ");
      break;
    case 1:
      Serial.print("DualShock Controller found ");
      break;
  }

  lmotor.setSpeed(200);  // left motor speed 200
  rmotor.setSpeed(200);  // right motor speed 200
  lmotor.run(RELEASE);   // release left motor
  rmotor.run(RELEASE);   // release right motor

  pinMode(echo, INPUT);      // echo as input
  pinMode(trigger, OUTPUT);  // trigger as output

  pinMode(infrared, INPUT);  // infrared as input

  pinMode(bobber, OUTPUT);  // buzzer as output
}


//-------------------------------------------------- LOOP
void loop() {

  if (error == !0)  // skip loop if no Controller found
    return;

  if (type == 1) {                  // DualShock Controller
    ps2x.read_gamepad();            // read Controller
    manualcontrol();                // use d-pad for manual control (already active)
    if (ps2x.Button(PSB_TRIANGLE))  // hold triangle to activate obstacle avoidance
      obstacleavoidance();
    if (ps2x.Button(PSB_CIRCLE))  // hold circle to activate following BOB
      followingbob();
    if (ps2x.Button(PSB_CROSS))  // hold cross to activate black-line driving
      blacklinedriving();
    if (ps2x.Button(PSB_SQUARE))  // hold square to activate avoid the black
      avoidtheblack();
    if (ps2x.ButtonPressed(PSB_START))  // press start to activate bobby-dance
      bobbydance();
    if (ps2x.ButtonPressed(PSB_SELECT))  // press select to activate bobbybirthday
      bobbybirthday();
  }
  delay(50);
}


//-------------------------------------------------- MANUAL CONTROL
void manualcontrol() {

  if (ps2x.Button(PSB_PAD_UP)) {  // move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_DOWN)) {  // move backward
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else if (ps2x.Button(PSB_PAD_LEFT)) {  // turn left
    lmotor.run(BACKWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_RIGHT)) {  // turn right
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  } else {  // stop
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- OBSTACLE AVIODANCE
void obstacleavoidance() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance <= 12) {  // move backward and turn right if distance is less than 12cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // otherwise move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
}


//-------------------------------------------------- FOLLOWING BOB
void followingbob() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance < keepDistance && theDistance >= 0) {  // move backward if the distance is less than 8cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance > (keepDistance + 3) && theDistance < (keepDistance + 20)) {  // move forward if the distance is more than 11cm
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
  if (theDistance > (keepDistance + 20)) {  // turn right if the distance is more than 28cm
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance >= keepDistance && theDistance <= (keepDistance + 3)) {  //stop if the distance is between 8cm and 11cm
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- IN ADDITION FOR OBSTACLE AVOIDANCE AND FOLLOWING BOB
int distance() {

  int echoTime;            // store the time for a ping to bounce off an object
  int calculatedDistance;  // store the calculated distance from the echo time

  digitalWrite(trigger, HIGH);  // ultrasonic pulse for 10ms
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  echoTime = pulseIn(echo, HIGH);  // time for the pulse to bounce back to the sensor

  calculatedDistance = echoTime / 2 / 29;  // calculate the distance of the reflected object (half the bounce time multiplied by the speed of sound)
  return calculatedDistance;               // send back the calculated distance
}


//-------------------------------------------------- BLACK-LINE DRIVING
void blacklinedriving() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move forward if black line detected
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else {  // turn right if not on a black line
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- AVOID THE BLACK
void avoidtheblack() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move backward and turn right if black line detected
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // move forward if not on a black line
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- BOBBY-DANCE
void bobbydance() {

  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(1000);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(1000);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(1200);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(FORWARD);
  delay(2000);
  lmotor.run(FORWARD);
  rmotor.run(BACKWARD);
  delay(2000);
}


void bobbybirthday() {

  int size = sizeof(durations) / sizeof(int);

  for (int note = 0; note < size; note++) {
    //to calculate the note duration, take one second divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int duration = 1000 / durations[note];
    tone(bobber, melody[note], duration);

    //to distinguish the notes, set a minimum time between them.
    //the note's duration + 30% seems to work well:
    int pauseBetweenNotes = duration * 1.30;
    delay(pauseBetweenNotes);

    //stop the tone playing:
    noTone(bobber);
  }
}

Dominik Bubak

Your code has a lot of delays.
Study how not to use delays, study blink without delay.

At this point, I had already figured out where you went wrong.

As a beginner, you don't know enough to be able to half follow someone else's design/instructions.

Step 1: follow the instructions completely and use the same components.
Step 2: test the project and get it working as the original designer intended. Any problems you encounter are unlikely to be in the code and more likely to be wiring errors or faulty components, so you have a good chance of finding & fixing them.
Step 3: get familiar with how the project behaves. It may have quirks you didn't expect.
Step 4: begin modifying the project to get closer to the way you wanted it or remove quirks etc. Go one small step and a time and test each time.

Thank you for the answer. I have used the delay 20 times, but as I understand it, delay pauses the program and executes my command during this time. If I were to use millis(), my bobby dance, for example, would no longer work.

The suggestion will not solve my problem.

delay() pauses your program and during the delay period Nothing. Else. Happens. Nothing.

a7

2 Likes

Thank you for the answer. I have already followed the instructions, but I have changed a few things. For example, the switch and the gamepad. Nobody has used a buzzer yet, but I wanted my robot to make sounds too. I've been working on it for 3 months at university and I kept running into difficulties. Everything works great, but I can't find a solution for the buzzer, because somehow it blocks the whole code afterwards. I first have to remove the power supply and then turn it on again for it to work. But of course I don't want to keep switching off my vehicle after I've activated my buzzer.

Yes I know. But if I write in my code that the left and right motors should rotate forwards, I use delay to specify a certain time in which this is executed. Then, for example, it should move backwards for a certain time.

Sorry, I took your words literally.

So now you don't have a software problem. Your sound function blocks, but should complete and then your other code would continue.

Can you just do the bobbybirthday() from your loop function, automatically with maybe a delay after!

Then can you do just the bobbybirthday() by command, with no motors or other things going on?

Please post a schematic of you project, be sure to show where power comes from and how it gets to the things that need it.

a7

Hi @dominik04,

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

From a first look your code should work. But maybe I am overlooking some detail.

To narrow down the problem you should simplify your buzzer-code.
Which is - if I understand right - the bobbybirthday() function
comment out all the code inside this function and then add a single tone() notone()
just to check if the function can be called and executed properly

best regards Stefan

You did :slight_smile: The melody takes approximately 9 seconds to play using a for-loop and delays.

We understand why you started your project with the use of delay; but there are scenarios where it will not result in code that does what you want it to do. You have just encountered one such scenario.

You will have to rework your code completely and get rid of delay everywhere in favour of a millis() based approach and use of finite state machines. For the bobbybirthday() function, you will need to get rid of the for-loop as well.

Before I explain how you can approach it, first something about your melody and durations. Each entry in in the melody array has a match in the durations array. You can combine the two in a class or struct; in the below I use the latter. A struct is like an entry in a phonebook where you have a name and a phone number and possibly other information combined together.

/*
struct for a note in a melody
*/
struct NOTE
{
  uint16_t note;
  uint32_t duration;
};

You can now create an array of those structs for the birthday melody (I hope I haven't made mistakes).

/*
array with notes and durations for birthday melody
*/
NOTE birthdayMelody[] = {
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_C5, 4},
  {NOTE_A4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 4},
  {NOTE_D4, 4},
  {NOTE_AS4, 4},
  {NOTE_AS4, 8},

  {NOTE_A4, 4},
  {NOTE_F4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
};

With the above, we can now start building a non-blocking 'happy birthday'

/*
Play the happy birthday melody in a non-blocking way
Returns:
  true if the playout of the melody is complete, false if still in progress
*/
bool bobbybirthdayNonblock()
{
  // status of note in melody
  enum MELODYSTATES
  {
    NOTPLAYING,
    PLAYING,
  };
  // remember play status of note
  static MELODYSTATES state = NOTPLAYING;

  // remember note that is playing
  static uint16_t noteIndex = 0;
  // remember time that note started
  static uint32_t noteStarttime;
  
  ...
  ...
}

All variables above are static; this is similar to a global variable but the variable is only known inside the function.

The enum is used for the finite state machine; the function can be in one of two states, either not playing a note or playing a note. The variable state keeps track of this.

The variable noteIndex replaces your variable note in the for-loop. And lastly there is a variable noteStarttime to keep track of the time that a note of the melody started playing.

The full function

/*
Play the happy birthday melody in a non-blocking way
Returns:
  true if the playout of the melody is complete, false if still in progress
*/
bool bobbybirthdayNonblock()
{
  // status of note in melody
  enum MELODYSTATES
  {
    NOTPLAYING,
    PLAYING,
  };
  // remember play status of note
  static MELODYSTATES state = NOTPLAYING;

  // remember note that is playing
  static uint16_t noteIndex = 0;
  // remember time that note started
  static uint32_t noteStarttime;

  // return value
  bool rv = false;

  // calculate the duration
  int duration = 1000 / birthdayMelody[noteIndex].duration;

  switch (state)
  {
    case NOTPLAYING:
      // play the note indicated by noteIndex
      tone(bobber, birthdayMelody[noteIndex].note, duration);
      // keep track of the start time
      noteStarttime = millis();
      // change the state of the finite state machine
      state = PLAYING;
      break;
    case PLAYING:
      // if it's time for the next note in the melody
      if (millis() - noteStarttime >= duration * 1.30)
      {
        // next note
        noteIndex++;
        // change the state
        state = NOTPLAYING;
        // if all notes of the melody have played
        if (noteIndex >= NUMELEMENTS(birthdayMelody))
        {
          // reset
          noteIndex = 0;
          // set the return value to indicate that the melody is completed
          rv = true;
        }
      }
      break;
  }

  // andicate to the caller the status of the palying of the melody.
  return rv;
}

There is one additional variable, rv. You might not have a need for it but it will be set to true when the melody played completely.

You used int size = sizeof(durationsOld) / sizeof(int); and there is nothing wrong with that. A more usiversal approach that can be used for any type of array is the following macro

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

This is used in the above code to calculate the number of elements in the birthdayMelody array.

Full demo code below; be aware that other delays in your existing code will affect this function; you will have to rewrite everything to get rid of the delays.

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

#include "pitches.h"

// note the use of const and of uint8_t
const uint8_t bobber = A5;  // variable for buzzer


/*
struct for a note in a melody
*/
struct NOTE
{
  uint16_t note;
  uint32_t duration;
};

/*
array with notes and durations for birthday melody
*/
NOTE birthdayMelody[] = {
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_C5, 4},
  {NOTE_A4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 4},
  {NOTE_D4, 4},
  {NOTE_AS4, 4},
  {NOTE_AS4, 8},

  {NOTE_A4, 4},
  {NOTE_F4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
};

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  bool melodyComplete = bobbybirthdayNonblock();
  if (melodyComplete == true)
  {
    Serial.println(F("melody complete"));
  }
}


/*
Play the happy birthday melody in a non-blocking way
Returns:
  true if the playout of the melody is complete, false if still in progress
*/
bool bobbybirthdayNonblock()
{
  // status of note in melody
  enum MELODYSTATES
  {
    NOTPLAYING,
    PLAYING,
  };
  // remember play status of note
  static MELODYSTATES state = NOTPLAYING;

  // remember note that is playing
  static uint16_t noteIndex = 0;
  // remember time that note started
  static uint32_t noteStarttime;

  // return value
  bool rv = false;

  // calculate the duration
  int duration = 1000 / birthdayMelody[noteIndex].duration;

  switch (state)
  {
    case NOTPLAYING:
      // play the note indicated by noteIndex
      tone(bobber, birthdayMelody[noteIndex].note, duration);
      // keep track of the start time
      noteStarttime = millis();
      // change the state of the finite state machine
      state = PLAYING;
      break;
    case PLAYING:
      // if it's time for the next note in the melody
      if (millis() - noteStarttime >= duration * 1.30)
      {
        // next note
        noteIndex++;
        // change the state
        state = NOTPLAYING;
        // if all notes of the melody have played
        if (noteIndex >= NUMELEMENTS(birthdayMelody))
        {
          // reset
          noteIndex = 0;
          // set the return value to indicate that the melody is completed
          rv = true;
        }
      }
      break;
  }

  // indicate to the caller the status of the palying of the melody.
  return rv;
}

Maybe more tomorrow as demo how to use a finite state machine for bobbydance().

3 Likes

For bobbydance() you can use the same approach as above. You have a sequence of moves; you can store them in an array of structs. The sturct below stores the 'settings' for the two motors as well as the duration of the move.

/*
struct for a dance move
*/
struct DANCEMOVE
{
  uint8_t left;
  uint8_t right;
  uint32_t duration;
};

The array (based on bobbydance()) below (again, I hope I did not miss something)

/*
array with dance moves and durations
*/
DANCEMOVE danceMoves[] = {
  {FORWARD, FORWARD, 1000},
  {FORWARD, FORWARD, 1000},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 1200},
  {RELEASE, RELEASE, 200},
  {BACKWARD, FORWARD, 2000},
  {FORWARD, BACKWARD, 2000},
};

The function for the dance starts in the same way as the melody. The enum again describes to states; in the move state the motors are instructed and a timer is started and in the wait state the program waits again till the time has lapsed before going to the next move.

/*
Dance in a non-blocking way
Returns:
  true if dance is complete, else false
*/
bool bobbydanceNonblock()
{
  // status of note in melody
  enum MOVESTATES
  {
    MOVE,
    WAIT,
  };
  // remember play status of note
  static MOVESTATES state = MOVE;

  // remember note that is playing
  static uint16_t danceIndex = 0;
  // remember time that note started
  static uint32_t moveStarttime;

  // return value
  bool rv = false;
  
  ...
  ...

See if you can complete bobbydanceNonblock() using bobbybirthdayNonblock() as the guide. If you're stuck, ask.

Below would be a full demo code without the finite state machine implementation of bobbydanceNonblock(); if bobbydanceNonblock() is implemented correctly bobby will dance and play the birthday melody at the same time.

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

#include "pitches.h"

#include <AFMotor.h>

AF_DCMotor lmotor(1);  // left motor
AF_DCMotor rmotor(2);  // right motor

/*
struct for a dance move
*/
struct DANCEMOVE
{
  uint8_t left;
  uint8_t right;
  uint32_t duration;
};

/*
array with dance moves and durations
*/
DANCEMOVE danceMoves[] = {
  {FORWARD, FORWARD, 1000},
  {FORWARD, FORWARD, 1000},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 200},
  {FORWARD, FORWARD, 200},
  {BACKWARD, BACKWARD, 1200},
  {RELEASE, RELEASE, 200},
  {BACKWARD, FORWARD, 2000},
  {FORWARD, BACKWARD, 2000},
  //{RELEASE, RELEASE, 20000}, // test
};



// note the use of const and of uint8_t
const uint8_t bobber = A5;  // variable for buzzer


/*
struct for a note in a melody
*/
struct NOTE
{
  uint16_t note;
  uint32_t duration;
};

/*
array with notes and durations for birthday melody
*/
NOTE birthdayMelody[] = {
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_D4, 4},
  {NOTE_C4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
  {NOTE_C4, 4},
  {NOTE_C4, 8},

  {NOTE_C5, 4},
  {NOTE_A4, 4},
  {NOTE_F4, 4},

  {NOTE_E4, 4},
  {NOTE_D4, 4},
  {NOTE_AS4, 4},
  {NOTE_AS4, 8},

  {NOTE_A4, 4},
  {NOTE_F4, 4},
  {NOTE_G4, 4},

  {NOTE_F4, 2},
};

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  bool melodyComplete = bobbybirthdayNonblock();
  if (melodyComplete == true)
  {
    Serial.println(F("====== melody complete ======"));
  }
  
  if(bobbydanceNonblock() == true)
  {
    Serial.println(F("====== Bobby did a dance ======"));
  }  
}


/*
Play the happy birthday melody in a non-blocking way
Returns:
  true if the playout of the melody is complete, false if still in progress
*/
bool bobbybirthdayNonblock()
{
  // status of note in melody
  enum MELODYSTATES
  {
    NOTPLAYING,
    PLAYING,
  };
  // remember play status of note
  static MELODYSTATES state = NOTPLAYING;

  // remember note that is playing
  static uint16_t noteIndex = 0;
  // remember time that note started
  static uint32_t noteStarttime;

  // return value
  bool rv = false;

  // calculate the duration
  int duration = 1000 / birthdayMelody[noteIndex].duration;

  switch (state)
  {
    case NOTPLAYING:
      // play the note indicated by noteIndex
      tone(bobber, birthdayMelody[noteIndex].note, duration);
      // keep track of the start time
      noteStarttime = millis();
      // change the state of the finite state machine
      state = PLAYING;
      break;
    case PLAYING:
      // if it's time for the next note in the melody
      if (millis() - noteStarttime >= duration * 1.30)
      {
        // next note
        noteIndex++;
        // change the state
        state = NOTPLAYING;
        // if all notes of the melody have played
        if (noteIndex >= NUMELEMENTS(birthdayMelody))
        {
          // reset
          noteIndex = 0;
          // set the return value to indicate that the melody is completed
          rv = true;
        }
      }
      break;
  }

  // indicate to the caller the status of the playing of the melody.
  return rv;
}

//-------------------------------------------------- BOBBY-DANCE
/*
Dance in a non-blocking way
Returns:
  true if dance is complete, else false
*/
bool bobbydanceNonblock()
{
 // status of note in melody
  enum MOVESTATES
  {
    MOVE,
    WAIT,
  };
  // remember status of move
  static MOVESTATES state = MOVE;

  // remember current dance move
  static uint16_t danceIndex = 0;
  // remember time that move started
  static uint32_t moveStarttime;

  // return value
  bool rv = false;

    for you to implement the finite state machine
  
  
  // indicate to the caller the status of the move
  return rv;
}

Note:
In loop() the return value bobbydanceNonblock() is not stored; it depends on your needs if you need to do that.

3 Likes

To be fair, no one overlooked anything. Not the OP, nor the responders.

I pointed out the use of delays as I think did others as the problem. The OP said she understood,

demonstrating a lack of understanding, but further comments on her part could only be interpreted as meaning that she did, indeed, understand.

Leaving the only interpretation of the original problem description, viz:

as meaning the sketch went off into the woods period full stop.

Not for nine seconds, and no mention that there was even a peep from the buzzer.

I certainly hope @sterretje's fine intro to programming in a different way lands and is indeed the solution to the problem.

But it is a reminder that until the problem is completely understood, there is potential for wasting time working on it.

So, @dominik04, might you have said that the buzzer plays the tune, but during that excruciating nine seconds the controls for your toy are unresponsive?

Note: all typos and thinkos in this post are because I was unceremoniously logged out by ? and when I came back only half the draft message had been auto saved and I'm just too lazy to comb through it just now. Maybe later.

a7

Hello, no, that's not what I meant. I'm not at all concerned with being able to operate my robot at the same time. I understand that I can't control anything else while it's running and that's why my problem is unfortunately not solved by @sterretje. However, I find it interesting how the delays were circumvented and I have definitely learned something new. So thanks for that!

Here is the normal sketch without using the buzzer:

#include <PS2X_lib.h>
#include <AFMotor.h>
#include <pitches.h>

#define PS2_DAT 9   // data
#define PS2_CMD 10  // command
#define PS2_SEL 2   // attention
#define PS2_CLK 13  // clock

PS2X ps2x;  // create PS2 Controller Class

int error = 0;  // for controller-connenction
byte type = 0;  // for controller-type

AF_DCMotor lmotor(1);  // left motor
AF_DCMotor rmotor(2);  // right motor

int echo = A1;     // echo pin connected to A1
int trigger = A2;  // trig pin connected to A2

long duration;        // variable for ultrasonic-sensor
int theDistance = 0;  // variable for ultrasonic-sensor

int keepDistance = 8;  // variable for ultrasonic-sensor

int infrared = A0;  // variable for infrared-sensor

int bobber = A5;  // variable for buzzer


//-------------------------------------------------- SETUP
void setup() {

  Serial.begin(9600);
  delay(400);  // time to startup, before configuring it

  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT);  // setup pins for PS2 Controller

  if (error == 0) {  // check for errors
    Serial.print("PS2 Controller successfully found and configured, B.O.B. is waiting :) -> ");
  } else {
    Serial.print("No PS2 Controller found, try again ");
    setup();
  }

  type = ps2x.readType();  // read type of Controller
  switch (type) {
    case 0:
      Serial.print("Unknown Controller type found ");
      break;
    case 1:
      Serial.print("DualShock Controller found ");
      break;
  }

  lmotor.setSpeed(200);  // left motor speed 200
  rmotor.setSpeed(200);  // right motor speed 200
  lmotor.run(RELEASE);   // release left motor
  rmotor.run(RELEASE);   // release right motor

  pinMode(echo, INPUT);      // echo as input
  pinMode(trigger, OUTPUT);  // trigger as output

  pinMode(infrared, INPUT);  // infrared as input

  pinMode(bobber, OUTPUT);  // buzzer as output
}


//-------------------------------------------------- LOOP
void loop() {

  if (error == !0)  // skip loop if no Controller found
    return;

  if (type == 1) {                  // DualShock Controller
    ps2x.read_gamepad();            // read Controller
    manualcontrol();                // use d-pad for manual control (already active)
    if (ps2x.Button(PSB_TRIANGLE))  // hold triangle to activate obstacle avoidance
      obstacleavoidance();
    if (ps2x.Button(PSB_CIRCLE))  // hold circle to activate following BOB
      followingbob();
    if (ps2x.Button(PSB_CROSS))  // hold cross to activate black-line driving
      blacklinedriving();
    if (ps2x.Button(PSB_SQUARE))  // hold square to activate avoid the black
      avoidtheblack();
    if (ps2x.ButtonPressed(PSB_START))  // press start to activate bobby-dance
      bobbydance();
  }
  delay(50);
}


//-------------------------------------------------- MANUAL CONTROL
void manualcontrol() {

  if (ps2x.Button(PSB_PAD_UP)) {  // move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_DOWN)) {  // move backward
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else if (ps2x.Button(PSB_PAD_LEFT)) {  // turn left
    lmotor.run(BACKWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_RIGHT)) {  // turn right
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  } else {  // stop
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- OBSTACLE AVIODANCE
void obstacleavoidance() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance <= 12) {  // move backward and turn right if distance is less than 12cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // otherwise move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
}


//-------------------------------------------------- FOLLOWING BOB
void followingbob() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance < keepDistance && theDistance >= 0) {  // move backward if the distance is less than 8cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance > (keepDistance + 3) && theDistance < (keepDistance + 20)) {  // move forward if the distance is more than 11cm
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
  if (theDistance > (keepDistance + 20)) {  // turn right if the distance is more than 28cm
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance >= keepDistance && theDistance <= (keepDistance + 3)) {  //stop if the distance is between 8cm and 11cm
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- IN ADDITION FOR OBSTACLE AVOIDANCE AND FOLLOWING BOB
int distance() {

  int echoTime;            // store the time for a ping to bounce off an object
  int calculatedDistance;  // store the calculated distance from the echo time

  digitalWrite(trigger, HIGH);  // ultrasonic pulse for 10ms
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  echoTime = pulseIn(echo, HIGH);  // time for the pulse to bounce back to the sensor

  calculatedDistance = echoTime / 2 / 29;  // calculate the distance of the reflected object (half the bounce time multiplied by the speed of sound)
  return calculatedDistance;               // send back the calculated distance
}


//-------------------------------------------------- BLACK-LINE DRIVING
void blacklinedriving() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move forward if black line detected
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else {  // turn right if not on a black line
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- AVOID THE BLACK
void avoidtheblack() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move backward and turn right if black line detected
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // move forward if not on a black line
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- BOBBY-DANCE
void bobbydance() {

  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(1000);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(1000);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(1200);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(FORWARD);
  delay(2000);
  lmotor.run(FORWARD);
  rmotor.run(BACKWARD);
  delay(2000);
}

Now I'll change the loop as an illustration of my problem:

void loop() {

  if (error == !0)  // skip loop if no Controller found
    return;

  if (type == 1) {                  // DualShock Controller
    ps2x.read_gamepad();            // read Controller
    manualcontrol();                // use d-pad for manual control (already active)
    if (ps2x.Button(PSB_TRIANGLE))  // hold triangle to activate obstacle avoidance
      obstacleavoidance();
    if (ps2x.Button(PSB_CIRCLE))  // hold circle to activate following BOB
      followingbob();
    if (ps2x.Button(PSB_CROSS))  // hold cross to activate black-line driving
      blacklinedriving();
    if (ps2x.Button(PSB_SQUARE))  // hold square to activate avoid the black
      avoidtheblack();
    if (ps2x.ButtonPressed(PSB_START))  // press start to activate bobby-dance
      bobbydance();
    if (ps2x.Button(PSB_SELECT)) // 
      buzzertest();
  }
  delay(50);
}

void buzzertest() {
  tone(bobber, 440, 60);
}

Perhaps to make it clearer now: I can drive forwards and backwards with the help of my controller, and I can do everything else too. Now I press "SELECT" on the controller once to play the sound. I can press it as much as I want and hold it for as long as I want. But all the other buttons on the controller suddenly stop working. The buzzer still works. To get all the functions back, I have to disconnect the power supply and press my switch. I switch it on next and can ride again as I like. However, if I press Select, everything starts all over again.

@alto777 I've never created a schematic before and it might take me a while to get it done but I'm happy to take the time. My experience is still too limited for that. If a picture of the vehicle and an explanation could help, then I am also open to that. Thank you for taking the time to help solving my problem.

Dominik Bubak

OK, I think we can all be on the same page now.

Just to be sure and remove any possibility for misunderstanding, please post in one code block the entire sketch that

  • does not have a nine seconds long melody
  • has buttons that "suddenly" stop working

As for the diagram, pencil and paper work well. You might google

electronic shematic

choose images and look at a few. But don't sweat it, just…

Portray all components as blocks, and draw the wires that connect them. Label the blocks with the component it represents, and show the pin numbers.

Pay particular attention and show all sources of power, and how power is routed to the components that need it. Indicate distances and the gauge of the wires.

A picture would help. Several would be better. No need to hire Richard Avedon, just make sure we can see the nature of your physical circumstances.

TIA

a7

Here is my entire sketch in one code block that does not include a nine seconds long melody and has buttons that "suddenly" stop working after using the buzzer:

#include <PS2X_lib.h>
#include <AFMotor.h>
#include <pitches.h>

#define PS2_DAT 9   // data
#define PS2_CMD 10  // command
#define PS2_SEL 2   // attention
#define PS2_CLK 13  // clock

PS2X ps2x;  // create PS2 Controller Class

int error = 0;  // for controller-connenction
byte type = 0;  // for controller-type

AF_DCMotor lmotor(1);  // left motor
AF_DCMotor rmotor(2);  // right motor

int echo = A1;     // echo pin connected to A1
int trigger = A2;  // trig pin connected to A2

long duration;        // variable for ultrasonic-sensor
int theDistance = 0;  // variable for ultrasonic-sensor

int keepDistance = 8;  // variable for ultrasonic-sensor

int infrared = A0;  // variable for infrared-sensor

int bobber = A5;  // variable for buzzer


//-------------------------------------------------- SETUP
void setup() {

  Serial.begin(9600);
  delay(400);  // time to startup, before configuring it

  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT);  // setup pins for PS2 Controller

  if (error == 0) {  // check for errors
    Serial.print("PS2 Controller successfully found and configured, B.O.B. is waiting :) -> ");
  } else {
    Serial.print("No PS2 Controller found, try again ");
    setup();
  }

  type = ps2x.readType();  // read type of Controller
  switch (type) {
    case 0:
      Serial.print("Unknown Controller type found ");
      break;
    case 1:
      Serial.print("DualShock Controller found ");
      break;
  }

  lmotor.setSpeed(200);  // left motor speed 200
  rmotor.setSpeed(200);  // right motor speed 200
  lmotor.run(RELEASE);   // release left motor
  rmotor.run(RELEASE);   // release right motor

  pinMode(echo, INPUT);      // echo as input
  pinMode(trigger, OUTPUT);  // trigger as output

  pinMode(infrared, INPUT);  // infrared as input

  pinMode(bobber, OUTPUT);  // buzzer as output
}


//-------------------------------------------------- LOOP
void loop() {

  if (error == !0)  // skip loop if no Controller found
    return;

  if (type == 1) {                  // DualShock Controller
    ps2x.read_gamepad();            // read Controller
    manualcontrol();                // use d-pad for manual control (already active)
    if (ps2x.Button(PSB_TRIANGLE))  // hold triangle to activate obstacle avoidance
      obstacleavoidance();
    if (ps2x.Button(PSB_CIRCLE))  // hold circle to activate following BOB
      followingbob();
    if (ps2x.Button(PSB_CROSS))  // hold cross to activate black-line driving
      blacklinedriving();
    if (ps2x.Button(PSB_SQUARE))  // hold square to activate avoid the black
      avoidtheblack();
    if (ps2x.ButtonPressed(PSB_START))  // press start to activate bobby-dance
      bobbydance();
    if (ps2x.Button(PSB_SELECT)) // 
      buzzertest();
  }
  delay(50);
}


//-------------------------------------------------- MANUAL CONTROL
void manualcontrol() {

  if (ps2x.Button(PSB_PAD_UP)) {  // move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_DOWN)) {  // move backward
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else if (ps2x.Button(PSB_PAD_LEFT)) {  // turn left
    lmotor.run(BACKWARD);
    rmotor.run(FORWARD);
  } else if (ps2x.Button(PSB_PAD_RIGHT)) {  // turn right
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  } else {  // stop
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- OBSTACLE AVIODANCE
void obstacleavoidance() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance <= 12) {  // move backward and turn right if distance is less than 12cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // otherwise move forward
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
}


//-------------------------------------------------- FOLLOWING BOB
void followingbob() {

  theDistance = distance();     // store the measured distance
  Serial.println(theDistance);  // print the measured distance

  if (theDistance < keepDistance && theDistance >= 0) {  // move backward if the distance is less than 8cm
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance > (keepDistance + 3) && theDistance < (keepDistance + 20)) {  // move forward if the distance is more than 11cm
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
  }
  if (theDistance > (keepDistance + 20)) {  // turn right if the distance is more than 28cm
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
  if (theDistance >= keepDistance && theDistance <= (keepDistance + 3)) {  //stop if the distance is between 8cm and 11cm
    lmotor.run(RELEASE);
    rmotor.run(RELEASE);
  }
}


//-------------------------------------------------- IN ADDITION FOR OBSTACLE AVOIDANCE AND FOLLOWING BOB
int distance() {

  int echoTime;            // store the time for a ping to bounce off an object
  int calculatedDistance;  // store the calculated distance from the echo time

  digitalWrite(trigger, HIGH);  // ultrasonic pulse for 10ms
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  echoTime = pulseIn(echo, HIGH);  // time for the pulse to bounce back to the sensor

  calculatedDistance = echoTime / 2 / 29;  // calculate the distance of the reflected object (half the bounce time multiplied by the speed of sound)
  return calculatedDistance;               // send back the calculated distance
}


//-------------------------------------------------- BLACK-LINE DRIVING
void blacklinedriving() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move forward if black line detected
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  } else {  // turn right if not on a black line
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- AVOID THE BLACK
void avoidtheblack() {

  int ifrstate = digitalRead(infrared);  // store the state of the infrared-sensor

  if (ifrstate == 1) {  // move backward and turn right if black line detected
    lmotor.run(FORWARD);
    rmotor.run(FORWARD);
    delay(500);
    lmotor.run(FORWARD);
    rmotor.run(BACKWARD);
    delay(500);
  } else {  // move forward if not on a black line
    lmotor.run(BACKWARD);
    rmotor.run(BACKWARD);
  }
}


//-------------------------------------------------- BOBBY-DANCE
void bobbydance() {

  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(1000);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(1000);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(200);
  lmotor.run(FORWARD);
  rmotor.run(FORWARD);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(BACKWARD);
  delay(1200);
  lmotor.run(RELEASE);
  rmotor.run(RELEASE);
  delay(200);
  lmotor.run(BACKWARD);
  rmotor.run(FORWARD);
  delay(2000);
  lmotor.run(FORWARD);
  rmotor.run(BACKWARD);
  delay(2000);
}

void buzzertest() {
  tone(bobber, 440, 60);
}

I hope that my first schematic is okay.

Here are two more pictures of my car:


1 Like

Very good enough and a better first time schematic than most.

If you can find an alternate source of 9 volts that could deliver more current, we would stop worrying that the battery is entirely inadequate for that system.

Just as a test.

Another experiment would be a bit trickier given your use of the motor shield - that would be to remove the items that require large currents (motors is what I see mostly) and replace them with low power proxies like LEDs with series current limiting resistors.

So instead of the right hand motor spinning, or whatever, a LED would light showing what is supposed to happen when.

In general, to the extent possible, try to get the logic working before you get the vehicle moving.

I can't pore over your code, but things that suddenly change with no reason are almost always hardware related issues; the 9 volt battery is notorious and universally derided as a power source for just about anything beyond smoke detectors.

If you have a volt meter, it might be instructive to monitor the voltage that the battery is managing to deliver - observe the battery voltage directly, and observe the 5 volt signal on the Arduino board that the battery is also expected to deliver.

The L298 motor driver is a 20th century part, it is unfortunate that they are still so popular. It can be made to work, but at some point when you are a bit further along you should consider replacing it with something modern, if only to increase the performance of your little truck. Which looks to me like that you are having more fun with than anything going on around here :expressionless: , even if just now things aren't going to plan.

a7

I recently used a power supply because I couldn't control my robot without a USB cable. I solved the problem differently. But what I actually want to say is that I offered the robot 9V and 500 milliamps to draw and it drew around milli300 amps when in use. The 9V block battery delivers 200mAh, so doesn't that mean it can run for around 40 minutes and the required current is sufficient?

The supplied current flowing through the USB cable will certainly be enough. But even in this construction I have the problem. What I would like to ask is whether the tests regarding the battery are then irrelevant? As I said, I am still a beginner and would be happy to be taught better.

I have also seen that there are passive buzzers with 2 or 3 pins, but unfortunately I could not find any information about the differences between them. There are also buzzers on a module. Is this just to make it easier to connect the buzzer with wire and fix the module? I also think it's a hardware problem.

Wow!

Pretty sure you are off by three orders of magnitude there.

But srsly. First, batteries have one number to say how much energy is in them, that's a product of current and time. 200 milliampere hours.

How long you can draw current. Within reason time and current can be traded off. 200 mA for an hour, 100 mA for two hours and so forth.

The other more important and harder to find number is the battery's ability to deliver current.

The nine volt battery cannot, for example, deliver 200 Amperes for 18 seconds. Or 1.8 seconds. Or 180 milliseconds… just for never ever no time at all.

Do the measurements. I think it is unlikely that that small battery can deliver adequate current to power your project. Period. If it could, it wouldn't be for very long.

There re batteries that woud work. LiPo batteries used in the radio control hobby are wonderful sources of power and can deliver enormous current, As such, they need to be treated with some respect, learn about them before you ever touch them. Ask here about anything along that line of inquiry before you spend or waste money.

HTH

a7

1 Like

Sorry, I meant 500 milliamps, of course. Thanks for all the advice, but regardless, I mentioned that it should also work via USB cable. No current is drawn from the battery during this time because the switch is not on. I'm not talking about the problem that it works with the USB cable and not without, but that nothing else works (except the buzzer) after the buzzer has made a sound. What can the battery do if it is not even in use?

You are currently a bit blind because you do not always know what is going on. I have stripped the sketch from post #16 so it does not control the motors but instead prints which buttons are pressed when the relevant function is called.

This should give you an idea if the buttons are still recognised after the buzzer was activated. If that is not the case

  1. I think that we can eliminate the motors and power as a possible cause; you can still strip a bit more around the motors out of the code but I do not know if that will make a difference.
  2. In PS2X_lib.h, you can enable debugging which might reveal something.

OOPS, forgot the code:

#include <PS2X_lib.h>
#include <AFMotor.h>
#include "pitches.h"

#define PS2_DAT 9   // data
#define PS2_CMD 10  // command
#define PS2_SEL 2   // attention
#define PS2_CLK 13  // clock

PS2X ps2x;  // create PS2 Controller Class

int error = 0;  // for controller-connenction
byte type = 0;  // for controller-type

AF_DCMotor lmotor(1);  // left motor
AF_DCMotor rmotor(2);  // right motor

int echo = A1;     // echo pin connected to A1
int trigger = A2;  // trig pin connected to A2

long duration;        // variable for ultrasonic-sensor
int theDistance = 0;  // variable for ultrasonic-sensor

int keepDistance = 8;  // variable for ultrasonic-sensor

int infrared = A0;  // variable for infrared-sensor

int bobber = A5;  // variable for buzzer


//-------------------------------------------------- SETUP
void setup()
{

  Serial.begin(9600);
  delay(400);  // time to startup, before configuring it

  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT);  // setup pins for PS2 Controller

  if (error == 0)
  {  // check for errors
    Serial.print("PS2 Controller successfully found and configured, B.O.B. is waiting :) -> ");
  }
  else
  {
    Serial.print("No PS2 Controller found, try again ");
    setup();
  }

  type = ps2x.readType();  // read type of Controller
  switch (type)
  {
    case 0:
      Serial.print("Unknown Controller type found ");
      break;
    case 1:
      Serial.print("DualShock Controller found ");
      break;
  }

  lmotor.setSpeed(200);  // left motor speed 200
  rmotor.setSpeed(200);  // right motor speed 200
  lmotor.run(RELEASE);   // release left motor
  rmotor.run(RELEASE);   // release right motor

  pinMode(echo, INPUT);      // echo as input
  pinMode(trigger, OUTPUT);  // trigger as output

  pinMode(infrared, INPUT);  // infrared as input

  pinMode(bobber, OUTPUT);  // buzzer as output
}


//-------------------------------------------------- LOOP
void loop()
{

  if (error == !0)  // skip loop if no Controller found
    return;

  if (type == 1)
  {                                 // DualShock Controller
    ps2x.read_gamepad();            // read Controller
    manualcontrol();                // use d-pad for manual control (already active)
    if (ps2x.Button(PSB_TRIANGLE))  // hold triangle to activate obstacle avoidance
      obstacleavoidance();
    if (ps2x.Button(PSB_CIRCLE))  // hold circle to activate following BOB
      followingbob();
    if (ps2x.Button(PSB_CROSS))  // hold cross to activate black-line driving
      blacklinedriving();
    if (ps2x.Button(PSB_SQUARE))  // hold square to activate avoid the black
      avoidtheblack();
    if (ps2x.ButtonPressed(PSB_START))  // press start to activate bobby-dance
      bobbydance();
    if (ps2x.Button(PSB_SELECT))  //
      buzzertest();
  }
  delay(50);
}


//-------------------------------------------------- MANUAL CONTROL
void manualcontrol()
{
  Serial.println("manual control");
}


//-------------------------------------------------- OBSTACLE AVIODANCE
void obstacleavoidance()
{
  Serial.println("obstacle avoidance");
}


//-------------------------------------------------- FOLLOWING BOB
void followingbob()
{
  Serial.println("following bob");
}


//-------------------------------------------------- IN ADDITION FOR OBSTACLE AVOIDANCE AND FOLLOWING BOB
int distance()
{
  int echoTime;            // store the time for a ping to bounce off an object
  int calculatedDistance;  // store the calculated distance from the echo time

  digitalWrite(trigger, HIGH);  // ultrasonic pulse for 10ms
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  echoTime = pulseIn(echo, HIGH);  // time for the pulse to bounce back to the sensor

  calculatedDistance = echoTime / 2 / 29;  // calculate the distance of the reflected object (half the bounce time multiplied by the speed of sound)
  return calculatedDistance;               // send back the calculated distance
}


//-------------------------------------------------- BLACK-LINE DRIVING
void blacklinedriving()
{
  Serial.println("black line driving");
}


//-------------------------------------------------- AVOID THE BLACK
void avoidtheblack()
{
  Serial.println("avoid the black");
}


//-------------------------------------------------- BOBBY-DANCE
void bobbydance()
{
  Serial.println("bobby dance");
}

void buzzertest()
{
  tone(bobber, 440, 60);
}