Battery-powered Arduino projects fail in two ways: unstable wake cycles and hidden current draw. I start by listing every component in active and sleep state, then I budget power in milliamp-hours before writing firmware.
For periodic sensing, watchdog-based wake-ups are usually enough. I keep each wake window short: read sensor, validate range, transmit, then sleep immediately. Serial logging stays disabled outside development builds because UART prints quietly destroy battery life.
Hardware choices matter as much as code. Linear regulators and LED indicators can dominate idle consumption. Replacing always-on modules with switchable rails, plus selecting low-leakage sensors, gave me a bigger gain than any firmware tweak.
In deployment, I log wake count and battery voltage every 100 cycles. That creates a degradation curve I can compare between firmware versions and weather conditions.