Resolving CPU315-2DP Primary Battery Fault: OB82 Diagnostics

David Krause18 min read
S7-300SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

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.

Critical context: Many CPU 31x generation modules (and every CPU 31xC / 31x PN/DP variant) do not require a backup battery. Backup of work memory, retentive flags, counters, timers, and data blocks is performed entirely by the MMC (Micro Memory Card) inserted in the slot on the front of the CPU. A supercapacitor / ionistor on the PCB holds the hardware real-time clock for up to ~6 weeks after power-off. No battery service or replacement is required for normal retention of program and data.

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.

Identify your variant first. Open the front cover. The order number is printed on a label behind the door in the format "6ES7 315-xxxx-xAB0". Confirm the exact part number against the Siemens S7-300 module data manual before ordering any replacement part. Do not assume the variant from the visible exterior.

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:

  1. Defined a local symbol OB82_PRIM_BATT_FLT somewhere else (FC / FB) and toggled it on every OB82 call, or
  2. Copied a CPU-specific bit (e.g. the "battery low" bit from a CPU 4xx or older CPU 3xx) and re-aliased it, or
  3. 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.

Do not use a generic 1/2 AA. The cell must be a 3.6 V lithium thionyl chloride type with axial leads and the correct JST connector. Alkaline or Li-MnO2 cells have a different discharge curve and will cause premature "battery exhausted" diagnostics.

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

  1. Connect the engineering station to the CPU (MPI / PROFIBUS for the classic 315-2DP, PROFINET for the 2EH14 variant).
  2. Open STEP 7 V5.5 / V5.6 or TIA Portal V15.1+ → "Online → Online & Diagnostics".
  3. Select "Diagnostic Buffer".
  4. Click "Save As" and export the entire buffer to a .txt file.
  5. 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)

  1. Confirm the order number ends in -2AFxx-0AB0 or -1AFxx-0AB0.
  2. Order 6ES7971-1AA00-0AA0 (1 cell) or 6ES7971-1AA00-0AB0 (10-cell pack) from Siemens.
  3. 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.
  4. Open the front cover. The cell is held in a clip directly behind the MMC slot. Disconnect the JST connector, swap, reconnect.
  5. 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:

  1. Request a de-protected version of the project from the OEM, with the OB82 logic either removed or replaced by SFC 51.
  2. 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.
  3. 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.
  4. 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.
Do not delete OB82 from the CPU without first understanding why the integrator placed it there. OB82 is one of the standard error OBs. If you delete it, the CPU will go to STOP on the next diagnostic event. The integrator chose to map OB82 to a tag deliberately, possibly to capture DP slave drop events. The fix is to narrow the condition, not to delete the OB.

Verification

After the fix, the following must all be true:

  1. Diagnostic buffer contains no entry with the text "Battery" or with EV_ID W#16#430x within 24 h of operation.
  2. 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).
  3. 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.
  4. 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).
  5. 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.

Back to blog