{"id":27627079,"url":"https://github.com/thespaceegg/mksservocan","last_synced_at":"2026-05-02T06:33:14.187Z","repository":{"id":288458166,"uuid":"968175115","full_name":"TheSpaceEgg/MKSServoCAN","owner":"TheSpaceEgg","description":"Arduino ESP32 library for controlling MKS SERVO42D/57D closed‑loop stepper drivers over CAN.","archived":false,"fork":false,"pushed_at":"2025-04-18T00:37:49.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-18T06:58:40.317Z","etag":null,"topics":["closed-loop-control","esp32","makerbase"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheSpaceEgg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-17T16:22:01.000Z","updated_at":"2025-04-18T00:36:32.000Z","dependencies_parsed_at":"2025-04-18T06:58:55.012Z","dependency_job_id":null,"html_url":"https://github.com/TheSpaceEgg/MKSServoCAN","commit_stats":null,"previous_names":["thespaceegg/mksservocan"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheSpaceEgg%2FMKSServoCAN","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheSpaceEgg%2FMKSServoCAN/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheSpaceEgg%2FMKSServoCAN/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheSpaceEgg%2FMKSServoCAN/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheSpaceEgg","download_url":"https://codeload.github.com/TheSpaceEgg/MKSServoCAN/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250443999,"owners_count":21431566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["closed-loop-control","esp32","makerbase"],"created_at":"2025-04-23T13:52:40.524Z","updated_at":"2026-05-02T06:33:13.213Z","avatar_url":"https://github.com/TheSpaceEgg.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MKSServoCAN\n\nArduino library for controlling **MKS SERVO42D/57D** closed‑loop stepper drivers over CAN.\n\n---\n\n## Features\n\n- Full support for all official MKS CAN commands (position, speed, homing, I/O, parameters, protection, emergency stop, etc.)  \n- Automatic CRC calculation and frame encoding  \n- Pluggable CAN‑bus backend via the `ICanBus` interface  \n  - **TWAI on ESP32** (built‑in)  \n  - **SPI/MCP2515** support (tested)  \n- Human‑friendly response decoding with `pollResponses()`  \n\n---\n\n## Installation\n\n1. Clone into your Arduino libraries folder if not available in **Library Manager**:  \n   ```bash\n   cd ~/Arduino/libraries\n   git clone https://github.com/YourUser/MKSServoCAN.git\n   ```\n2. **For ESP32/TWAI**: ensure your ESP32 board definitions are installed.  \n3. **For MCP2515**: install the [MCP_CAN library](https://github.com/coryjfowler/MCP_CAN_lib) (e.g. via Library Manager) and include `\u003cSPI.h\u003e`.\n\n---\n\n## Quick Start Examples\n\n### ESP32 + TWAI\n\n```cpp\n#include \u003cArduino.h\u003e\n#include \u003cTwaiCan.h\u003e\n#include \u003cMKSServoCAN.h\u003e\n\n#define MOTOR_ID  1\n\nTwaiCan bus(GPIO_NUM_27, GPIO_NUM_26);\n\nvoid setup() {\n  Serial.begin(115200);\n  while (!Serial);\n\n  if (!MKSServoCAN::begin(\u0026bus)) {\n    Serial.println(\"CAN init failed\");\n    while (1);\n  }\n\n  MKSServoCAN::goHome(MOTOR_ID);\n}\n\nvoid loop() {\n  MKSServoCAN::pollResponses();\n}\n```\n\n### SPI + MCP2515\n\n```cpp\n#include \u003cArduino.h\u003e\n#include \u003cMcpCan.h\u003e\n#include \u003cMKSServoCAN.h\u003e\n\n#define MOTOR_ID    1\n\n#define MCP_MISO    19\n#define MCP_MOSI    23\n#define MCP_SCLK    18\n#define MCP_CS      5\n#define MCP_INT     17\n\nMcpCan bus(\n  MCP_MISO,\n  MCP_MOSI,\n  MCP_SCLK,\n  MCP_CS,\n  MCP_INT,\n  CAN_500KBPS\n);\n\nvoid setup() {\n  Serial.begin(115200);\n  while (!Serial);\n\n  if (!MKSServoCAN::begin(\u0026bus)) {\n    Serial.println(\"CAN init failed\");\n    while (1);\n  }\n\n  MKSServoCAN::goHome(MOTOR_ID);\n}\n\nvoid loop() {\n  MKSServoCAN::pollResponses();\n}\n```\n\n---\n\n## Command Reference\n\n_All functions take a **device ID** (1–2047)._\n\n### Status Reads\n\n| Function                   | Code | Description                          |\n|----------------------------|------|--------------------------------------|\n| `readEncoderCarry(id)`     | 0x30 | 32‑bit carry + 14‑bit current value  |\n| `readEncoderAdd(id)`       | 0x31 | 48‑bit cumulative encoder count      |\n| `readSpeed(id)`            | 0x32 | Real‑time RPM                        |\n| `readPulses(id)`           | 0x33 | 32‑bit pulse count                   |\n| `readIOstatus(id)`         | 0x34 | 8‑bit I/O port status                |\n| `readRawEncoder(id)`       | 0x35 | Raw 48‑bit encoder count             |\n| `readAngleError(id)`       | 0x39 | Angle error (ticks)                  |\n| `readEnablePin(id)`        | 0x3A | EN‑pin state                         |\n| `readZeroStatus(id)`       | 0x3B | Zero‑on‑power return status          |\n| `releaseProtection(id)`    | 0x3D | Release locked‑rotor protection      |\n| `readProtectState(id)`     | 0x3E | Protection active (yes/no)           |\n\n### Parameter Configuration\n\n| Function                                | Code | Description                            |\n|-----------------------------------------|------|----------------------------------------|\n| `calibrate(id)`                         | 0x80 | Encoder calibration                    |\n| `setWorkMode(id, mode)`                 | 0x82 | 0=CR_OPEN…5=SR_vFOC                    |\n| `setCurrent(id, ma)`                    | 0x83 | Working current (mA)                   |\n| `setMicrostep(id, steps)`               | 0x84 | Micro‑step subdivision                 |\n| `setEnActive(id, lvl)`                  | 0x85 | EN‑pin active level                    |\n| `setDirection(id, dir)`                 | 0x86 | 0=CW,1=CCW                             |\n| `setAutoSleep(id, enable)`              | 0x87 | Auto turn‑off OLED                     |\n| `setProtect(id, enable)`                | 0x88 | Locked‑rotor protection                |\n| `setInterpolator(id, enable)`           | 0x89 | Subdivision interpolation              |\n| `setHoldCurrent(id, pct)`               | 0x9B | Holding current percentage             |\n| `setCanRate(id, rate)`                  | 0x8A | CAN bit rate (0=125k…3=1M)             |\n| `setCanId(id, newId)`                   | 0x8B | Change device CAN ID                   |\n| `setCanResponse(id, resp, act)`         | 0x8C | Slave respond \u0026 active flags           |\n| `setGroupId(id, gid)`                   | 0x8D | Group address                          |\n| `setKeylock(id, lock)`                  | 0x8F | Front‑panel key lock/unlock            |\n\n### Homing \u0026 Limits\n\n| Function                                       | Code | Description                      |\n|------------------------------------------------|------|----------------------------------|\n| `setHomeParams(id, trig, dir, spd, lim, mode)` | 0x90 | Configure homing                 |\n| `goHome(id)`                                   | 0x91 | Execute homing                   |\n| `setZeroPoint(id)`                             | 0x92 | Define current position as zero  |\n| `setNoLimitReturn(id, angle, ma)`              | 0x94 | “No‑limit” return parameters     |\n| `setLimitRemap(id, enable)`                    | 0x9E | Remap limit switches             |\n\n### Utilities\n\n| Function                                | Code     | Description                            |\n|-----------------------------------------|----------|----------------------------------------|\n| `setZeroMode(id, mode, en, speed, dir)` | 0x9A     | Zero on power‑up behaviour             |\n| `restoreDefaults(id)`                   | 0x3F     | Reset to factory parameters            |\n| `restart(id)`                           | 0x41     | Restart firmware                       |\n| `setEnTrigger(id, eTrig, pProt, tim, err)` | 0x9D   | EN‑trigger zero \u0026 pos‑error prot.      |\n| `readSystemParam(id, code)`             | 0x00+code| Read arbitrary system parameter        |\n\n### Motion \u0026 Control\n\n| Function                                    | Code         | Description                         |\n|---------------------------------------------|--------------|-------------------------------------|\n| `queryStatus(id)`                           | 0xF1         | Motor status                        |\n| `enableMotor(id, enable)`                   | 0xF3         | Enable/disable motor                |\n| `emergencyStop(id)`                         | 0xF7         | Emergency stop                      |\n| `speedMode(id, speed, accel, ccw)`          | 0xF6         | Constant speed mode                 |\n| `speedModeStop(id)`                         | 0xF6 (acc=0) | Stop speed mode                     |\n| `speedState(id, save)`                      | 0xFF         | Save/clear speed parameters         |\n| `posRelative(id, pulses, speed, accel, ccw)`| 0xFD         | Relative‑pulse move                 |\n| `posRelativeStop(id)`                       | 0xFD (acc=0) | Stop relative move                  |\n| `posAbsolute(id, axis, speed, accel)`       | 0xFE         | Absolute‑position move              |\n| `posAbsoluteStop(id)`                       | 0xFE (acc=0) | Stop absolute move                  |\n| `posAxis(id, relAxis, speed, accel)`        | 0xF4         | Relative‑axis move                  |\n| `posAxisStop(id)`                           | 0xF4 (acc=0) | Stop axis move                      |\n\n---\n\n## Supported Hardware\n\n- **ESP32 WROOM** with built‑in TWAI peripheral  \n- **Waveshare SN65HVD230** CAN transceiver  \n- **MCP2515** SPI‑to‑CAN bridge (3.3 V logic + 5 V VCC)  \n- **MKS SERVO42D/57D** driver modules  \n\n---\n\n## Future Plans\n\n- Support for A/B/C/D/E variants of the SERVO42/57 drivers  \n- Additional SPI‑based CAN backends (e.g. on AVR, STM32, Arduino Uno)  \n- Linux SBC support (Raspberry Pi, Jetson)  \n- Expanded MCU compatibility (Due, Teensy, etc.)  \n- Collaborative hardware compatibility matrix — **please share your test results!**\n\n---\n\n## External Resources\n\n- Official MKS SERVO42C repo: https://github.com/makerbase-motor/MKS-SERVO42C  \n- Official MKS SERVO57D repo: https://github.com/makerbase-motor/MKS-SERVO57D  \n\n---\n\n## Contributing\n\nPull requests and issues welcome. When submitting, please include your:\n\n- MCU type  \n- CAN transceiver model  \n- Hardware wiring (pin assignments)  \n- Test outcome (working/non‑working)  \n\n---\n\n## License\n\nCreative Commons Attribution‑NonCommercial 4.0 International  \n(CC BY‑NC 4.0)  \n\nAnyone may copy, share, modify, and distribute this code with attribution to **Will Hickmott**.  \nCommercial use (selling, bundling in a paid product, etc.) is **forbidden**.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthespaceegg%2Fmksservocan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthespaceegg%2Fmksservocan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthespaceegg%2Fmksservocan/lists"}