Problem with conditional loop

Hello everyone,

I'm stuck on a project. I want to create a Wi-Fi radio using an ESP01S, and I want to change the Wi-Fi radio station (URL) when I press a button. I also want it to go back to the first station when the last station is reached. Everything is working fine except the loop used to change the station. I've tried for hours, even with ChatGPT, but I haven't found the problem. Does anyone have an idea of how to do it?

Here's my code:

#include <ESP8266WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"

const char *ssid = "YOUR_WIFI_NAME";
const char *password = "YOUR_WIFI_PASSWORD";

const int buttonPin = 2;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

int totalStations = 3;

int currentStation = 0;

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2SNoDAC *out;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.printf("Starting radio with station: %s\n", radioStations[currentStation].c_str());
  startPlaying(radioStations[currentStation]);
}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if (currentStation < totalStations) {
      currentStation++;
    } else if (currentStation == totalStations - 1) {
      currentStation = 0;  // Go back to the first station
    }
    Serial.printf("Switching to station: %s\n", radioStations[currentStation].c_str());
    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }

  lastButtonState = buttonState;

  if (mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
  }

  delay(20);
}

void startPlaying(String url) {
  file = new AudioFileSourceICYStream(url.c_str());
  buff = new AudioFileSourceBuffer(file, 2048);
  out = new AudioOutputI2SNoDAC();
  mp3 = new AudioGeneratorMP3();
  mp3->begin(buff, out);
}

void stopPlaying() {
  mp3->stop();
  delete mp3;
  delete out;
  delete buff;
  delete file;
}
if (currentStation < totalStations) {
  currentStation++;
} else { 
  currentStation = 0; // Go back to the first station
}

Your logic is wrong, if currentStation == totalStations - 1, then it is also < totalStations, so the if wins and your else if will never run.

Try

if ( ++currentStation == totalStations )
{
  currentStation = 0;  // Go back to the first station
}

What happens when you press the button ?

I assume that it is wired to take the input pin LOW when the button is pressed. Are you using a breadboard and, if so, are its power rails continuous along their length or do they have a gap in the middle ?

When i push the button most of the time the station change to the second one but not to the third one .

I tried with what MaximoEsfuerzo and guix said me to try but none of them seems to work

Show your revised code

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"

const char *ssid = "wifi_name";
const char *password = "password";

const int buttonPin = 2;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

int totalStations = 3;

int currentStation = 0;

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2SNoDAC *out;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.printf("Starting radio with station: %s\n", radioStations[currentStation].c_str());
  startPlaying(radioStations[currentStation]);
}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if (currentStation < totalStations) {
      currentStation++;
    } else {
      currentStation = 0;  // Go back to the first station
    }
    Serial.printf("Switching to station: %s\n", radioStations[currentStation].c_str());
    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }




  lastButtonState = buttonState;

  if (mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
  }

  delay(20);
}

void startPlaying(String url) {
  file = new AudioFileSourceICYStream(url.c_str());
  buff = new AudioFileSourceBuffer(file, 2048);
  out = new AudioOutputI2SNoDAC();
  mp3 = new AudioGeneratorMP3();
  mp3->begin(buff, out);
}

void stopPlaying() {
  mp3->stop();
  delete mp3;
  delete out;
  delete buff;
  delete file;
}

This is still wrong : when currentStation is equal to totalStations - 1, you still increase it once. So after the if, currentStation is equal to totalStations, which is an invalid index of radioStations

Could you provide me a code snippet that should work ? (I am 14 years old so i am a beginner)

  if (buttonState == LOW && lastButtonState == HIGH) {
    if ( ++currentStation == totalStations )
    {
      currentStation = 0;  // Go back to the first station
    }
    Serial.printf("Switching to station: %s\n", radioStations[currentStation].c_str());
    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }

even with your code snippet , I am only able to go to the first and second station when i press the button but i am not able to go to the third station nether returning to the first station.

The modified code

#include <ESP8266WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"

const char *ssid = "flanolo";
const char *password = "16313022";

const int buttonPin = 2;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

int totalStations = 3;

int currentStation = 0;

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2SNoDAC *out;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.printf("Starting radio with station: %s\n", radioStations[currentStation].c_str());
  startPlaying(radioStations[currentStation]);
}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if ( ++currentStation == totalStations )
    {
      currentStation = 0;  // Go back to the first station
    }
    Serial.printf("Switching to station: %s\n", radioStations[currentStation].c_str());
    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }
  lastButtonState = buttonState;

  if (mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
  }

  delay(20);
}

void startPlaying(String url) {
  file = new AudioFileSourceICYStream(url.c_str());
  buff = new AudioFileSourceBuffer(file, 2048);
  out = new AudioOutputI2SNoDAC();
  mp3 = new AudioGeneratorMP3();
  mp3->begin(buff, out);
}

void stopPlaying() {
  mp3->stop();
  delete mp3;
  delete out;
  delete buff;
  delete file;
}

This WokSim makes visible what values your code is using
It is stripped down to the pure functionality of button-press, incrementing and the Strings

This is the serial printing and as you can see the stations rotate 1,2,0,1,2,0....

Setup-Start
Switching to station: 1
radioStations[1].c_str()=#http://26353.live.streamtheworld.com/CIGBFM.mp3#
Switching to station: 2
radioStations[2].c_str()=#http://19293.live.streamtheworld.com/CFJO_FM.mp3#
Switching to station: 0
radioStations[0].c_str()=#http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3#
Switching to station: 1
radioStations[1].c_str()=#http://26353.live.streamtheworld.com/CIGBFM.mp3#
Switching to station: 2
radioStations[2].c_str()=#http://19293.live.streamtheworld.com/CFJO_FM.mp3#
Switching to station: 0
radioStations[0].c_str()=#http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3#

How did you check if it works or not?
Are you sure you uploaded the last revised code and the upload was successful ?

If you checkd by ear "what stream do I hear?" it might be a problem of still some data left in the buffer

here is your code from post #12 with added serial printing to make visible what your code is really doing. As I don't have your libraries I haven't tested if it compiles there might be some typos in it but which should be easy to correct.

before rptining the URL-strings a leading # and at the end a a trailing # is added
to make visible where the string really starts and really ends

#include <ESP8266WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"

const char *ssid = "flanolo";
const char *password = "16313022";

const int buttonPin = 2;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

int totalStations = 3;

int currentStation = 0;

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2SNoDAC *out;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.printf("Starting radio with station: %s\n", radioStations[currentStation].c_str());
  startPlaying(radioStations[currentStation]);
}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if ( ++currentStation == totalStations )
    {
      currentStation = 0;  // Go back to the first station
    }
    Serial.print("Switching to station: ");
    Serial.println(currentStation);

    Serial.print("radioStations[");
    Serial.print(currentStation);
    Serial.print("].c_str()=#"); 
    Serial.print(radioStations[currentStation].c_str());    
    Serial.println("#"); 

    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }
  lastButtonState = buttonState;

  if (mp3->isRunning()) {
    Serial.println("if (mp3->isRunning() ) is true"); 
    if ( !mp3->loop() ) {
      Serial.println("if (!mp3->loop() ) is true"); 
      mp3->stop();
      Serial.println("mp3->stop() done"); 
    }
  }

  delay(20);
}

void startPlaying(String url) {
  Serial.println("entering startPlaying");
  Serial.print("url=#");
  Serial.print( url.c_str() );
  Serial.println("#");
  
  file = new AudioFileSourceICYStream(url.c_str());
  buff = new AudioFileSourceBuffer(file, 2048);
  out = new AudioOutputI2SNoDAC();
  mp3 = new AudioGeneratorMP3();
  mp3->begin(buff, out);
}

void stopPlaying() {
  mp3->stop();
  delete mp3;
  delete out;
  delete buff;
  delete file;
}

best regards Stefan

Thanks StefanL38 , the code in Wokwi works flawlessly but with the complete code, I am not able to go over the second station (I was able to do it maybe 2 time out of 15) neither return to the first station. Any ideas of what could cause that? Also the libraries I use come from the Esp8266Audio library.

Does the currentStation variable update its value as expected when you press the button ?

Well i tried the wokwi code that Stefan provided me and i tried it on my esp01s and it also work flawlessly . But when i try the code with all the wifi thing , it does not want to go over the second station. So I would say that it updates but only with the code snippet and not with the complete code

Are you saying that you can see the value of currentStation changing in the sequence 0,1,2,0,1,2 and so on but the stream selected does not change ?

No , what i am saying is that when I try with this code

const int buttonPin = 2;

int totalStations = 3;
int currentStation = 0;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);
  Serial.println("Setup-Start");

}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if ( ++currentStation == totalStations ) {
      currentStation = 0;  // Go back to the first station
    }

    Serial.print("Switching to station: ");
    Serial.println(currentStation);

    Serial.print("radioStations[");
    Serial.print(currentStation);
    Serial.print("].c_str()=#"); 
    Serial.print(radioStations[currentStation].c_str());    
    Serial.println("#"); 
  }

  lastButtonState = buttonState;
  delay(20);
}

it works flawlessly and we can see that value is changing and that the conditionnal loop is working. But with the complete code

#include <ESP8266WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"

const char *ssid = "flanolo";
const char *password = "16313022";

const int buttonPin = 2;

String radioStations[] = {
  "http://24273.live.streamtheworld.com/CITE1FM_SC?.mp3",
  "http://26353.live.streamtheworld.com/CIGBFM.mp3",
  "http://19293.live.streamtheworld.com/CFJO_FM.mp3"
};

int totalStations = 3;

int currentStation = 0;

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2SNoDAC *out;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.printf("Starting radio with station: %s\n", radioStations[currentStation].c_str());
  startPlaying(radioStations[currentStation]);
}

void loop() {
  static int lastButtonState = HIGH;
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && lastButtonState == HIGH) {
    if ( ++currentStation == totalStations )
    {
      currentStation = 0;  // Go back to the first station
    }
    Serial.print("Switching to station: ");
    Serial.println(currentStation);

    Serial.print("radioStations[");
    Serial.print(currentStation);
    Serial.print("].c_str()=#"); 
    Serial.print(radioStations[currentStation].c_str());    
    Serial.println("#"); 

    stopPlaying();
    startPlaying(radioStations[currentStation]);
  }
  lastButtonState = buttonState;

  if (mp3->isRunning()) {
    Serial.println("if (mp3->isRunning() ) is true"); 
    if ( !mp3->loop() ) {
      Serial.println("if (!mp3->loop() ) is true"); 
      mp3->stop();
      Serial.println("mp3->stop() done"); 
    }
  }

  delay(20);
}

void startPlaying(String url) {
  Serial.println("entering startPlaying");
  Serial.print("url=#");
  Serial.print( url.c_str() );
  Serial.println("#");
  
  file = new AudioFileSourceICYStream(url.c_str());
  buff = new AudioFileSourceBuffer(file, 2048);
  out = new AudioOutputI2SNoDAC();
  mp3 = new AudioGeneratorMP3();
  mp3->begin(buff, out);
}

void stopPlaying() {
  mp3->stop();
  delete mp3;
  delete out;
  delete buff;
  delete file;
}

i am only able to go from the first station (0) to the second station (1) but not the third station (2) and i am not able to return to the first station (0)

Hope this help

Try this version of the loop() function

void loop()
{
    static int lastButtonState = HIGH;
    int buttonState = digitalRead(buttonPin);

    if (buttonState == LOW && lastButtonState == HIGH)
    {
        currentStation++;
        if (currentStation >= totalStations)
        {
            currentStation = 0;  // Go back to the first station
        }
        Serial.print("Switching to station: ");
        Serial.println(currentStation);

        Serial.print("radioStations[");
        Serial.print(currentStation);
        Serial.print("].c_str()=#");
        Serial.print(radioStations[currentStation].c_str());
        Serial.println("#");

        stopPlaying();
        startPlaying(radioStations[currentStation]);
    }
    lastButtonState = buttonState;

    if (mp3->isRunning())
    {
        Serial.println("if (mp3->isRunning() ) is true");
        if (!mp3->loop())
        {
            Serial.println("if (!mp3->loop() ) is true");
            mp3->stop();
            Serial.println("mp3->stop() done");
        }
    }

    delay(20);
}

We are almost there! I am able to go to the third station but i can not return to the first station.