Portenta Machine Control With Python

I just Started with the Portenta (Machine Control), im a big fan of Python specially when i already have a running version of the program in python

im able to upload in the the H7 with openMV and use the onboard LED,

now im looking for documentation ( if it is posible ) to get in too the "Machine control board"

Check with your source for the Portenta (Machine Control), I would expect to be part of the package when you purchased it. The schematic is published at this: https://content.arduino.cc/assets/AKX00032-schematics.pdf that should have all the information you need.

import pyb # Import module for board related functions
from pyb import Pin

gpio0 = Pin('PI6', Pin.OUT_PP, Pin.PULL_NONE)
gpio1 = Pin('PH9', Pin.OUT_PP, Pin.PULL_NONE)
gpio2 = Pin('PJ9', Pin.OUT_PP, Pin.PULL_NONE)

while True:

  gpio0.on()
  pyb.delay(100)
  gpio0.off()
  gpio1.on()
  pyb.delay(100)
  gpio1.off()
  gpio2.on()
  pyb.delay(100)
  gpio2.off()

Thanks That was easier then it looked

maping the "DIGITAL OUTPUTS" was easy to understand but im still unable to understand the other ports, input, I/O, Analog

// EDIT i found the anolog read

adc0 = ADC(Pin('PC3'))
adc1 = ADC(Pin('PC2'))
adc2 = ADC(Pin('PA1'))

print("Analog value0:", adc0.read())
print("Analog value1:", adc1.read())
print("Analog value2:", adc2.read())
1 Like

i made some progress able to read 2nd until 8th digital pin with that

but during testing the 24V+ fell out of my hand and arced somewhere on the board 3v3 power is gone even directly connected to the H7 there is nothing, it will be a couple days until the new one arrives


I2C_ADDRESS = 0x23

# Initialize I2C communication
i2c = SoftI2C(sda=Pin('PH8'), scl=Pin('PH7'), freq=100000)

# Read the input states from the GPIO expander
def read_input_states():
    i2c.writeto(I2C_ADDRESS, bytes([0]))  # Send command to read input states
    input_states = i2c.readfrom(I2C_ADDRESS, 1)  # Read 3 bytes for input states
    return input_states


input_pins = ["Input 05", "Input 04", "Input 03", "Input 3",  "Input 02",  "Input 01",  "Input 07",  "Input 06",  "Input 8"]
while True:
    

  input_states = read_input_states()
  print("Input states:", input_states)
  # Interpret input states
  active_inputs = []
  for bit_position in range(8):
         if input_states[0] & (1 << bit_position):
             active_inputs.append(input_pins[bit_position])
     
  if active_inputs:
         print("Active input pins:", active_inputs)
  else:
         print("No active input pins.")
     

im currently reading down a rabit hole of how to get it to work when the new board arrives

after digging in the the arduino IDE lib "Arduino_MachineControl.h"
and reading all the files i think i have all the different addresses


#define TCA6424A_ADDRESS_ADDR_LOW   0x22 // address pin low (GND)
#define TCA6424A_ADDRESS_ADDR_HIGH  0x23 // address pin high (VCC)
#define TCA6424A_DEFAULT_ADDRESS    TCA6424A_ADDRESS_ADDR_LOW

#define TCA6424A_RA_INPUT0          0x00
#define TCA6424A_RA_INPUT1          0x01
#define TCA6424A_RA_INPUT2          0x02
#define TCA6424A_RA_OUTPUT0         0x04
#define TCA6424A_RA_OUTPUT1         0x05
#define TCA6424A_RA_OUTPUT2         0x06
#define TCA6424A_RA_POLARITY0       0x08
#define TCA6424A_RA_POLARITY1       0x09
#define TCA6424A_RA_POLARITY2       0x0A
#define TCA6424A_RA_CONFIG0         0x0C
#define TCA6424A_RA_CONFIG1         0x0D
#define TCA6424A_RA_CONFIG2         0x0E

#define TCA6424A_AUTO_INCREMENT     0x80

#define TCA6424A_LOW                0
#define TCA6424A_HIGH               1

#define TCA6424A_POLARITY_NORMAL    0
#define TCA6424A_POLARITY_INVERTED  1

#define TCA6424A_OUTPUT             0
#define TCA6424A_INPUT              1

#define TCA6424A_P00                0
#define TCA6424A_P01                1
#define TCA6424A_P02                2
#define TCA6424A_P03                3
#define TCA6424A_P04                4
#define TCA6424A_P05                5
#define TCA6424A_P06                6
#define TCA6424A_P07                7
#define TCA6424A_P10                8
#define TCA6424A_P11                9
#define TCA6424A_P12                10
#define TCA6424A_P13                11
#define TCA6424A_P14                12
#define TCA6424A_P15                13
#define TCA6424A_P16                14
#define TCA6424A_P17                15
#define TCA6424A_P20                16
#define TCA6424A_P21                17
#define TCA6424A_P22                18
#define TCA6424A_P23                19
#define TCA6424A_P24                20
#define TCA6424A_P25                21
#define TCA6424A_P26                22
#define TCA6424A_P27                23

for anyone who will ever need it

using python to control outputs (will make an edit soon to add the input)

import pyb # Import module for board related functions
from pyb import Pin,ADC
from machine import SoftI2C
import time

I2C_ADDRESS22 = 0x22

i2c = SoftI2C(sda=Pin('PH8'), scl=Pin('PH7'), freq=100000)

class I2CIO:
    def __init__(self, address, i2c, pin , pintype):
        if pin == 4:
            pin = 7
        elif pin == 5:
            pin = 6
        elif pin == 6:
            pin = 5
        elif pin == 7:
            pin = 4

        reg_addr = 0x00 + (pin // 8)  # TCA6424A_RA_OUTPUT0 + (pin / 8)
        bit_num = pin % 8

        self.address = address
        self.reg_addr = reg_addr
        self.bit_num = bit_num
        self.i2c = i2c
        self.write_setup(pintype)
        if pintype==0:
            self.off()
    # setup pin
    def write_setup(self, pintype):
        b = i2c.readfrom_mem(self.address, self.reg_addr+12, 1)[0]
        if pintype != 0:
            b |= (1 << self.bit_num)
        else:
            b &= ~(1 << self.bit_num)
        i2c.writeto_mem(self.address, self.reg_addr+12, bytes([b]))
        return b

    def on(self):
        self.write_output(1)
    def off(self):
        self.write_output(0)
    def write_output(self, value):
        b = i2c.readfrom_mem(self.address, self.reg_addr+4, 1)[0]
        if value != 0:
            b |= (1 << self.bit_num)
        else:
            b &= ~(1 << self.bit_num)
        i2c.writeto_mem(self.address, self.reg_addr+4, bytes([b]))
        return b

DO_0 = Pin('PI6', Pin.OUT_PP, Pin.PULL_NONE)
DO_1 = Pin('PH9', Pin.OUT_PP, Pin.PULL_NONE)
DO_2 = Pin('PJ9', Pin.OUT_PP, Pin.PULL_NONE)
DO_3 = Pin('PE2', Pin.OUT_PP, Pin.PULL_NONE)
DO_4 = Pin('PI3', Pin.OUT_PP, Pin.PULL_NONE)
DO_5 = Pin('PI2', Pin.OUT_PP, Pin.PULL_NONE)
DO_6 = Pin('PD3', Pin.OUT_PP, Pin.PULL_NONE)
DO_7 = Pin('PA14', Pin.OUT_PP, Pin.PULL_NONE)

ProCH00 = I2CIO(I2C_ADDRESS22, i2c, 0,0)
ProCH01 = I2CIO(I2C_ADDRESS22, i2c, 1,0)
ProCH02 = I2CIO(I2C_ADDRESS22, i2c, 2,0)
ProCH03 = I2CIO(I2C_ADDRESS22, i2c, 3,0)
ProCH04 = I2CIO(I2C_ADDRESS22, i2c, 4,0)
ProCH05 = I2CIO(I2C_ADDRESS22, i2c, 5,0)
ProCH06 = I2CIO(I2C_ADDRESS22, i2c, 6,0)
ProCH07 = I2CIO(I2C_ADDRESS22, i2c, 7,0)
ProCH08 = I2CIO(I2C_ADDRESS22, i2c, 8,0)
ProCH09 = I2CIO(I2C_ADDRESS22, i2c, 9,0)
ProCH010 = I2CIO(I2C_ADDRESS22, i2c, 10,0)
ProCH011 = I2CIO(I2C_ADDRESS22, i2c, 11,0)

print ("____ SETUP complete_____")
while True:

  pausetime = 200

  DO_0.on()
  pyb.delay(pausetime)
  DO_0.off()
  DO_1.on()
  pyb.delay(pausetime)
  DO_1.off()
  DO_2.on()
  pyb.delay(pausetime)
  DO_2.off()
  DO_3.on()
  pyb.delay(pausetime)
  DO_3.off()
  DO_4.on()
  pyb.delay(pausetime)
  DO_4.off()
  DO_5.on()
  pyb.delay(pausetime)
  DO_5.off()
  DO_6.on()
  pyb.delay(pausetime)
  DO_6.off()
  DO_7.on()
  pyb.delay(pausetime)
  DO_7.off()
  ProCH00.on()
  pyb.delay(pausetime)
  ProCH00.off()
  ProCH01.on()
  pyb.delay(pausetime)
  ProCH01.off()
  ProCH02.on()
  pyb.delay(pausetime)
  ProCH02.off()
  ProCH03.on()
  pyb.delay(pausetime)
  ProCH03.off()
  ProCH04.on()
  pyb.delay(pausetime)
  ProCH04.off()
  ProCH05.on()
  pyb.delay(pausetime)
  ProCH05.off()
  ProCH06.on()
  pyb.delay(pausetime)
  ProCH06.off()
  ProCH07.on()
  pyb.delay(pausetime)
  ProCH07.off()
  ProCH08.on()
  pyb.delay(pausetime)
  ProCH08.off()
  ProCH09.on()
  pyb.delay(pausetime)
  ProCH09.off()
  ProCH010.on()
  pyb.delay(pausetime)
  ProCH010.off()
  ProCH011.on()
  pyb.delay(pausetime)
  ProCH011.off()