Help with Serial Monitor and Everything Else

(First Post!)

Here I have a code that... was made by ChatGPT, and modified for a project I'm making.
It supposedly is to do the following:

  1. When the Arduino turns on, the LEDS will do an idle animation that has running lights going from left to right. The LCD Screen should display "Reaction-Time-Test!"
  2. The player presses the button again to start the game.
  3. The LEDS will randomize its lighting first before it stops at one random LED, then the Piezzo Buzzer sounds for half a second.
  4. The LCD Screen should play a stopwatch before the player moves an object aligned to a lit up LED.
  5. The Ultrasonic Sensor will detect (after 2 seconds) if an object is in the correct distance. The farthest LED will be about 40cm, second LED will be about 30cm, third LED will be about 20cm, fourth LED will be about 10cm.
  6. After two seconds, if the player aligns the object to the LIT up LED, the LCD screen will display "CORRECT!" then the stopwatch stops. Step 3 will happen again for Round 2. There will be 10 rounds.
  7. However, if the player doesn't align the object with an LED, the LCD displays "WRONG!" and they go back to the first round, regardless of what round they are in.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int echoPin = 2;               // EchoPin-ULTRASONIC
const int trigPin = 3;               // TriggerPin-ULTRASONIC
const int ONOFF = 4;                 // BUTTON
const int BEEP = 5;                  // BUZZER
const int LIGHT[] = { 6, 7, 8, 9 };  // LEDs

// For ULTRASONIC (in centimeters)
const int distance1 = 40;
const int distance2 = 30;
const int distance3 = 20;
const int distance4 = 10;

// Game Configuration
const int rounds = 10;
enum GameModes {
  IDLE,
  WAITING_FOR_BUTTON,
  RANDOMIZING_LEDS,
  WAITING_FOR_OBJECT,
  CHECKING_DISTANCE,
  CORRECT_ANSWER,
  WRONG_ANSWER
};

// Default GameMode
int state = IDLE;
unsigned long startTime;
int currentRound = 1;
int targetLED;

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(LIGHT[i], OUTPUT);
  }
  pinMode(ONOFF, INPUT_PULLUP);
  pinMode(BEEP, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(trigPin, OUTPUT);

  lcd.begin(16, 2);
  lcd.backlight();

  Serial.begin(9600);
}

void loop() {
  switch (state) {
    case IDLE:
      lcd.setCursor(0, 0);
      lcd.print("The R.T.T!");
      lcd.setCursor(0, 1);
      lcd.print("Press Button");
      idleAnimation();
      break;

    case WAITING_FOR_BUTTON:
      int buttonState = digitalRead(ONOFF);
      Serial.println("Button State: " + String(buttonState));
      if (ONOFF == LOW) {
        startGame();
      }
      break;

    case RANDOMIZING_LEDS:
      randomizeLEDs();
      break;

    case WAITING_FOR_OBJECT:  // DeterminingAnswer-STEP1
      if (millis() - startTime >= 2000) {
        state = CHECKING_DISTANCE;
      }
      break;

    case CHECKING_DISTANCE:  // DeterminingAnswer-STEP2
      int distance = getDistance();
      Serial.print("Distance: ");
      Serial.print(distance);
      Serial.println(" cm");

      if (distance == distance1) {
        targetLED = 0;
        state = CORRECT_ANSWER;
      } else if (distance == distance2) {
        targetLED = 1;
        state = CORRECT_ANSWER;
      } else if (distance == distance3) {
        targetLED = 2;
        state = CORRECT_ANSWER;
      } else if (distance == distance4) {
        targetLED = 3;
        state = CORRECT_ANSWER;
      } else {
        state = WRONG_ANSWER;
      }
      break;

    case CORRECT_ANSWER:  // Answer-CORRECT
      lcd.clear();
      lcd.print("CORRECT!");
      stopWatch();
      currentRound++;

      if (currentRound <= rounds) {
        state = RANDOMIZING_LEDS;
      } else {
        state = WAITING_FOR_BUTTON;
        lcd.clear();
        lcd.print("Game Over!");
        lcd.setCursor(0, 1);
        lcd.print("Press button to play");
        currentRound = 1;
      }
      break;

    case WRONG_ANSWER:  // Answer-WRONG
      lcd.clear();
      lcd.print("WRONG!");
      state = WAITING_FOR_BUTTON;
      currentRound = 1;
      break;
  }
}

void idleAnimation() {
  static int ledIndex = 0;
  static bool direction = true;
  static unsigned long previousMillis = 0;
  const unsigned long interval = 100;

  if (millis() - previousMillis >= interval) {
    previousMillis = millis();

    if (direction) {
      ledIndex++;
      if (ledIndex == 4) {
        ledIndex = 2;
        direction = false;
      }
    } else {
      ledIndex--;
      if (ledIndex == -1) {
        ledIndex = 1;
        direction = true;
      }
    }

    for (int i = 0; i < 4; i++) {
      digitalWrite(LIGHT[i], i <= ledIndex ? HIGH : LOW);
    }
  }
}

void startGame() {
  lcd.clear();
  lcd.print("Round ");
  lcd.print(currentRound);
  lcd.setCursor(0, 1);
  lcd.print("Get ready!");
  state = RANDOMIZING_LEDS;
}

void randomizeLEDs() {
  static unsigned long previousMillis = 0;
  const unsigned long interval = 50;
  static int ledIndex = 0;
  if (millis() - previousMillis >= interval) {
    previousMillis = millis();
    ledIndex = random(4);

    for (int i = 0; i < 4; i++) {
      digitalWrite(LIGHT[i], i == ledIndex ? HIGH : LOW);
    }

    if (ledIndex == 0) {
      startTime = millis();
      state = WAITING_FOR_OBJECT;

      tone(BEEP, 1000, 100);
    }
  }
}

int getDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH);
  int distance = duration * 0.034 / 2;

  return distance;
}

void stopWatch() {
  lcd.clear();
  lcd.print("Round ");
  lcd.print(currentRound);
  lcd.setCursor(0, 1);

  unsigned long roundStartTime = millis();

  while (true) {
    unsigned long elapsedTime = millis() - roundStartTime;

    lcd.print(elapsedTime / 1000);
    lcd.print(".");
    lcd.print(elapsedTime % 1000 / 100);

    if (digitalRead(ONOFF) == LOW) {
      break;
    }
  }
}

Here's the problem:

  1. The idle animation works, but I'm only stuck at the idle animation mode and the click of a button doesn't do anything. It doesn't progress me to the game and/or to start a round.
  2. I tried to fix this myself by reading the signal from both button and the ultrasonic sensor. But Serial Monitor doesn't show up anything.

To be honest, it took me quite a while to figure out anything from what ChatGPT sent out so please try to simplify your answer to me. Any help is appreciated.
As background, I went from learning how to light up LEDs to .. this.

(As much as possible, resist the urge to smite me for using ChatGPT to make a project. Thanks :dotted_line_face:)

Welcome

There is nothing in your code that changes the state from IDLE to WAITING_FOR_BUTTON. So it will never check the state of the button.

The "WAITING_FOR_BUTTON" code should be removed from the switch and placed directly in the loop, or maybe inside the "IDLE" code.

perhaps, testing buttonstate, not ONOFF, will give you some response. When you get to this case, anyway.

My standard advice:

Keep asking the robot until he/she/it gives you the correct result you expect.

One answer could probably be 42.

1 Like

A typical pattern for implementing a state machine is to have 2 (or 3) functions, beginState(), updateState() [and possibly endState()]

Then, the code you only need to execute once, like printing something on the LCD, recording the start time, etc. gets done in the beginState() function. Things that you want to check every time though loop like elapsed time, a button press, etc. gets put in the updateState() code.

Something like this:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int echoPin = 2;               // EchoPin-ULTRASONIC
const int trigPin = 3;               // TriggerPin-ULTRASONIC
const int ONOFF = 4;                 // BUTTON
const int BEEP = 5;                  // BUZZER
const int LIGHT[] = { 6, 7, 8, 9 };  // LEDs
const int nLights = sizeof (LIGHT) / sizeof(LIGHT[0]);


// For ULTRASONIC (in centimeters)
const int distance1 = 40;
const int distance2 = 30;
const int distance3 = 20;
const int distance4 = 10;

// Game Configuration
const int rounds = 10;
enum GameModes {
  IDLE,
  WAITING_FOR_BUTTON,
  RANDOMIZING_LEDS,
  WAITING_FOR_OBJECT,
  CHECKING_DISTANCE,
  CORRECT_ANSWER,
  WRONG_ANSWER
};

// Default GameMode
int state = IDLE;
unsigned long startTime;
int currentRound = 1;
int targetLED;



void setup() {
  for (int i = 0; i < nLights; i++) {
    pinMode(LIGHT[i], OUTPUT);
  }
  pinMode(ONOFF, INPUT_PULLUP);
  pinMode(BEEP, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(trigPin, OUTPUT);

  lcd.begin(16, 2);
  lcd.backlight();

  Serial.begin(9600);
  beginState(IDLE);
}

void loop() {
  updateState();

}


void beginState(int s) {
  state = s;
  Serial.print(F("Beginning state "));
  Serial.println(state);
  switch (state) {
    case IDLE:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("The R.T.T!");
      break;

    case WAITING_FOR_BUTTON:
      lcd.setCursor(0, 1);
      lcd.print("Press Button");
      idleAnimation();
      break;

    case RANDOMIZING_LEDS:
      // no setup required
      break;

    case WAITING_FOR_OBJECT:  // DeterminingAnswer-STEP1
      lcd.clear();
      lcd.print("Round ");
      lcd.print(currentRound);
      lcd.setCursor(0, 1);
      startTime = millis();
      break;

    case CHECKING_DISTANCE:  // DeterminingAnswer-STEP2
      {
        int distance = getDistance();
        int newState = CORRECT_ANSWER;

        Serial.print("Distance: ");
        Serial.print(distance);
        Serial.println(" cm");

        if (distance == distance1) {
          targetLED = 0;
          state = CORRECT_ANSWER;
        } else if (distance == distance2) {
          targetLED = 1;
        } else if (distance == distance3) {
          targetLED = 2;
        } else if (distance == distance4) {
          targetLED = 3;
        } else {
          newState = WRONG_ANSWER;
        }
        beginState(newState);
      }
      break;

    case CORRECT_ANSWER:  // Answer-CORRECT
      lcd.clear();
      lcd.print("CORRECT!");
      currentRound++;

      if (currentRound <= rounds) {
        beginState(RANDOMIZING_LEDS);
      } else {
        lcd.clear();
        lcd.print("Game Over!");
        lcd.setCursor(0, 1);
        lcd.print("Press button to play");
        currentRound = 1;
        beginState(WAITING_FOR_BUTTON);
      }
      break;

    case WRONG_ANSWER:  // Answer-WRONG
      lcd.clear();
      lcd.print("WRONG!");
      currentRound = 1;
      beginState(WAITING_FOR_BUTTON);
      break;
  }
}

void updatekState() {
  switch (state) {
    case IDLE:
      // IDLE only runs once so advance to waiting for button press
      beginState(WAITING_FOR_BUTTON);
      break;

    case WAITING_FOR_BUTTON:
      {
        int buttonState = digitalRead(ONOFF);
        Serial.print(F("Button State: "));
        Serial.println(buttonState);
        if (buttonState == LOW) {
          startGame();
        }
      }
      break;

    case RANDOMIZING_LEDS:
      randomizeLEDs();
      break;

    case WAITING_FOR_OBJECT:  // DeterminingAnswer-STEP1
      {
        lcd.setCursor(0, 1);
        unsigned long elapsedTime = millis() - startTime;

        lcd.print(elapsedTime / 1000);
        lcd.print(".");
        lcd.print(elapsedTime % 1000 / 100);

        if (millis() - startTime >= 2000) {
          beginState(CHECKING_DISTANCE);
        }
      }
      break;

    case CHECKING_DISTANCE:  // DeterminingAnswer-STEP2
      // nothing to do
      break;

    case CORRECT_ANSWER:  // Answer-CORRECT
      // nothing to do
      break;

    case WRONG_ANSWER:  // Answer-WRONG
      // nothing to do
      break;
  }

}
void idleAnimation() {
  static int ledIndex = 0;
  static bool direction = true;
  static unsigned long previousMillis = 0;
  const unsigned long interval = 100;

  if (millis() - previousMillis >= interval) {
    previousMillis = millis();

    if (direction) {
      ledIndex++;
      if (ledIndex == nLights) {
        ledIndex = 0;
        direction = false;
      }
    } else {
      ledIndex--;
      if (ledIndex == -1) {
        ledIndex = 0;
        direction = true;
      }
    }

    for (int i = 0; i < nLights; i++) {
      digitalWrite(LIGHT[i], i <= ledIndex ? HIGH : LOW);
    }
  }
}

void startGame() {
  lcd.clear();
  lcd.print("Round ");
  lcd.print(currentRound);
  lcd.setCursor(0, 1);
  lcd.print("Get ready!");
  beginState(RANDOMIZING_LEDS);
}

void randomizeLEDs() {
  static unsigned long previousMillis = 0;
  const unsigned long interval = 50;
  static int ledIndex = 0;
  if (millis() - previousMillis >= interval) {
    previousMillis = millis();
    ledIndex = random(nLights);

    for (int i = 0; i < nLights; i++) {
      digitalWrite(LIGHT[i], i == ledIndex ? HIGH : LOW);
    }

    if (ledIndex == 0) {
      tone(BEEP, 1000, 100);
      beginState(WAITING_FOR_OBJECT);
    }
  }
}

int getDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH);
  int distance = duration * 0.034 / 2;

  return distance;
}

void stopWatch() {
  lcd.clear();
  lcd.print("Round ");
  lcd.print(currentRound);
  lcd.setCursor(0, 1);

  unsigned long roundStartTime = millis();

  while (true) {
    unsigned long elapsedTime = millis() - roundStartTime;

    lcd.print(elapsedTime / 1000);
    lcd.print(".");
    lcd.print(elapsedTime % 1000 / 100);

    if (digitalRead(ONOFF) == LOW) {
      break;
    }
  }
}

Something needs to teach ChatGPT to comment its code!

As long as it keeps the comments short, information-free, and generally incorrect, we won't be able to tell the difference from human-generated comments, will we?

2 Likes

You should either keep asking chatGPT or
switch to learn programming yourself.

Just to state the what you have written and what I assume:
You tried to avoid own effort by using chatGPT. The result is not working.
Now you try to avoid own effort again by asking the humans in the arduino-forum.

You will receive helpful answers if you show some own effort.
You do this by asking code-specific questions.

If this is too much effort for you you can try this

Giving chatGPT a too less detailed prompt results in non-working code.
To be able to give chatGPT a precise prompt your description must be very very very detailed
or
you have to ask chatGPT all the things that do not work to correct them.

So make a choice:
Own effort through asking step-by-step code-specific questions in the arduino-forum
or
Own effort by repeated asking chatGPT

best regards Stefan

2 Likes

Being in line with post #8 @StefanL38, I would like to suggest that you follow the diagram of Fig-1 and --
1. Connect I2CLCD and check its functionaly.
2. Connect HC-SR04 Sonar and check its functionality.
3. Connect Buzzr and check its functionality.
4. Connect Button (SW1 of Fig-1) and check its functionality.
5. Connect all four LEDs and check their functionalities.
6. Finallay, take the help of the sketch of Step-7 to combine all the above module-wise sketches to make a single sketch and test it.

7. Test sketch to prepare which I have taken some help from ChatGPT. Upload it into Arduino UNO/NANO and observe the result. Modify the codes as needed to meet your objectives like the implementation of LCD-basd Stopwatch. I have not implemented the Stopwatch as I have not fully understood the purpose of the Stopwatch. If you explain clearly, I may try to implement it.

I have tested the sketch using 4-LED, Button, Buzzer, Sonar, I2CLCD, and Serial Monitor. I have obtained some partial results like: respone to Button, Buzzer activation, I2CLCD functionality, Sonar functionality.


Figure-1:

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);  // Adjust the address if needed

const int buttonPin = 2;
const int buzzerPin = 3;
const int ledPins[] = {4, 5, 6, 7}; // Connect LEDs to these pins
const int trigPin = 8; // Connect Trig pin of the ultrasonic sensor to this pin
const int echoPin = 9; // Connect Echo pin of the ultrasonic sensor to this pin

int rounD = 1;
int targetLed;
bool gameRunning = false;

void setup()
{
  Serial.begin(9600);
  lcd.begin();//(16, 2);
  lcd.print("Reaction-Time!");
  delay(2000);
  lcd.clear();

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input

  for (int i = 0; i < 4; i++)
  {
    pinMode(ledPins[i], OUTPUT);
  }
}

void loop()
{
  if (!gameRunning && digitalRead(buttonPin) == HIGH)
  {
    startGame();
  }

  if (gameRunning)
  {
    playRound();
  }
}

void startGame()
{
  lcd.clear();
  lcd.print("Pres SW1 2 start");

  while (digitalRead(buttonPin) == HIGH)
  {
    ;// Wait for button press to start the game
  }

  lcd.clear();
  lcd.print("Round 1");

  delay(1000); // Time for player to prepare

  gameRunning = true;
}

void playRound()
{
  targetLed = random(4);
  randomizeLeds();

  delay(2000); // Allow time for LED randomization

  digitalWrite(ledPins[targetLed], HIGH); // Turn on the target LED
  tone(buzzerPin, 1000, 500); // Sound the buzzer for 0.5 seconds

  lcd.clear();
  lcd.print("Align obj 2 LED");

  delay(2000); // Wait for player to align object

  int distances = measureDistance(targetLed);

  if (distances >= 5) //testing
  {
    lcd.clear();
    lcd.print("CORRECT!");
    delay(1000);
    lcd.clear();
    rounD++;

    if (rounD <= 10)
    {
      lcd.print("Round " + String(rounD));
      randomizeLeds();
      delay(1000);
    }
    else
    {
      lcd.print("Game Over!");
     delay(1000);
      gameRunning = false;
      rounD = 1;
    }
  }
  else
  {
    lcd.clear();
    lcd.print("WRONG! Try again");
    delay(2000);
    lcd.clear();
    rounD = 1;
  }
}

void randomizeLeds()
{
  for (int i = 0; i < 4; i++)
  {
    digitalWrite(ledPins[i], LOW);
  }

  for (int i = 0; i < 10; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      digitalWrite(ledPins[j], HIGH);
      delay(100);
      digitalWrite(ledPins[j], LOW);
    }
  }
}

int measureDistance(int targetLed)
{
  long duration;
  int distances;
  //-----------------------------
  digitalWrite(ledPins[targetLed], HIGH);
  delay(50); // Allow time for the LED to stabilize
  digitalWrite(ledPins[targetLed], LOW);
  //------------------------------------------------
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distances = duration * 0.034 / 2; // Convert to centimeters

  // Prints the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.println(distances);
  //--------------------------------------------------------
  return distances;
}
1 Like

my bad bro !!

i didn't mention that prior to posting this i did have to learn a lot to understand the really long code myself through god knows how many tutorials i found. its just that i was desperate to find a solution since, suprise, suprise, chatgpt cant fix everything!

(20 day late reply, had to take a time off dont mind)

Thank you!

this has provided some results similar to yours and i can see the game working together with your code.

i am confused though, since my ultrasonic sensor has been reading 0's and therefore the distance-detecting thingy doesn't work (at least for now, im looking if i disrupted the jumper wire connection).

1 Like

Thank you as well !

the game was actually starting from the button press (and the stopwatch feature you implemented works!).

However, after one button press to start the game it continually keeps on going to the next round and the next and the next after the two seconds is reached each round. Its not even pausing to take a break it just keeps going on and on.

UPDATE: The ultrasonic sensor was indeed disrupted. Everything is working, and now I have another question...
@GolamMostafa // please take my apology for this 20 day late question. nevertheless, how can i make sure that the LEDS have assigned distance values? For example, when a random LED lights up (for the player to align it with an object), the code will know that the object has indeed lined up with the random LED lit up. And if otherwise, the round won't progress? [in this situation id resort to chatgpt before id ask this question, but i know it'll just mess the whole code up]

heres an illustration with my question provided for your convenience (forgot the LCD screen in this illustration but its not really that important)

tl;dr: take a break and learn arrays.

@jogs have you posted a working but not yet doing everything correctly or how you want it sketch?

It looks like you want to associate a distance with each LED.

Here is where arrays may help. And later more powerful and convenient ways to package data that wants to travel around together.

If you have N LEDs, their pin numbers could be in an array.

N LEDs might also have an array to store/modify whether each is currently on or off.

An array of size N might store distances in a convenient unit. The distances might be measured by hand and written into the code. Or a training function coukd be programmed, which when invoked would let you position the box in N places and the program could "learn" the distances.

The output of the sesnor might be used to look through such an array and see if, and which, LED the box is parked in front of.

HTH

a7

2 Likes

You absolutely can not
image
The ultra-sonic sensor measures the distance and reports the distance.
That is all the ultrasonic-sensor "knows".

That is a deep misunderstanding of how it all works.

Your

code

can check if
image

By comparing the measured distance with a distance-value that is related to the LED that is lit up

And for doing this with more efficient code you should learn what arrays are and how to use them

1 Like

I think that went straight over the Op's head...... :sweat_smile:

1 Like

Seems like arrays really are important, thanks I'll look into it

If your wondering about my code, I basically copied it from GolamMostafa's code (and only changed the pin numbers a bit :grinning:). You can copy it from him too if you'd want to help me regarding this array thingy for my code (or rather GolamMostafa's code).

I'm not afraid to admit that your right hahaha i dont get it

:melting_face:

1 Like

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