Hello, I am running a master and slave board set up using Mega2560s. I have three questions about Wire.h and I2C, but if you don't have much time, I'd appreciate even an answer to the first one. I've ordered them in ascending complexity (I think) and you can just answer as many as you have time for. If you'd rather get a feel for the whole project and why I'm asking these questions, links to the whole code on github are at the end. Thank you!
Quick context: I'm setting up boards to each scan a piano keyboard to see if any notes have been played/released. I'll eventually need to scan four keyboards with slaves and the master will scan a fifth keyboard as well as being in charge of sending out the MIDI signals. I need to send that information to a master board so that the MIDI signals will all come from one place.
Right now, I'm just trying to get the master (without any scanning duties of its own) and a single slave working. I've verified that the circuits work, that the slave is set to the right address, master is requesting from the right address, and that, with the exception of the problems listed below, I2C is working okay.
First question: Right now, the slave board is returning 0 to the master board if it doesn't have any data to transmit (it works just fine if there's data to go out). This is causing the master board to have to deal with garbage 0s. I coded a work-around for the master to just ignore returned 0s, but this is causing other problems. How do I make sure that the slave doesn't send 0 to master if it doesn't have any data? Here's the relevant code for the master:
void queryKeyboard(int slaveAddress, int midiChannel)
{
Serial.println("In the queryKeyboard function.");
//send request for one byte to the address set in slaveAddress
if (Wire.requestFrom(slaveAddress, 1) == 1)
{
//read incoming value and assign it to incomingKeyData
int incomingKeyData = Wire.read();
//debugging info, can be deleted when done
Serial.print("Just got ");
Serial.print(incomingKeyData);
Serial.println(" from the slave board!");
//take incomingKeyData and send the right info to the MIDI port
rawDataToMidi(incomingKeyData, midiChannel);
}
}
Slave code:
//This transmits the pressed notes to the master board
void requestEvent()
{
Serial.println("master is requesting notes, in requestEvent");
//if there's something in the queue, send it to the master board (this is from the QueueArray library, a quick way to get a FIFO queue)
if (!queue.isEmpty())
{
Serial.println("sending notes");
Wire.write(queue.dequeue());
}
// There's no else { return 0 }, so I don't know why it's sending 1 to master if the queue is empty.
// Is it because the function was successful, so it's just returning that?
}
How to I change the slave code so it doesn't send anything to master if it doesn't have any data to send? (I found this thread about it, but I don't think it applies.)
Second question: My slave board doesn't stay in the loop when many notes are pressed in rapid succession if I don’t put long delays in the loop function. (The master also seems to have this problem.) I have no idea why this is happening, I’ve messed around with it for a while and can’t seem to make any headway. Any ideas where to start? The delays won’t work as a solution, because I need the information to be sent quickly to the MIDI port.
Third question: The reason I'm doing this is because I want to send information about keys being pressed on a keyboard to the master. Because of this, it would be much better if the master could deal with all the values that are waiting in the queue of played notes rather than one at a time. I've seen some example code (in the "request/response" section) that makes it look like it's possible to put up all the available data in an array and then transmit it, but the problem is is that the master board won't know how many notes have been played on the slave, so won't know how much to request from the queue.
How could I alter my code so that the master board would be able to read everything in the slave queue and move on to query the next slave after it's gotten all that the current slave had queued up? I noticed that KenF suggested just using serial communication in this thread. I think that doesn't apply because it's just talking about two boards (I'm eventually going to have four slave boards plus the one master). Would that be a better solution and, if so, how would I implement it?
Here's a link to the entire master code (I've commented the code extensively, so it should be easy to read).
Here's a link to the entire slave code (also commented).
Link to the QueueArray library (I don't think it's part of the problem, but it's here for the sake of completeness)