I recently obtained a new Portenta x8. I started working through the tutorials. I updated the FW to the latest:
ID=lmp-xwayland
NAME="Linux-microPlatform XWayland"
VERSION="4.0.11-934-91"
VERSION_ID=4.0.11-934-91
PRETTY_NAME="Linux-microPlatform XWayland 4.0.11-934-91"
HOME_URL="https://foundries.io/"
SUPPORT_URL="https://support.foundries.io/"
DEFAULT_HOSTNAME="portenta-x8"
LMP_MACHINE="portenta-x8"
LMP_FACTORY="arduino"
LMP_FACTORY_TAG="main"
IMAGE_ID=lmp-factory-image
IMAGE_VERSION=934
I followed the Data Exchange tutorial:
https://docs.arduino.cc/tutorials/portenta-x8/python-arduino-data-exchange/
The sketch running on the M4:
#include <RPC.h>
#include <SerialRPC.h>
/*
Tested with arduino-91.4 and mbed portenta 4.1.5.
This is a fake BME680 sensor example over rpc.
We implement several rpc stubs which will answer with the same (fixed)
data over and over. It works great as a real use-case for sensor acquisition
from M4 over RPC protocol on the Portenta-X8 without the need to actually wire the
sensors over I2C.
*/
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.begin(115200);
//while (!Serial){};
Serial.println("Fake BME680 test on M4");
Serial.println("Registering rpc calls...");
RPC.bind("temperature", []{ return 100; });
RPC.bind("humidity", []{ return 200; });
RPC.bind("pressure", []{ return 300; });
RPC.bind("gas", []{ return 400; });
RPC.bind("altitude", []{ return 500; });
/*if (RPC.cpu_id() == CM7_CPUID) {
// Introduce a brief delay to allow the M4 sufficient time
// to bind remote functions before invoking them.
delay(100);
}*/
spettacolino();
Serial.println("Finished Init");
}
void loop()
{
Serial.print("Temperature = ");
Serial.print(100);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(200);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(300);
Serial.println(" %");
Serial.print("Gas = ");
Serial.print(400);
Serial.println(" KOhms");
Serial.print("Approx. Altitude = ");
Serial.print(500);
Serial.println(" m");
Serial.println();
delay(1000);
}
void spettacolino() {
for(int i=0; i<6; i++) {
digitalWrite(LED_BUILTIN, LOW);
delay(800);
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
}
digitalWrite(LED_BUILTIN, LOW);
}
The docker-compose.yml for the container:
services:
python-sensor-rpc:
#image: hub.foundries.io/arduino/python-sensor-rpc:latest
image: python-sensor-rpc:latest
restart: unless-stopped
environment:
- PYTHONUNBUFFERED=1
volumes:
- /var/run/secrets:/app/config/
extra_hosts:
- "m4-proxy:172.17.0.1"
The python script running in the container:
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')
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.')
The output from running the python-sensor-rpc container is the following:
python-sensor-rpc-python-sensor-rpc-1 |
python-sensor-rpc-python-sensor-rpc-1 | ============================================
python-sensor-rpc-python-sensor-rpc-1 | == Portenta X8 Sensor reading ==
python-sensor-rpc-python-sensor-rpc-1 | ============================================
python-sensor-rpc-python-sensor-rpc-1 |
python-sensor-rpc-python-sensor-rpc-1 | Unable to retrive data from the M4.
python-sensor-rpc-python-sensor-rpc-1 | Unable to retrive data from the M4.
I verified that there is some serial data coming across by using the py-serial download from the documentation. (I named the container serial-debugger) It outputs the following:
serial-debugger | [1758922463.6315038] Call b'Pressure = '
serial-debugger | Pressure =
serial-debugger | [1758922463.6321552] Call b'100'
serial-debugger | 100
serial-debugger | [1758922464.6219401] Call b'Temperature = '
serial-debugger | Temperature =
serial-debugger | [1758922464.622339] Call b'100'
serial-debugger | 100
serial-debugger | [1758922464.6230464] Call b' *C'
serial-debugger | *C
serial-debugger | [1758922464.623662] Call b'\r\n'
serial-debugger |
serial-debugger |
serial-debugger | [1758922464.624251] Call b'Pressure = '
serial-debugger | Pressure =
serial-debugger | [1758922464.62478] Call b'200'
serial-debugger | 200
serial-debugger | [1758922464.6253357] Call b' hPa'
serial-debugger | hPa
serial-debugger | [1758922464.6258812] Call b'\r\n'
serial-debugger |
serial-debugger |
serial-debugger | [1758922464.6264505] Call b'Humidity = '
serial-debugger | Humidity =
serial-debugger | [1758922464.6270015] Call b'300'
serial-debugger | 300
serial-debugger | [1758922464.627612] Call b' %'
serial-debugger | %
serial-debugger | [1758922464.6281621] Call b'\r\n'
serial-debugger |
serial-debugger |
serial-debugger | [1758922464.6287236] Call b'400'
serial-debugger | 400
serial-debugger | [1758922464.6292787] Call b'Gas = '
serial-debugger | Gas =
serial-debugger | [1758922464.6297827] Call b' KOhms'
serial-debugger | KOhms
serial-debugger | [1758922464.6303189] Call b'\r\n'
From having done some research, some people in the past had success with using a blink example:
https://github.com/joel35/portenta-x8-blink-rpc/tree/main
I tried that and it gave me the same "unable to retrieve data from the M4".
So, I am all out of ideas. This is the most basic functionality and why this unit was purchased in the first place. It's the "hello world" of getting the RPC stuff to work, and should just work.
I would love to know if this is a known issue on this version of FW and if there is a plan to fix it, and when that might be. My company needs to make a decision on whether to buy more of these or pivot to another solution.
Thanks.