Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wire needs high level write_to and read_from methods [imported] #241

Open
cmaglie opened this issue Nov 15, 2012 · 0 comments
Open

Wire needs high level write_to and read_from methods [imported] #241

cmaglie opened this issue Nov 15, 2012 · 0 comments
Assignees

Comments

@cmaglie
Copy link
Member

cmaglie commented Nov 15, 2012

This is Issue 466 moved from a Google Code project.
Added by 2011-01-23T16:08:36.000Z by fabio.va...@gmail.com.
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Defect, Priority-Medium, Component-Core

Original description

Hi everybody,

Having now quite some experience in working with I2C devices I think that the current implementation of Wire lacks some very helpful routines to do something which is quite standard with I2C devices: write to a register and read from a register of the slave device (when arduino is the master).

The results is that, if you have a look at the various I2C devices Arduino libraries you'll see often the repetition of the following lines:

For slave register write:
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.send(REG_ADDRESS);
Wire.send(VAL_TO_WRITE);
Wire.endTransmission();

For slave register read:
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.send(REG_ADDRESS);
Wire.endTransmission();
Wire.beginTransmission(DEVICE_ADDRESS);
Wire.requestFrom(DEVICE_ADDRESS,NUM_BYTES_TO_READ);
int i = 0;
while(Wire.available()) { //ACC may send less than requested (abnormal)
buff[i] = Wire.receive(); // receive a byte
i++; }
Wire.endTransmission();

I saw code similar to that in almost all the I2C Arduino libs out there.. Of course, this results in huge code repetition if you are using more than one I2C device comporting increase in program memory and additional unneeded code complexity. This can also be seen in the Wire lib examples!

But let's make practical examples..


Example SFRRanger_reader in Wire lib examples:
// step 1: instruct sensor to read echoes
Wire.beginTransmission(112); // transmit to device arduino/Arduino#112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Wire.send(0x00); // sets register pointer to the command register (0x00)
Wire.send(0x50); // command sensor to measure in "inches" (0x50)
// use 0x51 for centimeters
// use 0x52 for ping microseconds
Wire.endTransmission(); // stop transmitting


// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(112); // transmit to device arduino/Arduino#112
Wire.send(0x02); // sets register pointer to echo arduino/Arduino#1 register (0x02)
Wire.endTransmission(); // stop transmitting

// step 4: request reading from sensor
Wire.requestFrom(112, 2); // request 2 bytes from slave device arduino/Arduino#112

// step 5: receive reading from sensor
if(2 <= Wire.available()) // if two bytes were received
{
reading = Wire.receive(); // receive high byte (overwrites previous reading)
reading = reading << 8; // shift high byte to be high 8 bits
reading |= Wire.receive(); // receive low byte as lower 8 bits
Serial.println(reading); // print the reading
}


digital_potentiometer example in Wire lib

Wire.beginTransmission(44); // transmit to device arduino/Arduino#44 (0x2c)
// device address is specified in datasheet
Wire.send(0x00); // sends instruction byte
Wire.send(val); // sends potentiometer value byte
Wire.endTransmission(); // stop transmitting


ADXL345 arduino driver, http://code.google.com/p/adxl345driver/

// Writes val to address register on device
void ADXL345::writeTo(byte address, byte val) {
Wire.beginTransmission(DEVICE); // start transmission to device
Wire.send(address); // send register address
Wire.send(val); // send value to write
Wire.endTransmission(); // end transmission
}

// Reads num bytes starting from address register on device in to _buff array
void ADXL345::readFrom(byte address, int num, byte _buff[]) {
Wire.beginTransmission(DEVICE); // start transmission to device
Wire.send(address); // sends address to read from
Wire.endTransmission(); // end transmission

Wire.beginTransmission(DEVICE); // start transmission to device
Wire.requestFrom(DEVICE, num); // request 6 bytes from device

int i = 0;
while(Wire.available()) // device may send less than requested (abnormal)
{
_buff[i] = Wire.receive(); // receive a byte
i++;
}
if(i != num){
status = ADXL345_ERROR;
error_code = ADXL345_READ_ERROR;
}
Wire.endTransmission(); // end transmission
}


ITG3200 http://code.google.com/p/itg-3200driver/

void ITG3200::writemem(byte _addr, byte _val) {
Wire.beginTransmission(_dev_address); // start transmission to device
Wire.send(_addr); // send register address
Wire.send(_val); // send value to write
Wire.endTransmission(); // end transmission
}

void ITG3200::readmem(byte _addr, int _nbytes, byte __buff[]) {
Wire.beginTransmission(_dev_address); // start transmission to device
Wire.send(_addr); // sends register address to read from
Wire.endTransmission(); // end transmission

Wire.beginTransmission(_dev_address); // start transmission to device
Wire.requestFrom(_dev_address, _nbytes);// send data n-bytes read
byte i = 0;
while (Wire.available()) {
__buff[i] = Wire.receive(); // receive DATA
i++;
}
Wire.endTransmission(); // end transmission
}


HMC5843 library https://launchpad.net/hmc58x3

void HMC5843::writeReg(unsigned char reg, unsigned char val) {
Wire.beginTransmission(HMC5843_ADDR);
Wire.send(reg); // send register address
Wire.send(val); // send value to write
Wire.endTransmission(); //end transmission
}

void HMC5843::getValues(float *x,float *y,float *z) {
int xr,yr,zr;
Wire.beginTransmission(HMC5843_ADDR);
Wire.send(HMC5843_R_XM); // will start from DATA X MSB and fetch all the others
Wire.endTransmission();

Wire.beginTransmission(HMC5843_ADDR);
Wire.requestFrom(HMC5843_ADDR, 6);
if(6 == Wire.available()) {
// read out the 3 values, 2 bytes each.
xr = Wire.receive();
xr = (xr << 8) + Wire.receive();
*x= ((float) xr) / x_scale;
yr = Wire.receive();
yr = (yr << 8) + Wire.receive();
*y = ((float) yr) / y_scale;
zr = Wire.receive();
zr = (zr << 8) + Wire.receive();
*z = ((float) zr) / z_scale;
// the HMC5843 will automatically wrap around on the next request
}
Wire.endTransmission();
}

Same happens for
http://interactive-matter.eu/2009/12/arduino-barometric-pressure-sensor-bmp085/
http://www.neufeld.newton.ks.us/electronics/?p=241
http://naneau.nl/2009/01/18/arduino-and-an-i2c-temperature-sensor/
http://bazaar.launchpad.net/~nxti2cdev/nxti2cdevice/trunk/view/head:/BaseNXTI2CDevice.cpp
http://www.arduino.cc/playground/Code/I2CEEPROM

and basically any code from Googleing "Arduino I2C" shows some examples of that.

Now, in the attached patch I implemented two simple functions which implements those functionalities. I'll gladly add documentation and write to the various maintainers of the I2C libs if this get inserted into Wire.

Interested in hearing your opinions,

Thanks,

Fabio Varesano

@sandeepmistry sandeepmistry transferred this issue from arduino/Arduino Sep 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant