Pages: [1] 2   Go Down
Author Topic: make Arduino act as EEPROM  (Read 1288 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi everyone,
i'm trying to power a gopro hero3 through the bus connector, so i need Arduino to act as a simple eeprom.
In this case i need to write value 9 to address 0 of eeprom so that the camera recognises arduino as a valid accessory.

http://www.benthicscience.com/beta/products/custom-builds/gopro-hero3-bus-access

how can i make Arduino act as an eeprom so that each time the gopro reads the bus Arduino returns the requested value?

thank a lot
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A single byte addressable EEPROM is possible.
But since the Arduino uses a software library, it sometimes stretches the clock. If the Master is not capable to do that, the Arduino will not work.

http://arduino.cc/en/Tutorial/MasterReader
http://arduino.cc/en/Tutorial/MasterWriter

The Arduino should use the onRequest and onReceive handlers. The onRequest for EEPROM data, the onReceive to receive the address byte.

The Arduino as I2C Slave does not know how many bytes are read by the Master with onRequest. So you do not know how much the address byte should be incrementend. That is not implemented in the library.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So what do you think is wrong with this code
Code:
#include <Wire.h>
#include <EEPROM.h>
void setup() {
  // put your setup code here, to run once:
  EEPROM.write(0,9); //Write 0x09 at address 0 of the eeprom
  Wire.begin(0);     //Join I2C bus with address 0
  Wire.onRequest(requestEvent); // register Event
}

void loop() {
  // put your main code here, to run repeatedly:
 
}
void requestEvent()
{
 
  Wire.write(EEPROM.read(0));
}
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The I2C address is the address of the I2C device.
The EEPROM register address selecting is the address inside the EEPROM. It is written to the EEPROM before data is read.

I2C address '0' is reserved. You have to find the I2C address of the original EEPROM, and use that for Wire.begin.

You sketch also needs the onReive, to receive the single byte register address.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what do you mean for ''address of the original EEPROM"?
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The "I2C address of the original EEPROM".

Every Slave on a I2C bus had an address. The Wire.begin( slave_address) use a 7-bit address.
http://arduino.cc/en/Reference/WireBegin

In the link they mention the "Microchip 24AA0", I think the I2C address for that chip is 0x50 to 0x57.

If you want to emulate that chip, you have to start with: Wire.begin( 0x50);
However, if address 0x51 ... 0x57 is used, you can't emulate the other I2C addresses.

Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Wire.h>


void setup() {
  Serial.begin(9600);
  Wire.begin(0x50);     //Join I2C bus with address 0x50
  }

void loop() {
  // put your main code here, to run repeatedly:
  Wire.onRequest(requestEvent); // register requestEvent
  Wire.onReceive(receiveEvent); // register receiveEvent
  }

void requestEvent()
{
  Serial.println("requestEvent");
}

void receiveEvent(int howMany)
{
    Serial.println("receiveEvent");
    Wire.write(0x09); //is it OK???
 
}

so the code should be like this?
p.s. Wire.onRequest() and WIre.onReceive() are ok in the loop or should they be in the setup???
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46077
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
p.s. Wire.onRequest() and WIre.onReceive() are ok in the loop or should they be in the setup???
They are registering event handlers. That needs to be done once.
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As PaulS wrote, they need to be in setup().

You write a message with Serial.println() from requestEvent() and receiveEvent(). That might not work at all, or just once.
Since those function are interrupt handlers, it might (it will) cause a conflict with the interrupt driven Serial library.
So you need extra code to work around that.

Make a global variable: volatile boolean flagRequest;

Set it 'true' in the requestEven().

Check in the loop if it is 'true', set it to 'false' and write a message with Serial.println().
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Wire.h>

volatile boolean RequestArrived, receiveCalled;

void setup()
{
  RequestArrived = false;
  receiveCalled = false;
  Serial.begin(9600);
  Wire.begin(0x50);   
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent); 
}

void loop()
{
  if(receiveCalled)
  {
    receiveCalled = false;
    char c = Wire.read();
    Serial.print("received ");
    Serial.println(byte(c));
  }
  if(RequestArrived)
  {
    RequestArrived = false;
    Serial.println("request");
  }   
}

void requestEvent()
{
  RequestArrived = true; 
}

void receiveEvent(int howMany)
{
  receiveCalled = true;
}

from your suggestions i wrote this code that is supposed to be working fine, but it never reaches the request. it only calls the receiveEvent.
i even trid to change the bitrate of the I2C bus from 100KHz to 400KHz but the result is always the same. do you think it could be a clock problem?
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i noticed even another fact:
if my Arduino UNO slaves triggers the receiveEvent at least, if use the same code with an Arduino DUE i do NOT have any response, any idea?
Moreover GoPro Hero3 works at 3V3 so i should expect the opposite, shouldn't i?
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The way you use the flags is good.
However, the Wire.read() should be in the receiveEvent(), I don't know if that buffer is still valid after the receiveEvent() has finished. I think not.

Just add a few global volatile variables:
Code:
volatile int receiveHowMany;
volatile int receiveData;
Fill them in the receiveEvent() and print them in the loop().

Perhaps you can also try I2C address 0x50 up to 0x57, and see what the other I2C addresses do.

I don't know why the Due has a different response. But timing and clock stretching has always been a problem when using an Arduino as I2C Slave. If the GoPro doesn't support it, only hardware EEPROM chips can be used.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for your support. But my problem is that i do not have any response from the request event, the receive seems to be OK yet.
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It starts with the receive, that is why I want to know what is received.

For an EEPROM, first the address (for the location inside the EEPROM) is send. That is what you receive. I assume you receive a single byte of '0x00'. After that the EEPROM is read or written to the location that just has been send.
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, in my case i have receive 0x00 with the receive event but then nothing happens
Logged

Pages: [1] 2   Go Up
Jump to: