Initiates an I²C write to the device at the specified address
Device
Name | Type | Description |
---|---|---|
deviceAddress | Integer |
The 8-bit I²C base address
|
registerPlusData | String |
The I²C sub-address and data, or "" for none
|
Integer — 0 for success, or an I²C Error Code
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;
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()); |