So I hooked up the wires from the I2C2 port of the Cube Orange to my Arduino Pro Mini like this:
> Pixhawk I2C2 SCL <==> Pro Mini SCL (A5)
> Pixhawk I2C2 SDA <==> Pro Mini SDA (A4)
> Pixhawk I2C2 GND <==> Pro Mini GND
Both the Pixhawk and Arduino are powered via different USB ports from my laptop.
So I made a simple Arduino code to see what kind of data comes from Lua I2C function calls, and it looks like this:
Then I made a simple Lua script to test i2c function calls. I used the safety switch as a condition, so the I2C functions get called only when I press the safety switch. The Lua script looks like this:
local i2c_bus_num = 0;
local slave_addr = 0x24;
local safety_switch_pressed = false;
local i2c_tried = false;
local arduino_i2c = i2c.get_device(i2c_bus_num, slave_addr);
arduino_i2c:set_retries(10);
function i2c_check_func()
safety_switch_pressed = not SRV_Channels:get_safety_state();
if(safety_switch_pressed == true and i2c_tried == false) then
gcs:send_text(6, " => Testing I2C");
arduino_i2c:write_register(0x10, 0x20);
i2c_tried = true;
end
if(safety_switch_pressed == false) then
i2c_tried = false;
end
return i2c_check_func, 100 -- Run at every 100ms i.e. 10Hz
end
gcs:send_text(6, " => Start")
return i2c_check_func()
With this setup, I am able to get the serial prints on my Arduino’s Serial Monitor when I press the Safety switch on my Pixhawk, like this:
My Questions are:
Since I am using the I2C2 port of the Cube Orange Plus, then why does the Lua script work with bus address 0? When I try with i2c bus address 1 (which is expected for I2C2), I do NOT receive any data on the Arduino’s serial monitor. Why is this? Isn’t I2C1 the expected bus 0?
The script only works if the Arduino starts after Pixhawk. If I reboot only the Pixhawk and try again (without making any changes to anything), then there is no data communication on the Arduino’s Serial Monitor. If I reset the Arduino after rebooting Pixhawk, then everything works normally. Why is this?
Hello @Yuri_Rage
Thank you for your response. Really appreciate it.
After sending data to Arduino, now I am trying to read data from the Arduino, but I am not receiving any data on Pixhawk.
I need a bit of your guidance since you already have spent a lot of time on this.
So I updated my Arduino Code to use the Wire.write() function, and it looks like this:
I also update my Lua script to use the i2c read_registers() function, and it looks like this:
local i2c_bus_num = 0;
local slave_addr = 0x24;
local safety_switch_pressed = false;
local i2c_tried = false;
local arduino_i2c = i2c.get_device(i2c_bus_num, slave_addr);
arduino_i2c:set_retries(3);
local i2c_data_received = 0x00;
function i2c_check_func()
safety_switch_pressed = not SRV_Channels:get_safety_state();
if(safety_switch_pressed == true and i2c_tried == false) then
gcs:send_text(6, " => Testing I2C");
arduino_i2c:write_register(0x10, 0x20);
i2c_data_received = arduino_i2c:read_registers(0x11);
gcs:send_text(6, " => Got Data: " .. tostring(i2c_data_received));
i2c_tried = true;
end
if(safety_switch_pressed == false) then
i2c_tried = false;
end
return i2c_check_func, 100 -- Run at every 100ms i.e. 10Hz
end
gcs:send_text(6, "DTPC Technologies BDS_0005 L5_v10")
return i2c_check_func()
Now when I press the safety switch of Pixhawk, I get this on the Arduino Serial Monitor, confirming that on i2c read_registers() function, 0x11 gets sent to the Arduino on “receive_data_func()”, and the “Wire.write()” function gets called inside the Arduino’s “request_data_func()”:
Sorry for the trouble. Actually, I am just trying to learn to make the basic code so that I can use it in a bigger system with a lot of custom requirements.
Using the library and editing it, and then getting stuck will consume a lot of time since then I have to debug the library functions also.
I just merged some changes to the arduino-i2c-slave library that you might find useful. It won’t impact any of the issues you’re having with read/write calls, but the Lua examples are now far more elegant in the way they handle integer and floating point packing/unpacking.
I also just submitted it for inclusion in the official Arduino Library manager.
Thank you soo much for your fast replies. I am able to solve my issue.
As you correctly mentioned, the issue was the Serial commands inside the i2c read and i2c send data handlers.
After removing the serial commands from both handlers, the data is now being sent correctly to the Pixhawk via I2C. Thank you soo much for your help.
Also, I found a simple way to manage the conversion from 16-bit unsigned to 16-bit signed data, as explained below:
In my Arduino code, I am storing my sensor data in “int16_t” variables which would require 2 bytes to send, and the full range is from -32768 to +32767.
So to avoid sign conversion in Lua, I am adding “32768” to my sensor data before sending, and then send the 2 bytes to Lua, as shown below:
Indeed, unsigned integers are far easier to manage. In the official library, I use string packing, which is easily modified to handle any numeric type, despite being a bit of overkill for simple unsigned values. For signed integers, you’d use local fmt = ('i%d'):format(#b) (lowercase i). Maybe I should add a comment to that effect. The OneWire DS18B20 example shows how to handle floating point (doubles), which is really where the elegance of string packing shines in this use case.
local function unpack_uint(b)
if type(b) ~= 'table' or #b == 0 then return ERROR_VALUE end
local packed_string = string.char(table.unpack(b))
local fmt = ('I%d'):format(#b) -- unsigned integer of table size
local val = string.unpack(fmt, packed_string)
return val
end
Hi @Yuri_Rage ,
Thank you for your constant help.
I am able to send and read data to/from my secondary STM32 (using in place of Arduino) successfully.
I am reading around 50 bytes from my secondary board (STM32) via I2C in one go. The I2C bus is running at 400kHz, which would take around 1 ms to read the 50 bytes.
I am wondering could this I2C transfer time impact the flight control loop time or not?
Does the I2C transfer work in a blocking way or unblocking way?
Do you have any idea about it?