Не удается заставить Adafruit MusicMaker и Ethernet работать одновременно

Работаю над проектом Интернета вещей.
Окружающая среда:

  • Adafruit Перо M4 Экспресс
  • Музыкальный продюсер Adafruit FeatherWing (усиленный, в глубине души это VS1053)
  • Silicognition PoE FeatherWing (электрически совместим с Adafruit Ethernet FeatherWing)
  • PlatformIO с кодом Visual Studio на Mac (все библиотеки обновлены)

Проблема:
Я могу заставить работать либо Ethernet, либо MusicMaker, но не оба одновременно.
Во время инициализации нет никаких ошибок, они просто не работают.

В частности, метод sineTest() MusicMaker не генерирует никакого звука, если Ethernet был инициализирован. Аналогично, метод connect() клиента Ethernet не может подключиться, если MusicMaker инициализирован. Оба метода работают нормально, если другое устройство не было инициализировано.

Контакты из перьев:

Purpose                    Pin
-------------------------- ---
VS1053 Chip select           6
VS1053 Data/command select  10
VS1053 Data request          9
SD Card Chip select          5
Ethernet Chip select        14

Обратите внимание, что в настоящее время я не использую SD-карту и не вызывал ее метод begin().
Обратите также внимание, что для выбора микросхемы Ethernet используется нестандартный вывод, поскольку по умолчанию он конфликтует с выбором данных/ команд VS1053.

Кроме того, PoE FeatherWing имеет на нем EEPROM с уникальным MAC-адресом, и чтение этого работает нормально.

Еще одно замечание: я думал, что эта комбинация работала в более раннем прототипе несколько месяцев назад, но, возможно, это было с Feather 32U4.

ТИА.

Код прототипа:

#include <Arduino.h>
#include <Adafruit_VS1053.h>
#include <Ethernet.h>
#include <IPAddress.h>
#include <SPI.h>
#include <Wire.h>


//
// Контакты для Ethernet и MusicMaker FeatherWings.
// ПРИМЕЧАНИЕ: В этих определениях предполагается, что Feather M4 Express с PoE FeatherWing
// изменен, чтобы его чип выбирался на выводе 14, поскольку конфликты по умолчанию
// с помощью контакта DCS производителя музыки.
//
#define VS1053_CS       6     // Микросхема VS1053 выбирает вывод (выход)
#define VS1053_DCS     10     // VS1053 Данные / команда выберите вывод (вывод)
#define SD_CARD_CS      5     // Выбор контакта чипа карты
#define VS1053_DREQ     9     // Запрос данных VS1053, в идеале вывод прерывания
#define ETHERNET_CS    14     // Микросхема Ethernet выбирает PIN. Обратите внимание, что это является пользовательским, поскольку значение по умолчанию конфликтует с VS1053_DCS.

//
// Пернатое крыло По.
//
#define MAC_EEPROM_I2C_ADDRESS      0x50  // I2C-адрес микросхемы 24AA02E48 EEPROM, который содержит наш MAC-адрес (на PoE FeatherWing).
#define MAC_EEPROM_REGISTER         0xFA  // Зарегистрировать в 24AA02E48, который содержит первый байт нашего MAC-адреса.

#define HANG      while( true ){ delay( 10 ); }
IPAddress         host = { 172, 24, 110, 1 };
uint16_t          port = 8000;
const char*       path = "/sounds/DingDong.mp3";
Adafruit_VS1053   player{ Adafruit_VS1053( -1, VS1053_CS, VS1053_DCS, VS1053_DREQ ) };
EthernetClient    client;
uint8_t           mp3Buf[VS1053_DATABUFFERLEN];
uint32_t          contentLength;
byte              macAddress[6]{};

uint32_t          beginRequest();
void              readMacAddress( byte* );

void setup()
{
  Serial.begin( 115200 );
  while( !Serial ){ delay( 10 ); }
  Serial.println( "MusicMaker/Ethernet Prototype" );

  Wire.begin();

  Ethernet.init( ETHERNET_CS );
  readMacAddress( macAddress );
  if( !Ethernet.begin( macAddress ))
  {
    Serial.printf( "Unable to initialize the network; hardware status is %d\n",
                   Ethernet.hardwareStatus());
    HANG;
  }

  Serial.print( "Mac address: " );
  for( int ii = 0; ii < 6; ii++ )
  {
    if( macAddress[ii] < 16 ) { Serial.print( '0' ); }
    Serial.print( macAddress[ii], HEX );
    if( ii < 5 ) { Serial.print( ':' ); }
  }
  Serial.println();
  Serial.print( "DNS IP:      " ); Serial.println( Ethernet.dnsServerIP());
  Serial.print( "Local IP:    " ); Serial.println( Ethernet.localIP());
  Serial.print( "Gateway IP:  " ); Serial.println( Ethernet.gatewayIP());
  Serial.print( "Subnet mask: " ); Serial.println( Ethernet.subnetMask());

  if( !player.begin())
  {
    Serial.println( "Unable to initialize the MusicMaker" );
    HANG;
  }
  Serial.println( "Initialized the MusicMaker" );
  player.setVolume( 40, 40 );
  player.sineTest( 0x44, 1000 ); // Сигнал 1 кГц в течение одной секунды.

  contentLength = beginRequest();
  Serial.printf( "HTTP content length: %d\n", contentLength );
}

void loop()
{
  if( player.readyForData())
  {
    if( client.available() > 0 )
    {
      uint8_t bytesRead = client.read( mp3Buf, VS1053_DATABUFFERLEN );
      if( bytesRead > 0 )
      {
        player.playData( mp3Buf, bytesRead );
        contentLength -= bytesRead;
        if( contentLength <= 0 )
        {
          Serial.println( "That should be all of our sound" );
        }
      }
    }
  }
}

uint32_t beginRequest()
{
  if( !client.connect( host, port ))
  {
    Serial.print( "Unable to connect to " );
    Serial.print( host ); Serial.print( ':' ); Serial.println( port );
    HANG;
  }

  Serial.print( "GET " ); Serial.print( path ); Serial.print( " HTTP/1.1\r\n" );
  Serial.print( "Host: " ); Serial.print( host ); Serial.print( "\r\n" );
  Serial.print( "Connection: close\r\n\r\n" );

  client.print( "GET " ); client.print( path ); client.print( " HTTP/1.1\r\n" );
  client.print( "Host: " ); client.print( host ); client.print( "\r\n" );
  client.print( "Connection: close\r\n\r\n" );

  char http[] = "HTTP/";
  client.find( http );                  // Пропустить HTTP/ часть заголовка.
  client.parseFloat( SKIP_WHITESPACE ); // Пропустить номер версии HTTP.

  int httpStatus = client.parseInt( SKIP_WHITESPACE );
  if( httpStatus < 200 || httpStatus > 299 )
  {
    Serial.printf( "GET request failed; HTTP status is %d\n", httpStatus );
    client.stop();
    HANG;
  }

  char lengthHeader[] = "Content-Length:";
  client.find( lengthHeader );
  int contentLength = client.parseInt();

    char endOfHeaders[] = "\r\n\r\n";
  if( !client.find( endOfHeaders ))
  {
    Serial.println( "Invalid HTTP response (missing trailing line endings)" );
    client.stop();
    HANG;
  }
  return contentLength;
}

void readMacAddress( byte* addr )
{
  Wire.beginTransmission( MAC_EEPROM_I2C_ADDRESS );
  Wire.write( MAC_EEPROM_REGISTER );
  int failed = Wire.endTransmission();
  if( failed )
  {
    Serial.printf( "Unable to retrieve MAC address; endTransmission returned %d\n", failed );
    HANG;
  }

  byte* b = addr;
  int bytesRead = Wire.requestFrom( MAC_EEPROM_I2C_ADDRESS, 6 );
  if( bytesRead < 6 )
  {
    Serial.printf( "Unable to retrieve MAC address; fewer than six bytes\n" );
    HANG;
  }

  while( Wire.available())
  {
    *b++ = Wire.read();
  }
}

, 👍0

Обсуждение

вставлена ли SD-карта? если да, то удалите его или установите высокий CS выход в начале настройки (). установите высокий CS выход проигрывателя перед Ethernet.begin(), @Juraj

Установите CS SD-карты и CS проигрывателя на выходы и установите их на высокий уровень перед Ethernet.init() и Ethernet.begin(). Если инициализированы и Ethernet, и проигрыватель, ни то, ни другое не работает. метод sineTest() игрока ничего не делает, а метод connect() EthernetClient возвращает ноль. Они оба используют SPI. Может ли там быть какой-то конфликт?, @David Patterson


1 ответ


Лучший ответ:

0

Оказалось, что это аппаратная проблема.

CS-pin PoE FeatherWing по умолчанию конфликтует с DCS-PIN MusicMaker. Вывод PoE CS можно изменить, вырезав трассировку на обратной стороне платы и подсоединив провод от пэда к любому выводу, который вы хотите использовать вместо него. Я сделал это.

Однако оказалось, что я не обрезал его полностью. Это приводило к тому, что библиотека Ethernet выводила DCS MusicMaker на низкий уровень каждый раз, когда она выводила Ethernet CS на низкий уровень.

Я, наконец, понял это, когда подключил логический анализатор ко всем выводам CS и выводам SPI. Было совершенно ясно, что у MusicMaker DCS проблемы с Ethernet CS.

Ура Логическому анализатору.

,