Problem Description
On a Siemens SIMATIC S7-300 CPU 315-2DP (order number block 6ES7 315-xxxx-xxxx), operators report a recurring or intermittent "Primary Battery" fault. The fault is reported through the diagnostic interrupt OB82 and is wired in the project to set a tag such as "allarme_batteria_plc" via the assignment pattern A #OB82_PRIM_BATT_FLT = "allarme_batteria_plc". In some installations the alarm appears immediately after power-on; in others it appears randomly during operation. Engineers who do not see an external battery compartment on the CPU are confused, because the S7-300 line is widely known as a "battery-backed" family.
The fault almost never indicates a real discharged backup cell on a current-generation 315-2DP. The Primary Battery detection is generated by one of three mechanisms: residual diagnostic logic carried over from an older project, a real but invisible backup battery (1/2 AA, 3.6 V lithium) that has reached end-of-life, or another OB82-triggering fault that has been masked by the battery tag.
Hardware Background: CPU 315-2DP and Its Variants
The order number 6ES7 315-xxxx-xxxx covers several firmware generations. The two relevant families for the Primary Battery fault are the legacy battery-equipped blocks and the current MMC-only blocks:
| Order number | Family | Internal battery holder | MMC slot |
|---|---|---|---|
| 6ES7 315-1AFxx-0AB0 | Original (early generation) | Yes (1× 1/2 AA lithium) | No (FEPROM) |
| 6ES7 315-2AFxx-0AB0 | CPU 315-2DP, classic | Yes (1× 1/2 AA lithium) | No (FEPROM) |
| 6ES7 315-2AG10-0AB0 | CPU 315-2DP | No | Yes (MMC required to run) |
| 6ES7 315-2AH14-0AB0 | CPU 315-2DP, current | No | Yes |
| 6ES7 315-2AJ13-0AB0 | CPU 315-2DP, extended temperature | No | Yes |
| 6ES7 315-2EH14-0AB0 | CPU 315-2 PN/DP | No | Yes |
The "no external battery" observation is consistent with the 2006+ generations (2AG10 / 2AH14 / 2AJ13 / 2EH14). If you can read the full order number from the front label and the production date code is post-2005, the CPU has no user-serviceable battery at all. The Primary Battery diagnostic bit is therefore spurious.
On the older 2AFxx-0AB0 the holder is internal (a 1/2 AA lithium thionyl chloride cell, ~3.6 V, accessed by removing the front cover behind the MMC slot). That cell is used only for clock backup when the MMC is removed and the supercapacitor has discharged; it is also the source of the only true "Battery exhausted" diagnostic event that the CPU can raise.
Understanding OB82 – Diagnostic Interrupt
OB82 is called by the CPU operating system when a module reports a diagnostic event over the backplane or the DP / PN interface. In STEP 7 V5.x and TIA Portal V13 and later, OB82 carries a fixed 20-byte local data set:
| Local byte | Name (German / English) | Meaning |
|---|---|---|
| LB0 / LB1 | OB82_EV_CLASS / EV_CLASS | Event class: B#16#39 entering, B#16#38 leaving |
| LB2 / LB3 | OB82_FLT_ID / FLT_ID | Fault ID: B#16#42 channel fault, B#16#43 / B#16#44 diagnostic interrupt entering/leaving |
| LB4..LB7 | OB82_PRIORITY / PRIORITY | Priority class (26 in default configuration) |
| LB8..LB11 | OB82_OB_NUMBER / OB_NUMBER | OB number 82 |
| LB12..LB13 | OB82_RESERVED_1 | Reserved |
| LB14..LB15 | OB82_IO_FLAG | I/O flag: 0 = module, 1 = submodule |
| LB16..LB17 | OB82_MDL_ADDR / MDL_ADDR | Logical base address of the faulting module |
| LB18..LB19 | OB82_MDL_DEFECT | Module defect (bit 0 = true) |
| LB20..LB21 | OB82_RACK_CPU / RACK_CPU | Rack / slot of CPU |
| LB22..LB25 | OB82_RESERVED_2 | Reserved |
| LB26..LB27 | OB82_DATE_TIME / DATE_TIME | Time stamp (8-byte S7 date-and-time format) |
The temporary OB82_FLT_ID tells you whether the interrupt came from a real channel fault (B#16#42) or from a diagnostic interrupt entering / leaving (B#16#43 / B#16#44). It does not, by itself, encode a "primary battery low" condition. Battery status on the S7-300 is reported separately through the diagnostic buffer of the CPU and through status bits in the system status list (SZL) – it is normally visible as a buffer entry with text "Battery exhausted – come" / "Battery exhausted – go", not as a per-module channel fault.
The variable referenced in the original code, OB82_PRIM_BATT_FLT, is therefore a project-specific symbol – it is not a system-supplied local in the standard S7-300 OB82 interface. Most likely the programmer has either:
- Defined a local symbol
OB82_PRIM_BATT_FLTsomewhere else (FC / FB) and toggled it on every OB82 call, or - Copied a CPU-specific bit (e.g. the "battery low" bit from a CPU 4xx or older CPU 3xx) and re-aliased it, or
- Mapped the input-fault bit from a CPU 948 / CPU 928 template, where a "primary battery" bit was genuinely generated by the firmware.
On every 315-2DP generation, the truth of a primary-battery condition is read out of the diagnostic buffer (Online in STEP 7 / TIA Portal under "CPU → Diagnostic Buffer") or out of the system status list SZL ID W#16#x112 / W#16#0011. If those sources do not show a battery event, the OB82_PRIM_BATT_FLT tag is being driven by something else.
Root Cause Analysis
Three independent failure paths are observed in the field. Treat them in order of probability for the symptom as described ("appears randomly, project is locked").
Cause 1 – No battery in this CPU, residual code driving the tag
The most common explanation. The project was originally written for an older S7-300 CPU with a battery (e.g. a 314-1AFxx or a 315-2AFxx) and was downloaded unchanged to a current-generation 315-2DP that has no battery. Every time OB82 fires, the tag is set. OB82 also fires for many reasons unrelated to a battery: a plugged / unplugged SM, a wire-break on a 6ES7 331 analog module, a DP slave drop, a hot-swap of a module on a hot-swap-capable ET 200M, an EMC event on the backplane, a momentary loss of 24 V on a 6ES7 321 digital input module. Because OB82 is also called when the event leaves, the tag is alternately set and cleared, which matches the "randomly on / randomly off" report.
Diagnostic check: open STEP 7 / TIA Portal online → CPU → Diagnostic Buffer. The buffer will show real fault entries (module removed, channel error, etc.). The buffer will not show a "primary battery" entry. If you see module / IO events but no battery events, Cause 1 is confirmed.
Cause 2 – Real battery, real end-of-life condition
Only relevant for the 6ES7 315-2AFxx-0AB0 and the early 6ES7 315-1AFxx-0AB0. The internal 1/2 AA lithium thionyl chloride cell has a typical service life of ~5 years at 25 °C. Symptoms:
- Real-time clock loses more than a few seconds per day after power-off.
- Diagnostic buffer entries "Battery exhausted – come" / "Battery exhausted – go".
- SF LED lights steady or blinks at a specific pattern (consult the S7-300 system manual for the exact blink code of the order number in use).
Replacement cell: Siemens part number 6ES7971-1AA00-0AA0 (1× 1/2 AA, 3.6 V, ~1.0 Ah, lithium thionyl chloride, lead-wire assembly with JST connector). Always replace with the CPU powered on to keep the supercapacitor / MMC backed; on a hot-swap-capable segment, swap on a configured spare slot.
Cause 3 – Another diagnostic event is calling OB82
The user program reacts to the tag, not to the buffer. If a digital input module loses 24 V for 200 ms (a brown-out of the load supply while CPU power is fine), the module will report a channel diagnostic that calls OB82 with EV_ID W#16#39 and FLT_ID B#16#42. The user's program sets the "battery" tag, but the actual cause is a brown-out elsewhere on the rack.
Diagnostic check: in the diagnostic buffer, sort by time and look for entries with text "Channel fault", "Wire break", "Sensor supply short circuit", or "Module removed / inserted". If you find them clustered around the same minute as the battery alarm, Cause 3 is confirmed.
Resolution: Resolve the Fault
Apply the steps in order. Each step is sufficient on its own if the root cause is unique; the most reliable field practice is to do Steps 1, 3, and 4, then re-evaluate. Step 2 applies only to the battery-equipped variants.
Step 1 – Read the full diagnostic buffer
- Connect the engineering station to the CPU (MPI / PROFIBUS for the classic 315-2DP, PROFINET for the 2EH14 variant).
- Open STEP 7 V5.5 / V5.6 or TIA Portal V15.1+ → "Online → Online & Diagnostics".
- Select "Diagnostic Buffer".
- Click "Save As" and export the entire buffer to a .txt file.
- Look for any entry with the text "Battery", "Buffer battery", "Backup battery", or the event ID W#16#4301 / W#16#4302 / W#16#23xx range.
If no battery event is present, jump to Step 3. If a battery event is present and the CPU is the battery-equipped variant, go to Step 2.
Step 2 – Replace the internal backup cell (battery-equipped variants only)
- Confirm the order number ends in -2AFxx-0AB0 or -1AFxx-0AB0.
- Order 6ES7971-1AA00-0AA0 (1 cell) or 6ES7971-1AA00-0AB0 (10-cell pack) from Siemens.
- The MMC alone is sufficient to retain program and data for an indefinite time, so the cell can be swapped with the power removed; data retention falls back to MMC. To keep the clock alive, perform the swap with power on.
- Open the front cover. The cell is held in a clip directly behind the MMC slot. Disconnect the JST connector, swap, reconnect.
- Power on. Clear the diagnostic buffer (Online → Clear / Reset). Acknowledge any "Battery exhausted – come" event.
Step 3 – Locate the source of the OB82 call
Open the cross-reference for the symbol OB82_PRIM_BATT_FLT and the tag "allarme_batteria_plc". The cross-reference will show every block that writes either. In the field case, the writer is the same FC / FB that is called by OB82. If the block is parameterized to write the tag on every OB82 call – regardless of FLT_ID, MDL_ADDR, or the EV_CLASS direction (coming / going) – that is the bug.
Insert an online monitor (watch table) on the input bits and on the output of the assignment. Toggle the relevant bits. Confirm whether "allarme_batteria_plc" follows OB82 only or follows other events as well. A common false trigger is the rack-fault (SF) LED on an SM with a wire break on channel 0 of a 6ES7 331-7KF02 – the channel-fault event calls OB82 even when the user program is not monitoring analog diagnostics.
Step 4 – Clean the legacy logic
If the program is editable (the user reports the project is locked; see Step 5), apply one of the following corrections depending on the project layout:
Option A – Delete the assignment. If the tag is only driven by OB82 and the tag has no consumer (no HMI alarm, no write to the SCADA), delete A #OB82_PRIM_BATT_FLT = "allarme_batteria_plc" entirely.
Option B – Gate the assignment on the system status list. Replace the unconditional assignment with a conditional one that only fires on a real battery event. Use SFC 51 "RDSYSST" to read SZL W#16#x112 at restart or in a cyclic OB:
// STL – CPU 315-2DP, STEP 7 V5.5+
CALL "RDSYSST"
REQ :=TRUE
SZL_ID :=W#16#311
INDEX :=W#16#0001
RET_VAL :=#ret
BUSY :=#busy
SZL_HEADER:=
DR :=#dr
// First 4 bytes of DR for SZL W#16#311 / index W#16#0001
// contain the battery status word:
// bit 0 = "Battery exhausted"
// bit 1 = "Battery not installed"
A #dr[0]; // battery status word LSB
AN M 100.1; // bit 1 = battery not installed (mask out for MMC-only CPUs)
= "allarme_batteria_plc";
Call SFC 51 in OB35 (cyclic interrupt, default 100 ms) or in OB1 (one scan per restart). The OB82-based assignment is removed. Battery monitoring is now driven by a polled read, with no spurious OB82 side-effect.
Option C – Use SFC 51 at startup only. If the system runs without OB35, call SFC 51 in OB100 (warm restart) and latch the result into a retentive flag. This is the minimum-invasive change to a project that is otherwise untouched.
// SCL – OB100
IF "FirstScan" = FALSE THEN
"FirstScan" := TRUE;
"RDSYSST_DB".REQ := TRUE;
"RDSYSST_DB".SZL_ID := W#16#311;
"RDSYSST_DB".INDEX := W#16#0001;
"RDSYSST_DB".RET_VAL := 0;
"RDSYSST_DB".BUSY := FALSE;
"RDSYSST_DB".DR[0] := 0;
CALL "RDSYSST" , "RDSYSST_DB";
"allarme_batteria_plc" := ("RDSYSST_DB".DR[0] AND W#16#0001) <> 0;
END_IF;
Step 5 – Handle the locked project
The user explicitly states the project cannot be edited (password-protected by the integrator / OEM). The legitimate options are:
- Request a de-protected version of the project from the OEM, with the OB82 logic either removed or replaced by SFC 51.
- If the OEM is no longer available, request support from Siemens Industry Online Support under the original project reference. Siemens cannot recover lost passwords but can provide a re-flash procedure that allows a fresh project to be loaded – the existing program will be lost, so this is a last resort.
- Suppress the tag at the HMI / SCADA level. Most HMI alarm systems (WinCC, WinCC Flexible, FactoryTalk View, TIA Portal HMI) allow you to disable a discrete alarm by tag without touching the PLC program. The PLC will still set the bit, but no operator-facing alarm is generated.
- Move the alarm handling to a different bit. In OB1, copy the inverse of the offending tag to a new tag
"allarme_batteria_plc_OK"and raise the operator alarm on the negation. This is a hack and is not recommended for safety-relevant plants, but it stops nuisance alarms in non-safety processes.
Verification
After the fix, the following must all be true:
- Diagnostic buffer contains no entry with the text "Battery" or with EV_ID W#16#430x within 24 h of operation.
- Tag
"allarme_batteria_plc"stays FALSE continuously (or TRUE continuously, if the plant's intended state is "battery low" – verify the integrator's intent from the HMI configuration). - OB82 is called on a real diagnostic event (e.g. pull a digital input module hot-swap) and the integrator's downstream logic still works.
- No SF / BF LED is lit. On a 315-2DP, SF is on the front; BF1 is the first PROFIBUS interface, BF2 is the second. A steady SF LED on power-up after the fix is a sign the diagnostic buffer was not cleared (Online → Clear / Reset).
- Real-time clock drift is below 5 s/day after a 1 h power-off (only relevant for battery-equipped variants).
Edge Cases and Related Faults
Edge case A – Random / intermittent appearance
This is the strongest signal of Cause 1. OB82 is called both for an event arriving (OB82_EV_CLASS = B#16#39) and for the same event leaving (OB82_EV_CLASS = B#16#38). A program that sets the tag on either call will appear to "blink". Most often the real event is a DP slave drop, a wire-break on a 6ES7 331 analog input, or a momentary loss of 24 V sensor supply on a 6ES7 321 digital input module.
Edge case B – Project locked + integrator unreachable
See Step 5. The HMI / SCADA suppression path is the only non-invasive fix. Note that suppressing the alarm removes the only operator-visible signal that the PLC has a real diagnostic event; the SF LED on the CPU must still be checked daily by maintenance.
Edge case C – Replacement CPU, new order number
If the CPU was replaced in the last 1–5 years, the new module is almost certainly the -2AH14-0AB0 or -2AJ13-0AB0 (no battery). The diagnostic buffer will show no battery event; the project lock is the only obstacle. HMI suppression is a valid interim fix; a long-term fix requires the OEM to deliver a current project file.
Edge case D – MMC missing or corrupted
The MMC is mandatory for all CPU 31x generation firmware ≥ 2.x. If the MMC is missing, the CPU will go to STOP with diagnostic buffer "MMC not inserted". The MMC also stores the diagnostic buffer and the project password. A corrupted MMC may produce a spurious "Battery exhausted – come" entry on every restart. Replace the MMC (6ES7 953-8Lxxx-0AA0 family) only with a Siemens-approved MMC; third-party SD-to-MMC adapters are not supported and may brick the CPU.
Edge case E – Safety-integrated plant
On a F-CPU (CPU 315F-2DP, 6ES7 315-6FFxx-0AB0) or on a plant classified SIL 2 / 3, do not suppress the alarm at the HMI. Battery monitoring is one of the implicit prerequisites for retention of the safety program. Suppression of a real battery low is a SIL violation. Replace the cell, fix the project, or escalate to the safety integrator.
Spare Parts and Order Numbers
| Item | Order number | Notes |
|---|---|---|
| CPU 315-2DP, no battery, current production | 6ES7 315-2AH14-0AB0 | Default for new builds |
| CPU 315-2DP, no battery, extended temperature | 6ES7 315-2AJ13-0AB0 | -25 °C to +60 °C |
| CPU 315-2 PN/DP, no battery | 6ES7 315-2EH14-0AB0 | PROFINET variant |
| CPU 315-2DP, with battery, legacy | 6ES7 315-2AFxx-0AB0 | Battery-equipped, FEPROM |
| Backup battery 1/2 AA, 3.6 V | 6ES7971-1AA00-0AA0 (1×) / -0AB0 (10×) | Lithium thionyl chloride |
| MMC 512 KB | 6ES7 953-8LF20-0AA0 | Minimum for typical 315-2DP projects |
| MMC 2 MB | 6ES7 953-8LJ30-0AA0 | For larger programs |
| MMC 4 MB | 6ES7 953-8LL20-0AA0 | For large projects / many DBs |
| Front connector, 40-pin | 6ES7 392-1AM00-0AA0 | Screw-type |
Cross-check the exact part number against the current Siemens catalog (Mall / Industry Online Support) before placing an order. Discontinued variants may still be available through Siemens spare-parts services for 10+ years after end of production.
Diagnostic Buffer Quick Reference
| Buffer text fragment | Meaning | Action |
|---|---|---|
| "Battery exhausted – come" | Battery voltage below threshold (battery-equipped variant) | Replace cell 6ES7971-1AA00-0AA0 |
| "Battery exhausted – go" | Battery voltage recovered | No action; verify after a power cycle |
| "MMC not inserted" | MMC missing on startup | Insert MMC; cycle power |
| "MMC error" | MMC corrupted or unsupported | Replace MMC with Siemens-approved type |
| "Module removed" / "Module inserted" | Hot-swap event on ET 200M or S7-300 rack | Verify against maintenance work; reset diagnostic buffer |
| "Channel fault" | Wire break, sensor short, over-range | Check field wiring for the indicated slot / channel |
| "DP slave failure" | PROFIBUS slave drop | Check bus terminator, baud rate, slave address, cable |
| "Station failure" | PROFINET device drop | Check device name, IP, topology |
Diagnosis Flow
The decision path for a Primary Battery alarm on a 315-2DP is:
Start
|
+-- Read order number on front label
| |
| +-- -2AFxx or -1AFxx (battery-equipped)? --> Check SZL W#16#311
| | |
| | +-- Battery exhausted in buffer? --> Replace cell 6ES7971-1AA00
| | +-- No battery event? --> Continue
| |
| +-- -2AG10 / -2AH14 / -2AJ13 / -2EH14 (MMC-only)? --> Continue
|
+-- Open Online & Diagnostics --> Diagnostic Buffer
| |
| +-- Look for non-battery events clustered around the alarm time
| | +-- DP slave / channel fault / module removed? --> Fix root cause (Cause 3)
| |
| +-- No real events? --> Cause 1 (legacy code)
|
+-- Is the project editable?
|
+-- Yes --> Apply Option A / B / C from Step 4
+-- No --> Apply HMI suppression or escalate to OEM (Step 5)
Confirm with the verification checklist (5 items) before closing the work order. The fix is in the project, not in the hardware, for 9 of 10 cases observed in the field.
Does the CPU 315-2DP have a backup battery?
It depends on the order number. The -2AFxx-0AB0 and -1AFxx-0AB0 generations have an internal 1/2 AA lithium holder. The -2AG10-0AB0, -2AH14-0AB0, -2AJ13-0AB0, and -2EH14-0AB0 generations have no battery – all backup is done by the MMC and a supercapacitor for the real-time clock. Read the order number off the front label to confirm.
What does the OB82 variable OB82_PRIM_BATT_FLT actually mean?
It is not a system-supplied local variable in the standard OB82 interface on the S7-300. The standard interface is OB82_EV_CLASS, OB82_FLT_ID, OB82_MDL_ADDR, OB82_MDL_DEFECT, OB82_RACK_CPU, and OB82_DATE_TIME. OB82_PRIM_BATT_FLT is a project-specific tag (often carried over from a CPU 948 or 928 template) that the integrator defined in the project; the integrator is the only source of truth for its meaning.
How do I unlock a password-protected STEP 7 project without losing the program?
Siemens cannot recover a lost STEP 7 V5.x project password. The only safe path is to request an unlocked copy from the OEM / integrator. If the OEM is no longer available, you must rebuild the project from documentation (or accept that the program will be replaced) and load a fresh project. Do not attempt to brute-force the password; the S7-300 password check is implemented in firmware and is intentionally rate-limited to make guessing impractical.
Can I just delete OB82 to stop the alarm?
No. Deleting OB82 causes the CPU to go to STOP on the next diagnostic event – the standard reaction to a missing error OB is STOP. The correct fix is to narrow the condition that writes "allarme_batteria_plc" (e.g. gate the assignment on the SZL battery status word via SFC 51) or to suppress the alarm at the HMI / SCADA layer.
Why does the alarm appear randomly and not continuously?
Because OB82 is called both when a diagnostic event arrives (OB82_EV_CLASS = B#16#39) and when it leaves (OB82_EV_CLASS = B#16#38). A program that sets the tag on either call will follow the real event's on / off cycle, which is normally driven by an intermittent fault such as a DP slave drop, a wire-break, or a momentary loss of 24 V sensor supply. Read the diagnostic buffer to identify the real event, and either fix the underlying electrical issue or filter the assignment.