I2C write more than one byte of data


#2

I don’t really understand your code; the cmd stuff seems totally unused?

You don’t need to use a blob either, you can just use a string - they can contain any binary value in squirrel.

eg

i2c.write(0x60 << 1, format("\x03%c%c%c%c", 0x46, 0xf1, 0x3a, 0xe5));

…to send \x03 then 4 arbitrary runtime specified values.

Error -3 most likely indicates that the device is sending a NAK to the data. What device are you talking to? This isn’t noted in your post.


#3

I am porting code from arduino for MLX90621 melexis infrared sensor.
in the code line
local resp1 = i2c.write(0xc0, “\x04”+"\xaa"+"\x54"+"\x56"+"\x00");

\x04–> 0x04 is a command not sub address.
The actual address is 0x93
I am trying to write oscillator trimming value using this command.
Thanks for helping

image

This may explain my problem better

image


#4

A link to the library you’re trying to port would be good.

But yes, that write looks correct (check bytes looks right etc). You don’t need to concatenate the string like that but it won’t do any harm.

What is your “i2c enable” pin wiring? What pullups do you have on the bus?


#5

I have put 10k pullup registors on SDA and clock lines

i2c <- “i2cAB” in hardware ? hardware.i2cAB : hardware.i2c89;
i2c.configure(CLOCK_SPEED_400_KHZ);
ex_en <- “i2cAB” in hardware ? hardware.pinC : hardware.pinE;

ENABLE <- “i2cAB” in hardware ? 0 : 1;
DISABLE <- “i2cAB” in hardware? 1 : 0;
ex_en.configure(DIGITAL_OUT, ENABLE);

to start and truncate I2C comunication


#6

Reading from EEPROM is working fine.
But reading and writing to RAM is not woking


#7

What is the i2c enable?


#8

I am using Pin-C of electric imp to start I2C communication by writing 0, creating the start of the I2C communication and pulling it high again to stop the communication.

There is an EEPROM and RAM in the sensor both are on I2C. I am ableto read data from EEPROM but writing to the RAM gives error. I think the pullups are working fine as I am able to read from EEPROM

The working code is

function readEEPROM(){
server.log(“read EEPROM data::::::::::::::::::::::::::::::::::::::::::::::”);
local cmd = blob();
cmd.writen(0x00, ‘b’);
ex_en.configure(DIGITAL_OUT, ENABLE);
imp.sleep(0.05);
server.log(“Sending:”);
server.log( cmd.tostring());
local resp = i2c.write(0x50 << 1, cmd.tostring());
server.log("Sending response------------------------------ "+resp);
//imp.sleep(REINSTATE_TIME);
if(resp==0){
server.log(“Successfully send command”);
eepromData = i2c.read(0x50 << 1, “”, 256);
server.log(“length of RAM data---------------------”+(eepromData.len()));
}
ex_en.configure(DIGITAL_OUT, DISABLE);
server.log(eepromData[OSC_TRIM_VALUE])
}


#9

Yeah, I’m asking what circuitry is connected to that pin?


#10

…regardless, scope traces of the i2c bus are likely needed to progress further. I’d also check the power supply to the device is ok (does it have local bypass caps, etc?)


#11

Hi Hugo sorry for delay I was occupied with something else.

I have removed all the external circuit. I have connected the sensor with imp004 on bread board.I have connected to i2CQP to the sensor directly.

I have not used any external pullup in the SDA or Clock line.
The sensor also donot have any pullup.

But still I am able to read data from EEPROM. I am sending code snipet with results

eepromData <- array(256);
i2c <- “i2cQP” in hardware ? hardware.i2cQP : hardware.i2cNM;
i2c.configure(CLOCK_SPEED_400_KHZ);
ex_en <- hardware.pinP;
ex_en1 <- hardware.pinQ;
ENABLE <- “i2cQP” in hardware ? 0 : 1;
DISABLE <- “i2cQP” in hardware? 1 : 0;

function readEEPROM(){
server.log(“read EEPROM data::::::::::::::::::::::::::::::::::::::::::::::”);
local cmd = blob();
cmd.writen(0x00, ‘b’);
server.log(“Pin P state”+ex_en.read());
server.log(“Pin Q state”+ex_en1.read());
imp.sleep(0.05);
server.log(“Sending:”);
server.log( cmd.tostring());
local resp = i2c.write(0x50 << 1, cmd.tostring());
server.log("Sending response------------------------------ "+resp);
if(resp==0){
server.log(“Successfully send command”);
eepromData = i2c.read(0x50 << 1, “”, 256);
server.log(“length of data---------------------”+(eepromData.len()));
}
server.log(“Pin P state”+ex_en.read());
server.log(“Pin Q state”+ex_en1.read());
}

readEEPROM();

Result:

2018-07-08 00:28:03 +05:30 [Device] Pin P state0
2018-07-08 00:28:03 +05:30 [Device] Pin Q state0
2018-07-08 00:28:03 +05:30 [Device] Sending:
2018-07-08 00:28:03 +05:30 [Device] binary: 00
2018-07-08 00:28:03 +05:30 [Device] Sending response------------------------------ 0
2018-07-08 00:28:03 +05:30 [Device] Successfully send command
2018-07-08 00:28:03 +05:30 [Device] length of data---------------------256
2018-07-08 00:28:03 +05:30 [Device] Pin P state0
2018-07-08 00:28:03 +05:30 [Device] Pin Q state0

When I2C comunication starts?

Please explain when there is no pull on the sensor, like the “SA56004X temperature sensor” given in I2C documentation, How we should put pullup resistor? Please sight any example, I searched but i could not get one.

Also please explain the result I am getting
Any clue will be a great help.

Oscilloscope reading will take some while. I have to order one.


#12

I2C is an open drain bus. It requires pull up resistors. Please add these and retest - it’s rather a miracle it’s working at all without them. 4k7 to 3.3v should be fine.

Datasheets for slave devices may not always show pull-ups, but these are always required - you have one set of pullups per bus not one set per device.


#13

Thanks Hugo, I will try and get back


#14

Hi Hugo,
Thanks a lot
I tried with the pullup resistors on the data, and clock line, Now I can write data it is giving ack(0).
so one problem solved.
But
This sensor works like charm with Arduino. In that also external pullup was required. now same pullups I have given here.
Now I got the read error MASTER_RECEIVE_SELECT_ERROR (-10)
I was also surprised why it was giving EEPROM data. In manufacturer’s manual it says no internal pullup, external pull up is required. No matter what I do EEPROM data is reading.
Now I am able to write comands but after writing a command, the value to be read, there it is giving error.


#15

I think seeing the current state of the code would be useful?

Please use the “</>” button in the editor when you paste it, so it formats correctly.


#16
eepromData <- array(256);
 ptatData<-array(64);
 const OSC_TRIM_VALUE    =    0xF7
 i2c <- "i2cQP" in hardware ? hardware.i2cQP : hardware.i2cNM;
 i2c.configure(CLOCK_SPEED_400_KHZ);
 ex_en <- hardware.pinP;
 ex_en1 <- hardware.pinQ;
 ENABLE <- "i2cQP" in hardware ? 0 : 1;
 DISABLE <- "i2cQP" in hardware? 1 : 0;

function readEEPROM(){
server.log("read EEPROM data::::::::::::::::::::::::::::::::::::::::::::::");
local cmd = blob();
cmd.writen(0x00, 'b');
server.log("Pin P state"+ex_en.read());
server.log("Pin Q state"+ex_en1.read());
imp.sleep(0.05);
server.log("Sending:");
server.log( cmd.tostring());
server.log("Pin P state"+ex_en.read());
server.log("Pin Q state"+ex_en1.read());
local resp = i2c.write(0x50 << 1, cmd.tostring());
server.log("Pin P state"+ex_en.read());
server.log("Pin Q state"+ex_en1.read());
server.log("Sending response------------------------------  "+resp);   
if(resp==0){
    server.log("Successfully send command");
    eepromData = i2c.read(0x50 << 1, "", 256);
    server.log("length of data---------------------"+(eepromData.len()));
}
 server.log("Pin P state"+ex_en.read());
 server.log("Pin Q state"+ex_en1.read()+eepromData[0xf7]);
}

function start(){
server.log("start:::::::::::::::::::::::::::::::::::::::");
local resp = i2c.write(0x60 << 1, "\x01"+"\x08");
server.log("Sending response------------------------------  "+resp);   
if(resp==0){
    server.log("Successfully send command for measurement");
    local resp1 = i2c.write(0x60 << 1, "\x02"+"\x00"+"\x01"+"\x40");
if(resp1==0){
    server.log("Successfully send command for temp measurement"+resp1);
    ptatData=i2c.read(0x60 << 1, "\x00",64);
    if(null == ptatData){
   server.error("i2c_recv: Not working. "+ i2c.readerror());
}
    }
    
//server.log("length of data---------------------"+ptatData.len());
}
 server.log(ptatData);
}

function writeTrimmingValue(){
server.log("osc trimming value::::::::::::::::::::::::::::::::::::::::::");
local cmd = blob();
cmd.writen(0x04, 'b');
cmd.writen(eepromData[OSC_TRIM_VALUE] - 0xAA, 'b');
cmd.writen(eepromData[OSC_TRIM_VALUE], 'b');
cmd.writen(0x56, 'b');
cmd.writen(0x00, 'b');
server.log("Sending:");   
server.log(cmd.tostring());
local resp3 = i2c.write(0x60 << 1, cmd.tostring());  
server.log("Sending response------------------------------  "+resp3);
}

function readConfig(){
server.log("Read Configuration:::::::::::::::::::::::::::::::::::::::");
local resp5 = i2c.write(0x60 << 1, "\x02"+"\x00"+"\x01"+"\x40");
local conf=array(64);
server.log("Sending response------------------------------  "+resp5);   
if(resp5==0){
    server.log("Successfully send command for Read Configuration");
    conf = i2c.read(0x60 << 1, "\x00",3);
    if(null == conf){
   server.error("i2c_recv: Not working. Reason: "+ i2c.readerror());
}
}
 server.log(conf);
}

 function setConf(){
server.log("Set Configuration:::::::::::::::::::::::::::::::::::::::");
local resp6 = i2c.write(0x60 << 1, "\x03"+"\xE9"+"\x3E"+"\xF1"+"\x46");
server.log("Sending response------------------------------  "+resp6);   
if(resp6==0){
    server.log("Successfully send command for Set Configuration");
}
}




readEEPROM();
writeTrimmingValue();
//setConf();
start();
//readConfig();

Th result is:

2018-07-11 08:16:05 +05:30 [Status] Downloading new code; 1.99% program storage used
2018-07-11 08:16:05 +05:30 [Device] read EEPROM data::::::::::::::::::::::::::::::::::::::::::::::
2018-07-11 08:16:05 +05:30 [Device] Pin P state0
2018-07-11 08:16:05 +05:30 [Device] Pin Q state0
2018-07-11 08:16:05 +05:30 [Device] Sending:
2018-07-11 08:16:05 +05:30 [Device] binary: 00
2018-07-11 08:16:05 +05:30 [Device] Pin P state0
2018-07-11 08:16:05 +05:30 [Device] Pin Q state0
2018-07-11 08:16:05 +05:30 [Device] Pin P state0
2018-07-11 08:16:05 +05:30 [Device] Pin Q state0
2018-07-11 08:16:05 +05:30 [Device] Sending response------------------------------ 0
2018-07-11 08:16:05 +05:30 [Device] Successfully send command
2018-07-11 08:16:05 +05:30 [Device] length of data---------------------256
2018-07-11 08:16:05 +05:30 [Device] Pin P state0
2018-07-11 08:16:05 +05:30 [Device] Pin Q state083
2018-07-11 08:16:05 +05:30 [Device] osc trimming value::::::::::::::::::::::::::::::::::::::::::
2018-07-11 08:16:05 +05:30 [Device] Sending:
2018-07-11 08:16:05 +05:30 [Device] binary: 04 a9 53 56 00
2018-07-11 08:16:06 +05:30 [Device] Sending response------------------------------ 0
2018-07-11 08:16:06 +05:30 [Device] start:::::::::::::::::::::::::::::::::::::::
2018-07-11 08:16:06 +05:30 [Device] Sending response------------------------------ 0
2018-07-11 08:16:06 +05:30 [Device] Successfully send command for measurement
2018-07-11 08:16:06 +05:30 [Device] Successfully send command for temp measurement0
2018-07-11 08:16:06 +05:30 [Device] ERROR: i2c_recv: Not working. -10
2018-07-11 08:16:06 +05:30 [Device] (null : 0x0)

I am using imp004 breakout board I have also provided the pullup resiortors. I have put nothing else.


#17

Thanks for helping…


#18

One issue here is that your read command is sending “\x00” when nothing is expected. Also, you are issuing the read IR data command, telling it that you’re about to read 64 bytes, then reading 3 of them after this spurious write.

To read IR data, this should work:

// Issue IR data read command, step 1, 0x40 bytes, and read them
local irdata = i2c.read(0x60 << 1, "\x02\x00\x01\x40", 64);
if (irdata == null) server.log("i2c error "+i2c.readerror());
else {
  server.log("read "+irdata.len()+" bytes");
}

#19

Thank you very much, It is working, thanks a lot. It was really a pain.
Could you please explain
i2c.read(0x60 << 1, “\x02\x00\x01\x40”, 64);
“\x02\x00\x01\x40” This is register address?
For reading any data, I need to send the string sequence in place of register address?
Any ways thanks a lot it is working.


#20

Hi Hugo,
can you please tell, what I am doing wrong in this command?
I have to write this command
image
Reading irData is working fine.

 function setConf(){
    server.log("Set Configuration:::::::::::::::::::::::::::::::::::::::");
    local resp6 = i2c.write(0x60 << 1, "\x03"+"\xE9"+"\x3E"+"\xF1"+"\x46");
    server.log("Sending response------------------------------  "+resp6);   
    if(resp6==0){
        server.log("Successfully send command for Set Configuration");
    }
}

setConf();

Result I am getting is:

018-07-12 07:02:43 +05:30 [Device] Set Configuration:::::::::::::::::::::::::::::::::::::::
2018-07-12 07:02:43 +05:30 [Device] Sending response------------------------------ -3

#21

Sorry for leaping in, but Hugo is travelling today. The sequence "\x02\x00\x01\x40" is 0x02 for read, 0x00 for the start address, 0x01 for the address increment, and 0x40 for the number of reads (64). See p31 of the datasheet.

Yes, you send as a string the data the component (whatever it is) expects. In this case that’s the command plus three bytes of data, but it might just be a register address, a different comment, or an address plus further data. The crucial thing is that you just provide a string of the bytes and impOS does all the work sending in in the correct way.