Design files

In essence, EDAsolver design files are a hardware description language. They can be thought of as VHDL for board designs. Design files describe what types of components connect to each other. Unlike a schematic, design files usually abstract out the individual pin connections, but this can be easily overridden if a more custom solution is needed. Design files then can be run through EDAsolver to get a list of all possible designs along with BOMs, netlists, and power estimates.

Design files can specify that a very specific ADC chip will be connected to a specific processor, but design files are more powerful than that. If a component does not have to be a particular model, a designer can direct EDAsolver to check all ADC chips or just those matching a set of criteria, such as sampling speed and resolution. This selection process is similar to filtering results on Digikey or Mouser, except that each possible component choice is taken into account within the context of the rest of the system.

Here is an example of a design file for a competition robot:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
{
    "power_supplies": [{
        "voltage": 7.2,
        "current": 15
    }],
    "components": [
        {
            "class": "arduino",
            "preserve_pins": ["pwm", "pc_serial", "i2c"],
            "components": [
                {
                    "type": "solenoid",
                    "control": "digital",
                    "quantity": 5,
                    "power_percentage": 0.175
                },
                {
                    "type": "servo",
                    "quantity": 2,
                    "power_percentage": 0.25
                },
                {
                    "class": "line_sensor_array",
                    "quantity": 2
                },
                {
                    "class": ["digital_line_sensor", "analog_line_sensor"],
                    "quantity": 4
                },
                {
                    "class": "simple_led",
                    "quantity": 8,
                    "power_percentage": 0.2
                },
                {
                    "class": "rgb_led"
                },
                {
                    "class": "photoresistor",
                    "quantity": 5
                },
                {
                    "model": "rover_5_driver",
                    "power_percentage": 0.5,
                    "override": [{
                        "key": "['requires']['pins'][type=digital,direction=out]",
                        "value": {
                            "type": "digital",
                            "range": "dir1-dir4,ch1_enc1,ch1_enc2,ch2_enc1,ch2_enc2",
                            "direction": "out",
                            "voltage": "vcc"
                        }
                    }]
                }
            ]
        }
    ]
}

While some of this may not make sense yet, it is actually very intuitive once the basics are learned.

Design file types

There are two main types of design files: tree and graph. Tree filesare much simpler to write by hand but graph files are more powerful and allow for designs that tree files do not. The above example is a tree design file.

It is important to understand that connections in design files are directed by nature. The network of components is a directed graph. Please familiarize yourself with the terms of predecessors and successors from these notes if you are not familiar with them already. Direction is important because a component needs to have all its requirements satisfied by its predecessors. Everithing that it provides is available for use by its successors.

Tree design files

Many design structures can be represented as a tree. These types of files represent a few components that connect to another set of subcomponents, and so on. Usually the root of the tree is some sort of processor, as is the case in the above example. To give an idea of the hierarchy, a processor might be the root, a motor controller might be a subcomponent, and a few motors might be subcomponents of the motor controller. Here is the basic structure of a tree design file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
    "power_supplies": [ "..." ],
    "components": [
        {
            "first_component_params": "go_here"
        },
        {
            "second_component_params": "go_here"
        },
        "..."
    ]
}

Of course, this example does not specify a real tree, only a list of components that do not connect. In the parameters section of any component, a components key can be added to begin a new branch of the tree. The parent component will then connect to all children components. Here is a structure example of this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
    "power_supplies": [ "..." ],
    "components": [
        {
            "first_component_params": "go_here",
            "components": [
                {
                    "first_subcomponent_params": "go_here"
                },
                {
                    "second_subcomponent_params": "go_here",
                    "components": [
                        {
                            "first_subsubcomponent_params": "go_here"
                        },
                        "..."
                    ]
                },
                "..."
            ]
        },
        {
            "second_component_params": "go_here"
        },
        "..."
    ]
}

Note than an important parameter is the quantity parameter, which allows multiple instances of a component to be added in a single parameter section, which is a great relief if you are dealing with a large number of components.

Connections are made from each component to its direct subcomponents. For example, first_component would be connected to first_subcomponent and second_subcomponent but not first_subsubcomponent. If first_component had a quantity of greater than one, than each instance of first_component would be connected to the subcomponents.

While EDAsolver does not require this, it certainly allows for large shortcuts to be taken. As a simple example, a designer could simply tell EDAsolver that 100 relays are connected to an Arduino. Obviously this will not work literally, but EDAsolver can insert digital multiplexers in between the Arduino and the relays such that the design works correctly. By doing this, EDAsolver will try multiple combinations of multiplexing setups, but as always, this can be hardcoded to any degree of detail if the situation requires it.

Graph design files

Any design with certain kinds of cycles will not be possible with tree design files, so graph design files provide the needed flexibility.

Graph design files are similar to tree design files except that connections are specified manually rather than using nested JSON.

Here is an example graph design file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
    "type": "graph",
    "power_supplies": [{
        "voltage": 7.2,
        "current": 15
    }],
    "components": [
        {
            "id": 1,
            "model": "arduino_mega_2560"
        },
        {
            "id": 2,
            "model": "rover_5_driver"
        },
        {
            "id": 3,
            "model": "lv_ez3_analog"
        },
        {
            "id": 4,
            "model": "lv_ez3_analog"
        },
        {
            "id": 5,
            "model": "hitec_hs_422"
        },
        {
            "id": 6,
            "model": "tb6612fng"
        },
        {
            "id": 7,
            "model": "lsm303dlhc"
        }
    ],
    "links": [
        {"tail": 1, "head": 5},
        {"tail": 1, "head": 2},
        {"tail": 1, "head": 3},
        {"tail": 1, "head": 4},
        {"tail": 1, "head": 7},
        {"tail": 1, "head": 6}
    ]
}

Graph design files have a type key with a value of graph to designate that the file is of the graph format.

The objects in the components key are the same as the objects in the tree design files, except that they are just one level deep and that they have a unique id key for each one.

The other major difference from the tree design files is that the graph files have a links key that specifies the connections between the different components, directed of course.

The power_supplies key

This key should contain an array of the power supplies available to all components in the design. For battery-powered devices, this will describe the operating voltage of the battery and the maximum current that should be drawn from it. For wall-wart powered devices, this will be the voltage and the maximum current that it can supply.

If the maximum current is high enough that it can be neglected, simply specify a large current.

Note

The entire power interface of EDAsolver needs some work. Ideally, it should support AC power supplies and have a much more cohesive interface.

If you have read the documentation on components, this key is pretty much identical to the power_supplies key for components.

Parameter syntax

A parameter can be added by simply adding a key and a value to the component object in the design file. Parameters can filter on component type, class, model, or any other attribute of components.

TO BE CONTINUED

Special parameters

While most parameters serve to filter possible components, there are a few parameters that have special functions:

quantity

This parameter allows multiple instances of a component to be added in a single parameter section, which is a great relief if you are dealing with a large number of components.

preserve_pins

This parameter is a list of pin types that EDAsolver should try not to consume. For example, in the robot design file at the top of this chapter, the following was set:

1
2
3
{
    "preserve_pins": ["pwm", "pc_serial", "i2c"]
}

The reason that PWM and I2C pins are included in this list is because the designers knew that they may need to add support for extra servos and sensors after the board had been built. During schematic capture, the extra PWM and I2C pins could be routed to an extension header that can be used later on.

power_percentage

This parameter is essentially a duty cycle. It allows a designer to specify that a device will only be at full power for a certain percentage of time. Alternatively, it can mean that a device will be operating at a certain power percentage 100% of the time. In the example at the top, the servos had the following parameter:

1
2
3
{
    "power_percentage": 0.25
}

This means that the each solenoid will be at full power roughly 25% of the time.

If this parameter is left out, EDAsolver will assume a 100% duty cycle.

Note

Currently this parameter has little to do with the actual solved designs. It affects the power calculations, but these are currently under development and not very accurate. This parameter can be safely left out at this point, and is mostly for possible future use.

override

The override parameter is a very powerful parameter that allows traits of components to be overridden. In the example at the top, the motor driver was specified as

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
    "model": "rover_5_driver",
    "power_percentage": 0.5,
    "override": [{
        "key": "['requires']['pins'][type=digital,direction=out]",
        "value": {
            "type": "digital",
            "range": "dir1-dir4,ch1_enc1,ch1_enc2,ch2_enc1,ch2_enc2",
            "direction": "out",
            "voltage": "vcc"
        }
    }]
}

The rover_5_driver component is defined as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "name": "Rover 5 Motor Driver Board",
    "links": ["https://www.sparkfun.com/products/11593"],
    "cost": 24.95,
    "popularity": 3,

    "requires": {
        "power_supplies": [ "..." ],
        "pins": [
            "...",
            {
                "type": "digital",
                "range": "ch1_enc1,ch1_enc2,ch2_enc1,ch2_enc2,ch3_enc1,ch3_enc2,ch4_enc1,ch4_enc2",
                "direction": "out",
                "voltage": "vcc"
            },
            "..."
        ]
    },
    "provides": "..."
}

After the override is applied, that particular instance of the component will only use the first two encoders for the rest of the design process:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "name": "Rover 5 Motor Driver Board",
    "links": ["https://www.sparkfun.com/products/11593"],
    "cost": 24.95,
    "popularity": 3,

    "requires": {
        "power_supplies": [ "..." ],
        "pins": [
            "...",
            {
                "type": "digital",
                "range": "ch1_enc1,ch1_enc2,ch2_enc1,ch2_enc2",
                "direction": "out",
                "voltage": "vcc"
            },
            "..."
        ]
    },
    "provides": "..."
}

The override key is a chain of key values and optionally key-value filter pairs, by using the "=" notation to select from lists. Chaining keys will guarantee selection of a single object, but key-value filters have the possibility of selecting multiple objects because they traverse lists.

To specify multiple key-value pairs to filter a list (all must be satisfied), separate these pairs by a comma, as seen above.

Specifying a value of {} will effectively delete the key from the component definition.

Custom components

This section assumes that you have read through some of the documentation on Components.

Custom components can be added to a design in the following format:

1
2
3
4
5
{
    "custom_components": [ "..." ],
    "power_supplies": [ "..." ],
    "components": [ "..." ]
}

Where the custom_components key is a list of user-defined Components to be included in the solving process. There is no difference between a component being included in this section or the official components repository.

Please note that you will additionally have to include the type, class, and model keys for custom components as these are normally defined in the background through directory structure.

Here is an example that defines a custom stepper motor control module:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
    "custom_components": [{
        "name": "Etch-A-Sketch module",
        "links": [],
        "cost": 24.95,
        "popularity": 1,

        "type": "misc",
        "class": "robot_team",
        "model": "etch_a_sketch",

        "requires": {
            "power_supplies": [
                {
                    "voltage_min": 5,
                    "voltage_max": 12,
                    "current": 0.5
                }
            ],
            "pins": [
                {
                    "type": "digital",
                    "range": "clk1,dir1,clk2,dir2",
                    "direction": "in",
                    "voltage": 5
                }
            ]
        },
        "provides": {
            "pins": [{
                "type": "stepper",
                "groups": [
                    {
                    "a1": "a1_l",
                    "a2": "a2_l",
                    "b1": "b1_l",
                    "b2": "b2_l"
                    },
                    {
                    "a1": "a1_r",
                    "a2": "a2_r",
                    "b1": "b1_r",
                    "b2": "b2_r"
                    }
                ],
                "direction": "out"
            }]
        }
    }],

    "power_supplies": [{
        "voltage": 7.2,
        "current": 15
    }],
    "components": [
        {
            "model": "arduino_uno_r3",
            "components": [
                {
                    "model": "etch_a_sketch",
                    "power_percentage": 0.5,
                    "components": [
                        {
                            "class": "stepper",
                            "quantity": 2
                        }
                    ]
                }
            ]
        }
    ]
}