Adding a unique ID to each sub-menu

As far as I can know about menus in WordPress – handlers use menu arguments. You can try to use this.

Using the argument filter, we can pass the ID of the item:

add_filter(
    'nav_menu_item_args',
    function( $args, $item, $depth ) {
        $args->item_id = $item->ID;

        return $args;
    },
    10,
    3
);

Then use custom argument anywhere.

add_filter(
    'walker_nav_menu_start_el',
    function($item_output, $item) {
        if ( get_field( 'dropdown', $item) == 'yes' ) { 
            return '<button aria-expanded="false" aria-controls="submenu-'. $item->ID . '" class="header__button">' . $item->title . '</button>';
        }
        return $item_output;
    },
    10,
    2
);
class My_Nav_Menu_Walker extends Walker_Nav_Menu {
    /**
     * Starts the list before the elements are added.
     *
     * @see Walker::start_lvl()
     *
     * @param string   $output Used to append additional content (passed by reference).
     * @param int      $depth  Depth of menu item. Used for padding.
     * @param stdClass $args   An object of wp_nav_menu() arguments.
     */
    public function start_lvl( &$output, $depth = 0, $args = null ) {
        if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
            $t="";
            $n = '';
        } else {
            $t = "\t";
            $n = "\n";
        }
        $indent = str_repeat( $t, $depth );

        // Default class.
        $classes = array( 'sub-menu' );

        // ! Get parent item ID:
        $id = isset( $args->item_id ) ? ' id="submenu-' . absint( $args->item_id ) . '"' : '';

        /**
         * Filters the CSS class(es) applied to a menu list element.
         *
         * @since 4.8.0
         *
         * @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
         * @param stdClass $args    An object of `wp_nav_menu()` arguments.
         * @param int      $depth   Depth of menu item. Used for padding.
         */
        $class_names = implode( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
        $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

        // ! Insert ID:
        $output .= "{$n}{$indent}<ul{$class_names}{$id}>{$n}";
    }
}

It remains to include the file with an custom walker
and point it to the menu:

wp_nav_menu(
    array(
        'container' => false,
        'theme_location' => 'primary',
        'items_wrap' => '<ul class="header__nav-items header__nav-items--primary">%3$s</ul>',
        'walker'  => new My_Nav_Menu_Walker()
    )
);

I have not tested the code. In some cases there can be a conflict and you can either use clone for the menu argument, or use another way to limit the scope of an custom argument.