I2c Slave mode.

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 !!!

Is there a better slave library for the Arduino ?

Thank in advance Peter A

Hi , 9 days without a reply must means that :-

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

Sorry Peter I can't help.

not a lot of people use the arduino in i2c slave mode

I would say that's the most likely case, or maybe c/.

I will have an interest in doing so soon but have no experience with it yet.

Do you know if the Arduino in slave mode can coexist with other i2c devices. You initialize wire with an address which implies so.


Rob

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.

Which would go something like this on the flyport :-
( My code from read a adc chip , which works )
http://www.byvac.com/bv3/index.php?route=product/product&path=54&product_id=77

I2CStart ( );
I2CWrite ( adc ); // the i2c address , * 2 from the arduino address used.
I2CWrite ( 0x04 ); // the command reg used
I2CRestart ( );
I2CWrite( adc + 0x01);
high = I2CRead(0);
low = I2CRead(1); // ack 1 = last byte
I2CStop ( );

Not sure how or if that help , The problem is that the “void requestEvent()” is never triggered

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...

Also does your flyport give any type of return

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	
}
/*! @} */

Thanks wayneft , you are right.

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

thanks again peter

Still not fully working.

I can sent it data and that work , I can get data from it.
but if I try to send it data , it will send data back.

I2CWrite( adc + 0x01);

What is adc equal too?

I don't know if this will help, but I did some stuff on I2C master/slave here:

I just used the Wire.h include, not the I2C library.

Not sure how or if that help , The problem is that the “void requestEvent()” is never triggered

Can you post your code? Where do you configure that requestEvent is to be used?

Hey Nick, you haven't posted for a while, where's ya bin?


Rob

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;
  }  
  
  
}
  Wire.begin(4);                // join i2c bus with address #2

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.

peter247:
A Morse key are a radio ham?

No, it came with an electronics kit I got for the kids.

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.

Also any additional code you add to requestEvent will stretch the clock, so if the Flyport doesn't support clock stretching you may have problems.

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.

Thanks again Peter