Hi, trying to get an Arduino in slave mode to send back data to a Flyport in master mode.
I can give the Arduino data, but the i2c restart, and ask for data is not working.
( I`ve had it working between “Arduino to Arduino”, but not “Arduino to !Arduino”
Ive put a print statement in "void requestEvent()" and its never called !!!
a / not I lot of people use i2c
b/ not a lot of people use the arduino in i2c slave mode
c/ No one uses the arduino in i2c slave mode connected to any device other than a second arduino
Can you post your code? Also, is your master using a repeated start or is it using a stop then start. The Wire library doesn't support using a repeated start as a Master so I don't know how it would behave handling a Repeated Start as a slave.
For the arduino side Im just using the example wire/slave_sender , on the master side Im using what flyport uses to handle i2c , which is very literal.
Instead of sending I2CRestart ( ); can you try sending a stop and then a start again and see if that makes a difference? Also does your flyport give any type of return values for I2C commands? It would help to know when the problem is happening i.e no acknowledge to address, etc...
No , but the library is just talking to the internal register , so If you know what you was doing ( which I don`t ) I guess you could quickly make a new command to return any flag.
The is the flyport library for i2c .
/**
\defgroup I2C
@{
The I2C library allows the user to communicate with external devices with I2C bus, like flash memories or sensors. The Flyport is initialized as I2C master.
*/
/**
* I2CInit - Initializes the I2C module.
* \param None
* \return None
*/
void I2CInit(BYTE I2CSpeed)
{
TRISGbits.TRISG2 = 1;
TRISGbits.TRISG3 = 1;
I2C1TRN = 0x0000;
I2C1RCV = 0x0000;
I2C1BRG = I2CSpeed; // Set I2C module at 100 KHz
I2C1CON = 0x8200; // Configuration of module
}
/**
* I2CStart - Sends a start sequence on the bus.
* \param None
* \return None
*/
void I2CStart()
{
I2C1CONbits.SEN = 1; // Sends a start sequence on I2C bus
while(I2C1CONbits.SEN); // waits the end of start
}
/**
* I2CRestart - Sends a repeated start sequence on the bus .
* \param None
* \return None
*/
void I2CRestart()
{
I2C1CONbits.RSEN=1; // Sends a repeated start sequence
while(I2C1CONbits.RSEN); // waits the end of restart
}
/**
* I2CStop - Stops the trasmissions on the bus.
* \param None
* \return None
*/
void I2CStop()
{
I2C1CONbits.PEN=1; // Initiate a Stop condition on the bus
while(I2C1CONbits.PEN); // waits the end of stop
}
/**
* I2CWrite - writes one byte on the bus.
* \param None
* \return None
*/
void I2CWrite(BYTE data)
{
I2C1TRN = data; // Sends a byte on the bus
while(I2C1STATbits.TRSTAT || I2C1STATbits.TBF); // waits the end of trasmissions
// Idle
while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.RSEN || I2C1CONbits.ACKEN);
}
/**
* I2CRead - Reads one byte from the data bus .
* \param None
* \return None
*/
BYTE I2CRead(BYTE ack)
{
I2C1CONbits.RCEN=1; // Reads one byte from the bus
while(I2C1CONbits.RCEN); // waits the end of the read
I2C1STATbits.I2COV = 0; // Resets the overflow flag
I2C1CONbits.ACKDT = ack;
I2C1CONbits.ACKEN = 1; // Initiate an aknowledge sequence
while(I2C1CONbits.ACKEN); // wait the end of the acknowledge sequence
return I2C1RCV; // Returns the byte
}
/*! @} */
The Arduino is a little non-standard, in that it doesn`t support the , Start , send data , restart + 1, read data , stop method.
I have to make them two separate commands :-
start , send data , stop
start + 1 , read data , stop
A couple of things have slowed me down: first I was trying to add a 3D library to my software. That OpenGL stuff with its matrix multiplication can do your head in if you are getting a bit on in years, as I am. I think I am getting the hang of it, although in small steps:
(Nothing to do with Arduinos BTW).
Second, my home is in total chaos as we are trying to get more organized. In particular I seem to be swamped by Arduinos, stepper motors, mosfets, power supplies, etc. This is an attempt to move away from this working environment:
I am getting extra shelving made with a view to getting things a bit better organized. Also I have been putting all my parts onto a "parts database" so I can quickly look up where all my voltage regulator chips are.
Apologies to anyone who thinks this is a bit off-topic.
Hi Nick, oh yes I know that one, I don`t have a walk in wardrobes I have a walk in project bins.
A Morse key are a radio ham? .
I`m getting something back if I split the parts up with a long wait inbetween.
But very hit and miss .
My code is cut down , just for testing , so not a lot can go wrong
#include <Wire.h>
int cmd;
byte return_value = 0;
void setup()
{
Wire.begin(4); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop()
{
// check serial port etc
delay(100);
}
// send a reply / data back to the master
void requestEvent()
{
switch (cmd)
{
case 4:
Wire.send("hello - cmd 4 ");
break;
//
default:
Wire.send("DEFAULT ");
break;
}
}
// get some data from the master
void receiveEvent(int howMany)
{
int counter = 0;
return_value = 0;
cmd = Wire.receive();
switch (cmd)
{
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
}
This is wrong. The Wire library shifts the address left by one bit and adds in the read/write bit. So it will join as address 4 (actually looking for 8/9 depending on whether you are writing/reading).
What documentation do you have for the Flyport? It isn't obvious what address it is looking for your device on. Nor what it is sending or expecting to receive.
However I would say that if the requestEvent is not being called at all then you have the wrong address.
Hi Nick, I`m using address 8 for the master on the flyport, so I do know about the shift.
I am triggering the requestEvent !!! , but like I said, I can`t use :-
start ( write address ) , send data , restart ( write address + 1 ) , read data , stop .
I`ve found I need to use :-
start ( write address ) , send data , stop , start ( write address + 1 ) , raed data , stop.
I also needed to add a couple of ms wait between the stop start.
Ive got it working now , Ill see if it still working when I start adding code in requestEvent.
what it is sending or expecting to receive
I know how the program for the arduino better than for the pic chips , so I`m using it as a co-pro , plus move some load away from the flyport.
The flyport has zero documentation, so been able to use the arduino is a good fall back tool.
peter247:
Hi Nick, I`m using address 8 for the master on the flyport, so I do know about the shift.
Oh good. It's just your comment that threw me:
Wire.begin(4); // join i2c bus with address #2
So you mean "address 8" (or 4, depending on how you look at it).
I'm glad it's working. All you should need to do in the requestEvent is a single Wire.send (). The library handles the rest. Be aware that doing multiple Wire.send will not work properly in a requestEvent. So if you need to send 10 bytes (say) then create a buffer and send that buffer with a single send.
Thanks , so only one Wire.send () , and hope the flyport does clock stretching , which I know it does because I had to make a mod for that to get it to read and write to eeproms.