CelliesProjects / wm8978-esp32

Arduino IDE library for wm8978 dac on ESP32.
MIT License
22 stars 5 forks source link

M5.Lcd operations are blocked? #4

Closed pierreverbakel closed 3 years ago

pierreverbakel commented 4 years ago

Hello,

Nice piece of work! I got it to work on a M5-Node. I had one, and was always wondering how to get this sound-chip to work. I did not see any Arduino examples about it. The sound is really clear on an external amplied speaker. Impressed with the chip (https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/base/WM8978%20_en.pdf)

I have added some M5-functions to show something on the screen, change the volume for both internal speaker and external audio. My question, my screen does only show a white area on the M5-Basic Version, and sometimes I see some screen-garbling on a black screen when pushing a button clearing the screen with M5.Lcd.clear();

On the M5-Grey the screen starts white and then turns black as per instruction. But no texts.

Do you have any idea where this interference comes from? Some shared I2S port or something? I would like to integrate the sound-stream playing in my project, and there I use the screen on the M5. If you have any wise judgement, that would be welcome.

PS: What I intended with this script is to add some buttons to control the volume. Button A to switch between Internal Speaker and Button B to lower the volume and Button C to make the volume higher in steps.

// ==========================================================
// Added by PV:
#include <Arduino.h>
#include <M5Stack.h>

// PV This script uses both the Speaker Jack on the M5Stack NODE Base and the speaker of the M5Stack

#include <WM8978.h> /* https://github.com/CelliesProjects/wm8978-esp32 */
#include <Audio.h>  /* https://github.com/schreibfaul1/ESP32-audioI2S */

/* M5Stack Node WM8978 I2C pins */
#define I2C_SDA     21
#define I2C_SCL     22

/* M5Stack Node I2S pins */
#define I2S_BCK      5
#define I2S_WS      13
#define I2S_DOUT     2
#define I2S_DIN     34

/* M5Stack WM8978 MCLK gpio number and frequency */
#define I2S_MCLKPIN  0
#define I2S_MFREQ  (24 * 1000 * 1000)

WM8978 dac;
Audio audio; //  PV: I believe that this line starts to disrupt the screen operation. 

char audio_stream_str[100];

void setup() {
  M5.begin(); //  M5.begin(bool LCDEnable, bool SDEnable, bool SerialEnable, bool I2CEnable)

  delay(2000);
  Serial.println(F("M5Node Test , playing a Audio Stream from Internet"));

  M5.Lcd.setTextFont(4);
  M5.Lcd.setCursor(20, 100);
  M5.Lcd.print("Music-Stream Player");

  delay(3000);

  /* Setup wm8978 I2C interface */
  if (!dac.begin(I2C_SDA, I2C_SCL)) {
    ESP_LOGE(TAG, "Error setting up dac. System halted");
    while (1) delay(100);
  }

  /* Setup wm8978 MCLK on gpio - for example M5Stack Node needs this clock on gpio 0 */
  double retval = dac.setPinMCLK(I2S_MCLKPIN, I2S_MFREQ);
  if (!retval)
    ESP_LOGE(TAG, "Could not set %.2fMHz clock signal on GPIO %i", I2S_MFREQ / (1000.0 * 1000.0), I2S_MCLKPIN);
  else
    ESP_LOGI(TAG, "Set %.2fMHz clock signal on GPIO %i", retval / (1000.0 * 1000.0), I2S_MCLKPIN);

  /* Setup wm8978 I2S interface */
  audio.setPinout(I2S_BCK, I2S_WS, I2S_DOUT, I2S_DIN);

  WiFi.begin("xxx", "xxx");
  while (!WiFi.isConnected()) {
    Serial.print(F("."));
    delay(100);
  }
  ESP_LOGI(TAG, "Connected");

  ESP_LOGI(TAG, "Starting MP3...\n");
  //audio.connecttohost("http://icecast.omroep.nl/3fm-bb-mp3");
  strcpy_P(audio_stream_str, PSTR("http://icecast.omroep.nl/3fm-bb-mp3"));
  audio.connecttohost(audio_stream_str);

  dac.setSPKvol(40); /* max 63 */
  //dac.setSPKvol(55);  // OK volume 
  //dac.setSPKvol(57); // Seems to be the sweetspot for the Internal Speaker
  //dac.setSPKvol(59); // 59 is a bit distorted
  //dac.setSPKvol(63); /* 63 is overmodulating */
  dac.setHPvol(32, 32); // See : https://github.com/CelliesProjects/wm8978-esp32/blob/master/src/WM8978.cpp
}  // End of setup()

void loop() {
  char my_tmp_str[100];
  static char  volume_control_device = 'O';
  static int OutputVol = 32; // Default Output-Volume (Through 3.5mm jack)
  static int SpeakerVol = 40; // Default Speaker-Volume (Through M5Stack Speaker)

  audio.loop();
  //delay(1);

  M5.update();

  if (M5.BtnA.wasPressed()) {
    M5.Lcd.clear();
    M5.Lcd.printf("A wasPressed \r\n");
    Serial.println("A wasPressed");
    if (volume_control_device == 'O'){
      M5.Lcd.printf("Internal Speaker Control\r\n");
      Serial.printf("Internal Speaker Control\r\n");
      volume_control_device = 'I';
    } else {
      M5.Lcd.printf("External Speaker Control\r\n");
      Serial.printf("External Speaker Control\r\n");
      volume_control_device = 'O';
    }
  }

  if (M5.BtnB.wasPressed()) {
    M5.Lcd.clear();
    M5.Lcd.printf("B wasPressed \r\n");
    Serial.println("B wasPressed");
    if (volume_control_device == 'O'){
      OutputVol--;
      OutputVol--;
      if (OutputVol < 0){
        OutputVol = 0;
      }
      dac.setHPvol(OutputVol, OutputVol);
      M5.Lcd.printf("Output volume %d\r\n", OutputVol); 
      Serial.printf("Output volume %d\r\n", OutputVol); 
    } else {
      SpeakerVol--;
      SpeakerVol--;
      if (SpeakerVol < 0){
        SpeakerVol = 0;
      }
      dac.setSPKvol(SpeakerVol);
      M5.Lcd.printf("Speaker volume %d\r\n", SpeakerVol); 
      Serial.printf("Speaker volume %d\r\n", SpeakerVol); 
    }
  }

  if (M5.BtnC.wasPressed()) {
    M5.Lcd.clear();
    M5.Lcd.printf("C wasPressed \r\n");
    Serial.println("C wasPressed");
    if (volume_control_device == 'O'){
      OutputVol++;
      OutputVol++;
      if (OutputVol > 63){
        OutputVol = 63;
      }
      dac.setHPvol(OutputVol, OutputVol);
      M5.Lcd.printf("Output volume %d\r\n", OutputVol); 
      Serial.printf("Output volume %d\r\n", OutputVol); 
    } else {
      SpeakerVol++;
      SpeakerVol++;
      if (SpeakerVol > 63){
        SpeakerVol = 63;
      }
      dac.setSPKvol(SpeakerVol);
      M5.Lcd.printf("Speaker volume %d\r\n", SpeakerVol); 
      Serial.printf("Speaker volume %d\r\n", SpeakerVol); 
    }
  }
} // End of loop()
CelliesProjects commented 4 years ago

I run into similar troubles every time I use the M5 all-in-one driver. The display part is based on https://github.com/Bodmer/TFT_eSPI which I tend to use for M5 related projects. See https://github.com/CelliesProjects/M5AnalogClock for an example. Not sure if it will solve your issue but it solved quite a few M5 issues for me.

Also worth a look is https://github.com/tobozo/ESP32-Chimera-Core.

And code you post is formatted nicely if you put 3 backticks ``` before and after.

pierreverbakel commented 4 years ago

OK, I have myself been working in one piece of software for an ESP32 with ESP8266Audio (https://github.com/earlephilhower/ESP8266Audio) to use SAM TTS. I used the standard M5-Library in parallel to that without screenproblems like I have now.
Would it be possible to use that library instead of yours as well. I have no good overview how I2S works and to which extent they should be exchangeable. There must be something which is done diferently in the ESP8266Audio library (Supporting ESP32, do not get mislead by its name) also. I know that what they have implemented is a version of the driver written by Bodmer and changed and added some functions. So it could be exchanged with some efforts in my test-sketch. Also another button-library would have to be incorporated. It is all possible, but it would be nice to maintain co-habitance with the standard M5-Library. I will have a look if I can make it with the TFT_eSPI library. Thanks anyway! I edited the post, so now it looks easier to understand. It is not high level stuff, but just a way to add a touch to your example for M5Stack specifically.

CelliesProjects commented 3 years ago

This PR might help you out wrt to the LCD issues.

The default setup of ESP32-AudioI2S use pins 26 and 27 which are also in use by the LCD. With above PR this should be fixed.

pierreverbakel commented 3 years ago

Hello, I just reviewed the PR https://github.com/schreibfaul1/ESP32-audioI2S/pull/71 And downloaded the updated library files.

I can confirm now that the following works on a M5Stack Node-Base with a M5Stack Grey on top of it. The display used to be white only. I understand now because of the Pin-Defaults coinciding with the pins controlling LCD.

So the important lines in the example are now:

// M5Stack Node I2S pins
#define I2S_BCK      5
#define I2S_WS      13
#define I2S_DOUT     2
#define I2S_DIN     34

//Audio audio;  // Without parameters (older library)

// With Parameters in updated library  https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/src/Audio.cpp
Audio audio(I2S_BCK, I2S_WS, I2S_DOUT);

The screen no longer lights up white and the lines like M5.Lcd.print("Music-Stream Player"); now do work! Thanks for the hints! Again the sound when connected to an external Speaker (with its own powersource and amplifier) is really pleasing to the ears! The 1970s compact-transistorradio-sound days (The internal speaker of the M5Stack) are finally over!

CelliesProjects commented 3 years ago

You might be interested in https://github.com/CelliesProjects/eStreamPlayer32

You don't need a local server, it works fine without. Do step 0 and continue the setup at step 6.

Closing this issue for now.