Power-loss recovery for the Elegoo Centauri Carbon 1 (CC1) and Centauri Carbon 2 (CC2) running COSMOS firmware and Klipper.
This project provides a custom Klipper power_loss module and installer that detect a mains power outage, save the current print state when possible, and offer print recovery after power is restored.
- Power-loss detection: Monitors the printer's power-outage sensor using GPIO.
- Print-state preservation: Saves relevant print information when a print is running or paused.
- Recovery options: Provides options to resume a saved print or discard the saved state.
- COSMOS integration: Installs the Klipper module using an overlay mount to accommodate the firmware's read-only filesystem.
- Multiple printer profiles: Includes separate configuration defaults for the Centauri Carbon 1 and Centauri Carbon 2.
- Installer and removal support: Includes an installer with model selection, configuration options, and an uninstall procedure.
Important
Original author: jagonmo. This project is a derivative of jagonmo's power_loss module. jagonmo reverse engineered Elegoo's firmware, found the pins, designed the module, and proved it end to end with a real power cut on a Centauri Carbon 1. Nearly everything here builds on that work. See Credits for details.
| Model | Status |
|---|---|
| Centauri Carbon 1 (CC1) | Built-in defaults (printer_model: cc1). |
| Centauri Carbon 2 (CC2) | COSMOS for the CC2 is in alpha. Defaults from Elegoo's official config (printer_model: cc2). The outage sensor is confirmed by an unplug test on a real CC2; the charge pin is not independently verified. See Centauri Carbon 2. |
Warning
This module is experimental and has not been validated across printers or hardware revisions. Test it with a print you don't care about before relying on it. See Known limitations.
- How it works
- Hardware
- Centauri Carbon 1
- Centauri Carbon 2
- Installation
- Configuration
- Commands
- Detection methods
- Usage
- Resume sequence
- Known limitations
- Troubleshooting
- Credits and license
flowchart TD
A[Klipper starts] --> B[Enable supercap charging]
B --> C[Watch outage pin]
C -->|Outage persists past debounce| D{Printing or paused?}
D -->|Yes| E[Save state to disk<br/>write + fsync + atomic rename]
D -->|No| F[Skip save]
E --> G[Turn off heaters]
F --> G
G --> H[sync + remount filesystems read-only]
H --> I[Power returns, next boot]
I --> J{Saved state found?}
J -->|Yes| K[Prompt: Resume Precise / Resume Safe / Discard]
J -->|No| L[Normal startup]
- Charges the supercapacitor when Klipper becomes ready.
- Detects an outage on a dedicated GPIO pin, using edge events with a polling fallback, and debounces it so a brief flicker doesn't trigger a save.
- Saves position, temperatures, fan, speed and file offset to disk. This only happens if a print is running or paused.
- Protects the filesystems by running
syncand remounting writable ext*/FAT mounts read-only. It does not shut the system down. - Offers a resume on the next boot through a Mainsail/Fluidd prompt.
Pins for each model (the printer_model defaults):
| Function | CC1 port | CC1 GPIO | CC2 port | CC2 GPIO | Used by this module |
|---|---|---|---|---|---|
| Outage detection | PG0 | 192 | PG9 | 201 | Input (read) |
| Supercap charge enable | PC1 | 65 | PD20 | 116 | Output (control) |
| Supercap output to power rail | PG11 | 203 | PG11 | 203 | Never used |
Linux GPIO numbers use the Allwinner rule 32 × (port letter index, A=0) + pin. That reproduces all three CC1 numbers, and the CC2 numbers are derived the same way. The CC2 port names come from the [por] section of Elegoo's printer_dsp.cfg.
Important
The "supercap output to rail" line connects the supercap to the power rail. The module refuses to start if the configured rail_gpio is also used as the sensor or charge pin. On both CC1 and CC2 that is GPIO 203 and is guarded by default. Don't remove that guard without checking with a multimeter what is on the other side.
jagonmo reported this from a real outage test on a CC1 with mains fully unplugged: with the supercap charged, the SoC stayed alive for roughly 5–15 seconds. Whether motors and heaters keep any residual power is unconfirmed, so the module assumes they don't and only moves the toolhead on resume.
printer_model: cc1 is the default, so on a CC1 you don't have to set the model at all. The module uses these defaults:
[power_loss]
printer_model: cc1
sensor_gpio: 192 # PG0
charge_gpio: 65 # PC1
rail_gpio: 203 # PG11, guarded and never drivenImportant
These settings need to be added to the printer.cfg through the Web Interface.
Where the numbers come from. The CC1 is the printer the original module was written for. The pins come from Elegoo's official CC1 firmware sources (gpio.h and por.cpp), as worked out in jagonmo's original module. The ports convert to Linux GPIO numbers with the standard Allwinner formula, 32 × (port letter index, A=0) + pin: PG0 is 32 × 6 + 0 = 192, PC1 is 32 × 2 + 1 = 65, and PG11 is 32 × 6 + 11 = 203. The same pin table was posted in OpenCentauri/cosmos issue 348.
Note
Unlike the CC2 defaults, the CC1 pins were confirmed on real hardware by the original author, so you don't need to re-derive them. You should still verify the module on your own printer before trusting it with a long print:
- Run
POWER_LOSS_STATUSand check that it showsmodel=cc1 sensor=GPIO192 charge=GPIO65 rail_guard=203. After about 30 secondscharge_doneshould becomeTrue. - Run
POWER_LOSS_TEST_READ N=100with mains on. The readings should be all0. The default polarity is that1means an outage. - With the printer idle, unplug mains for about 10 seconds and check
klippy.logforpower_loss: OUTAGE DETECTED. - Only then do a controlled test with a print you don't care about.
- Original author's test. jagonmo ran the original module on a real CC1 running COSMOS with mains fully unplugged. With the supercap charged, the SoC stayed alive for roughly 5–15 seconds.
- This version. The hardware results listed in this README for this version (the debounce, atomic save, model profiles and installer) come from a CC2. No CC1 results have been reported for it yet, so treat the CC1 path as limited-tested until they are.
What the cc1 profile sets up that the other models don't:
- Tray macro and wipe.
tray_macrodefaults toMOVE_TO_TRAY, and the built-in wipe pattern is on. The wipe uses fixed CC1 coordinates, which is why it is only allowed withprinter_model: cc1. Setwipe: Falseto skip it, or pointtray_macroat your own sequence. homing_override_z_lift. The default of5.0matches the Z lift in the COSMOS[homing_override]that the original was written against. If you changed that macro, update this value to match, or the resumed Z height will be wrong.- COSMOS status. COSMOS on the CC1 is described by its docs as stable enough for everyday printing but still actively developed, and it warns that the stock mainboard has very little spare resource (see Stability and memory). Read the release changelogs before updating COSMOS, because an update can overwrite the init script change the installer makes.
If you test this on a CC1 (or find that something doesn't match), please open an issue or PR so this section can record it.
With printer_model: cc2 the module uses these defaults:
[power_loss]
printer_model: cc2
sensor_gpio: 201 # PG9
charge_gpio: 116 # PD20
rail_gpio: 203 # PG11, guarded and never drivenImportant
These settings need to be added to the printer.cfg through the Web Interface.
Where the numbers come from. Elegoo's official CC2 config (debugfile/printer_dsp.cfg in elegooofficial/CentauriCarbon2) has a [por] section with sensor_pin=host:PG9, ctrl_pin=host:PG11, charge_pin=host:PD20 and charge_time=30.0. The same pin table was posted in OpenCentauri/cosmos issue 348. The conversion to Linux GPIO numbers uses the standard Allwinner formula, which matches the CC1's known values. It assumes the CC2 uses the same SoC pin numbering. A hardware test on one CC2 (below) supports that for the outage sensor.
Note
The CC2 numbers come from Elegoo's config, and only the outage sensor has been confirmed on hardware. On startup the module logs a warning for cc2. Before trusting a save:
- Run
POWER_LOSS_STATUSandcat /sys/kernel/debug/gpio(if debugfs is mounted) and check that the lines are named or behave as expected. - Run
POWER_LOSS_TEST_READ N=100with mains on. If the readings are all1, the sensor polarity is probably opposite to the CC1 and you needinvert_sensor: True. The official config does not state the polarity. - Only then do a controlled test with a print you don't care about.
One tester ran this on a CC2 (alpha COSMOS, installed as described in Auto installing on the Centauri Carbon 2) with the default cc2 profile:
POWER_LOSS_STATUSreportedmodel=cc2 sensor=GPIO201 charge=GPIO116 rail_guard=203, andcharge_donebecameTrueafter about 30 seconds. Detection ran inpollingmode.- With mains on,
POWER_LOSS_TEST_READ N=100returned 100 zeros, so the default polarity (1 means outage) is right andinvert_sensorisn't needed. - With the printer idle, unplugging mains for about 10 seconds produced
OUTAGE DETECTED,not printing, skipping state save, and read-only remounts of/data,/user-resource,/board-resource,/opt/usrand the USB stick. The system logged a normal Stats line afterwards.
That confirms the sensor pin, polarity and the outage handler. Still untested on a CC2: saving state during a real print and a full resume, and whether the charge pin (GPIO 116) is what keeps the board alive. The printer was idle, so no state was written.
Differences from cc1:
- No tray macro or wipe by default.
tray_macrois blank and the built-in wipe pattern is disabled. The wipe uses CC1 coordinates, so it is rejected for any model other thancc1. Iftray_macrois blank, the resume skips the purge entirely rather than purging over the part. Pointtray_macroat your own parking macro if you want a purge. - Re-check
homing_override_z_lift. It must match the Z lift in your CC2's[homing_override]. - COSMOS for the CC2 is in alpha. The module loaded and read its GPIOs on a tested CC2 running that build, so sysfs access works there, but alpha firmware can change between releases. Elegoo's CC2 config shows a different architecture from the CC1 (a separate DSP core running the motion MCU), so check the COSMOS docs, the CC2 hardware pages and the alpha announcement for what your build supports.
Use printer_model: custom for any other board. It has no GPIO defaults, so you must set sensor_gpio and charge_gpio yourself, and rail_gpio too so the rail line is guarded.
If you confirm the CC2 behavior on real hardware (or find that a number is wrong), please open an issue or PR so the defaults can be corrected.
COSMOS's root filesystem is read-only, so the module is installed through an overlay mount over Klipper's extras directory. The installer does this for you, but you run it on the printer itself, over SSH. It is not something you run on your computer.
From a terminal on your computer, replace <printer-ip> with the printer's IP address (from your router's device list or the printer's network settings):
ssh root@<printer-ip>The first time you connect, SSH asks you to accept the printer's host key. Type yes. macOS and Linux have ssh in the terminal, Windows 10 and later have it in PowerShell and Windows Terminal, and PuTTY also works.
| Printer | User | Password | Source |
|---|---|---|---|
| CC1 (COSMOS) | root |
OpenCentauri |
OpenCentauri docs for the patched firmware, the cc-fw-tools README, and third-party COSMOS add-ons. The COSMOS install guide doesn't state it. |
| CC2 (COSMOS alpha) | root |
none | OpenCentauri's CC2 alpha announcement. |
Warning
Both are open or well-known logins, so anyone on your network can log in as root. Don't expose the printer's SSH port to the internet. Consider switching to key-based login with ssh-copy-id root@<printer-ip>, which the OpenCentauri firmware tools README recommends, and use passwd on the printer to set a password.
If SSH says Permission denied, the password is wrong or the login has changed on your version, so check the COSMOS docs or ask on the OpenCentauri Discord. If it says Connection refused or times out, check the IP address and that the printer is on your network.
Follow the section for your printer:
- Auto installing on the Centauri Carbon 1: COSMOS is installed with the standard OpenCentauri method.
- Auto installing on the Centauri Carbon 2: COSMOS for the CC2 is in alpha testing, so the install is different and riskier.
Both sections end with the same two shared steps, described after them: running the installer and adding the config.
COSMOS on the CC1 is installed with the OpenCentauri installer, as described on the OpenCentauri website. This module goes on top of a working COSMOS install.
You need: a CC1 running COSMOS, the printer on your network (and its IP address), an SSH client, and no print running.
- Install COSMOS Firmware. Follow the official CC1 COSMOS install guide.
- Connect over SSH as
rootwith the passwordOpenCentauri. See Connecting over SSH. - Run the installer from the SSH session. See Running the installer:
or if you want to bypass the scripts auto printer detection feature and specify the CC1 then use:
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | shcurl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | sh -s -- --model cc1 - Add the config and restart Klipper. Paste a
[power_loss]section withprinter_model: cc1intoprinter.cfgand runRESTART. See Add the config and restart Klipper.
Important
COSMOS for the CC2 is an early technical preview in alpha testing at the time of writing. This applies to the CC2 and CC2C only; the C2 and C2C aren't supported. To install COSMOS on your CC2 follow the steps in OpenCentauri's alpha announcement on their Discord: announcement. That post is the source of truth and may have changed, so read it before you begin and report what you run into, good and bad. I used this method on my CC2.
Install this module:
- Install COSMOS Firmware. Follow the official CC2 COSMOS install guide.
- Connect over SSH as
rootand leave the password blank. See Connecting over SSH. - Run the installer from the SSH session. See Running the installer:
or if you want to bypass the scripts auto printer detection feature and specify the CC2 then use:
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | shcurl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | sh -s -- --model cc2 - Add the config and restart Klipper. Paste a
[power_loss]section withprinter_model: cc2intoprinter.cfgand runRESTART. See Add the config and restart Klipper.
Run this in your SSH session on the printer. It is the same for both models.
To pin a specific release, replace main with a tag or commit:
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | shTo pass options, such as the model, use sh -s --:
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | sh -s -- --model cc2Note
This needs the printer to have internet access and either curl or wget. If it doesn't, use Copy the files over below. Piping a script into sh runs whatever is at that URL. If you'd rather read it first, download install.sh, open it, then run sh install.sh. The installer only needs curl or wget.
Download install.sh and power_loss.py to a folder on your computer, then from that folder:
scp install.sh power_loss.py root@<printer-ip>:/tmp/
ssh root@<printer-ip>
sh /tmp/install.shThe installer uses the power_loss.py sitting next to it instead of downloading one. If scp fails with an SFTP-related error, add -O (scp -O ...). If /tmp isn't usable, any writable directory such as /user-resource works.
- Checks that it's running as root, that the Klipper
extrasdirectory exists, and that the kernel supports overlayfs. - Identifies your printer. It looks at system identification strings (device-tree model, hostname, OS release) and, as a weaker signal, at printer configs that reference a DSP rpmsg MCU (CC2 style). It always shows what it found and asks you to confirm. If it can't tell, it shows a menu: CC1, CC2 or custom. For a custom board it asks for the three GPIO numbers.
- Downloads
power_loss.py, checks that it looks like the module and compiles, and verifies a SHA-256 if you supplied one. - Copies it into
/data/klipper-extras-upperand mounts the overlay. - Persists the mount by adding a marked block to
/etc/init.d/klipper, after backing it up to/etc/init.d/klipper.bak-power_loss. If it can't find astart)block, it leaves the file alone and prints the block for you to add. - Prints the
[power_loss]section for your model, or appends it to a file you name with--printer-cfg, after backing that file up.
It never restarts Klipper, because that would interrupt a print. Restart it yourself when the printer is idle.
Important
Detection is a best guess and I haven't verified the identification strings on real CC1 or CC2 units. That's why it always asks for confirmation. Check the model it picks before you accept it.
| Option | Description |
|---|---|
--model cc1|cc2|custom |
Skip detection and prompts. |
--sensor N --charge N --rail N |
Linux GPIO numbers for --model custom. The rail line is guarded and never driven. |
--printer-cfg PATH |
Append the [power_loss] section to this file. It is skipped if the file already has one. Pasting it into printer.cfg in the web interface works just as well. |
--yes, -y |
Accept the detected model without asking. It fails if nothing could be detected. |
--no-persist |
Don't patch the init script. The mount then lasts until the next reboot. |
--uninstall |
Remove the module, the init patch and the overlay. The saved state file and your printer.cfg are left alone. |
--no-mount |
Copy and patch files only, with no mount and no root check. Intended for testing. |
| Environment variable | Description |
|---|---|
POWER_LOSS_REPO |
owner/name of the repository to download from. Defaults to peepsnet/CentauriCarbon-1-2-PowerLoss-Script. |
POWER_LOSS_REF |
Branch, tag or commit to download. Defaults to main. |
POWER_LOSS_SHA256 |
Require this checksum for power_loss.py. |
Non-interactive example (for example over SSH with no terminal), using a pinned tag and a checksum:
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/v1.0.0/install.sh | \
POWER_LOSS_REPO=peepsnet/CentauriCarbon-1-2-PowerLoss-Script POWER_LOSS_REF=v1.0.0 POWER_LOSS_SHA256=<sha256> \
sh -s -- --model cc1 --printer-cfg /path/to/printer.cfgNote
A COSMOS update may overwrite /etc/init.d/klipper. Check it after every update and re-run the installer if the block is gone. Re-running is safe: every step skips what is already done.
If you'd rather not use the script:
mkdir -p /data/klipper-extras-upper /data/klipper-extras-work
cp power_loss.py /data/klipper-extras-upper/power_loss.py
mount -t overlay klipper-extras-overlay \
-o lowerdir=/usr/share/klipper/klippy/extras,upperdir=/data/klipper-extras-upper,workdir=/data/klipper-extras-work \
/usr/share/klipper/klippy/extrasTo make it permanent, add this inside the start) block of /etc/init.d/klipper, before the start-stop-daemon line:
if ! grep -q '^klipper-extras-overlay ' /proc/mounts; then
mount -t overlay klipper-extras-overlay \
-o lowerdir=/usr/share/klipper/klippy/extras,upperdir=/data/klipper-extras-upper,workdir=/data/klipper-extras-work \
/usr/share/klipper/klippy/extras
fiAdd the [power_loss] section the installer printed (see Configuration for every option) to printer.cfg. The COSMOS docs say printer.cfg is the user-facing config and can be edited in the web interface, so the easiest way is to paste the section there. Don't put it in klipper-readonly/*.cfg: COSMOS resets those files on every firmware update (see COSMOS: Features).
CC1 minimal printer.cfg entry
[power_loss]
printer_model: cc1
save_path: /data/power_loss_state.json
# Must match the Z lift in your [homing_override]:
homing_override_z_lift: 5.0CC2 minimal printer.cfg entry
[power_loss]
printer_model: cc2
save_path: /data/power_loss_state.json
# Must match the Z lift in your [homing_override]:
homing_override_z_lift: 5.0Then restart Klipper while no print is running, by running this in the web interface's console:
RESTART
or Restart the entire printer from the command line
rebootIf the module doesn't load, REBOOT_MACHINE does a full reboot. The installer's overlay mount is set up at boot, so a reboot also confirms that it persists.
In the Mainsail/Fluidd console run:
POWER_LOSS_STATUS
After about 30 seconds it should report charge_done=True and show which detection= method is active.
curl -fsSL https://raw.githubusercontent.com/peepsnet/CentauriCarbon-1-2-PowerLoss-Script/main/install.sh | sh -s -- --uninstallEvery option has a default on cc1. cc2 has pin defaults from Elegoo's config, and custom has none, so you must set the GPIO options. Only declare the options you want to change.
| Option | Default | Description |
|---|---|---|
printer_model |
cc1 |
cc1, cc2 or custom. Selects the defaults below. custom has no GPIO defaults. |
sensor_gpio |
192 on cc1, 201 on cc2, required on custom |
Linux GPIO for outage detection. |
charge_gpio |
65 on cc1, 116 on cc2, required on custom |
Linux GPIO that enables supercap charging. |
rail_gpio |
203 on cc1 and cc2, none on custom |
Supercap output-to-rail line. Never driven. Startup fails if it matches the sensor or charge pin. |
poll_interval |
0.01 |
Seconds between reads when using the polling fallback. |
debounce_time |
0.05 |
Seconds an outage must persist before it counts. Filters electrical noise and flickers. |
charge_time |
30 |
Seconds the supercap is assumed to need to charge. Reported by POWER_LOSS_STATUS. |
save_path |
/data/power_loss_state.json |
Where the state file is written. Must be on a writable partition. |
z_hop |
10.0 |
Safety lift (mm) before homing X/Y on resume. |
travel_speed |
3000 |
Speed (mm/min) for hop and travel moves on resume. |
homing_override_z_lift |
5.0 |
Must match the G0 Z<N> lift in your [homing_override] macro. See limitations. |
purge_mm |
15.0 |
Filament purged at the tray before resuming, to clear ooze. |
move_temp |
200.0 |
Nozzle temperature to reach before any movement. The full target keeps heating in the background. |
tray_macro |
MOVE_TO_TRAY on cc1, blank otherwise |
Macro that parks the toolhead at the purge tray. If blank, the purge and wipe are skipped. |
wipe |
True on cc1, False otherwise |
Run the built-in tray wipe pattern (CC1 coordinates). Rejected on any model other than cc1. |
invert_sensor |
False |
Set to True if the sensor polarity turns out to be inverted. |
| Command | Description |
|---|---|
POWER_LOSS_STATUS |
Shows monitor status: pins, charge state, pending resume and the active detection method. |
POWER_LOSS_RESUME |
Resumes from the exact position at the moment of the outage. |
POWER_LOSS_RESUME_SAFE |
Resumes from the last completed layer. It repeats part of a layer but avoids resuming mid-move or mid-wipe. |
POWER_LOSS_DISCARD |
Deletes the saved state without resuming. |
POWER_LOSS_TEST_READ N=<n> |
Shows the last n sensor readings. It is non-blocking and safe to run mid-print. |
POWER_LOSS_RESUME_SAFE is the highlighted choice in the prompt. If the outage happened before the first layer change, it falls back to the precise capture automatically.
The module tries these in order and falls back if one fails:
- Raw GPIO ioctl (v1 uAPI) requests edge events on
/dev/gpiochip0using only the Python standard library. It is interrupt-driven, so the reactor stays idle between events. - Sysfs polling reads the pin every
poll_intervalseconds. It is the guaranteed fallback.
POWER_LOSS_STATUS reports which one is active, and the choice is also logged at startup.
Note
A GPIO line has one exclusive owner in the kernel. The module requests the edge events before touching sysfs for this reason. If you export GPIO 192 manually while Klipper is running, the ioctl tier will fail with EBUSY and the module will fall back to polling.
In edge mode, the pin level is re-read after debounce_time to confirm the outage. If that read fails, the module trusts the edge and saves anyway, so it errs toward saving.
The power-loss recovery script offers two recovery modes: Resume Precise and Resume Safe. Both allow you to continue an interrupted print, but they differ in which saved checkpoint they use to determine where printing should resume.
Purpose: Resume as close as possible to the exact point where power was lost. Resume Precise uses the position and G-code file offset saved when the power outage was detected.
Advantages
- Minimizes the amount of material that may need to be printed again.
- Attempts to continue as close as possible to the interruption point.
- Can reduce the size of the visible transition between the original print and the resumed print.
Risks and limitations
- The saved position may not perfectly match the actual toolhead position when power is lost.
- Motion lookahead, movements in progress, or extrusion state may affect the accuracy of recovery.
- An inaccurate restart can cause excess material, a visible seam, or, in the worst case, a collision.
Best suited for: Situations where minimizing repeated printing is a priority and you are comfortable with the potential recovery risks.
Purpose: Resume from a more conservative checkpoint to reduce the risk of restarting in the middle of a movement or extrusion operation. Resume Safe uses the saved checkpoint associated with the last completed layer change rather than the exact point where the outage occurred.
Advantages
- Reduces the risk of resuming from an inconsistent toolhead or extrusion state.
- Avoids relying entirely on the checkpoint captured at the instant of the outage.
- Is the recommended starting choice for most recovery situations.
Trade-offs and limitations
- Some previously printed material may be printed again.
- Reprinting part of a layer can create a thicker area or a visible seam.
- Recovery is not guaranteed if the part moves, cools, or loses adhesion during the outage.
Best suited for: Most users who prioritize a more conservative recovery over minimizing repeated printing.
| Behavior | Resume Precise | Resume Safe |
|---|---|---|
| Recovery checkpoint | Position saved at outage detection | Last layer-change checkpoint |
| Amount of material repeated | Typically less | May repeat part of a layer |
| Recovery approach | More exact | More conservative |
| Potential visible seam | Possible | Possible |
| Recommended starting choice | Situational | Yes |
For most users, Resume Safe is the recommended starting choice because it favors a more conservative restart position.
Resume Precise may be preferable when minimizing repeated material is more important, provided you understand the potential risks.
If the outage occurs before the first layer change, the script automatically falls back to the precise checkpoint.
Important
Neither recovery mode guarantees a perfect print. The printer may lose physical position, the part may shift or cool, and the resumed print may have a visible transition line. Always test power-loss recovery with an inexpensive, noncritical print before relying on it for a valuable or lengthy print.
Warning
Centauri Carbon 2 (CC2) compatibility and recovery behavior may depend on the firmware version, GPIO configuration, and printer hardware. Verify the complete recovery process on your own printer before relying on it.
When you choose a resume option, the module does the following:
- Heats the nozzle to
move_temp(the bed and full nozzle target keep heating in the background) so a nozzle stuck to the part can release. - Marks Z at the saved height and hops up by
z_hop. - Homes X/Y with a real
G28 X Y. This avoids trusting a saved XY position that may be off by several mm due to motion lookahead. - Corrects Z for the
[homing_override]lift: it re-declares Z assaved_z + z_hop + homing_override_z_lift. - Waits for full temperatures, then runs
tray_macro(defaultMOVE_TO_TRAYoncc1), purgespurge_mmof filament and runs the wipe pattern. If notray_macrois set, this step is skipped entirely. - Travels to the saved X/Y while still elevated, then lowers to the saved Z.
- Restores extruder state by replaying the G-code file up to the resume offset to find the extrude mode (
M82/M83) and lastEvalue. It does not trust Klipper's live state. Fan and speed factor are also restored. - Reloads the file with
M23,M26andM24, and deletes the state file.
The state file contains two position packages: instant (captured at the outage) and checkpoint (captured at the last layer change). Each package is only ever used as a whole. The module never mixes position and file offset from different packages.
Where to read more:
| Topic | Link |
|---|---|
| COSMOS repository and release changelogs | OpenCentauri/cosmos and its releases |
| Installing and updating COSMOS | COSMOS: Install |
| CC2 alpha COSMOS build | OpenCentauri Discord announcement |
Where printer.cfg lives, cosmos.conf, recovery |
COSMOS: Features: "Klipper Configuration", "COSMOS settings", "Recovery" |
| Fixing config problems | COSMOS: Troubleshooting, Configuration and recovery |
| Memory and stability limits | COSMOS: Troubleshooting, Stability and memory |
| SSH login for OpenCentauri firmware | Patched firmware: Features and cc-fw-tools |
| Community help | OpenCentauri Discord |
homing_override_z_liftis printer-specific. The Z correction assumes a realG0 Z<N>inside your[homing_override]macro. If you change that macro, this value becomes silently wrong.- The wipe pattern and
MOVE_TO_TRAYare CC1 specific. The wipe coordinates are hardcoded, so the module only allowswipe: Truewithprinter_model: cc1. Setwipe: Falseto skip it, or usetray_macrofor your own sequence. - Motor and heater power during an outage is unconfirmed. The module assumes there is none and doesn't attempt an emergency retract or Z hop at outage time.
- Polling uses a small timer. The COSMOS docs warn that the stock mainboard has little spare resource (see Stability and memory). In
pollingmode the module reads the sensor everypoll_intervalseconds (default 0.01). If you see stability problems, try a larger value such as0.02. Outage detection is then delayed by up to that long. - Filesystems stay read-only until reboot. After an outage the module remounts the writable filesystems (including the USB stick) read-only and doesn't undo it. If power returns before the board dies, the printer keeps running but can't write files, so reboot it. A possible improvement is to detect power returning and reboot or remount automatically.
- A brief outage still runs the full flow. Debounce filters noise and sub-
debounce_timeflickers, but any outage longer than that triggers the save and filesystem protection even if power returns a moment later. - The resume leaves a visible seam where the print continues. This is inherent to this kind of recovery.
- The debounce re-read ioctl is unverified on this kernel. If it fails, the module saves on the edge alone.
- CC2 support is only partly tested. The pin numbers come from Elegoo's config via a standard conversion. An unplug test on one idle CC2 confirmed the outage sensor and polarity, but a save during a real print, a resume, and the charge pin haven't been verified. The CC1 defaults come from known hardware, and even those have only had limited testing.
| Symptom | Check |
|---|---|
Unknown command: POWER_LOSS_STATUS |
The overlay isn't mounted or Klipper wasn't restarted. Run ls /usr/share/klipper/klippy/extras/power_loss.py. |
detection=polling |
The ioctl tier failed. Check klippy.log for the reason, for example EBUSY if something else owns GPIO 192. |
| Resume prompt never appears | The prompt is retried for about 20 seconds after boot. Run POWER_LOSS_RESUME_SAFE manually. |
Startup error: no verified default GPIOs |
You set printer_model: custom without sensor_gpio and charge_gpio. Set them explicitly. |
| Printer can't save files after an outage | Expected: the filesystems were remounted read-only. Reboot the printer. |
| Z height wrong after resume | Verify homing_override_z_lift against your [homing_override] macro. The console prints the declared Z. |
| Save never triggers | Try invert_sensor: True, and watch readings with POWER_LOSS_TEST_READ N=100. |
| State file not written | Confirm save_path is on a writable partition. |
This project is a derivative of power_loss by jagonmo. jagonmo did the hard part, and this README, the module and the installer all follow that design. In particular, these come from the original:
- The idea and the research. Working out from Elegoo's official firmware that the Centauri Carbon can detect an outage and keep the board alive on a supercapacitor, and finding the GPIOs involved. That includes the decision never to touch the supercap-to-rail line (GPIO 203).
- The hardware test. The real power-cut test on a CC1 running COSMOS, which found 5–15 seconds of hold-up.
- The module design. The two saved position packages (
instantat the outage andcheckpointat the last layer change), and thePOWER_LOSS_RESUMEandPOWER_LOSS_RESUME_SAFEcommands. - The resume sequence. Reheating the nozzle before moving, real X/Y homing instead of trusting a saved position, the Z correction for
[homing_override], and the tray purge and wipe. - Filesystem protection. Syncing and remounting read-only instead of shutting down, because a full shutdown can leave the board needing a physical replug.
- Hard-won findings. Requesting GPIO edge events before exporting the pin through sysfs, because the kernel gives a line only one owner. Resending the resume prompt a few times after boot because the UI may not be connected yet.
- The names. The module name, the command names and the config option names.
What this version adds: printer_model profiles for CC1, CC2 and custom boards, with the CC2 pins taken from Elegoo's config. It also adds a configurable rail-pin guard, outage debounce, an atomic state save, saving only while a print is running, a configurable tray macro, a pin re-read after the debounce, and the GitHub installer.
Thank you, jagonmo.
The original credits these, and so does this project:
- Elegoo's official firmware (
por.cpp,virtual_sdcard.cpp,break_save.cpp,gpio.h), GPL-3.0, for the detection mechanism, saved-state fields and CC1 GPIO pin numbers. The CC2printer_dsp.cfg[por]section supplied the CC2 pins. - KlipperPLR (BigTreeTech, forked from Yumi-Lab/Yumi_PLR) for deriving extrude mode and the last
Evalue by replaying the G-code file. - docs.opencentauri.cc for hardware and architecture documentation.
- OpenCentauri/cosmos issue 348, where the CC1 and CC2 pin table was posted.
The original states that, because its design is based on Elegoo's GPL-3.0 files, any distribution should carry the same license. This version follows that and is distributed under the GPL-3.0. Please keep the attribution notices in the source files if you redistribute it.