Sending complex data across I2C / Arduino

Hi All,

Setup: I am building a four motor rover, with a pan-tilt platform + SONAR. The motors are driven using a dedicated motor drive of appropriate voltage / amperage (2ch 30A drive w/ each channel driving 2 motors). The pan-tilt platform is bespoke with two S3003 servos driven through a servo driver. The SONAR is run of the mill HC-SR04 that feeds into the arduino.

Set up uses R-Pi as a Master and I aim to use the Arduino as a Slave through I2C. The Clock and Data Lines are connected through a logic converter; and a simple check of the I2C connection using "hello world" blinking program works. Everything is powered using a high capacity / high discharge 12V battery. The electro mechanical set up was earlier testing using just the Arduino (without RPi) and it works fine.

Why the Pi at all: I need to integrate both LiDAR and a visual camera besides creating a composite using all three positioning datasets (SONAR / LiDAR / VisCam). Moreover, the Pi will be used for PLAN / SLAM calculations too. Just the Arduino doesn't cut it for my needs.

Problem: I am trying to control the Motor Drive / SONAR / Pan-Tilt connected to the Arduino, from the RPi - through I2C. As mentioned above, I got the wire library to work successfully (thanks to many videos / articles on the net). I am however stuck in the next step.

I would like to send an array / dataframe / struct of information to the Arduino via I2C (for instance, imagine asking the pan-tilt system to move to angle 27* / 102*; I need to send a call to the function that moves these two servos, and provide this info. Or imagine moving the motors to make a turn, I need to provide differential speed info to the arduino about where I want to go (80,120) [motor control function].

How do I do this? Or is there no way to do this [can't believe this will be the case].

I understand I may not be the first one to ask this question: so, any pointers to previous solutions is also quite appreciated.

Thanks a ton.

Warm regards,

You can search for serial data transmission protocols.

But it will be much more efficient to use WiFi (TCP is more recommended than UDP) or SPI.

https://forum.arduino.cc/t/solved-sending-array-data-with-i2c/537012

https://community.st.com/s/question/0D50X0000ALud2SSQR/what-is-the-best-protocol-to-send-arrays-i2c-spi-

https://www.reddit.com/r/esp8266/comments/4s2q9q/esp8266_sending_large_array/

The I2C bus is weak, because the high level is by pullup resistors. That will not go well with motors nearby. How close is the Arduino to the Raspberry Pi ? More than 20 cm ?
If you can use communication over Serial, that would be better. Then you can also use the buffer (64 byte) to send a few commands. Just plug the Arduino into a USB port and use Python to communicate with the Arduino.

You could define a 'struct' and send that 'struct' over I2C as a package. For example a byte for the type of command and a few more bytes for the data.
The onReceive handler puts the data in global memory and sets a flag. The loop() reads that flag and clears the flag and processes the data.

If you don't show it, then I have my doubts :grimacing:

If you don't show it, then I have my doubts

:smiley: .. Here is the code I used for that

On the Arduino side:

#include <Wire.h>

int ledPin = 13;
void setup() {
  // put your setup code here, to run once:
  Wire.begin(0x8);

  Wire.onReceive(receiveEvent);

  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW);
}

void receiveEvent(int howMany) {
  // put your main code here, to run repeatedly:
  while(Wire.available())
  {
    char c = Wire.read();
    digitalWrite(ledPin, c);
  }
}

void loop()
{
  delay(100);
}

On the R-Pi side:

from smbus import SMBus
addr = 0x8
bus = SMBus(1)

numb = 1

numb = 1
print("Enter 1 or 0")

while numb == 1:
    
    ledState = input("  ")
    if ledState == "1":
        bus.write_byte(addr, 0x1)
    elif ledState == "0":
        bus.write_byte(addr, 0x0)
    else:
        numb = 0

Disclaimer - these snippets are closely adapted from code I found on the web. I can find a reference for credits ; but important thing is this is not my own. So I am not surprised the code worked.

To answer your other questions: The arduino is going to be placed less than 20cm from the Pi.

Serial Port as an option - thanks. I will definitely read up about it.

Last thing - about sending the struct as a series of bytes. Can you point me to an example that does it? That is really what I want to see - to learn how to do it. Thanks.

Warm regards,

Thank you for the links. I will go through them.

As for WiFi - I am afraid my arduino (Nano) isn't capable. Will look up SPI. As @Koepel pointed out, I will also look up USB Serial connection.

As for WiFi - I am afraid my arduino (Nano) isn't capable

Note that GitHub - jeelabs/esp-link: esp8266 wifi-serial bridge, outbound TCP, and arduino/AVR/LPC/NXP programmer is the original esp-link software which has notably been forked by arduino.org as Esp-Link and shipped with the initial Arduino Uno Wifi.

The esp-link firmware connects a micro-controller to the internet using an ESP8266 Wifi module. It implements a number of features:

  • Transparent bridge between Wifi and serial, useful for debugging or inputting into a uC
  • Flash-programming attached Arduino/AVR microcontrollers and LPC800-series and other ARM microcontrollers via Wifi

https://github.com/jeelabs/esp-link

Hardware configuration for normal operation

This firmware is designed for any esp8266 module. The recommended connections for an esp-01 module are:

  • URXD: connect to TX of microcontroller*
  • UTXD: connect to RX of microcontroller*
  • GPIO0: connect to RESET of microcontroller*
  • GPIO2: optionally connect green LED to 3.3V (indicates wifi status)*

https://github.com/jeelabs/esp-link/blob/master/FLASHING.md

Thanks. That is a trove of info in your posts. I will spend the next few days at least reading up on those.

This explains the basics: Arduino in Target mode · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub
I did not give a full example, because of all the trouble.

Robin2 made a full working example here: Use I2C for communication between Arduinos
I think my comments are valid, but he did not change it.

GolamMostafa also made a full working example, but I can't find it right now.

Thanks much. I had accidentally stumbled upon your git page on common mistakes earlier. :slight_smile: Will also go through your Wiki. I think I saw GolamMostafa's article too (through googling). Thanks for all the resource links.