Go Down

Topic: I2c Slave mode. (Read 2672 times) previous topic - next topic

peter247

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"

I`ve put a print statement in "void requestEvent()" and it`s never called !!!

Is there a better slave library for the Arduino ?

Thank in advance Peter A
http://peter224722.blogspot.com

peter247

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
http://peter224722.blogspot.com

Graynomad

Sorry Peter I can't help.

Quote
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
Rob Gray aka the GRAYnomad www.robgray.com

wayneft

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.
I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

peter247

For the arduino side I`m just using the example wire/slave_sender , on the master side I`m 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
http://peter224722.blogspot.com

wayneft

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...
I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

peter247

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

Code: [Select]
/**
\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
}
/*! @} */
http://peter224722.blogspot.com

peter247

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
http://peter224722.blogspot.com

peter247

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.

http://peter224722.blogspot.com

wayneft

Quote
I2CWrite( adc + 0x01);


What is adc equal too?
I2C GPS Shield

Checkout my Open Source GPS Tracker on Kickstarter

Nick Gammon

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

http://www.gammon.com.au/i2c

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

Quote
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?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Graynomad

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

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Nick Gammon

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:

http://www.gammon.com.au/movies/TinyGL3.mov

(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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

peter247

#13
Jul 30, 2011, 02:57 pm Last Edit: Jul 31, 2011, 10:23 am by peter247 Reason: 1
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

Code: [Select]
#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;
 }  
 
 
}

http://peter224722.blogspot.com

Nick Gammon

Quote
Code: [Select]
  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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up