Your First Project
Creating a Project
Use acctl new to create a new project:
acctl new my_first_machine
cd my_first_machine
This creates a complete project with all the files you need:
my_first_machine/
├── project.json # Project configuration
├── control/ # Your control program (Rust)
│ ├── Cargo.toml # Rust package manifest
│ └── src/
│ ├── main.rs # Entry point (auto-generated — do not edit)
│ ├── program.rs # Your control logic (edit this!)
│ └── gm.rs # Generated memory mappings
├── www/ # Web HMI (React + TypeScript)
│ ├── package.json
│ ├── index.html
│ ├── vite.config.ts
│ └── src/
│ ├── main.tsx
│ ├── App.tsx
│ └── ...
├── datastore/ # Persistent storage
│ └── autocore_gnv.ini
└── .gitignore
A git repository is also initialized automatically.
Understanding the Project Structure
| Directory / File | Purpose | When You Edit It |
|---|---|---|
project.json | Defines variables, hardware modules, cycle time | When adding variables, changing cycle time, or configuring hardware |
control/src/program.rs | Your control logic | This is where you spend most of your time |
control/src/main.rs | Entry point — connects to the server | Never (auto-generated) |
control/src/gm.rs | Rust struct mapping your variables | Never (auto-generated by acctl codegen) |
control/Cargo.toml | Rust dependencies | When adding external Rust libraries |
www/ | Web-based HMI | When building operator screens |
datastore/ | Non-volatile storage (persists across restarts) | Managed by the server; you read/write via commands |
The project.json File
The project.json file is the heart of your project. Here is the default one that acctl new generates:
{
"name": "my_first_machine",
"version": "0.1.0",
"description": "AutoCore project: my_first_machine",
"modules": {},
"control": {
"enable": true,
"source_directory": "./control",
"entry_point": "main.rs",
"signals": {
"tick": {
"description": "System Tick (10ms)",
"source": "internal",
"scan_rate_us": 10000
}
}
},
"variables": {}
}
Let’s break down each section:
control — Configures the control program execution:
| Field | Description | Example |
|---|---|---|
enable | Whether the control program should run | true |
source_directory | Path to the Rust source code | "./control" |
entry_point | The main Rust file | "main.rs" |
signals.tick.scan_rate_us | Cycle time in microseconds | 10000 (= 10 ms = 100 Hz) |
signals.tick.source | Where the tick comes from | "internal" (server-generated) |
Common cycle times:
| scan_rate_us | Cycle Time | Frequency | Typical Use |
|---|---|---|---|
1000 | 1 ms | 1 kHz | High-speed motion control |
2000 | 2 ms | 500 Hz | Servo drives |
5000 | 5 ms | 200 Hz | General motion |
10000 | 10 ms | 100 Hz | Process control, I/O |
50000 | 50 ms | 20 Hz | Slow processes, monitoring |
variables — Defines all the data points in your system. We will cover this in detail in Working with Variables.
modules — Configures hardware interface modules (EtherCAT, Modbus, etc.). We will cover this in the hardware integration chapters.
Building and Running Locally
If you are running the AutoCore server on your development machine (which is the typical development workflow):
# Step 1: Push the project configuration to the server
acctl push project
# Step 2: Build and deploy the control program, then start it
acctl push control --start
The push control command:
- Compiles your Rust control program
- Uploads the binary to the server
- With
--start, starts the control program immediately
If you only want to build without starting:
acctl push control
Then start it separately:
acctl control start
Viewing Logs
Your control program’s log output is captured by the server and can be viewed with:
# Show recent logs
acctl logs
# Stream logs in real time (like tail -f)
acctl logs --follow
Press Ctrl+C to stop streaming.
You can also check the control program’s status:
acctl control status
This shows whether the program is running, stopped, or has encountered an error.