Skip to main content
Responded to comments.
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

This part looks weird:

void sendMP3Command(String MP3File, uint8_t Command) {      
  char *TextArray[MaxMP3Name];
  MP3File.toCharArray(TextArray, MaxMP3Name);
  txMP3.Filename = TextArray;

You have made an array of 13 pointers to strings. This is not what you want. You want the file name to end up into txMP3.Filename.

This would be closer:

void sendMP3Command(String MP3File, uint8_t Command) {      
 MP3File.toCharArray(txMP3.Filename, MaxMP3Name);

Personally I wouldn't be using the String class at all, but that should be better.


Now:

void onReceiveEvent(int numbytes){
  if(numbytes == 16){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

Are you sure it's 16 bytes? What if you change the struct? Let the compiler do the thinking for you:

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof (RXdata)){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

How you've recommended it is actually how I tried it originally (I don't like using Strings either) - which just ends up giving me the error "invalid conversion from 'volatile char*' to 'const char*' [-fpermissive]" (on the Slave)

This minimal example compiles OK:

#include <Wire.h>
#include <I2C_Anything.h>
const uint8_t MaxMP3Name = 13;
struct RECEIVE_DATA_STRUCTURE{
  char Filename[MaxMP3Name];
  uint8_t VolLeft;
  uint8_t VolRight;
  uint8_t Command;   
};

volatile RECEIVE_DATA_STRUCTURE RXdata;
volatile uint8_t newData; // flag to detect I2C activity

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof RXdata){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

void setup() 
{
}

void loop() 
{
}

This part looks weird:

void sendMP3Command(String MP3File, uint8_t Command) {      
  char *TextArray[MaxMP3Name];
  MP3File.toCharArray(TextArray, MaxMP3Name);
  txMP3.Filename = TextArray;

You have made an array of 13 pointers to strings. This is not what you want. You want the file name to end up into txMP3.Filename.

This would be closer:

void sendMP3Command(String MP3File, uint8_t Command) {      
 MP3File.toCharArray(txMP3.Filename, MaxMP3Name);

Personally I wouldn't be using the String class at all, but that should be better.


Now:

void onReceiveEvent(int numbytes){
  if(numbytes == 16){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

Are you sure it's 16 bytes? What if you change the struct? Let the compiler do the thinking for you:

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof (RXdata)){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

This part looks weird:

void sendMP3Command(String MP3File, uint8_t Command) {      
  char *TextArray[MaxMP3Name];
  MP3File.toCharArray(TextArray, MaxMP3Name);
  txMP3.Filename = TextArray;

You have made an array of 13 pointers to strings. This is not what you want. You want the file name to end up into txMP3.Filename.

This would be closer:

void sendMP3Command(String MP3File, uint8_t Command) {      
 MP3File.toCharArray(txMP3.Filename, MaxMP3Name);

Personally I wouldn't be using the String class at all, but that should be better.


Now:

void onReceiveEvent(int numbytes){
  if(numbytes == 16){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

Are you sure it's 16 bytes? What if you change the struct? Let the compiler do the thinking for you:

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof (RXdata)){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

How you've recommended it is actually how I tried it originally (I don't like using Strings either) - which just ends up giving me the error "invalid conversion from 'volatile char*' to 'const char*' [-fpermissive]" (on the Slave)

This minimal example compiles OK:

#include <Wire.h>
#include <I2C_Anything.h>
const uint8_t MaxMP3Name = 13;
struct RECEIVE_DATA_STRUCTURE{
  char Filename[MaxMP3Name];
  uint8_t VolLeft;
  uint8_t VolRight;
  uint8_t Command;   
};

volatile RECEIVE_DATA_STRUCTURE RXdata;
volatile uint8_t newData; // flag to detect I2C activity

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof RXdata){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

void setup() 
{
}

void loop() 
{
}
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

This part looks weird:

void sendMP3Command(String MP3File, uint8_t Command) {      
  char *TextArray[MaxMP3Name];
  MP3File.toCharArray(TextArray, MaxMP3Name);
  txMP3.Filename = TextArray;

You have made an array of 13 pointers to strings. This is not what you want. You want the file name to end up into txMP3.Filename.

This would be closer:

void sendMP3Command(String MP3File, uint8_t Command) {      
 MP3File.toCharArray(txMP3.Filename, MaxMP3Name);

Personally I wouldn't be using the String class at all, but that should be better.


Now:

void onReceiveEvent(int numbytes){
  if(numbytes == 16){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}

Are you sure it's 16 bytes? What if you change the struct? Let the compiler do the thinking for you:

void onReceiveEvent(int numbytes){
  if(numbytes == sizeof (RXdata)){ 
    I2C_readAnything(RXdata);      
    newData = 2;    
  }   
}