I2C Reading for Grid Eye from Arduino to Electric Imp

edited July 2015 in Device Code
Hello all,

I am writing a piece of code so I can interact with the Grid Eye. I am porting the code from the Arduino on to the Imp. I am having issue though when I read upperLevel and lowerLevel.

The error is here

2015-07-20 15:17:38 UTC-7 [Status] Device connected
2015-07-20 15:17:38 UTC-7 [Device] Beginning Program
2015-07-20 15:17:38 UTC-7 [Device] binary: 55 70 70 65 72 20 4c 65 76 65 6c 20 00
2015-07-20 15:17:38 UTC-7 [Device] binary: 4c 6f 77 65 72 20 4c 65 76 65 6c 20 00
2015-07-20 15:17:38 UTC-7 [Device] ERROR: bitwise op between 'string' and 'integer'
2015-07-20 15:17:38 UTC-7 [Device] ERROR: at GridEye:53
2015-07-20 15:17:38 UTC-7 [Device] ERROR: from main:90

I am only supposed to read one byte for each upperLevel and lowerLevel.

For the arduino, it works fine and I notice that the lowerLevel is almost always 0 for it. Here is the Arduino Code for reference.

https://github.com/logxen/GridEYE-Breakout/blob/master/firmware/Grid_Eye_Breakout/Grid_Eye_Breakout.ino

I have read the i2c reference and tried a lot of things. I remember that at one point it worked ok but I can't find the build and don't want to go through them all.


To clarify, when I have this:
//upperLevel = upperLevel[0]
//lowerLevel = lowerLevel[0]

I get values of 0.

Here is the code for the imp (device). The i2c reading will be on the function GridEye.
i2c <- hardware.i2c12;

hardware.i2c12.configure(CLOCK_SPEED_100_KHZ);

//Original I2C address is 0x068. Shifted to the right one bit is 0xD0
const i2c_grideye = 0xD0;


Threshold <- 0;

function hexStringToInt(hexString)
{
// Does the string start with '0x'? If so, remove it
if (hexString.slice(0, 2) == "0x"){
hexString = hexString.slice(2)
// Get the integer value of the remaining string

local intValue = 0

foreach (character in hexString)
{
local nibble = character - '0'
if (nibble > 9) nibble = ((nibble & 0x1F) - 7)
intValue = (intValue << 4) + nibble
}

return intValue + 2
}
}

function GridEye(){
server.log("Beginning Program")
local pixelTempL = "0x80";
local aveTemp = 0;
local celsius = 0;
for(local pixel = 0; pixel < 64; pixel++)
{
//Must pass pixelTempL as a string
i2c.write(i2c_grideye, pixelTempL);
local upperLevel = i2c.read(i2c_grideye, "", 1);
//local lowerLevel = i2c.read(i2c_grideye, "", 1);
//server.log("upperLevel " + upperLevel)
local lowerLevel = i2c.read(i2c_grideye, "", 1);
//local upperLevel = i2c.read(i2c_grideye, "", 1);
//server.log("lowerLevel " + lowerLevel)

//upperLevel = upperLevel[0]
//lowerLevel = lowerLevel[0]

server.log("Upper Level " + upperLevel)
server.log("Lower Level " + lowerLevel)

local temperature = ((upperLevel << 8) | lowerLevel);
server.log("Temperature " + temperature)
if (temperature > 2047){
temperature = temperature - 4096;
}

celsius = temperature * 0.25;

aveTemp += celsius;

pixelTempL = hexStringToInt(pixelTempL);
pixelTempL = format("0x%02X", pixelTempL)
server.log("Next Address" + pixelTempL)
}

/*i2c.write(i2c_grideye, "\x0E")
local upperLevelTherm = i2c.read(i2c_grideye, "", 1);
local lowerLevelTherm = i2c.read(i2c_grideye, "", 1);
upperLevelTherm = upperLevelTherm[0]
lowerLevelTherm = lowerLevelTherm[0]
local temperatureTherm = ((lowerLevelTherm << 8) | upperLevelTherm);
local celsiusTherm = temperatureTherm * 0.0625;
*/

aveTemp *= 0.015625;

if (aveTemp > Threshold)
{
//send occupancy signal
}
else
{
//send vacancy signal
}
server.log("Average Temperature: " + aveTemp)
imp.wakeup(10, GridEye)
}
GridEye();


For reference, here is the what the GridEye is

http://na.industrial.panasonic.com/products/sensors/sensors-automotive-industrial-applications/grid-eye-infrared-array-sensor

Ultimately I want to get the values for all 64 pixels and average them.


Thanks for any assistance. :)

Update 1: So now for upper level, I get a random char. I decided to change the code above to read in 4 bytes for upperLevel and I get random chars (i.e z, t, }, u, ~, |, etc). I changed it back to read 1 byte but it still gets me the random chars.

Update 2: Now its back to normal reading in a bunch of bytes like my output above.

Update 3: It seems to be alternating between random character and the string of bytes. The code is still the same as above.

Update 4: Fixed something in the hexStringToInt function.

Comments

  • In general when you do an i2c read you should put the address in the transaction, ie instead of:

    //Must pass pixelTempL as a string
    i2c.write(i2c_grideye, pixelTempL);
    local upperLevel = i2c.read(i2c_grideye, "", 1);
    local lowerLevel = i2c.read(i2c_grideye, "", 1);


    you'd do:

    // Read two bytes
    local d = i2c.read(i2c_grideye, pixelTempL, 2);
    local upperLevel = d[0];
    local lowerLevel = d[1];


    The other question is about IO levels. The imp is 3.3v, arduinos are generally 5v. Is the i2c bus 3.3v or 5v?

    I also don't quite get why you're translating hex to binary. I2C devices don't usually return hex. Got a link to a datasheet?
  • Hi Hugo,

    Thank you very much for your timely reply. I will try this out and update you in another comment to avoid confusion. As for the data sheet, it is on the link here:

    http://na.industrial.panasonic.com/products/sensors/sensors-automotive-industrial-applications/grid-eye-infrared-array-sensor

    This Grid-Eye is only 3.3 V tolerant so I am sure the i2C bus is 3.3 V.
  • So I still for upperLevel and lowerLevel, I get 0 for both. Something is up with my Hex2int function. I just fixed it, but it shouldn't affect the issue with upper and lower levels
  • Oh! I just noticed you have this line:

    local pixelTempL = "0x80";

    This is wrong. You are setting pixelTempL to be a 4 byte long string when I suspect you're trying to set it to a single byte of value 0x80. For that you should do:

    local pixelTempL = "\x80";

    (as it's a string).

    However, that's probably not the best way to do this as you are trying to read out the entire array so you might as well just read it all at once with this:

    local image = i2c.read(i2c_grideye, "\x80", 64*2);

    ...then "image" will contain 128 bytes, or 2 bytes for each pixel. You can then process the array separately. This will be a lot quicker.
  • Hi Hugo,

    Thank you again for your reply. Yea I found out about setting the local pixelTempL to be "\x80", but like you said, it wasn't the best way of doing it since I have to read out an entire array, this wouldn't be good. Your solution was just what I needed and very easy. I finally got it working haha.

    There is just one problem and I noticed this before. I did a quick search for this but I just want to verify something with something you posted earlier here:

    https://forums.electricimp.com/discussion/1643/device-messages-throttled

    In the above code, I have it to where the GridEye function repeats every 10 seconds. However, I changed this to where it will run every 0.25 seconds. I only left two "server.logs()" in the program (the Beginning Program one and the Ave Temperature). I eventually get an error message that says "Messages Throttled." To my understanding this is because I am displaying a lot in a short amount of time. Is this right?

    Thank you again Hugo! :)
  • Glad it's working! Looks like a fun chip...

    Yep, that's just because we limit the number of log messages sent from the imp. The imp is still running code, it's just log messages aren't sent to the server.

    If you're trying to do stuff fast, then logging isn't a great idea as the message has to be encrypted, put in TCP buffers, and sent to the server - you'll end up being restricted in your execution speed by the amount of un-acked TCP data in the outbound buffers.
  • Hello all,
    i'm working on project same this one but its much simple
    i want to use this sensor to turn on or off the lights or the ac ,
    but i have problem that i'm not good in programming
    may anyone to help me with that.
Sign In or Register to comment.