Skip to main content

i2c.write(deviceAddress, registerPlusData)

Initiates an I²C write to the device at the specified address

Availability

Device

Parameters

Name Type Description
deviceAddress Integer The 8-bit I²C base address
registerPlusData String The I²C sub-address and data, or "" for none

Returns

Integer — 0 for success, or an I²C Error Code

Description

The first two characters of the string to be written via the I²C bus are typically used as the most-significant byte and the least-significant byte of the sub-address — typically the device register you wish to access. A peripheral with 8-bit registers needs only a single byte for its address. An empty string, "", may be passed to initiate an empty-payload write phase.

Though the registerPlusData parameter takes a string, this can easily be used to send binary data if you use any of a number of simple conversion processes, as listed below. Pick the one that most closely aligns with how you are storing your binary data:

local sendStringOne = format("%c%c%c", 0xA5, 0xD3, 0x00);
local sendStringTwo = integerOne.tochar() + integerTwo.tochar();
locat sendStringThree = blobOne.tostring();

Squirrel strings can include NULL characters (unlike C strings) so you can send any binary value this way.

On completion, 0 is returned for success, or non-zero for an error condition. A list of error codes can be found on the i2c.readerror() page.

Please note that many vendors’ device datasheets specify a 7-bit base I²C address. In this case, you will need to bit-shift the address left by 1 (ie. multiply it by 2) to form the 8-bit address required by the imp API:

local impReadyI2Caddress = datasheetI2Caddress << 1;

Example Code

The code below provides an example of using an I²C device. It configures an SA56004X temperature sensor — as found on the Hannah R2 reference design — by requesting the CLOCK_SPEED_400_KHZ clocking rate.

const REG_LTHB = "\x00";
const REG_LTLB = "\x22";
const REG_SR = "\x02";
const REG_CONW = "\x09";
const REG_CRW = "\x0A";
const REG_SHOT = "\x0F";
const REG_AM = "\xBF";
class TempSensor {
_i2c = null;
_addr = null;
constructor(i2c, address) {
_i2c = i2c;
_addr = address;
}
function get() {
// Configure a single shot reading
_i2c.write(_addr, REG_CONW + "\xD5");
// Set conversion rate to 1Hz
_i2c.write(_addr, REG_CRW + "\x04");
// Ask the sensor to perform a one-shot reading
_i2c.write(_addr, REG_SHOT + "\x00");
// Wait for the sensor to finish the reading
while ((_i2c.read(_addr, REG_SR, 1)[0] & 0x80) == 0x80);
// Get 11-bit signed temperature value in 0.125C steps
local hi = _i2c.read(_addr, REG_LTHB, 1)[0];
local lo = _i2c.read(_addr, REG_LTLB, 1)[0];
local temp = (hi << 3) | (lo >> 5);
// Convert from a 11-bit integer to a Celsius temperature
if (temp & 0x400) {
// Negative two's complement value
return -((~temp & 0x7FF) + 1) * 0.125;
} else {
// Positive value
return temp * 0.125;
}
}
}
// Configure an imp001 i2c bus
hardware.i2c89.configure(CLOCK_SPEED_400_KHZ);
// Create TempSensor object
tempSensor <- TempSensor(hardware.i2c89, 0x98);
// Read temperature
server.log(tempSensor.get());