Communication Between Linux and Arduino

Hello, Arduino.
I followed the link
https://docs.arduino.cc/tutorials/portenta-x8/python-arduino-data-exchange/.

I'm trying to print data on a serial port using the Arduino IDE; could you possibly assist me in communicating between Arduino and Linux on an Arduino Portenta X8 board?

Thank you,
PSR.

You will find it helpful to spend some time studying the Serial Input Basics tutorial.

If that doesn't cover your questions, follow the instructions in the "How to get the best out of this forum", linked at the head of every forum topic, to improve your post and the chances of getting help.

You can use a terminal interface, for example, that is multi-platform and can also be used from a Linux with the screen command. With Shellminator, for instance, you can quickly set up your own commands that can be accessed from Linux.

It has a ton of examples and a good documentation:

Also, there is a video about the topic:

Actually, I'm attempting the aforementioned link as communication between Linux and arduino with an arduino portenta x8 board; could you possibly help on this?

It is not clear for me how did you test it.
Please show your code as requested in Forum guidelines .
Connection diagram and photos that clearly show your wiring can also be very helpful.

I'm trying to communicate between stm32 micro controller and nxp micro processor of arduino portenta x8.
https://docs.arduino.cc/tutorials/portenta-x8/python-arduino-data-exchange/ ,
i have flashed the arduino code is

//#include <RPMsgCommunication.h> 
#include <SerialRPC.h>
#include <Wire.h>

#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Adafruit_BME280 bme;

void setup()
{
   pinMode(PA_12, INPUT);

    RPC.begin();

   Serial.begin(115200);

   Serial.println("BME280 test on M4");
   Wire.begin();

   for (auto status = bme.begin(); !status; delay(250)) {
       Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
       Serial.print("SensorID was: 0x");
       Serial.println(bme.sensorID(), 16);
   }

   RPC.bind("status", []{ return bme.sensorID() == 0x60; });
   RPC.bind("temperature", []{ return bme.readTemperature(); });
   RPC.bind("humidity", []{ return bme.readHumidity(); });
   RPC.bind("pressure", []{ return bme.readPressure() / 100.0F; });

   Serial.println("Starting");
}

void loop()
{
   delay(10);
}```

and In adb shell i have run python-sensor code is

```import time
from msgpackrpc import Address as RpcAddress, Client as RpcClient, error as RpcError


# Fixed configuration parameters
port = 8884
publish_interval = 5

# The M4 Proxy address needs to be mapped via Docker's extra hosts
m4_proxy_address = 'm4-proxy'
m4_proxy_port = 5000

def get_data_from_m4():
   """Get data from the M4 via RPC (MessagePack-RPC)

   The Arduino sketch on the M4 must implement the following methods
   returning the suitable values from the attached sensor:

   * `temperature`
   * `humidity`
   * `pressure`
   * `gas`
   * `altitude`

   """

   rpc_address = RpcAddress(m4_proxy_address, m4_proxy_port)

   data = ()

   try:
       print("rpc_address=" , rpc_address)
       rpc_client = RpcClient(rpc_address)
       temperature = rpc_client.call('temperature')

       rpc_client = RpcClient(rpc_address)
       humidity = rpc_client.call('humidity')

       rpc_client = RpcClient(rpc_address)
       pressure = rpc_client.call('pressure')

       rpc_client = RpcClient(rpc_address)
       gas = rpc_client.call('gas')

       rpc_client = RpcClient(rpc_address)
       altitude = rpc_client.call('altitude')

       data = temperature, humidity, pressure, gas, altitude

   except RpcError.TimeoutError:
       print("Unable to retrive data from the M4.")

   return data


if __name__ == '__main__':

   print()
   print("============================================")
   print("==       Portenta X8 Sensor reading       ==")
   print("============================================")
   print()

   try:
       while True:
           data = get_data_from_m4()
           if len(data) > 0:
               print("Temperature: ", data[0])
               print("Humidity: ", data[1])
               print("Pressure: ", data[2])
               print("Gas: ", data[3])
               print("Altitude: ", data[4])
           time.sleep(publish_interval)
   except KeyboardInterrupt:
       print('Stopped.')

but while build the docker container of sensor is


unable to get the sensor data of BMP280,
i;m attached Arduino portetnax8 and Hat carrier schematics.
Could you please review and please support me to develop.
ABX00049-schematics.pdf (5.5 MB)
ASX00049-schematics.zip (4.4 MB)

Thanks,
PSR.

Hi,

Could you please respond anyone help me to develop.

Sorry, I have no idea what are you doing...

Can we meet online today? Let me explain.

@b707 @jremington @dani007200964 ,
Could you please respond.

I followed the tutorial from this link:
https://docs.arduino.cc/tutorials/portenta-x8/python-arduino-data-exchange/

However, when checking the Docker logs for python-sensor-rpc , I encountered an error:

,
what i have done so far,

  • Uploaded the provided Arduino sketch to the Portenta X8.
  • Followed the steps to set up the Python RPC server in Docker.

The Docker container fails with the error shown in the logs.
Could you help me troubleshoot this issue? Here’s the code I uploaded to the Arduino

#include <RPC.h>
#include <SerialRPC.h>
#include <Wire.h>

#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Adafruit_BME280 bme;

void setup()
{
    pinMode(PA_12, INPUT);

    // RPC.begin();

    Serial.begin(115200);

    Serial.println("BME280 test on M4");
    Wire.begin();

    for (auto status = bme.begin(); !status; delay(250)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
        Serial.print("SensorID was: 0x");
        Serial.println(bme.sensorID(), 16);
    }


    RPC.bind("status", []{ return bme.sensorID() == 0x60; });
    RPC.bind("temperature", []{ return bme.readTemperature(); });
    RPC.bind("humidity", []{ return bme.readHumidity(); });
    RPC.bind("pressure", []{ return bme.readPressure() / 100.0F; });

    Serial.println("Starting");
}

void loop()
{
    delay(10);
}

Hello Ptillisch,

Could you please respond this, What i have done i was posted.
kindly go through and help me to develop.

Advance Thanks,
PSR.

Hello again @sridhar_p0266. I see there is a bug in the "M4_BME280_RPC" sketch that is included in the "python-sensor-rpc" ZIP package from the download link in that tutorial. If we look at the Python script that runs on the Portenta X8's Linux machine, we see this:

        rpc_client = RpcClient(rpc_address)
        temperature = rpc_client.call('temperature')

        rpc_client = RpcClient(rpc_address)
        humidity = rpc_client.call('humidity')

        rpc_client = RpcClient(rpc_address)
        pressure = rpc_client.call('pressure')

        rpc_client = RpcClient(rpc_address)
        gas = rpc_client.call('gas')

        rpc_client = RpcClient(rpc_address)
        altitude = rpc_client.call('altitude')

Meanwhile the M4_BME280_RPC sketch binds the following RPC messages:

  • status
  • temperature
  • humidity
  • pressure

Note that the sketch does not bind a gas or altitude message. When the Python script calls the missing messages, it causes a RpcError.TimeoutError exception to be raised, and thus you get this "Unable to retrive data from the M4." [sic] message from the Python script instead of the expected sensor data.

I have reported this bug to the Arduino documentation team. I apologize for any inconvenience this has caused.

There are a couple of different options for how you can resolve this problem:

Option A: Use BMP680 Sensor

The Python script is actually written for use with the BMP680 sensor. Unlike M4_BME280_RPC sketch, the "M4_BME680_RPC" sketch that is included in the tutorial's "python-sensor-rpc" ZIP package does provide all the RPC messages that are called by the Python script.

So if you happen to have a BMP680 sensor on hand, then the easiest solution would be to switch to using that sensor instead of the BMP280. I'll provide instructions you can follow to do that:

  1. Unplug the USB cable and any other power sources from the Portenta X8 board.
  2. Disconnect the BMP280 sensor from the Portenta X8.
  3. Connect the BMP680 sensor to the Portenta X8.
  4. Connect the USB cable of the Portenta X8 board.
  5. Use Arduino Cloud Editor to upload the M4_BME680_RPC sketch from the tutorial's "python-sensor-rpc" ZIP package to the Portenta X8 board.
  6. Wait for the sketch to upload successfully.

After doing that, you should see the expected output from the Python script, something like this

python-sensor-rpc_1  | Temperature:  25.904266357421875
python-sensor-rpc_1  | Humidity:  25.564695358276367
python-sensor-rpc_1  | Pressure:  976.4400024414062
python-sensor-rpc_1  | Gas:  136.496
python-sensor-rpc_1  | Altitude:  311.0769348144531

(you don't need to take any action at all in the Portenta X8's Linux machine as long as the Python script is still running)

Option B: Remove Calls to Missing RPC Messages

Since the BMP280 sensor does provide altitude data, it would be possible to add the missing altitude message to the M4_BME280_RPC sketch. However, unlike the BMP680, the BMP280 does not have a VOC sensing capability, so it is not possible to add a gas message to the sketch that would return meaningful data.

For this reason, I think the most appropriate path forward with the BMP280 sensor would be to remove the calls to the missing RPC messages from the Python script. I'll provide instructions you can follow to do that:

  1. Start any text editor application.
    You can use a text editor like VIM on the Portenta X8's Linux machine if you like, but since it is generally more convenient to do development work on your PC, I'll assume you are using your PC for the rest of these instructions.
  2. Use the text editor to open the src/m4_to_python.py file from the folder extracted from the tutorial's "python-sensor-rpc" ZIP package.
  3. Change line 47 in the script from this:
            data = temperature, humidity, pressure, gas, altitude
    
    to this:
            data = temperature, humidity, pressure
    
  4. Delete lines 41-45 from the script:
            rpc_client = RpcClient(rpc_address)
            gas = rpc_client.call('gas')
    
            rpc_client = RpcClient(rpc_address)
            altitude = rpc_client.call('altitude')
    
  5. Delete these lines from the script:
                    print("Gas: ", data[3])
                    print("Altitude: ", data[4])
    
  6. Save the file.
  7. If the original Python script is running on the Portenta X8's Linux machine, press the Ctrl+C keyboard shortcut in its shell window, then wait until it exits from the container:
    ^CGracefully stopping... (press Ctrl+C again to force)
    Aborting on container exit...
    [+] Stopping 1/1
     ✔ Container python-sensor-rpc-python-sensor-rpc-1  Stopped                                                                                                                                                
    10.4s
    canceled
    fio@portenta-x8-2a0fca09dab6fad9:/var/rootdirs/home/fio/python-sensor-rpc$
    
  8. Follow the instructions from the tutorial to upload the python-sensor-rpc folder that contains the modified Python script to the Portenta X8's Linux machine (adb push ...), build the container (docker build ...), and run the container (docker compose up), just the same as you did before:
    https://docs.arduino.cc/tutorials/portenta-x8/python-arduino-data-exchange/#the-python-application

After doing that, you should see the expected output from the Python script, something like this

python-sensor-rpc_1  | Temperature:  25.904266357421875
python-sensor-rpc_1  | Humidity:  25.564695358276367
python-sensor-rpc_1  | Pressure:  976.4400024414062

Please let me know if you have any questions or problems while following those instructions.

Hello Ptillisch,

Thanks a lot for your coordination earlier! I was done what you say, and i have run the py-serial rpc and python-sensor-data of BMP280 attached.

import time
from msgpackrpc import Address as RpcAddress, Client as RpcClient, error as RpcError


# Fixed configuration parameters
port = 8884
publish_interval = 5

# The M4 Proxy address needs to be mapped via Docker's extra hosts
m4_proxy_address = 'm4-proxy'
m4_proxy_port = 5001

def get_data_from_m4():
    """Get data from the M4 via RPC (MessagePack-RPC)

    The Arduino sketch on the M4 must implement the following methods
    returning the suitable values from the attached sensor:

    * `temperature`
    * `humidity`
    * `pressure`
    * `gas`
    * `altitude`

    """

    rpc_address = RpcAddress(m4_proxy_address, m4_proxy_port)

    data = ()

    try:
        rpc_client = RpcClient(rpc_address)
        temperature = rpc_client.call('temperature')

        rpc_client = RpcClient(rpc_address)
        humidity = rpc_client.call('humidity')

        rpc_client = RpcClient(rpc_address)
        pressure = rpc_client.call('pressure')

        data = temperature, humidity, pressure

    except RpcError.TimeoutError:
        print("Unable to retrive data from the M4.")

    return data


if __name__ == '__main__':

    print()
    print("============================================")
    print("==       Portenta X8 Sensor reading       ==")
    print("============================================")
    print()

    try:
        while True:
            data = get_data_from_m4()
            if len(data) > 0:
                print("Temperature: ", data[0])
                print("Humidity: ", data[1])
                print("Pressure: ", data[2])
            time.sleep(publish_interval)
    except KeyboardInterrupt:
        print('Stopped.')

i have upload arduino code from arduino cloud editor,

#include <SerialRPC.h>
#include <Wire.h>

#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Adafruit_BME280 bme;

void setup()
{
    pinMode(PA_12, INPUT);

    // RPC.begin();

    Serial.begin(115200);

    Serial.println("BME280 test on M4");
    Wire.begin();

    for (auto status = bme.begin(); !status; delay(250)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
        Serial.print("SensorID was: 0x");
        Serial.println(bme.sensorID(), 16);
    }


    RPC.bind("status", []{ return bme.sensorID() == 0x60; });
    RPC.bind("temperature", []{ return bme.readTemperature(); });
    RPC.bind("humidity", []{ return bme.readHumidity(); });
    RPC.bind("pressure", []{ return bme.readPressure() / 100.0F; });

    Serial.println("Starting");
}

void loop()
{
    delay(10);
}

Here, In serial monitor not showing serial.println logs,

while runs the Docker container, i'm getting below data


,
i made the connections of BMP280 with Arduino portenta x8 with Hat Carrier J5 header pins is 3rd pin =SCL, 5th Pin= SDA.

Could please help me to rectify this issue.

Thanks
PSR

OK, I was afraid of this but wanted to focus on fixing one bug at a time.

In addition to the bug in the Python script provided by the tutorial, there is also a bug in the firmware of the Portenta X8's M7 core:

The bug has already been fixed:

However, it seems that there hasn't been a new release of the image for the X8's Linux image (which is how the M7 firmware is distributed) since the time of that fix. So it will be necessary to manually update the M7 firmware to pull in the fix for this bug. I'll provide instructions you can follow to do that:

  1. Click the following link to download the binary for version 0.0.5 of the firmware:
    STM32H747AII6_CM7.zip (45.2 KB)
    I am providing the binary I built because it is a bit complicated and inconvenient to build it yourself. However, if you prefer, you are welcome to build the firmware yourself from the source code instead of trusting the binary I am providing. The instructions for doing that are here (note that they don't mention there is a requirement to have a recent version of the ARM GNU Toolchain AKA "arm-none-eabi-gcc" or "gcc-arm-none-eabi" installed).
  2. Wait for the download to finish.
  3. Extract the downloaded file to any convenient location on your computer.
  4. Use adb push to upload the STM32H747AII6_CM7.bin file from the extracted folder to the Portenta X8 's Linux machine, just as you did before with the python-sensor-rpc folder.
  5. Use adb shell to open a shell on the Portenta X8 's Linux machine as usual.
  6. Type the following command (reference) in the terminal prompt of the Portenta X8 's Linux machine shell:
    sudo mount -o remount,rw /usr && sudo mv STM32H747AII6_CM7.bin /usr/lib/firmware/arduino/stm32h7-fw/STM32H747AII6_CM7.bin && sudo bash -c /usr/arduino/extra/program.sh
    
  7. Press the Enter key.
  8. Wait for the firmware update to finish successfully.
  9. Use docker compose up to run the python-sensor-rpc container, just as you did when following the instructions I provided in my previous reply.

After doing that, you should see the expected output from the Python script, something like this

python-sensor-rpc_1  | Temperature:  25.904266357421875
python-sensor-rpc_1  | Humidity:  25.564695358276367
python-sensor-rpc_1  | Pressure:  976.4400024414062

Please let me know if you have any questions or problems while following those instructions.

Hello Ptillisch,

  1. I have successfully downloaded the .bin file and was able to run it, as shown below:
  2. I uploaded the M4_BME280_RPC sketch using the Arduino Cloud Editor.
  3. I built and ran the Docker container for py-serialrpc without any issues:
  4. However, when trying to run the python-sensor-rpc script to get sensor data, I encountered the following error:

Could you please help me troubleshoot this issue and get the sensor data?

Thank you in advance,
PSR

Are you using the container with the Python script that has the modifications I specified in post #19?

Hello @ptillisch,

Thank you for your continued support.

I’ve made the modifications you suggested in the python-sensor-rpc script and have included the updated code below.

import time
from msgpackrpc import Address as RpcAddress, Client as RpcClient, error as RpcError


# Fixed configuration parameters
port = 8884
publish_interval = 5

# The M4 Proxy address needs to be mapped via Docker's extra hosts
m4_proxy_address = 'm4-proxy'
m4_proxy_port = 5001

def get_data_from_m4():
    """Get data from the M4 via RPC (MessagePack-RPC)

    The Arduino sketch on the M4 must implement the following methods
    returning the suitable values from the attached sensor:

    * `temperature`
    * `humidity`
    * `pressure`

    """

    rpc_address = RpcAddress(m4_proxy_address, m4_proxy_port)

    data = ()

    try:
        rpc_client = RpcClient(rpc_address)
        temperature = rpc_client.call('temperature')

        rpc_client = RpcClient(rpc_address)
        humidity = rpc_client.call('humidity')

        rpc_client = RpcClient(rpc_address)
        pressure = rpc_client.call('pressure')

        data = temperature, humidity, pressure

    except RpcError.TimeoutError:
        print("Unable to retrive data from the M4.")

    return data


if __name__ == '__main__':

    print()
    print("============================================")
    print("==       Portenta X8 Sensor reading       ==")
    print("============================================")
    print()

    try:
        while True:
            data = get_data_from_m4()
            if len(data) > 0:
                print("Temperature: ", data[0])
                print("Humidity: ", data[1])
                print("Pressure: ", data[2])
            time.sleep(publish_interval)
    except KeyboardInterrupt:
        print('Stopped.')

Could you please review it and help identify or rectify any remaining issues?

Thanks again,
PSR.

Please provide the output you get from running the following command from a shell terminal on the Portenta X8's Linux machine:

cat /etc/os-release

I ran the following command:
cat /etc/os-release
And got the following output:

Thanks,
PSR