Message Boards Message Boards

I2C interface for Mathematica on Raspberrypi

GROUPS:

The ozzmaker.com BerryIMU has a BMP180 temperature-pressure sensor and a LSM9DS0 magnetometer-accelerometer-gyroscope sensor. Mathematica can read-write sensor registers and has advantages in processing the outputs to physical values. This project is intended to evaluate Raspberrypi Zero Mathematica performances on sensors handling.

functions

rGet[reg_] := 
  StringTrim[
   RunProcess[{"i2cget", "-y", "1", chipAdr, reg}, 
    "StandardOutput"]];
rPut[reg_, value_] := 
  StringTrim[
   RunProcess[{"i2cset", "-y", "1", chipAdr, reg, value}, 
    "StandardOutput"]];
(* Get unSigned and Signed Short Integer *)
usGet[reg1_, reg2_] := (
   r = Flatten[{rGet[reg1], rGet[reg2]}];
   r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
   BitShiftLeft[r1[[1]], 8] + r1[[2]]
   );
ssGet[reg1_, reg2_] := (
   r = Flatten[{rGet[reg1], rGet[reg2]}];
   r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
   r2 = BitShiftLeft[r1[[1]], 8] + r1[[2]];
   If[r2 > 32767, -32768 + (r2 - 32768), r2]
   );

LSM9DS0 magnetic field sensor

chipAdr = "0x1e";
(* CTRL_REG5 _XM, 24h set magnetsensor data rate*)

rPut["0x24", "0x00"];
(* CTRL_REG7 _XM, 26h set magnetsensor to continuous conversion*)

rPut["0x26", "0x00"];
d = Table[Pause[0.3]; usGet["0x09", "0x08"], {100}];
ListLinePlot[d]

BMP180 temperature/pressure sensor

chipAdr = "0x77";
ac1 = ssGet["0xaa", "0xab"];
ac2 = ssGet["0xac", "0xad"];
ac3 = ssGet["0xae", "0xaf"];
ac4 = usGet["0xb0", "0xb1"];
ac5 = usGet["0xb2", "0xb3"];
ac6 = usGet["0xb4", "0xb5"];
b1 = ssGet["0xb6", "0xb7"];
b2 = ssGet["0xb8", "0xb9"];
mb = ssGet["0xba", "0xbb"];
mc = ssGet["0xbc", "0xbd"];
md = ssGet["0xbe", "0xbf"];
rPut["0xf4", "0x2e"]; Pause[0.05];
ut = usGet["0xf6", "0xf7"];
x1 = (ut - ac6)*ac5/2.^15;
x2 = mc*2.^11/(x1 + md);
b5 = x1 + x2;
t = (b5 + 8.)/2.^4/10.

(* prssure *)

rPut["0xf4", "0x34"]; Pause[0.05];
up = usGet["0xf6", "0xf7"];
b6 = b5 - 4000.;
x1 = (b2*(b6*b6/2^12))/2^11;
x2 = ac2*b6/2^11;
x3 = x1 + x2;
b3 = ((ac1*4 + x3) + 2)/4.;
x1 = ac3*b6/2^13;
x2 = (b1*(b6*b6/2^12))/2^16;
x3 = ((x1 + x2) + 2)/2^2;
b4 = ac4*(x3 + 32768)/2^15;
b7 = (up - b3)*50000;
If[b7 < FromDigits["80000000", 16], p = b7*2/b4, p = b7/b4*2];
x1 = p/2^8*p/2^8;
x1 = x1*3038/2^16;
x2 = (-7357*p)/2^16;
p = p + (x1 + x2 + 3791)/2^4;
p = p*0.01
POSTED BY: Hirokazu Kobayashi
Answer
5 months ago

Hi Hirokazu,

Mathematica actually has a built-in device driver for interfacing with I2C devices, you can see some examples here : http://reference.wolfram.com/language/ref/device/I2C.html

For example, the code you have that uses RunProcess can be replaced with calls like this:

(*open a connection to the device*)
dev = DeviceOpen["I2C",chipAddr]
(*read a single byte from a register*)
DeviceWrite[dev,reg];DeviceRead[dev]
(*write a single byte value to a register*)
DeviceWrite[dev,reg];DeviceWrite[dev,value];

Thanks,

Ian

POSTED BY: Ian Johnson
Answer
5 months ago

hi Ian

My first test was one that followed wolfram reference, DeviceOpen[] etc. as you shown, however in my environment (Mathematica 10.3 on Raspberrypi Zero), I only got errorneous results. For example, FindDevices[] can't find my I2C BerryIMU module, but returns FunctionDemo, GPIO, RandomSignalDemo, RaspberryPiWeatherStation, and WriteDemo.

So, I appreciate if you will show your environment and sample working code.

Thank you,

Kbys

POSTED BY: Hirokazu Kobayashi
Answer
5 months ago

Group Abstract Group Abstract