2

I have created a gui in python that allows an arduino controlled mecanum wheel cart to move around.

The cart allows for 8 different move directions and can rotate left and right. Commands are sent over a serial connection between the laptop(w10, python) and the arduino.

I have an Enum class in python representing the different move directions.

I have a corresponding enum in the arduino to interprete the commands from the python task.

What is an easy way to share a single common enum definition for both coding environments?

1

3 Answers 3

3

No. Enums in C/C++ and enum.Enum in python are two very different things. However, there is a powerful solution. I suggest writing the C/C++/Arduino header from your python code. With python's powerful introspection, it's easy to scan through your python enum/class with __dict__ and write a .h file that your Arduino code can use. This is how I generate Verilog and SystemVerilog headers that match the enums and constants in related python projects. Running the python applications produces a new header file, always in sync.

EDIT: A MORE EXPLICIT EXAMPLE

I've built an assembler for an FPGA-based microprocessor. The assembler is in python, while the processor is programmed in Verilog. So I create a Verilog header file like this:

# Compute the 'after' content.
content = '// opcodes.vh\n'
content += '`ifndef _opcodes_vh\n'
content += '`define _opcodes_vh\n'
content += '// DO NOT EDIT -- FILE GENERATED BY ASSEMBLER\n'
content += '// ------------------------------------\n'
content += '// OPCODES\n'
content += '// ------------------------------------\n'
A = Arch
for i in A.__dict__:
    if i.startswith('OPC_'):
        o = i.replace('OPC_', 'OPCODE_')
        s = '`define ' + o
        while len(s) < 40:
            s = s + ' '
        hexval = str(hex(A.__dict__[i])).replace('0x', '')
        decval = str(A.__dict__[i])
        s = s + "7'h" + hexval + '\t\t// ' + str(decval) + '\n'
        content += s
content += '// END OF GENERATED FILE.\n'
content += '`endif'

# Write to very specific location for Vivado to see it.
file = open(self.opcodes_filename, 'w', encoding='utf-8')
file.write(content)
file.close()

The final output looks like this:

// opcodes.vh
`ifndef _opcodes_vh
`define _opcodes_vh
// DO NOT EDIT -- FILE GENERATED BY ASSEMBLER
// ------------------------------------
// OPCODES
// ------------------------------------
`define OPCODE_LD_GPR_EXPR              7'h0        // 0
`define OPCODE_LD_GPR_GPTR              7'h1        // 1
`define OPCODE_SV_EXPR_GPR              7'h2        // 2
...
`define OPCODE_IO_T                     7'h4a       // 74
`define OPCODE_TX_T                     7'h4b       // 75
// END OF GENERATED FILE.
`endif
Sign up to request clarification or add additional context in comments.

Comments

1

As @TomServo said, have your Python code write the Arduino header. Here's an example using either aenum 3.01 or Python 3.10 2:

from aenum import Enum   # or "from enum import Enum"

class CHeader(Enum):
    def __init_subclass__(cls, **kwds):
        # write Enums to C header file
        cls_name = cls.__name__
        header_path = getattr(cls, '_%s__header' % cls_name)
        with open(header_path, 'w') as fh:
            fh.write('initial header stuff here\n')
            for enum in cls:
                fh.write('#define %s %r\n' % (enum.name, enum.value))

class Arduino(CHeader):
    #
    _order_ = 'ONE TWO'  # only if using Python 2
    #
    __header = './arduino.h'
    #
    ONE = 1
    TWO = 2

Which would result in:

initial header stuff here
#define ONE 1
#define TWO 2

1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

2 In aenum 3.0 and Python 3.10 __init_subclass__ will be called after the enum members are added to the Enum class (in prior versions __init_subclass__ is called before the members are added).

3 Comments

One could also read the arduino file in Python to generate the Python Enum.
Is it possible first write a definition file for the enum, and run a script to generated all the enum definition for both C, C++ and Python. I have coded C in micro processor, C++ in the GUI and Python GUI running on PC. But I would like to share the enum const value for all those 3 kinds of languages. Thanks.
arduino.stackexchange.com/a/79700/86014 Something like this answer, but need tweaks, I'm not sure such tool exists. Thanks.
1

Optional solution is to have the enum in *.py file, which C file can include and python can import.

The file will look like:

#if 0
"""
#endif
typedef enum my_enum{
#if 0
"""
from enum import IntEnum, unique
@unique
class MyEnum(IntEnum):
#endif
    FIRST = 0,
    SECOND = 1,
    THIRD = 2,
#if 0
"""
#endif
}my_enum_e;

#if 0
"""
#endif

The idea behind it is that Python ignores all the C preprocessor commands, as they are in Python triple-quoted strings, which is where I put the C only code.

In the other hand, C ignores everything inside #if 0 - where I put the python code.

The disadvantage in this structure is it bit confusing and I didn't find way to make the numbering automatic.

2 Comments

Great! as you mention a bit ugly to look at but once understood a nice way to avoid maintaining the code in 2 environments
If you liked this answer, maybe you will also like stackoverflow.com/a/75570512/8913338 which based on similar ideas

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.