├── .gitignore
├── render.png
├── easy-esc.jpg
├── hardware
├── .gitignore
├── stm32f103.pdf
├── assembly
│ ├── stm32f103-bottom-pos.csv
│ ├── stm32f103-BOM.csv
│ └── stm32f103-top-pos.csv
├── stm32f103.kicad_prl
└── stm32f103.kicad_pro
├── firmware
├── .gitignore
├── test
│ └── README
├── include
│ ├── stm32f1xxMT6071_NCP81155.h
│ └── README
├── lib
│ ├── README
│ └── MT6701
│ │ ├── MT6701_I2C.h
│ │ └── MT6701_I2C.cpp
└── src
│ ├── clock.c
│ └── main.cpp
├── mechanical
├── motormount_b.stl
├── motormount_back.stl
├── motormount_test.stl
├── motormount_front.FCStd
├── stm32f103-motormount_top.stl
├── motormount-back-stlinkcutout.stl
├── stm32f103-motormount-back.FCStd
├── stm32f103-motormount-back.FCStd1
├── stm32f103-motormount-back-rotor.stl
└── aliexpress-motor.step
├── controller
├── src
│ ├── preload.ts
│ ├── index.html
│ ├── app.tsx
│ ├── renderer.ts
│ ├── Home.tsx
│ └── index.ts
├── README.md
├── webpack.plugins.ts
├── .eslintrc.json
├── webpack.renderer.config.ts
├── tsconfig.json
├── webpack.main.config.ts
├── webpack.rules.ts
├── forge.config.ts
├── .gitignore
└── package.json
├── .vscode
└── extensions.json
├── README.md
└── platformio.ini
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .pio/
3 | c_cpp_properties.json
4 | launch.json
5 |
6 |
--------------------------------------------------------------------------------
/render.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/render.png
--------------------------------------------------------------------------------
/easy-esc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/easy-esc.jpg
--------------------------------------------------------------------------------
/hardware/.gitignore:
--------------------------------------------------------------------------------
1 | assembly/
2 | gerbers/
3 | *backups/
4 | fp-info-cache
5 | *.kicad_pcb-bak
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/firmware/.gitignore:
--------------------------------------------------------------------------------
1 | .pio
2 | .vscode/.browse.c_cpp.db*
3 | .vscode/c_cpp_properties.json
4 | .vscode/launch.json
5 | .vscode/ipch
6 |
--------------------------------------------------------------------------------
/hardware/stm32f103.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/hardware/stm32f103.pdf
--------------------------------------------------------------------------------
/mechanical/motormount_b.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/motormount_b.stl
--------------------------------------------------------------------------------
/mechanical/motormount_back.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/motormount_back.stl
--------------------------------------------------------------------------------
/mechanical/motormount_test.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/motormount_test.stl
--------------------------------------------------------------------------------
/mechanical/motormount_front.FCStd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/motormount_front.FCStd
--------------------------------------------------------------------------------
/mechanical/stm32f103-motormount_top.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/stm32f103-motormount_top.stl
--------------------------------------------------------------------------------
/mechanical/motormount-back-stlinkcutout.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/motormount-back-stlinkcutout.stl
--------------------------------------------------------------------------------
/mechanical/stm32f103-motormount-back.FCStd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/stm32f103-motormount-back.FCStd
--------------------------------------------------------------------------------
/mechanical/stm32f103-motormount-back.FCStd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/stm32f103-motormount-back.FCStd1
--------------------------------------------------------------------------------
/mechanical/stm32f103-motormount-back-rotor.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VIPQualityPost/easy-esc-stm32f103-mt6701-ncp81155/HEAD/mechanical/stm32f103-motormount-back-rotor.stl
--------------------------------------------------------------------------------
/controller/src/preload.ts:
--------------------------------------------------------------------------------
1 | // See the Electron documentation for details on how to use preload scripts:
2 | // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
3 |
--------------------------------------------------------------------------------
/controller/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | easy-esc-stm32f103-mt6701-ncp81155
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/controller/src/app.tsx:
--------------------------------------------------------------------------------
1 | import { createRoot } from "react-dom/client";
2 | import { Home } from "./Home";
3 |
4 | function render() {
5 | const root = createRoot(document.getElementById("app"));
6 | root.render();
7 | }
8 |
9 | render();
10 |
--------------------------------------------------------------------------------
/hardware/assembly/stm32f103-bottom-pos.csv:
--------------------------------------------------------------------------------
1 | Ref,Val,Package,PosX,PosY,Rot,Side
2 | "J201","MOTOR","PinHeader_1x03_P1.27mm_Vertical",145.935600,-82.307000,90.000000,bottom
3 | "J202","FPC","FPC-SMD_3P-P1.00_HDGC_1.0K-LS-3PWB-BOTTOMCONTACT",153.530200,-81.697400,180.000000,bottom
4 |
--------------------------------------------------------------------------------
/controller/README.md:
--------------------------------------------------------------------------------
1 | # Controller UI
2 |
3 | ## Run locally
4 |
5 | ```sh
6 | # Install the Yarn dependency manager using NPM
7 | npm install --global yarn
8 |
9 | # Navigate to the controller folder
10 | cd ./controller
11 |
12 | # Install dependencies
13 | yarn
14 |
15 | # Run development server
16 | yarn start
17 | ```
18 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "platformio.platformio-ide"
6 | ],
7 | "unwantedRecommendations": [
8 | "ms-vscode.cpptools-extension-pack"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/controller/webpack.plugins.ts:
--------------------------------------------------------------------------------
1 | import type IForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
2 |
3 | // eslint-disable-next-line @typescript-eslint/no-var-requires
4 | const ForkTsCheckerWebpackPlugin: typeof IForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
5 |
6 | export const plugins = [
7 | new ForkTsCheckerWebpackPlugin({
8 | logger: 'webpack-infrastructure',
9 | }),
10 | ];
11 |
--------------------------------------------------------------------------------
/controller/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "node": true
6 | },
7 | "extends": [
8 | "eslint:recommended",
9 | "plugin:@typescript-eslint/eslint-recommended",
10 | "plugin:@typescript-eslint/recommended",
11 | "plugin:import/recommended",
12 | "plugin:import/electron",
13 | "plugin:import/typescript"
14 | ],
15 | "parser": "@typescript-eslint/parser"
16 | }
17 |
--------------------------------------------------------------------------------
/controller/webpack.renderer.config.ts:
--------------------------------------------------------------------------------
1 | import type { Configuration } from 'webpack';
2 |
3 | import { rules } from './webpack.rules';
4 | import { plugins } from './webpack.plugins';
5 |
6 | rules.push({
7 | test: /\.css$/,
8 | use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
9 | });
10 |
11 | export const rendererConfig: Configuration = {
12 | module: {
13 | rules,
14 | },
15 | plugins,
16 | resolve: {
17 | extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/controller/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES6",
4 | "allowJs": true,
5 | "module": "commonjs",
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "noImplicitAny": true,
9 | "sourceMap": true,
10 | "baseUrl": ".",
11 | "outDir": "dist",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "paths": {
15 | "*": ["node_modules/*"]
16 | },
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src/**/*"]
20 | }
21 |
--------------------------------------------------------------------------------
/controller/webpack.main.config.ts:
--------------------------------------------------------------------------------
1 | import type { Configuration } from 'webpack';
2 |
3 | import { rules } from './webpack.rules';
4 |
5 | export const mainConfig: Configuration = {
6 | /**
7 | * This is the main entry point for your application, it's the first file
8 | * that runs in the main process.
9 | */
10 | entry: './src/index.ts',
11 | // Put your normal webpack config below here
12 | module: {
13 | rules,
14 | },
15 | resolve: {
16 | extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/firmware/test/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for PlatformIO Test Runner and project tests.
3 |
4 | Unit Testing is a software testing method by which individual units of
5 | source code, sets of one or more MCU program modules together with associated
6 | control data, usage procedures, and operating procedures, are tested to
7 | determine whether they are fit for use. Unit testing finds problems early
8 | in the development cycle.
9 |
10 | More information about PlatformIO Unit Testing:
11 | - https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # easy-esc-stm32f103-mt6701-ncp81155
2 |
3 | Small, closed loop simpleFOC driver board, that can be assembled for <$10 with mostly basic components at LCSC. has support for current sensing and mounting WS2812 RGBLED for indicating, as well as USB C for serial communication and programming. SWD + UART via STLINK 14 pin connector.
4 |
5 | The targe for this project was to create an all-in-one simpleFOC board with high resolution magnetic encoder, current sensing, simpleFOC BLDC driver board which can be assembled with top-side only components, 2 layers, mostly basic components from LCSC library, and which can be powered entirely from USB 2.0 specification (500mA) for mostly use with haptic texture type applications. Additionally, it has a compact size of 38x38mm.
6 |
7 | 
8 |
--------------------------------------------------------------------------------
/controller/webpack.rules.ts:
--------------------------------------------------------------------------------
1 | import type { ModuleOptions } from 'webpack';
2 |
3 | export const rules: Required['rules'] = [
4 | // Add support for native node modules
5 | {
6 | // We're specifying native_modules in the test because the asset relocator loader generates a
7 | // "fake" .node file which is really a cjs file.
8 | test: /native_modules[/\\].+\.node$/,
9 | use: 'node-loader',
10 | },
11 | {
12 | test: /[/\\]node_modules[/\\].+\.(m?js|node)$/,
13 | parser: { amd: false },
14 | use: {
15 | loader: '@vercel/webpack-asset-relocator-loader',
16 | options: {
17 | outputAssetBase: 'native_modules',
18 | },
19 | },
20 | },
21 | {
22 | test: /\.tsx?$/,
23 | exclude: /(node_modules|\.webpack)/,
24 | use: {
25 | loader: 'ts-loader',
26 | options: {
27 | transpileOnly: true,
28 | },
29 | },
30 | },
31 | ];
32 |
--------------------------------------------------------------------------------
/controller/src/renderer.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file will automatically be loaded by webpack and run in the "renderer" context.
3 | * To learn more about the differences between the "main" and the "renderer" context in
4 | * Electron, visit:
5 | *
6 | * https://electronjs.org/docs/latest/tutorial/process-model
7 | *
8 | * By default, Node.js integration in this file is disabled. When enabling Node.js integration
9 | * in a renderer process, please be aware of potential security implications. You can read
10 | * more about security risks here:
11 | *
12 | * https://electronjs.org/docs/tutorial/security
13 | *
14 | * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration`
15 | * flag:
16 | *
17 | * ```
18 | * // Create the browser window.
19 | * mainWindow = new BrowserWindow({
20 | * width: 800,
21 | * height: 600,
22 | * webPreferences: {
23 | * nodeIntegration: true
24 | * }
25 | * });
26 | * ```
27 | */
28 |
29 | import "./app";
30 |
--------------------------------------------------------------------------------
/firmware/include/stm32f1xxMT6071_NCP81155.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // encoder interface
4 | #define ENC_A PC13
5 | #define ENC_B PC14
6 | #define ENC_Z PC15
7 |
8 | #define ENC_PUSH PB1
9 | #define ENC_MODE PB0
10 | #define ENC_I2C_EN PB2
11 |
12 | // mosfet driver pins
13 | // allow for dir switch to match encoder on build flag MOTOR_CW
14 |
15 | #define PWM_U PA9
16 | #define EN_U PB14
17 | #define PWM_V PA8
18 | #define EN_V PB13
19 | #define PWM_W PA10
20 | #define EN_W PB15
21 |
22 | // current sensing pins
23 | #define CUR_U PA1
24 | #define CUR_V PA0
25 | #define CUR_W PA4
26 |
27 | // ws2812E
28 | #define RGB_LED PA15
29 |
30 | // SPI1
31 | #define SPI1_MOSI PA7
32 | #define SPI1_MISO PA6
33 | #define SPI1_SCLK PA5
34 |
35 | // UART1
36 | #define UART1_TX PB6
37 | #define UART1_RX PB7
38 |
39 | // CANBUS1
40 | #define CAN_TX PB9
41 | #define CAN_RX PB8
42 |
43 | // I2C2
44 | #define I2C2_SDA PB11
45 | #define I2C2_SCL PB10
46 |
47 | // UART2
48 | #define UART2_TX PA2
49 | #define UART2_RX PA3
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/hardware/assembly/stm32f103-BOM.csv:
--------------------------------------------------------------------------------
1 | Comment,Designator,Footprint,LCSC
2 | 5K,"R102,R101",0402_R,
3 | 22R,"R106,R107",0402_R,
4 | 1uF,"C206,C201,C210,C107,C106",0402_C,
5 | WS2812,D101,SMD_5050,
6 | 0R,"R209,R207,R223,R203,R201,R217,R213,R202,R113,R220,R218,R208,R112,R214,R110,R109",0402_R,
7 | NCP81155,"U205,U201,U206",DFN-8_3x3mm,C173765
8 | 0.1uF,"C101,C212,C218,C211,C109,C111,C110,C108",0402_C,
9 | 1N5819WS,"D201,D202,D203",D_SOD-323,C191023
10 | 22R,"R215,R216,R221",1206_R,
11 | 47pF,"C105,C104",0402_C,
12 | 10k,"R219,R108,R103,R222",0402_R,
13 | RESET,SW101,TS-1187A-B-A-B,C318884
14 | LT199,"U204,U203,U202",SOT-363_SC-70-6,C2888104
15 | 10uF,"C214,C215",0402_C,
16 | AO3400A,"Q201,Q205,Q203,Q202,Q101,Q206,Q204",SOT-23,C20917
17 | 470nF,"C222,C205,C223",0402_C,
18 | 5.1k,"R105,R104",0402_R,
19 | 20pF,"C102,C103",0402_C,
20 | 12MHz,Y101,Crystal_SMD_3225,
21 | HIROSE TYPE C ,J101,HRO_TYPE-C-31-M-12,C165948
22 | 100uF,"C221,C220,C213",1206_C,
23 | STM32F103,U103,LQFP-48_7x7mm,C8734
24 | XC6206,U102,SOT-23,C5446
25 | B5819W SL,D204,D_SOD-123,C8598
26 | MT6701,U101,QFN-16-1EP_3x3mm,C2913974
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; PlatformIO Project Configuration File
2 | ;
3 | ; Build options: build flags, source filter
4 | ; Upload options: custom upload port, speed and extra flags
5 | ; Library options: dependencies, extra library storages
6 | ; Advanced options: extra scripting
7 | ;
8 | ; Please visit documentation for the other options and examples
9 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | [platformio]
12 | default_envs = easyesc_stm32f1xx_MT6701_NCP81155
13 | src_dir = firmware/src
14 | lib_dir = firmware/lib
15 | include_dir = firmware/include
16 | test_dir = firmware/test
17 |
18 | [env:easyesc_stm32f1xx_MT6701_NCP81155]
19 | platform = ststm32@~15.6.0
20 | board = genericSTM32F103C8
21 | framework = arduino
22 | monitor_speed = 115200
23 | upload_protocol = stlink
24 | debug_tool = stlink
25 | lib_deps =
26 | askuric/Simple FOC@^2.3.0
27 |
28 | lib_archive = false
29 | build_flags =
30 | -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
31 | -D USBCON
32 | -D HAS_MONITOR
33 | -D MT6701_I2C
34 | -D HAL_QSPI_MODULE_DISABLED
35 | -D HAL_RTC_MODULE_DISABLED
36 | -D HAL_DAC_MODULE_DISABLED
37 | -D HAL_ETH_MODULE_DISABLED
38 | -D HAL_SD_MODULE_DISABLED
39 | -flto
40 |
--------------------------------------------------------------------------------
/firmware/lib/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project specific (private) libraries.
3 | PlatformIO will compile them to static libraries and link into executable file.
4 |
5 | The source code of each library should be placed in a an own separate directory
6 | ("lib/your_library_name/[here are source files]").
7 |
8 | For example, see a structure of the following two libraries `Foo` and `Bar`:
9 |
10 | |--lib
11 | | |
12 | | |--Bar
13 | | | |--docs
14 | | | |--examples
15 | | | |--src
16 | | | |- Bar.c
17 | | | |- Bar.h
18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
19 | | |
20 | | |--Foo
21 | | | |- Foo.c
22 | | | |- Foo.h
23 | | |
24 | | |- README --> THIS FILE
25 | |
26 | |- platformio.ini
27 | |--src
28 | |- main.c
29 |
30 | and a contents of `src/main.c`:
31 | ```
32 | #include
33 | #include
34 |
35 | int main (void)
36 | {
37 | ...
38 | }
39 |
40 | ```
41 |
42 | PlatformIO Library Dependency Finder will find automatically dependent
43 | libraries scanning project source files.
44 |
45 | More information about PlatformIO Library Dependency Finder
46 | - https://docs.platformio.org/page/librarymanager/ldf.html
47 |
--------------------------------------------------------------------------------
/controller/forge.config.ts:
--------------------------------------------------------------------------------
1 | import type { ForgeConfig } from '@electron-forge/shared-types';
2 | import { MakerSquirrel } from '@electron-forge/maker-squirrel';
3 | import { MakerZIP } from '@electron-forge/maker-zip';
4 | import { MakerDeb } from '@electron-forge/maker-deb';
5 | import { MakerRpm } from '@electron-forge/maker-rpm';
6 | import { AutoUnpackNativesPlugin } from '@electron-forge/plugin-auto-unpack-natives';
7 | import { WebpackPlugin } from '@electron-forge/plugin-webpack';
8 |
9 | import { mainConfig } from './webpack.main.config';
10 | import { rendererConfig } from './webpack.renderer.config';
11 |
12 | const config: ForgeConfig = {
13 | packagerConfig: {
14 | asar: true,
15 | },
16 | rebuildConfig: {},
17 | makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})],
18 | plugins: [
19 | new AutoUnpackNativesPlugin({}),
20 | new WebpackPlugin({
21 | mainConfig,
22 | renderer: {
23 | config: rendererConfig,
24 | entryPoints: [
25 | {
26 | html: './src/index.html',
27 | js: './src/renderer.ts',
28 | name: 'main_window',
29 | preload: {
30 | js: './src/preload.ts',
31 | },
32 | },
33 | ],
34 | },
35 | }),
36 | ],
37 | };
38 |
39 | export default config;
40 |
--------------------------------------------------------------------------------
/firmware/include/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project header files.
3 |
4 | A header file is a file containing C declarations and macro definitions
5 | to be shared between several project source files. You request the use of a
6 | header file in your project source file (C, C++, etc) located in `src` folder
7 | by including it, with the C preprocessing directive `#include'.
8 |
9 | ```src/main.c
10 |
11 | #include "header.h"
12 |
13 | int main (void)
14 | {
15 | ...
16 | }
17 | ```
18 |
19 | Including a header file produces the same results as copying the header file
20 | into each source file that needs it. Such copying would be time-consuming
21 | and error-prone. With a header file, the related declarations appear
22 | in only one place. If they need to be changed, they can be changed in one
23 | place, and programs that include the header file will automatically use the
24 | new version when next recompiled. The header file eliminates the labor of
25 | finding and changing all the copies as well as the risk that a failure to
26 | find one copy will result in inconsistencies within a program.
27 |
28 | In C, the usual convention is to give header files names that end with `.h'.
29 | It is most portable to use only letters, digits, dashes, and underscores in
30 | header file names, and at most one dot.
31 |
32 | Read more about using header files in official GCC documentation:
33 |
34 | * Include Syntax
35 | * Include Operation
36 | * Once-Only Headers
37 | * Computed Includes
38 |
39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
40 |
--------------------------------------------------------------------------------
/hardware/stm32f103.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 0,
4 | "active_layer_preset": "All Layers",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 0.6200000047683716,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": false,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 39,
65 | 40
66 | ],
67 | "visible_layers": "fffffff_ffffffff",
68 | "zone_display_mode": 0
69 | },
70 | "meta": {
71 | "filename": "stm32f103.kicad_prl",
72 | "version": 3
73 | },
74 | "project": {
75 | "files": []
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/controller/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 | .DS_Store
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # TypeScript cache
43 | *.tsbuildinfo
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 | .env.test
63 |
64 | # parcel-bundler cache (https://parceljs.org/)
65 | .cache
66 |
67 | # next.js build output
68 | .next
69 |
70 | # nuxt.js build output
71 | .nuxt
72 |
73 | # vuepress build output
74 | .vuepress/dist
75 |
76 | # Serverless directories
77 | .serverless/
78 |
79 | # FuseBox cache
80 | .fusebox/
81 |
82 | # DynamoDB Local files
83 | .dynamodb/
84 |
85 | # Webpack
86 | .webpack/
87 |
88 | # Vite
89 | .vite/
90 |
91 | # Electron-Forge
92 | out/
--------------------------------------------------------------------------------
/controller/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "controller",
3 | "productName": "controller",
4 | "version": "1.0.0",
5 | "description": "My Electron application description",
6 | "main": ".webpack/main",
7 | "scripts": {
8 | "start": "electron-forge start",
9 | "package": "electron-forge package",
10 | "make": "electron-forge make",
11 | "publish": "electron-forge publish",
12 | "lint": "eslint --ext .ts,.tsx ."
13 | },
14 | "keywords": [],
15 | "license": "MIT",
16 | "devDependencies": {
17 | "@electron-forge/cli": "^6.2.1",
18 | "@electron-forge/maker-deb": "^6.2.1",
19 | "@electron-forge/maker-rpm": "^6.2.1",
20 | "@electron-forge/maker-squirrel": "^6.2.1",
21 | "@electron-forge/maker-zip": "^6.2.1",
22 | "@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
23 | "@electron-forge/plugin-webpack": "^6.2.1",
24 | "@types/dom-serial": "^1.0.3",
25 | "@types/react": "^18.2.14",
26 | "@types/react-dom": "^18.2.6",
27 | "@typescript-eslint/eslint-plugin": "^5.0.0",
28 | "@typescript-eslint/parser": "^5.0.0",
29 | "@vercel/webpack-asset-relocator-loader": "1.7.3",
30 | "css-loader": "^6.0.0",
31 | "electron": "25.2.0",
32 | "eslint": "^8.0.1",
33 | "eslint-plugin-import": "^2.25.0",
34 | "fork-ts-checker-webpack-plugin": "^7.2.13",
35 | "node-loader": "^2.0.0",
36 | "style-loader": "^3.0.0",
37 | "ts-loader": "^9.2.2",
38 | "ts-node": "^10.0.0",
39 | "typescript": "~4.5.4"
40 | },
41 | "dependencies": {
42 | "electron-squirrel-startup": "^1.0.0",
43 | "react": "^18.2.0",
44 | "react-dom": "^18.2.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/firmware/src/clock.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /**
4 | * @brief System Clock Configuration
5 | * @retval None
6 | */
7 | void SystemClock_Config(void)
8 | {
9 | RCC_OscInitTypeDef RCC_OscInitStruct = {};
10 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
11 | RCC_PeriphCLKInitTypeDef PeriphClkInit = {};
12 |
13 | /** Initializes the RCC Oscillators according to the specified parameters
14 | * in the RCC_OscInitTypeDef structure.
15 | */
16 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
17 | RCC_OscInitStruct.HSEState = RCC_HSE_ON;
18 | RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
19 | RCC_OscInitStruct.HSIState = RCC_HSI_ON;
20 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
21 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
22 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
23 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
24 | {
25 | Error_Handler();
26 | }
27 |
28 | /** Initializes the CPU, AHB and APB buses clocks
29 | */
30 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
31 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
32 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
33 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
34 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
35 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
36 |
37 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
38 | {
39 | Error_Handler();
40 | }
41 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB;
42 | PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
43 | PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL;
44 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
45 | {
46 | Error_Handler();
47 | }
48 | }
--------------------------------------------------------------------------------
/firmware/lib/MT6701/MT6701_I2C.h:
--------------------------------------------------------------------------------
1 | #ifndef MT6701_I2C_H
2 | #define MT6701_I2C_H
3 |
4 | #include "Arduino.h"
5 | #include "SimpleFOC.h"
6 | // #include "SimpleFOCDrivers.h"
7 | #include
8 |
9 | struct MT6701_I2CConfig_s {
10 | int chip_address;
11 | int bit_resolution;
12 | int angle_register;
13 | int data_start_bit;
14 | };
15 | // some predefined structures
16 |
17 | #if defined(TARGET_RP2040)
18 | #define SDA I2C_SDA
19 | #define SCL I2C_SCL
20 | #endif
21 |
22 |
23 | class MT6701_Serial_I2C: public Sensor{
24 | public:
25 | /**
26 | * MagneticSensorI2C class constructor
27 | * @param chip_address I2C chip address
28 | * @param bits number of bits of the sensor resolution
29 | * @param angle_register_msb angle read register msb
30 | * @param _bits_used_msb number of used bits in msb
31 | */
32 | MT6701_Serial_I2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _msb_bits_used);
33 |
34 | /**
35 | * MagneticSensorI2C class constructor
36 | * @param config I2C config
37 | */
38 | MT6701_Serial_I2C(MT6701_I2CConfig_s config);
39 |
40 | /** sensor initialise pins */
41 | void init(TwoWire* _wire = &Wire);
42 |
43 | // implementation of abstract functions of the Sensor class
44 | /** get current angle (rad) */
45 | float getSensorAngle() override;
46 |
47 | /** experimental function to check and fix SDA locked LOW issues */
48 | int checkBus(byte sda_pin , byte scl_pin );
49 |
50 | int getRawCount();
51 |
52 | int readRegister(uint8_t reg_addr, byte data_len_bits, byte start_bit);
53 |
54 | private:
55 | float cpr; //!< Maximum range of the magnetic sensor
56 | uint16_t lsb_used; //!< Number of bits used in LSB register
57 | uint8_t lsb_mask;
58 | uint8_t msb_mask;
59 |
60 | // I2C variables
61 | uint8_t angle_register_msb; //!< I2C angle register to read
62 | uint8_t chip_address; //!< I2C chip select pins
63 |
64 | // I2C functions
65 | /** Read one I2C register value */
66 | int read(uint8_t angle_register_msb);
67 |
68 | /**
69 | * Function getting current angle register value
70 | * it uses angle_register variable
71 | */
72 | // int getRawCount();
73 |
74 | /* the two wire instance for this sensor */
75 | TwoWire* wire;
76 |
77 |
78 | };
79 |
80 |
81 | #endif
--------------------------------------------------------------------------------
/controller/src/Home.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useState } from "react";
2 |
3 | const baudRate = 115200;
4 |
5 | export const Home = () => {
6 | const [ports, setPorts] = useState([]);
7 | const [connectedPort, setConnectedPort] = useState(null);
8 | const [serialOutput, setSerialOutput] = useState("");
9 | const reader = useRef>();
10 | const readableStreamClosed = useRef>();
11 |
12 | const changePort = async (port?: SerialPort) => {
13 | if (connectedPort) {
14 | try {
15 | reader.current.cancel();
16 | await readableStreamClosed.current.catch(() => {
17 | /* Ignore the error */
18 | });
19 | await connectedPort.close();
20 | setConnectedPort(null);
21 | console.log("closed port");
22 | } catch (e) {
23 | console.log(e);
24 | }
25 | }
26 |
27 | if (port) {
28 | await port.open({
29 | baudRate,
30 | });
31 | console.log("opened port");
32 | setConnectedPort(port);
33 |
34 | const decoder = new TextDecoderStream();
35 | readableStreamClosed.current = port.readable.pipeTo(decoder.writable);
36 | reader.current = decoder.readable.getReader();
37 | while (true) {
38 | const { value, done } = await reader.current.read();
39 | if (value) {
40 | setSerialOutput((serialOutput) => serialOutput + value);
41 | }
42 | if (done) {
43 | console.log("[readLoop] DONE", done);
44 | reader.current.releaseLock();
45 | break;
46 | }
47 | }
48 | }
49 | };
50 |
51 | useEffect(() => {
52 | navigator.serial.getPorts().then((ports) => setPorts(ports));
53 | }, []);
54 |
55 | return (
56 | <>
57 | Controller
58 | Ports:{" "}
59 |
73 |
74 |
Output
75 | {serialOutput.split("\n").map((line) => (
76 |
77 | {line}
78 |
79 | ))}
80 |
81 | >
82 | );
83 | };
84 |
--------------------------------------------------------------------------------
/firmware/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "MT6701_I2C.h"
4 | #include "stm32f1xxMT6071_NCP81155.h"
5 |
6 | // Motor specific parameters
7 | #define POLEPAIRS 4
8 | #define RPHASE 0.7
9 | #define MOTOR_KV 1000
10 |
11 | #ifdef MT6701_I2C
12 | MT6701_I2CConfig_s mt6701_config = {
13 | .chip_address = 0b0000110,
14 | .bit_resolution = 14,
15 | .angle_register = 0x03,
16 | .data_start_bit = 8};
17 | MT6701_Serial_I2C mt6701 = MT6701_Serial_I2C(mt6701_config);
18 | TwoWire enc_i2c(I2C2_SDA, I2C2_SCL);
19 | #endif
20 |
21 | // Prepare SimpleFOC constructors.
22 | BLDCDriver3PWM driver = BLDCDriver3PWM(PWM_U, PWM_V, PWM_W, EN_U, EN_V, EN_W);
23 | BLDCMotor motor = BLDCMotor(POLEPAIRS,RPHASE,MOTOR_KV);
24 | Commander commander = Commander(Serial);
25 |
26 | void doMotor(char *cmd){
27 | commander.motor(&motor,cmd);
28 | }
29 |
30 | void mt6701_i2c_enable(bool state)
31 | {
32 | digitalWrite(ENC_MODE, state);
33 | digitalWrite(ENC_I2C_EN, state);
34 | }
35 |
36 | void setup(){
37 | Serial.begin();
38 | commander.add('M',doMotor,"motor");
39 |
40 | #ifdef SIMPLEFOC_STM32_DEBUG
41 | SimpleFOCDebug::enable(&Serial);
42 | #endif
43 |
44 | pinMode(ENC_MODE, OUTPUT);
45 | pinMode(ENC_I2C_EN, OUTPUT);
46 |
47 | #ifdef MT6701_I2C
48 | // set the MT6701 to Serial mode
49 | mt6701_i2c_enable(1);
50 | delay(1000); // let chip settle
51 | mt6701.init(&enc_i2c);
52 | motor.linkSensor(&mt6701);
53 | #endif
54 |
55 | // setup the driver
56 | driver.pwm_frequency = 25000;
57 | driver.voltage_power_supply = 5;
58 | driver.voltage_limit = 3;
59 | driver.init();
60 | motor.linkDriver(&driver);
61 |
62 | // closed loop parameters
63 | motor.PID_velocity.P = 0.3;
64 | motor.PID_velocity.I = 20;
65 | motor.PID_velocity.D = 0.003;
66 | motor.PID_velocity.output_ramp = 50;
67 | motor.LPF_velocity.Tf = 0.2;
68 | motor.LPF_angle.Tf = 0; // try to avoid
69 |
70 | // motor parameters
71 | motor.voltage_sensor_align = 2;
72 | motor.current_limit = 0.8;
73 | motor.velocity_limit = 50;
74 | motor.controller = MotionControlType::angle;
75 |
76 | motor.init();
77 | motor.initFOC();
78 |
79 | // Monitor initialization
80 | #ifdef HAS_MONITOR
81 | motor.useMonitoring(Serial);
82 | motor.monitor_start_char = 'M';
83 | motor.monitor_end_char = 'M';
84 | motor.monitor_downsample = 200;
85 | commander.verbose = VerboseMode::machine_readable;
86 | #endif
87 |
88 | motor.target = 2;
89 | }
90 |
91 | void loop()
92 | {
93 | motor.loopFOC();
94 | motor.move();
95 |
96 | commander.run();
97 |
98 | #ifdef HAS_MONITOR
99 | motor.monitor();
100 | #endif
101 | }
--------------------------------------------------------------------------------
/hardware/assembly/stm32f103-top-pos.csv:
--------------------------------------------------------------------------------
1 | Designator,Mid X,Mid Y,Layer,Rotation
2 | C101,150.6092,-96.8866,T ,90
3 | C102,167.0684,-85.5836,T ,0
4 | C103,163.2076,-87.0568,T ,90
5 | C104,162.4456,-106.3374,T ,0
6 | C105,160.5406,-106.3374,T ,180
7 | C106,154.1906,-108.3166,T ,180
8 | C107,154.1906,-107.326,T ,180
9 | C108,169.9894,-91.4002,T ,90
10 | C109,160.693,-87.0568,T ,90
11 | C110,160.3374,-101.202,T ,-90
12 | C111,167.3758,-101.1792,T ,180
13 | C201,150.6092,-98.8424,T ,-90
14 | C202,144.3496,-91.5428,T ,180
15 | C203,144.4004,-98.93275,T ,180
16 | C204,144.4746,-106.2592,T ,180
17 | C205,138.4086,-90.984,T ,180
18 | C206,153.706,-102.5308,T ,180
19 | C207,144.3496,-87.682,T ,180
20 | C208,144.3869,-94.99575,T ,180
21 | C209,144.4492,-102.373,T ,180
22 | C210,152.381,-105.5058,T ,-90
23 | C211,152.8374,-93.60275,T ,180
24 | C212,149.9392,-93.59005,T ,180
25 | C213,144.2592,-111.4662,T ,-90
26 | C214,138.4934,-101.357,T ,180
27 | C215,138.4426,-93.9656,T ,180
28 | C216,152.8374,-89.25935,T ,180
29 | C217,149.9418,-89.22125,T ,180
30 | C218,155.7226,-93.6113,T ,180
31 | C219,155.7226,-89.2679,T ,180
32 | C220,146.4944,-87.1058,T ,-90
33 | C221,142.9638,-85.9646,T ,0
34 | C222,138.5468,-105.675,T ,180
35 | C223,138.4706,-98.2582,T ,180
36 | D101,148.3742,-112.951,T ,90
37 | D201,138.4426,-88.818,T ,90
38 | D202,138.468,-96.1078,T ,90
39 | D203,138.5442,-103.4992,T ,90
40 | D204,141.8716,-111.4146,T ,-90
41 | J101,160.8454,-114.1332,T ,0
42 | J102,169.9132,-108.0118,T ,180
43 | J104,137.2234,-108.0238,T ,90
44 | Q101,157.8505,-100.3918,T ,0
45 | Q201,141.386,-92.3744,T ,180
46 | Q202,141.4444,-99.73575,T ,180
47 | Q203,141.4932,-107.0876,T ,180
48 | Q204,141.386,-88.9012,T ,180
49 | Q205,141.4309,-96.23015,T ,180
50 | Q206,141.4932,-103.5922,T ,180
51 | R101,157.9244,-94.626,T ,180
52 | R102,157.9244,-93.61,T ,180
53 | R103,161.7344,-87.0568,T ,90
54 | R104,159.55,-107.834,T ,90
55 | R105,162.6742,-107.834,T ,90
56 | R106,160.5914,-107.832,T ,90
57 | R107,161.6328,-107.836,T ,90
58 | R108,168.567,-86.0408,T ,90
59 | R109,170.8022,-96.8104,T ,180
60 | R110,170.8022,-95.7944,T ,0
61 | R112,157.9244,-98.1058,T ,0
62 | R113,157.9244,-97.0898,T ,0
63 | R201,144.3496,-93.6002,T ,180
64 | R202,144.4004,-100.96575,T ,180
65 | R203,144.4746,-108.3176,T ,180
66 | R204,144.3496,-92.5588,T ,180
67 | R205,144.4004,-99.94875,T ,180
68 | R206,144.4746,-107.2752,T ,180
69 | R207,144.3496,-89.7394,T ,180
70 | R208,144.3869,-97.02775,T ,180
71 | R209,144.4746,-104.4558,T ,180
72 | R210,144.3496,-88.698,T ,180
73 | R211,144.3869,-96.01175,T ,180
74 | R212,144.4746,-103.389,T ,180
75 | R213,153.2692,-87.76075,T ,-90
76 | R214,150.3736,-87.72065,T ,-90
77 | R215,152.7682,-84.3644,T ,-45
78 | R216,149.4408,-84.3136,T ,-45
79 | R217,152.2532,-87.75875,T ,-90
80 | R218,149.3322,-87.72465,T ,-90
81 | R219,149.9692,-94.63145,T ,180
82 | R220,156.1544,-87.7693,T ,-90
83 | R221,156.0448,-84.3644,T ,-45
84 | R222,148.4686,-94.04725,T ,90
85 | R223,155.113,-87.7713,T ,-90
86 | SW101,162.3186,-83.4246,T ,180
87 | U101,153.581,-98.1058,T ,90
88 | U102,157.0862,-107.0618,T ,180
89 | U103,164.2713,-95.3826,T ,-90
90 | U201,148.247,-98.309,T ,90
91 | U202,152.3468,-91.42725,T ,90
92 | U203,149.4512,-91.41455,T ,90
93 | U204,155.232,-91.4358,T ,90
94 | U205,149.7202,-103.1096,T ,180
95 | U206,149.7202,-107.2244,T ,180
96 | Y101,165.8746,-87.8442,T ,180
--------------------------------------------------------------------------------
/controller/src/index.ts:
--------------------------------------------------------------------------------
1 | import { app, BrowserWindow } from "electron";
2 | // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack
3 | // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
4 | // whether you're running in development or production).
5 | declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
6 | declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
7 |
8 | // Handle creating/removing shortcuts on Windows when installing/uninstalling.
9 | if (require("electron-squirrel-startup")) {
10 | app.quit();
11 | }
12 |
13 | const setupSerialDevice = (mainWindow: BrowserWindow) => {
14 | mainWindow.webContents.session.on(
15 | "select-serial-port",
16 | (event, portList, webContents, callback) => {
17 | // Add listeners to handle ports being added or removed before the callback for `select-serial-port`
18 | // is called.
19 | mainWindow.webContents.session.on("serial-port-added", (event, port) => {
20 | console.log("serial-port-added FIRED WITH", port);
21 | // Optionally update portList to add the new port
22 | });
23 |
24 | mainWindow.webContents.session.on(
25 | "serial-port-removed",
26 | (event, port) => {
27 | console.log("serial-port-removed FIRED WITH", port);
28 | // Optionally update portList to remove the port
29 | }
30 | );
31 |
32 | event.preventDefault();
33 | }
34 | );
35 |
36 | mainWindow.webContents.session.setPermissionCheckHandler(
37 | (webContents, permission, requestingOrigin, details) => {
38 | return true;
39 | // if (permission === "serial" && details.securityOrigin === "file:///") {
40 | // return true;
41 | // }
42 |
43 | // return false;
44 | }
45 | );
46 |
47 | mainWindow.webContents.session.setDevicePermissionHandler((details) => {
48 | return true;
49 |
50 | // if (details.deviceType === "serial" && details.origin === "file://") {
51 | // return true;
52 | // }
53 |
54 | // return false;
55 | });
56 | };
57 |
58 | const createWindow = (): void => {
59 | // Create the browser window.
60 | const mainWindow = new BrowserWindow({
61 | height: 600,
62 | width: 800,
63 | webPreferences: {
64 | preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
65 | },
66 | });
67 |
68 | setupSerialDevice(mainWindow);
69 |
70 | // and load the index.html of the app.
71 | mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
72 |
73 | // Open the DevTools.
74 | mainWindow.webContents.openDevTools();
75 | };
76 |
77 | // This method will be called when Electron has finished
78 | // initialization and is ready to create browser windows.
79 | // Some APIs can only be used after this event occurs.
80 | app.on("ready", createWindow);
81 |
82 | // Quit when all windows are closed, except on macOS. There, it's common
83 | // for applications and their menu bar to stay active until the user quits
84 | // explicitly with Cmd + Q.
85 | app.on("window-all-closed", () => {
86 | if (process.platform !== "darwin") {
87 | app.quit();
88 | }
89 | });
90 |
91 | app.on("activate", () => {
92 | // On OS X it's common to re-create a window in the app when the
93 | // dock icon is clicked and there are no other windows open.
94 | if (BrowserWindow.getAllWindows().length === 0) {
95 | createWindow();
96 | }
97 | });
98 |
99 | // In this file you can include the rest of your app's specific main process
100 | // code. You can also put them in separate files and import them here.
101 |
--------------------------------------------------------------------------------
/firmware/lib/MT6701/MT6701_I2C.cpp:
--------------------------------------------------------------------------------
1 | #include "MT6701_I2C.h"
2 |
3 | // MagneticSensorI2C(uint8_t _chip_address, float _cpr, uint8_t _angle_register_msb)
4 | // @param _chip_address I2C chip address
5 | // @param _bit_resolution bit resolution of the sensor
6 | // @param _angle_register_msb angle read register
7 | // @param _bits_used_msb number of used bits in msb
8 | MT6701_Serial_I2C::MT6701_Serial_I2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _bits_used_msb){
9 | // chip I2C address
10 | chip_address = _chip_address;
11 | // angle read register of the magnetic sensor
12 | angle_register_msb = _angle_register_msb;
13 | // register maximum value (counts per revolution)
14 | cpr = pow(2, _bit_resolution);
15 |
16 | // depending on the sensor architecture there are different combinations of
17 | // LSB and MSB register used bits
18 | // AS5600 uses 0..7 LSB and 8..11 MSB
19 | // AS5048 uses 0..5 LSB and 6..13 MSB
20 | // used bits in LSB
21 | lsb_used = _bit_resolution - _bits_used_msb;
22 | // extraction masks
23 | lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
24 | msb_mask = (uint8_t)( (2 << _bits_used_msb) - 1 );
25 | wire = &Wire;
26 | }
27 |
28 | MT6701_Serial_I2C::MT6701_Serial_I2C(MT6701_I2CConfig_s config){
29 | chip_address = config.chip_address;
30 |
31 | // angle read register of the magnetic sensor
32 | angle_register_msb = config.angle_register;
33 | // register maximum value (counts per revolution)
34 | cpr = pow(2, config.bit_resolution);
35 |
36 | int bits_used_msb = config.data_start_bit - 7;
37 | lsb_used = config.bit_resolution - bits_used_msb;
38 | // extraction masks
39 | lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
40 | msb_mask = (uint8_t)( (2 << bits_used_msb) - 1 );
41 | wire = &Wire;
42 | }
43 |
44 | void MT6701_Serial_I2C::init(TwoWire* _wire){
45 |
46 | wire = _wire;
47 |
48 | // I2C communication begin
49 | wire->begin();
50 |
51 | this->Sensor::init(); // call base class init
52 | }
53 |
54 | // Shaft angle calculation
55 | // angle is in radians [rad]
56 | float MT6701_Serial_I2C::getSensorAngle(){
57 | // (number of full rotations)*2PI + current sensor angle
58 | return ( getRawCount() / (float)cpr) * _2PI ;
59 | }
60 |
61 |
62 |
63 | // function reading the raw counter of the magnetic sensor
64 | int MT6701_Serial_I2C::getRawCount(){
65 | return (int)MT6701_Serial_I2C::read(angle_register_msb);
66 | }
67 |
68 | // I2C functions
69 | /*
70 | * Read a register from the sensor
71 | * Takes the address of the register as a uint8_t
72 | * Returns the value of the register
73 | */
74 | int MT6701_Serial_I2C::read(uint8_t angle_reg_msb) {
75 | // read the angle register first MSB then LSB
76 | byte angle_raw[2];
77 | uint16_t readValue = 0;
78 | wire->beginTransmission(chip_address);
79 | wire->write(angle_reg_msb);
80 | wire->endTransmission(false);
81 | wire->requestFrom(chip_address, (uint8_t)2);
82 |
83 | for(byte i=0; i<2; i++){
84 | // Read the two sequential registers
85 | angle_raw[i] = wire->read();
86 | }
87 |
88 | // Stack the upper and lower bits
89 | readValue = angle_raw[0] << 8;
90 | readValue = (readValue | angle_raw[1]) >> 2;
91 | return readValue;
92 | }
93 |
94 | /**
95 | * Read a specific register and return the value at the address.
96 | */
97 | int MT6701_Serial_I2C::readRegister(uint8_t reg_addr, byte data_len_bits, byte start_bit) {
98 | byte reg_data;
99 | uint16_t readValue = 0;
100 | wire->beginTransmission(chip_address);
101 | wire->write(reg_addr);
102 | wire->endTransmission(false);
103 |
104 | wire->requestFrom(chip_address, (uint8_t)1);
105 |
106 | reg_data = wire->read();
107 |
108 | readValue = reg_data;
109 | return readValue;
110 | }
111 | /*
112 | * Checks whether other devices have locked the bus. Can clear SDA locks.
113 | * This should be called before sensor.init() on devices that suffer i2c slaves locking sda
114 | * e.g some stm32 boards with AS5600 chips
115 | * Takes the sda_pin and scl_pin
116 | * Returns 0 for OK, 1 for other master and 2 for unfixable sda locked LOW
117 | */
118 | int MT6701_Serial_I2C::checkBus(byte sda_pin, byte scl_pin) {
119 |
120 | pinMode(scl_pin, INPUT_PULLUP);
121 | pinMode(sda_pin, INPUT_PULLUP);
122 | delay(250);
123 |
124 | if (digitalRead(scl_pin) == LOW) {
125 | // Someone else has claimed master!");
126 | return 1;
127 | }
128 |
129 | if(digitalRead(sda_pin) == LOW) {
130 | // slave is communicating and awaiting clocks, we are blocked
131 | pinMode(scl_pin, OUTPUT);
132 | for (byte i = 0; i < 16; i++) {
133 | // toggle clock for 2 bytes of data
134 | digitalWrite(scl_pin, LOW);
135 | delayMicroseconds(20);
136 | digitalWrite(scl_pin, HIGH);
137 | delayMicroseconds(20);
138 | }
139 | pinMode(sda_pin, INPUT);
140 | delayMicroseconds(20);
141 | if (digitalRead(sda_pin) == LOW) {
142 | // SDA still blocked
143 | return 2;
144 | }
145 | _delay(1000);
146 | }
147 | // SDA is clear (HIGH)
148 | pinMode(sda_pin, INPUT);
149 | pinMode(scl_pin, INPUT);
150 |
151 | return 0;
152 | }
--------------------------------------------------------------------------------
/hardware/stm32f103.kicad_pro:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "3dviewports": [],
4 | "design_settings": {
5 | "defaults": {
6 | "board_outline_line_width": 0.09999999999999999,
7 | "copper_line_width": 0.19999999999999998,
8 | "copper_text_italic": false,
9 | "copper_text_size_h": 1.5,
10 | "copper_text_size_v": 1.5,
11 | "copper_text_thickness": 0.3,
12 | "copper_text_upright": false,
13 | "courtyard_line_width": 0.049999999999999996,
14 | "dimension_precision": 4,
15 | "dimension_units": 3,
16 | "dimensions": {
17 | "arrow_length": 1270000,
18 | "extension_offset": 500000,
19 | "keep_text_aligned": true,
20 | "suppress_zeroes": false,
21 | "text_position": 0,
22 | "units_format": 1
23 | },
24 | "fab_line_width": 0.09999999999999999,
25 | "fab_text_italic": false,
26 | "fab_text_size_h": 1.0,
27 | "fab_text_size_v": 1.0,
28 | "fab_text_thickness": 0.15,
29 | "fab_text_upright": false,
30 | "other_line_width": 0.15,
31 | "other_text_italic": false,
32 | "other_text_size_h": 1.0,
33 | "other_text_size_v": 1.0,
34 | "other_text_thickness": 0.15,
35 | "other_text_upright": false,
36 | "pads": {
37 | "drill": 0.762,
38 | "height": 1.524,
39 | "width": 1.524
40 | },
41 | "silk_line_width": 0.15,
42 | "silk_text_italic": false,
43 | "silk_text_size_h": 1.0,
44 | "silk_text_size_v": 1.0,
45 | "silk_text_thickness": 0.15,
46 | "silk_text_upright": false,
47 | "zones": {
48 | "min_clearance": 0.5
49 | }
50 | },
51 | "diff_pair_dimensions": [
52 | {
53 | "gap": 0.0,
54 | "via_gap": 0.0,
55 | "width": 0.0
56 | }
57 | ],
58 | "drc_exclusions": [],
59 | "meta": {
60 | "version": 2
61 | },
62 | "rule_severities": {
63 | "annular_width": "error",
64 | "clearance": "error",
65 | "connection_width": "warning",
66 | "copper_edge_clearance": "error",
67 | "copper_sliver": "warning",
68 | "courtyards_overlap": "ignore",
69 | "diff_pair_gap_out_of_range": "error",
70 | "diff_pair_uncoupled_length_too_long": "error",
71 | "drill_out_of_range": "error",
72 | "duplicate_footprints": "warning",
73 | "extra_footprint": "warning",
74 | "footprint": "error",
75 | "footprint_type_mismatch": "ignore",
76 | "hole_clearance": "error",
77 | "hole_near_hole": "error",
78 | "invalid_outline": "error",
79 | "isolated_copper": "warning",
80 | "item_on_disabled_layer": "error",
81 | "items_not_allowed": "error",
82 | "length_out_of_range": "error",
83 | "lib_footprint_issues": "warning",
84 | "lib_footprint_mismatch": "warning",
85 | "malformed_courtyard": "error",
86 | "microvia_drill_out_of_range": "error",
87 | "missing_courtyard": "ignore",
88 | "missing_footprint": "warning",
89 | "net_conflict": "warning",
90 | "npth_inside_courtyard": "ignore",
91 | "padstack": "warning",
92 | "pth_inside_courtyard": "ignore",
93 | "shorting_items": "error",
94 | "silk_edge_clearance": "ignore",
95 | "silk_over_copper": "warning",
96 | "silk_overlap": "ignore",
97 | "skew_out_of_range": "error",
98 | "solder_mask_bridge": "error",
99 | "starved_thermal": "error",
100 | "text_height": "warning",
101 | "text_thickness": "warning",
102 | "through_hole_pad_without_hole": "error",
103 | "too_many_vias": "error",
104 | "track_dangling": "warning",
105 | "track_width": "error",
106 | "tracks_crossing": "error",
107 | "unconnected_items": "error",
108 | "unresolved_variable": "error",
109 | "via_dangling": "warning",
110 | "zones_intersect": "error"
111 | },
112 | "rules": {
113 | "max_error": 0.005,
114 | "min_clearance": 0.0,
115 | "min_connection": 0.0,
116 | "min_copper_edge_clearance": 0.0,
117 | "min_hole_clearance": 0.25,
118 | "min_hole_to_hole": 0.25,
119 | "min_microvia_diameter": 0.19999999999999998,
120 | "min_microvia_drill": 0.09999999999999999,
121 | "min_resolved_spokes": 1,
122 | "min_silk_clearance": 0.0,
123 | "min_text_height": 0.7999999999999999,
124 | "min_text_thickness": 0.08,
125 | "min_through_hole_diameter": 0.3,
126 | "min_track_width": 0.0,
127 | "min_via_annular_width": 0.09999999999999999,
128 | "min_via_diameter": 0.5,
129 | "solder_mask_clearance": 0.0,
130 | "solder_mask_min_width": 0.0,
131 | "solder_mask_to_copper_clearance": 0.0,
132 | "use_height_for_length_calcs": true
133 | },
134 | "teardrop_options": [
135 | {
136 | "td_allow_use_two_tracks": true,
137 | "td_curve_segcount": 5,
138 | "td_on_pad_in_zone": false,
139 | "td_onpadsmd": true,
140 | "td_onroundshapesonly": false,
141 | "td_ontrackend": false,
142 | "td_onviapad": true
143 | }
144 | ],
145 | "teardrop_parameters": [
146 | {
147 | "td_curve_segcount": 0,
148 | "td_height_ratio": 1.0,
149 | "td_length_ratio": 0.5,
150 | "td_maxheight": 2.0,
151 | "td_maxlen": 1.0,
152 | "td_target_name": "td_round_shape",
153 | "td_width_to_size_filter_ratio": 0.9
154 | },
155 | {
156 | "td_curve_segcount": 0,
157 | "td_height_ratio": 1.0,
158 | "td_length_ratio": 0.5,
159 | "td_maxheight": 2.0,
160 | "td_maxlen": 1.0,
161 | "td_target_name": "td_rect_shape",
162 | "td_width_to_size_filter_ratio": 0.9
163 | },
164 | {
165 | "td_curve_segcount": 0,
166 | "td_height_ratio": 1.0,
167 | "td_length_ratio": 0.5,
168 | "td_maxheight": 2.0,
169 | "td_maxlen": 1.0,
170 | "td_target_name": "td_track_end",
171 | "td_width_to_size_filter_ratio": 0.9
172 | }
173 | ],
174 | "track_widths": [
175 | 0.0,
176 | 0.3,
177 | 0.5,
178 | 0.75,
179 | 1.0
180 | ],
181 | "via_dimensions": [
182 | {
183 | "diameter": 0.0,
184 | "drill": 0.0
185 | }
186 | ],
187 | "zones_allow_external_fillets": true
188 | },
189 | "layer_presets": [],
190 | "viewports": []
191 | },
192 | "boards": [],
193 | "cvpcb": {
194 | "equivalence_files": []
195 | },
196 | "erc": {
197 | "erc_exclusions": [],
198 | "meta": {
199 | "version": 0
200 | },
201 | "pin_map": [
202 | [
203 | 0,
204 | 0,
205 | 0,
206 | 0,
207 | 0,
208 | 0,
209 | 1,
210 | 0,
211 | 0,
212 | 0,
213 | 0,
214 | 2
215 | ],
216 | [
217 | 0,
218 | 2,
219 | 0,
220 | 1,
221 | 0,
222 | 0,
223 | 1,
224 | 0,
225 | 2,
226 | 2,
227 | 2,
228 | 2
229 | ],
230 | [
231 | 0,
232 | 0,
233 | 0,
234 | 0,
235 | 0,
236 | 0,
237 | 1,
238 | 0,
239 | 1,
240 | 0,
241 | 1,
242 | 2
243 | ],
244 | [
245 | 0,
246 | 1,
247 | 0,
248 | 0,
249 | 0,
250 | 0,
251 | 1,
252 | 1,
253 | 2,
254 | 1,
255 | 1,
256 | 2
257 | ],
258 | [
259 | 0,
260 | 0,
261 | 0,
262 | 0,
263 | 0,
264 | 0,
265 | 1,
266 | 0,
267 | 0,
268 | 0,
269 | 0,
270 | 2
271 | ],
272 | [
273 | 0,
274 | 0,
275 | 0,
276 | 0,
277 | 0,
278 | 0,
279 | 0,
280 | 0,
281 | 0,
282 | 0,
283 | 0,
284 | 2
285 | ],
286 | [
287 | 1,
288 | 1,
289 | 1,
290 | 1,
291 | 1,
292 | 0,
293 | 1,
294 | 1,
295 | 1,
296 | 1,
297 | 1,
298 | 2
299 | ],
300 | [
301 | 0,
302 | 0,
303 | 0,
304 | 1,
305 | 0,
306 | 0,
307 | 1,
308 | 0,
309 | 0,
310 | 0,
311 | 0,
312 | 2
313 | ],
314 | [
315 | 0,
316 | 2,
317 | 1,
318 | 2,
319 | 0,
320 | 0,
321 | 1,
322 | 0,
323 | 2,
324 | 2,
325 | 2,
326 | 2
327 | ],
328 | [
329 | 0,
330 | 2,
331 | 0,
332 | 1,
333 | 0,
334 | 0,
335 | 1,
336 | 0,
337 | 2,
338 | 0,
339 | 0,
340 | 2
341 | ],
342 | [
343 | 0,
344 | 2,
345 | 1,
346 | 1,
347 | 0,
348 | 0,
349 | 1,
350 | 0,
351 | 2,
352 | 0,
353 | 0,
354 | 2
355 | ],
356 | [
357 | 2,
358 | 2,
359 | 2,
360 | 2,
361 | 2,
362 | 2,
363 | 2,
364 | 2,
365 | 2,
366 | 2,
367 | 2,
368 | 2
369 | ]
370 | ],
371 | "rule_severities": {
372 | "bus_definition_conflict": "error",
373 | "bus_entry_needed": "error",
374 | "bus_to_bus_conflict": "error",
375 | "bus_to_net_conflict": "error",
376 | "conflicting_netclasses": "error",
377 | "different_unit_footprint": "error",
378 | "different_unit_net": "error",
379 | "duplicate_reference": "error",
380 | "duplicate_sheet_names": "error",
381 | "endpoint_off_grid": "warning",
382 | "extra_units": "error",
383 | "global_label_dangling": "warning",
384 | "hier_label_mismatch": "error",
385 | "label_dangling": "error",
386 | "lib_symbol_issues": "warning",
387 | "missing_bidi_pin": "warning",
388 | "missing_input_pin": "warning",
389 | "missing_power_pin": "error",
390 | "missing_unit": "warning",
391 | "multiple_net_names": "warning",
392 | "net_not_bus_member": "warning",
393 | "no_connect_connected": "warning",
394 | "no_connect_dangling": "warning",
395 | "pin_not_connected": "error",
396 | "pin_not_driven": "error",
397 | "pin_to_pin": "warning",
398 | "power_pin_not_driven": "error",
399 | "similar_labels": "warning",
400 | "simulation_model_issue": "error",
401 | "unannotated": "error",
402 | "unit_value_mismatch": "error",
403 | "unresolved_variable": "error",
404 | "wire_dangling": "error"
405 | }
406 | },
407 | "libraries": {
408 | "pinned_footprint_libs": [],
409 | "pinned_symbol_libs": []
410 | },
411 | "meta": {
412 | "filename": "stm32f103.kicad_pro",
413 | "version": 1
414 | },
415 | "net_settings": {
416 | "classes": [
417 | {
418 | "bus_width": 12,
419 | "clearance": 0.2,
420 | "diff_pair_gap": 0.25,
421 | "diff_pair_via_gap": 0.25,
422 | "diff_pair_width": 0.2,
423 | "line_style": 0,
424 | "microvia_diameter": 0.3,
425 | "microvia_drill": 0.1,
426 | "name": "Default",
427 | "pcb_color": "rgba(0, 0, 0, 0.000)",
428 | "schematic_color": "rgba(0, 0, 0, 0.000)",
429 | "track_width": 0.25,
430 | "via_diameter": 0.8,
431 | "via_drill": 0.4,
432 | "wire_width": 6
433 | }
434 | ],
435 | "meta": {
436 | "version": 3
437 | },
438 | "net_colors": null,
439 | "netclass_assignments": null,
440 | "netclass_patterns": []
441 | },
442 | "pcbnew": {
443 | "last_paths": {
444 | "gencad": "",
445 | "idf": "",
446 | "netlist": "",
447 | "specctra_dsn": "",
448 | "step": "stm32f103.step",
449 | "vrml": ""
450 | },
451 | "page_layout_descr_file": ""
452 | },
453 | "schematic": {
454 | "annotate_start_num": 0,
455 | "drawing": {
456 | "dashed_lines_dash_length_ratio": 12.0,
457 | "dashed_lines_gap_length_ratio": 3.0,
458 | "default_line_thickness": 6.0,
459 | "default_text_size": 50.0,
460 | "field_names": [],
461 | "intersheets_ref_own_page": false,
462 | "intersheets_ref_prefix": "",
463 | "intersheets_ref_short": false,
464 | "intersheets_ref_show": false,
465 | "intersheets_ref_suffix": "",
466 | "junction_size_choice": 3,
467 | "label_size_ratio": 0.375,
468 | "operating_point_overlay_i_precision": 3,
469 | "operating_point_overlay_i_range": "~A",
470 | "operating_point_overlay_v_precision": 3,
471 | "operating_point_overlay_v_range": "~V",
472 | "pin_symbol_size": 25.0,
473 | "text_offset_ratio": 0.15
474 | },
475 | "legacy_lib_dir": "",
476 | "legacy_lib_list": [],
477 | "meta": {
478 | "version": 1
479 | },
480 | "net_format_name": "",
481 | "page_layout_descr_file": "",
482 | "plot_directory": "",
483 | "spice_current_sheet_as_root": false,
484 | "spice_external_command": "spice \"%I\"",
485 | "spice_model_current_sheet_as_root": true,
486 | "spice_save_all_currents": false,
487 | "spice_save_all_dissipations": false,
488 | "spice_save_all_voltages": false,
489 | "subpart_first_id": 65,
490 | "subpart_id_separator": 0
491 | },
492 | "sheets": [
493 | [
494 | "a2811dd7-4266-496a-832b-7a7f6af8583e",
495 | ""
496 | ],
497 | [
498 | "17dbf9dd-18e6-4e1a-9835-ecd5b9028b5a",
499 | "MOTOR STAGE"
500 | ]
501 | ],
502 | "text_variables": {}
503 | }
504 |
--------------------------------------------------------------------------------
/mechanical/aliexpress-motor.step:
--------------------------------------------------------------------------------
1 | ISO-10303-21;
2 | HEADER;
3 | FILE_DESCRIPTION(('FreeCAD Model'),'2;1');
4 | FILE_NAME('Open CASCADE Shape Model','2023-04-03T18:58:35',('Author'),(
5 | ''),'Open CASCADE STEP processor 7.5','FreeCAD','Unknown');
6 | FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));
7 | ENDSEC;
8 | DATA;
9 | #1 = APPLICATION_PROTOCOL_DEFINITION('international standard',
10 | 'automotive_design',2000,#2);
11 | #2 = APPLICATION_CONTEXT(
12 | 'core data for automotive mechanical design processes');
13 | #3 = SHAPE_DEFINITION_REPRESENTATION(#4,#10);
14 | #4 = PRODUCT_DEFINITION_SHAPE('','',#5);
15 | #5 = PRODUCT_DEFINITION('design','',#6,#9);
16 | #6 = PRODUCT_DEFINITION_FORMATION('','',#7);
17 | #7 = PRODUCT('BLDC','BLDC','',(#8));
18 | #8 = PRODUCT_CONTEXT('',#2,'mechanical');
19 | #9 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design');
20 | #10 = ADVANCED_BREP_SHAPE_REPRESENTATION('',(#11,#15),#512);
21 | #11 = AXIS2_PLACEMENT_3D('',#12,#13,#14);
22 | #12 = CARTESIAN_POINT('',(0.,0.,0.));
23 | #13 = DIRECTION('',(0.,0.,1.));
24 | #14 = DIRECTION('',(1.,0.,-0.));
25 | #15 = MANIFOLD_SOLID_BREP('',#16);
26 | #16 = CLOSED_SHELL('',(#17,#50,#114,#178,#203,#228,#253,#278,#303,#328,
27 | #353,#378,#403,#428,#437,#446,#458,#467,#476,#485,#494,#503));
28 | #17 = ADVANCED_FACE('',(#18),#45,.T.);
29 | #18 = FACE_BOUND('',#19,.F.);
30 | #19 = EDGE_LOOP('',(#20,#30,#37,#38));
31 | #20 = ORIENTED_EDGE('',*,*,#21,.T.);
32 | #21 = EDGE_CURVE('',#22,#24,#26,.T.);
33 | #22 = VERTEX_POINT('',#23);
34 | #23 = CARTESIAN_POINT('',(17.25,0.,0.));
35 | #24 = VERTEX_POINT('',#25);
36 | #25 = CARTESIAN_POINT('',(17.25,0.,15.));
37 | #26 = LINE('',#27,#28);
38 | #27 = CARTESIAN_POINT('',(17.25,0.,0.));
39 | #28 = VECTOR('',#29,1.);
40 | #29 = DIRECTION('',(0.,0.,1.));
41 | #30 = ORIENTED_EDGE('',*,*,#31,.T.);
42 | #31 = EDGE_CURVE('',#24,#24,#32,.T.);
43 | #32 = CIRCLE('',#33,17.25);
44 | #33 = AXIS2_PLACEMENT_3D('',#34,#35,#36);
45 | #34 = CARTESIAN_POINT('',(0.,0.,15.));
46 | #35 = DIRECTION('',(0.,0.,1.));
47 | #36 = DIRECTION('',(1.,0.,0.));
48 | #37 = ORIENTED_EDGE('',*,*,#21,.F.);
49 | #38 = ORIENTED_EDGE('',*,*,#39,.F.);
50 | #39 = EDGE_CURVE('',#22,#22,#40,.T.);
51 | #40 = CIRCLE('',#41,17.25);
52 | #41 = AXIS2_PLACEMENT_3D('',#42,#43,#44);
53 | #42 = CARTESIAN_POINT('',(0.,0.,0.));
54 | #43 = DIRECTION('',(0.,0.,1.));
55 | #44 = DIRECTION('',(1.,0.,0.));
56 | #45 = CYLINDRICAL_SURFACE('',#46,17.25);
57 | #46 = AXIS2_PLACEMENT_3D('',#47,#48,#49);
58 | #47 = CARTESIAN_POINT('',(0.,0.,0.));
59 | #48 = DIRECTION('',(-0.,-0.,-1.));
60 | #49 = DIRECTION('',(1.,0.,0.));
61 | #50 = ADVANCED_FACE('',(#51,#54,#65,#76,#87,#98),#109,.F.);
62 | #51 = FACE_BOUND('',#52,.F.);
63 | #52 = EDGE_LOOP('',(#53));
64 | #53 = ORIENTED_EDGE('',*,*,#39,.T.);
65 | #54 = FACE_BOUND('',#55,.F.);
66 | #55 = EDGE_LOOP('',(#56));
67 | #56 = ORIENTED_EDGE('',*,*,#57,.T.);
68 | #57 = EDGE_CURVE('',#58,#58,#60,.T.);
69 | #58 = VERTEX_POINT('',#59);
70 | #59 = CARTESIAN_POINT('',(-8.25,-5.8533E-11,0.));
71 | #60 = CIRCLE('',#61,1.25);
72 | #61 = AXIS2_PLACEMENT_3D('',#62,#63,#64);
73 | #62 = CARTESIAN_POINT('',(-9.5,-5.853273E-11,0.));
74 | #63 = DIRECTION('',(0.,0.,-1.));
75 | #64 = DIRECTION('',(1.,0.,0.));
76 | #65 = FACE_BOUND('',#66,.F.);
77 | #66 = EDGE_LOOP('',(#67));
78 | #67 = ORIENTED_EDGE('',*,*,#68,.T.);
79 | #68 = EDGE_CURVE('',#69,#69,#71,.T.);
80 | #69 = VERTEX_POINT('',#70);
81 | #70 = CARTESIAN_POINT('',(1.25,-9.5,0.));
82 | #71 = CIRCLE('',#72,1.25);
83 | #72 = AXIS2_PLACEMENT_3D('',#73,#74,#75);
84 | #73 = CARTESIAN_POINT('',(0.,-9.5,0.));
85 | #74 = DIRECTION('',(0.,0.,-1.));
86 | #75 = DIRECTION('',(1.,0.,0.));
87 | #76 = FACE_BOUND('',#77,.F.);
88 | #77 = EDGE_LOOP('',(#78));
89 | #78 = ORIENTED_EDGE('',*,*,#79,.T.);
90 | #79 = EDGE_CURVE('',#80,#80,#82,.T.);
91 | #80 = VERTEX_POINT('',#81);
92 | #81 = CARTESIAN_POINT('',(6.,0.,0.));
93 | #82 = CIRCLE('',#83,6.);
94 | #83 = AXIS2_PLACEMENT_3D('',#84,#85,#86);
95 | #84 = CARTESIAN_POINT('',(0.,0.,0.));
96 | #85 = DIRECTION('',(0.,0.,-1.));
97 | #86 = DIRECTION('',(1.,0.,0.));
98 | #87 = FACE_BOUND('',#88,.F.);
99 | #88 = EDGE_LOOP('',(#89));
100 | #89 = ORIENTED_EDGE('',*,*,#90,.T.);
101 | #90 = EDGE_CURVE('',#91,#91,#93,.T.);
102 | #91 = VERTEX_POINT('',#92);
103 | #92 = CARTESIAN_POINT('',(10.75,5.635E-11,0.));
104 | #93 = CIRCLE('',#94,1.25);
105 | #94 = AXIS2_PLACEMENT_3D('',#95,#96,#97);
106 | #95 = CARTESIAN_POINT('',(9.5,5.634959E-11,0.));
107 | #96 = DIRECTION('',(0.,0.,-1.));
108 | #97 = DIRECTION('',(1.,0.,0.));
109 | #98 = FACE_BOUND('',#99,.F.);
110 | #99 = EDGE_LOOP('',(#100));
111 | #100 = ORIENTED_EDGE('',*,*,#101,.T.);
112 | #101 = EDGE_CURVE('',#102,#102,#104,.T.);
113 | #102 = VERTEX_POINT('',#103);
114 | #103 = CARTESIAN_POINT('',(1.250000000002,9.5,0.));
115 | #104 = CIRCLE('',#105,1.25);
116 | #105 = AXIS2_PLACEMENT_3D('',#106,#107,#108);
117 | #106 = CARTESIAN_POINT('',(2.18492E-12,9.5,0.));
118 | #107 = DIRECTION('',(0.,0.,-1.));
119 | #108 = DIRECTION('',(1.,0.,0.));
120 | #109 = PLANE('',#110);
121 | #110 = AXIS2_PLACEMENT_3D('',#111,#112,#113);
122 | #111 = CARTESIAN_POINT('',(-6.3E-16,5.6E-16,0.));
123 | #112 = DIRECTION('',(0.,0.,1.));
124 | #113 = DIRECTION('',(1.,0.,0.));
125 | #114 = ADVANCED_FACE('',(#115,#118,#129,#140,#151,#162),#173,.T.);
126 | #115 = FACE_BOUND('',#116,.T.);
127 | #116 = EDGE_LOOP('',(#117));
128 | #117 = ORIENTED_EDGE('',*,*,#31,.T.);
129 | #118 = FACE_BOUND('',#119,.T.);
130 | #119 = EDGE_LOOP('',(#120));
131 | #120 = ORIENTED_EDGE('',*,*,#121,.F.);
132 | #121 = EDGE_CURVE('',#122,#122,#124,.T.);
133 | #122 = VERTEX_POINT('',#123);
134 | #123 = CARTESIAN_POINT('',(1.25,-7.5,15.));
135 | #124 = CIRCLE('',#125,1.25);
136 | #125 = AXIS2_PLACEMENT_3D('',#126,#127,#128);
137 | #126 = CARTESIAN_POINT('',(8.9E-16,-7.5,15.));
138 | #127 = DIRECTION('',(0.,0.,1.));
139 | #128 = DIRECTION('',(1.,0.,0.));
140 | #129 = FACE_BOUND('',#130,.T.);
141 | #130 = EDGE_LOOP('',(#131));
142 | #131 = ORIENTED_EDGE('',*,*,#132,.F.);
143 | #132 = EDGE_CURVE('',#133,#133,#135,.T.);
144 | #133 = VERTEX_POINT('',#134);
145 | #134 = CARTESIAN_POINT('',(8.75,-1.E-15,15.));
146 | #135 = CIRCLE('',#136,1.25);
147 | #136 = AXIS2_PLACEMENT_3D('',#137,#138,#139);
148 | #137 = CARTESIAN_POINT('',(7.5,-8.9E-16,15.));
149 | #138 = DIRECTION('',(0.,0.,1.));
150 | #139 = DIRECTION('',(1.,0.,0.));
151 | #140 = FACE_BOUND('',#141,.T.);
152 | #141 = EDGE_LOOP('',(#142));
153 | #142 = ORIENTED_EDGE('',*,*,#143,.F.);
154 | #143 = EDGE_CURVE('',#144,#144,#146,.T.);
155 | #144 = VERTEX_POINT('',#145);
156 | #145 = CARTESIAN_POINT('',(-6.25,1.E-15,15.));
157 | #146 = CIRCLE('',#147,1.25);
158 | #147 = AXIS2_PLACEMENT_3D('',#148,#149,#150);
159 | #148 = CARTESIAN_POINT('',(-7.5,8.9E-16,15.));
160 | #149 = DIRECTION('',(0.,0.,1.));
161 | #150 = DIRECTION('',(1.,0.,0.));
162 | #151 = FACE_BOUND('',#152,.T.);
163 | #152 = EDGE_LOOP('',(#153));
164 | #153 = ORIENTED_EDGE('',*,*,#154,.T.);
165 | #154 = EDGE_CURVE('',#155,#155,#157,.T.);
166 | #155 = VERTEX_POINT('',#156);
167 | #156 = CARTESIAN_POINT('',(2.75,0.,15.));
168 | #157 = CIRCLE('',#158,2.75);
169 | #158 = AXIS2_PLACEMENT_3D('',#159,#160,#161);
170 | #159 = CARTESIAN_POINT('',(0.,0.,15.));
171 | #160 = DIRECTION('',(0.,0.,-1.));
172 | #161 = DIRECTION('',(1.,0.,0.));
173 | #162 = FACE_BOUND('',#163,.T.);
174 | #163 = EDGE_LOOP('',(#164));
175 | #164 = ORIENTED_EDGE('',*,*,#165,.F.);
176 | #165 = EDGE_CURVE('',#166,#166,#168,.T.);
177 | #166 = VERTEX_POINT('',#167);
178 | #167 = CARTESIAN_POINT('',(1.25,7.5,15.));
179 | #168 = CIRCLE('',#169,1.25);
180 | #169 = AXIS2_PLACEMENT_3D('',#170,#171,#172);
181 | #170 = CARTESIAN_POINT('',(0.,7.5,15.));
182 | #171 = DIRECTION('',(0.,0.,1.));
183 | #172 = DIRECTION('',(1.,0.,0.));
184 | #173 = PLANE('',#174);
185 | #174 = AXIS2_PLACEMENT_3D('',#175,#176,#177);
186 | #175 = CARTESIAN_POINT('',(-6.3E-16,5.6E-16,15.));
187 | #176 = DIRECTION('',(0.,0.,1.));
188 | #177 = DIRECTION('',(1.,0.,0.));
189 | #178 = ADVANCED_FACE('',(#179),#198,.F.);
190 | #179 = FACE_BOUND('',#180,.F.);
191 | #180 = EDGE_LOOP('',(#181,#189,#196,#197));
192 | #181 = ORIENTED_EDGE('',*,*,#182,.T.);
193 | #182 = EDGE_CURVE('',#58,#183,#185,.T.);
194 | #183 = VERTEX_POINT('',#184);
195 | #184 = CARTESIAN_POINT('',(-8.25,-5.8533E-11,5.));
196 | #185 = LINE('',#186,#187);
197 | #186 = CARTESIAN_POINT('',(-8.25,-5.853273E-11,0.));
198 | #187 = VECTOR('',#188,1.);
199 | #188 = DIRECTION('',(0.,0.,1.));
200 | #189 = ORIENTED_EDGE('',*,*,#190,.T.);
201 | #190 = EDGE_CURVE('',#183,#183,#191,.T.);
202 | #191 = CIRCLE('',#192,1.25);
203 | #192 = AXIS2_PLACEMENT_3D('',#193,#194,#195);
204 | #193 = CARTESIAN_POINT('',(-9.5,-5.853273E-11,5.));
205 | #194 = DIRECTION('',(0.,0.,-1.));
206 | #195 = DIRECTION('',(1.,0.,0.));
207 | #196 = ORIENTED_EDGE('',*,*,#182,.F.);
208 | #197 = ORIENTED_EDGE('',*,*,#57,.F.);
209 | #198 = CYLINDRICAL_SURFACE('',#199,1.25);
210 | #199 = AXIS2_PLACEMENT_3D('',#200,#201,#202);
211 | #200 = CARTESIAN_POINT('',(-9.5,-5.853273E-11,0.));
212 | #201 = DIRECTION('',(0.,0.,-1.));
213 | #202 = DIRECTION('',(1.,0.,0.));
214 | #203 = ADVANCED_FACE('',(#204),#223,.F.);
215 | #204 = FACE_BOUND('',#205,.F.);
216 | #205 = EDGE_LOOP('',(#206,#214,#221,#222));
217 | #206 = ORIENTED_EDGE('',*,*,#207,.T.);
218 | #207 = EDGE_CURVE('',#69,#208,#210,.T.);
219 | #208 = VERTEX_POINT('',#209);
220 | #209 = CARTESIAN_POINT('',(1.25,-9.5,5.));
221 | #210 = LINE('',#211,#212);
222 | #211 = CARTESIAN_POINT('',(1.25,-9.5,0.));
223 | #212 = VECTOR('',#213,1.);
224 | #213 = DIRECTION('',(0.,0.,1.));
225 | #214 = ORIENTED_EDGE('',*,*,#215,.T.);
226 | #215 = EDGE_CURVE('',#208,#208,#216,.T.);
227 | #216 = CIRCLE('',#217,1.25);
228 | #217 = AXIS2_PLACEMENT_3D('',#218,#219,#220);
229 | #218 = CARTESIAN_POINT('',(0.,-9.5,5.));
230 | #219 = DIRECTION('',(0.,0.,-1.));
231 | #220 = DIRECTION('',(1.,0.,0.));
232 | #221 = ORIENTED_EDGE('',*,*,#207,.F.);
233 | #222 = ORIENTED_EDGE('',*,*,#68,.F.);
234 | #223 = CYLINDRICAL_SURFACE('',#224,1.25);
235 | #224 = AXIS2_PLACEMENT_3D('',#225,#226,#227);
236 | #225 = CARTESIAN_POINT('',(0.,-9.5,0.));
237 | #226 = DIRECTION('',(0.,0.,-1.));
238 | #227 = DIRECTION('',(1.,0.,0.));
239 | #228 = ADVANCED_FACE('',(#229),#248,.T.);
240 | #229 = FACE_BOUND('',#230,.F.);
241 | #230 = EDGE_LOOP('',(#231,#239,#246,#247));
242 | #231 = ORIENTED_EDGE('',*,*,#232,.T.);
243 | #232 = EDGE_CURVE('',#80,#233,#235,.T.);
244 | #233 = VERTEX_POINT('',#234);
245 | #234 = CARTESIAN_POINT('',(6.,0.,-10.));
246 | #235 = LINE('',#236,#237);
247 | #236 = CARTESIAN_POINT('',(6.,0.,0.));
248 | #237 = VECTOR('',#238,1.);
249 | #238 = DIRECTION('',(0.,0.,-1.));
250 | #239 = ORIENTED_EDGE('',*,*,#240,.T.);
251 | #240 = EDGE_CURVE('',#233,#233,#241,.T.);
252 | #241 = CIRCLE('',#242,6.);
253 | #242 = AXIS2_PLACEMENT_3D('',#243,#244,#245);
254 | #243 = CARTESIAN_POINT('',(0.,0.,-10.));
255 | #244 = DIRECTION('',(0.,0.,-1.));
256 | #245 = DIRECTION('',(1.,0.,0.));
257 | #246 = ORIENTED_EDGE('',*,*,#232,.F.);
258 | #247 = ORIENTED_EDGE('',*,*,#79,.F.);
259 | #248 = CYLINDRICAL_SURFACE('',#249,6.);
260 | #249 = AXIS2_PLACEMENT_3D('',#250,#251,#252);
261 | #250 = CARTESIAN_POINT('',(0.,0.,0.));
262 | #251 = DIRECTION('',(0.,0.,1.));
263 | #252 = DIRECTION('',(1.,0.,0.));
264 | #253 = ADVANCED_FACE('',(#254),#273,.F.);
265 | #254 = FACE_BOUND('',#255,.F.);
266 | #255 = EDGE_LOOP('',(#256,#264,#271,#272));
267 | #256 = ORIENTED_EDGE('',*,*,#257,.T.);
268 | #257 = EDGE_CURVE('',#91,#258,#260,.T.);
269 | #258 = VERTEX_POINT('',#259);
270 | #259 = CARTESIAN_POINT('',(10.75,5.635E-11,5.));
271 | #260 = LINE('',#261,#262);
272 | #261 = CARTESIAN_POINT('',(10.75,5.634959E-11,0.));
273 | #262 = VECTOR('',#263,1.);
274 | #263 = DIRECTION('',(0.,0.,1.));
275 | #264 = ORIENTED_EDGE('',*,*,#265,.T.);
276 | #265 = EDGE_CURVE('',#258,#258,#266,.T.);
277 | #266 = CIRCLE('',#267,1.25);
278 | #267 = AXIS2_PLACEMENT_3D('',#268,#269,#270);
279 | #268 = CARTESIAN_POINT('',(9.5,5.634959E-11,5.));
280 | #269 = DIRECTION('',(0.,0.,-1.));
281 | #270 = DIRECTION('',(1.,0.,0.));
282 | #271 = ORIENTED_EDGE('',*,*,#257,.F.);
283 | #272 = ORIENTED_EDGE('',*,*,#90,.F.);
284 | #273 = CYLINDRICAL_SURFACE('',#274,1.25);
285 | #274 = AXIS2_PLACEMENT_3D('',#275,#276,#277);
286 | #275 = CARTESIAN_POINT('',(9.5,5.634959E-11,0.));
287 | #276 = DIRECTION('',(0.,0.,-1.));
288 | #277 = DIRECTION('',(1.,0.,0.));
289 | #278 = ADVANCED_FACE('',(#279),#298,.F.);
290 | #279 = FACE_BOUND('',#280,.F.);
291 | #280 = EDGE_LOOP('',(#281,#289,#296,#297));
292 | #281 = ORIENTED_EDGE('',*,*,#282,.T.);
293 | #282 = EDGE_CURVE('',#102,#283,#285,.T.);
294 | #283 = VERTEX_POINT('',#284);
295 | #284 = CARTESIAN_POINT('',(1.250000000002,9.5,5.));
296 | #285 = LINE('',#286,#287);
297 | #286 = CARTESIAN_POINT('',(1.250000000002,9.5,0.));
298 | #287 = VECTOR('',#288,1.);
299 | #288 = DIRECTION('',(0.,0.,1.));
300 | #289 = ORIENTED_EDGE('',*,*,#290,.T.);
301 | #290 = EDGE_CURVE('',#283,#283,#291,.T.);
302 | #291 = CIRCLE('',#292,1.25);
303 | #292 = AXIS2_PLACEMENT_3D('',#293,#294,#295);
304 | #293 = CARTESIAN_POINT('',(2.18492E-12,9.5,5.));
305 | #294 = DIRECTION('',(0.,0.,-1.));
306 | #295 = DIRECTION('',(1.,0.,0.));
307 | #296 = ORIENTED_EDGE('',*,*,#282,.F.);
308 | #297 = ORIENTED_EDGE('',*,*,#101,.F.);
309 | #298 = CYLINDRICAL_SURFACE('',#299,1.25);
310 | #299 = AXIS2_PLACEMENT_3D('',#300,#301,#302);
311 | #300 = CARTESIAN_POINT('',(2.18492E-12,9.5,0.));
312 | #301 = DIRECTION('',(0.,0.,-1.));
313 | #302 = DIRECTION('',(1.,0.,0.));
314 | #303 = ADVANCED_FACE('',(#304),#323,.F.);
315 | #304 = FACE_BOUND('',#305,.F.);
316 | #305 = EDGE_LOOP('',(#306,#314,#321,#322));
317 | #306 = ORIENTED_EDGE('',*,*,#307,.T.);
318 | #307 = EDGE_CURVE('',#122,#308,#310,.T.);
319 | #308 = VERTEX_POINT('',#309);
320 | #309 = CARTESIAN_POINT('',(1.25,-7.5,10.));
321 | #310 = LINE('',#311,#312);
322 | #311 = CARTESIAN_POINT('',(1.25,-7.5,15.));
323 | #312 = VECTOR('',#313,1.);
324 | #313 = DIRECTION('',(-0.,-0.,-1.));
325 | #314 = ORIENTED_EDGE('',*,*,#315,.T.);
326 | #315 = EDGE_CURVE('',#308,#308,#316,.T.);
327 | #316 = CIRCLE('',#317,1.25);
328 | #317 = AXIS2_PLACEMENT_3D('',#318,#319,#320);
329 | #318 = CARTESIAN_POINT('',(8.9E-16,-7.5,10.));
330 | #319 = DIRECTION('',(0.,0.,1.));
331 | #320 = DIRECTION('',(1.,0.,0.));
332 | #321 = ORIENTED_EDGE('',*,*,#307,.F.);
333 | #322 = ORIENTED_EDGE('',*,*,#121,.F.);
334 | #323 = CYLINDRICAL_SURFACE('',#324,1.25);
335 | #324 = AXIS2_PLACEMENT_3D('',#325,#326,#327);
336 | #325 = CARTESIAN_POINT('',(8.9E-16,-7.5,15.));
337 | #326 = DIRECTION('',(0.,0.,1.));
338 | #327 = DIRECTION('',(1.,0.,-0.));
339 | #328 = ADVANCED_FACE('',(#329),#348,.F.);
340 | #329 = FACE_BOUND('',#330,.F.);
341 | #330 = EDGE_LOOP('',(#331,#339,#346,#347));
342 | #331 = ORIENTED_EDGE('',*,*,#332,.T.);
343 | #332 = EDGE_CURVE('',#133,#333,#335,.T.);
344 | #333 = VERTEX_POINT('',#334);
345 | #334 = CARTESIAN_POINT('',(8.75,-1.E-15,10.));
346 | #335 = LINE('',#336,#337);
347 | #336 = CARTESIAN_POINT('',(8.75,-8.9E-16,15.));
348 | #337 = VECTOR('',#338,1.);
349 | #338 = DIRECTION('',(-0.,-0.,-1.));
350 | #339 = ORIENTED_EDGE('',*,*,#340,.T.);
351 | #340 = EDGE_CURVE('',#333,#333,#341,.T.);
352 | #341 = CIRCLE('',#342,1.25);
353 | #342 = AXIS2_PLACEMENT_3D('',#343,#344,#345);
354 | #343 = CARTESIAN_POINT('',(7.5,-8.9E-16,10.));
355 | #344 = DIRECTION('',(0.,0.,1.));
356 | #345 = DIRECTION('',(1.,0.,0.));
357 | #346 = ORIENTED_EDGE('',*,*,#332,.F.);
358 | #347 = ORIENTED_EDGE('',*,*,#132,.F.);
359 | #348 = CYLINDRICAL_SURFACE('',#349,1.25);
360 | #349 = AXIS2_PLACEMENT_3D('',#350,#351,#352);
361 | #350 = CARTESIAN_POINT('',(7.5,-8.9E-16,15.));
362 | #351 = DIRECTION('',(0.,0.,1.));
363 | #352 = DIRECTION('',(1.,0.,-0.));
364 | #353 = ADVANCED_FACE('',(#354),#373,.F.);
365 | #354 = FACE_BOUND('',#355,.F.);
366 | #355 = EDGE_LOOP('',(#356,#364,#371,#372));
367 | #356 = ORIENTED_EDGE('',*,*,#357,.T.);
368 | #357 = EDGE_CURVE('',#144,#358,#360,.T.);
369 | #358 = VERTEX_POINT('',#359);
370 | #359 = CARTESIAN_POINT('',(-6.25,1.E-15,10.));
371 | #360 = LINE('',#361,#362);
372 | #361 = CARTESIAN_POINT('',(-6.25,8.9E-16,15.));
373 | #362 = VECTOR('',#363,1.);
374 | #363 = DIRECTION('',(-0.,-0.,-1.));
375 | #364 = ORIENTED_EDGE('',*,*,#365,.T.);
376 | #365 = EDGE_CURVE('',#358,#358,#366,.T.);
377 | #366 = CIRCLE('',#367,1.25);
378 | #367 = AXIS2_PLACEMENT_3D('',#368,#369,#370);
379 | #368 = CARTESIAN_POINT('',(-7.5,8.9E-16,10.));
380 | #369 = DIRECTION('',(0.,0.,1.));
381 | #370 = DIRECTION('',(1.,0.,0.));
382 | #371 = ORIENTED_EDGE('',*,*,#357,.F.);
383 | #372 = ORIENTED_EDGE('',*,*,#143,.F.);
384 | #373 = CYLINDRICAL_SURFACE('',#374,1.25);
385 | #374 = AXIS2_PLACEMENT_3D('',#375,#376,#377);
386 | #375 = CARTESIAN_POINT('',(-7.5,8.9E-16,15.));
387 | #376 = DIRECTION('',(0.,0.,1.));
388 | #377 = DIRECTION('',(1.,0.,-0.));
389 | #378 = ADVANCED_FACE('',(#379),#398,.F.);
390 | #379 = FACE_BOUND('',#380,.F.);
391 | #380 = EDGE_LOOP('',(#381,#390,#396,#397));
392 | #381 = ORIENTED_EDGE('',*,*,#382,.F.);
393 | #382 = EDGE_CURVE('',#383,#383,#385,.T.);
394 | #383 = VERTEX_POINT('',#384);
395 | #384 = CARTESIAN_POINT('',(2.75,0.,-10.));
396 | #385 = CIRCLE('',#386,2.75);
397 | #386 = AXIS2_PLACEMENT_3D('',#387,#388,#389);
398 | #387 = CARTESIAN_POINT('',(0.,0.,-10.));
399 | #388 = DIRECTION('',(0.,0.,-1.));
400 | #389 = DIRECTION('',(1.,0.,0.));
401 | #390 = ORIENTED_EDGE('',*,*,#391,.T.);
402 | #391 = EDGE_CURVE('',#383,#155,#392,.T.);
403 | #392 = LINE('',#393,#394);
404 | #393 = CARTESIAN_POINT('',(2.75,0.,-10.));
405 | #394 = VECTOR('',#395,1.);
406 | #395 = DIRECTION('',(0.,0.,1.));
407 | #396 = ORIENTED_EDGE('',*,*,#154,.T.);
408 | #397 = ORIENTED_EDGE('',*,*,#391,.F.);
409 | #398 = CYLINDRICAL_SURFACE('',#399,2.75);
410 | #399 = AXIS2_PLACEMENT_3D('',#400,#401,#402);
411 | #400 = CARTESIAN_POINT('',(0.,0.,-10.));
412 | #401 = DIRECTION('',(0.,0.,-1.));
413 | #402 = DIRECTION('',(1.,0.,0.));
414 | #403 = ADVANCED_FACE('',(#404),#423,.F.);
415 | #404 = FACE_BOUND('',#405,.F.);
416 | #405 = EDGE_LOOP('',(#406,#414,#421,#422));
417 | #406 = ORIENTED_EDGE('',*,*,#407,.T.);
418 | #407 = EDGE_CURVE('',#166,#408,#410,.T.);
419 | #408 = VERTEX_POINT('',#409);
420 | #409 = CARTESIAN_POINT('',(1.25,7.5,10.));
421 | #410 = LINE('',#411,#412);
422 | #411 = CARTESIAN_POINT('',(1.25,7.5,15.));
423 | #412 = VECTOR('',#413,1.);
424 | #413 = DIRECTION('',(-0.,-0.,-1.));
425 | #414 = ORIENTED_EDGE('',*,*,#415,.T.);
426 | #415 = EDGE_CURVE('',#408,#408,#416,.T.);
427 | #416 = CIRCLE('',#417,1.25);
428 | #417 = AXIS2_PLACEMENT_3D('',#418,#419,#420);
429 | #418 = CARTESIAN_POINT('',(0.,7.5,10.));
430 | #419 = DIRECTION('',(0.,0.,1.));
431 | #420 = DIRECTION('',(1.,0.,0.));
432 | #421 = ORIENTED_EDGE('',*,*,#407,.F.);
433 | #422 = ORIENTED_EDGE('',*,*,#165,.F.);
434 | #423 = CYLINDRICAL_SURFACE('',#424,1.25);
435 | #424 = AXIS2_PLACEMENT_3D('',#425,#426,#427);
436 | #425 = CARTESIAN_POINT('',(0.,7.5,15.));
437 | #426 = DIRECTION('',(0.,0.,1.));
438 | #427 = DIRECTION('',(1.,0.,-0.));
439 | #428 = ADVANCED_FACE('',(#429),#432,.T.);
440 | #429 = FACE_BOUND('',#430,.T.);
441 | #430 = EDGE_LOOP('',(#431));
442 | #431 = ORIENTED_EDGE('',*,*,#190,.T.);
443 | #432 = PLANE('',#433);
444 | #433 = AXIS2_PLACEMENT_3D('',#434,#435,#436);
445 | #434 = CARTESIAN_POINT('',(-9.5,-5.853288E-11,5.));
446 | #435 = DIRECTION('',(-0.,-0.,-1.));
447 | #436 = DIRECTION('',(-1.,0.,0.));
448 | #437 = ADVANCED_FACE('',(#438),#441,.T.);
449 | #438 = FACE_BOUND('',#439,.T.);
450 | #439 = EDGE_LOOP('',(#440));
451 | #440 = ORIENTED_EDGE('',*,*,#215,.T.);
452 | #441 = PLANE('',#442);
453 | #442 = AXIS2_PLACEMENT_3D('',#443,#444,#445);
454 | #443 = CARTESIAN_POINT('',(-1.7E-16,-9.5,5.));
455 | #444 = DIRECTION('',(-0.,-0.,-1.));
456 | #445 = DIRECTION('',(-1.,0.,0.));
457 | #446 = ADVANCED_FACE('',(#447,#450),#453,.T.);
458 | #447 = FACE_BOUND('',#448,.T.);
459 | #448 = EDGE_LOOP('',(#449));
460 | #449 = ORIENTED_EDGE('',*,*,#240,.T.);
461 | #450 = FACE_BOUND('',#451,.T.);
462 | #451 = EDGE_LOOP('',(#452));
463 | #452 = ORIENTED_EDGE('',*,*,#382,.F.);
464 | #453 = PLANE('',#454);
465 | #454 = AXIS2_PLACEMENT_3D('',#455,#456,#457);
466 | #455 = CARTESIAN_POINT('',(-4.6E-16,-6.7E-16,-10.));
467 | #456 = DIRECTION('',(-0.,-0.,-1.));
468 | #457 = DIRECTION('',(-1.,0.,0.));
469 | #458 = ADVANCED_FACE('',(#459),#462,.T.);
470 | #459 = FACE_BOUND('',#460,.T.);
471 | #460 = EDGE_LOOP('',(#461));
472 | #461 = ORIENTED_EDGE('',*,*,#265,.T.);
473 | #462 = PLANE('',#463);
474 | #463 = AXIS2_PLACEMENT_3D('',#464,#465,#466);
475 | #464 = CARTESIAN_POINT('',(9.5,5.634941E-11,5.));
476 | #465 = DIRECTION('',(-0.,-0.,-1.));
477 | #466 = DIRECTION('',(-1.,0.,0.));
478 | #467 = ADVANCED_FACE('',(#468),#471,.T.);
479 | #468 = FACE_BOUND('',#469,.T.);
480 | #469 = EDGE_LOOP('',(#470));
481 | #470 = ORIENTED_EDGE('',*,*,#290,.T.);
482 | #471 = PLANE('',#472);
483 | #472 = AXIS2_PLACEMENT_3D('',#473,#474,#475);
484 | #473 = CARTESIAN_POINT('',(2.18472E-12,9.5,5.));
485 | #474 = DIRECTION('',(-0.,-0.,-1.));
486 | #475 = DIRECTION('',(-1.,0.,0.));
487 | #476 = ADVANCED_FACE('',(#477),#480,.T.);
488 | #477 = FACE_BOUND('',#478,.T.);
489 | #478 = EDGE_LOOP('',(#479));
490 | #479 = ORIENTED_EDGE('',*,*,#315,.T.);
491 | #480 = PLANE('',#481);
492 | #481 = AXIS2_PLACEMENT_3D('',#482,#483,#484);
493 | #482 = CARTESIAN_POINT('',(8.5E-16,-7.5,10.));
494 | #483 = DIRECTION('',(0.,0.,1.));
495 | #484 = DIRECTION('',(0.,1.,0.));
496 | #485 = ADVANCED_FACE('',(#486),#489,.T.);
497 | #486 = FACE_BOUND('',#487,.T.);
498 | #487 = EDGE_LOOP('',(#488));
499 | #488 = ORIENTED_EDGE('',*,*,#340,.T.);
500 | #489 = PLANE('',#490);
501 | #490 = AXIS2_PLACEMENT_3D('',#491,#492,#493);
502 | #491 = CARTESIAN_POINT('',(7.5,-7.5E-16,10.));
503 | #492 = DIRECTION('',(0.,0.,1.));
504 | #493 = DIRECTION('',(1.,0.,0.));
505 | #494 = ADVANCED_FACE('',(#495),#498,.T.);
506 | #495 = FACE_BOUND('',#496,.T.);
507 | #496 = EDGE_LOOP('',(#497));
508 | #497 = ORIENTED_EDGE('',*,*,#365,.T.);
509 | #498 = PLANE('',#499);
510 | #499 = AXIS2_PLACEMENT_3D('',#500,#501,#502);
511 | #500 = CARTESIAN_POINT('',(-7.5,9.2E-16,10.));
512 | #501 = DIRECTION('',(0.,0.,1.));
513 | #502 = DIRECTION('',(1.,0.,0.));
514 | #503 = ADVANCED_FACE('',(#504),#507,.T.);
515 | #504 = FACE_BOUND('',#505,.T.);
516 | #505 = EDGE_LOOP('',(#506));
517 | #506 = ORIENTED_EDGE('',*,*,#415,.T.);
518 | #507 = PLANE('',#508);
519 | #508 = AXIS2_PLACEMENT_3D('',#509,#510,#511);
520 | #509 = CARTESIAN_POINT('',(-1.7E-16,7.5,10.));
521 | #510 = DIRECTION('',(0.,0.,1.));
522 | #511 = DIRECTION('',(0.,1.,0.));
523 | #512 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3)
524 | GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#516)) GLOBAL_UNIT_ASSIGNED_CONTEXT
525 | ((#513,#514,#515)) REPRESENTATION_CONTEXT('Context #1',
526 | '3D Context with UNIT and UNCERTAINTY') );
527 | #513 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );
528 | #514 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) );
529 | #515 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() );
530 | #516 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#513,
531 | 'distance_accuracy_value','confusion accuracy');
532 | #517 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#7));
533 | #518 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#519)
534 | ,#512);
535 | #519 = STYLED_ITEM('color',(#520),#15);
536 | #520 = PRESENTATION_STYLE_ASSIGNMENT((#521,#527));
537 | #521 = SURFACE_STYLE_USAGE(.BOTH.,#522);
538 | #522 = SURFACE_SIDE_STYLE('',(#523));
539 | #523 = SURFACE_STYLE_FILL_AREA(#524);
540 | #524 = FILL_AREA_STYLE('',(#525));
541 | #525 = FILL_AREA_STYLE_COLOUR('',#526);
542 | #526 = COLOUR_RGB('',0.949019609525,0.619607859787,0.399999997426);
543 | #527 = CURVE_STYLE('',#528,POSITIVE_LENGTH_MEASURE(0.1),#529);
544 | #528 = DRAUGHTING_PRE_DEFINED_CURVE_FONT('continuous');
545 | #529 = COLOUR_RGB('',9.803921802644E-02,9.803921802644E-02,
546 | 9.803921802644E-02);
547 | ENDSEC;
548 | END-ISO-10303-21;
549 |
--------------------------------------------------------------------------------