The Direct Math: Binary to Decimal Conversion

If your specific query is how do I convert binary to decimal for the standard 8-bit sequence 10110011, the direct decimal answer is 179. The foundational formula relies on summing each bit multiplied by 2 raised to the power of its positional index, starting from 0 on the far right. Substituting the exact values from our target sequence:

(1 × 2^7) + (0 × 2^6) + (1 × 2^5) + (1 × 2^4) + (0 × 2^3) + (0 × 2^2) + (1 × 2^1) + (1 × 2^0)
= 128 + 0 + 32 + 16 + 0 + 0 + 2 + 1 = 179

In embedded electronics, we rarely convert binary just for abstract math exercises. We do it to translate raw Analog-to-Digital Converter (ADC) registers into real-world decimal measurements. Below is a reference table of neighboring 8-bit values within a ±20% range of our target (143 to 215), which is useful when debugging sensor drift or mapping byte-level serial protocols.

Binary (8-bit)Decimal ValueHex EquivalentContext / Note
100011111430x8F-20% threshold boundary
100110011530x99Common mid-low sensor read
101100111790xB3Target query value
110010002000xC8Typical 5V mapped midpoint
110101112150xD7+20% threshold boundary

Translating ADC Binary Registers to Decimal AC Voltage

When you interface a microcontroller like the ESP32-WROOM-32 with an AC voltage sensor (such as the ZMPT101B), the hardware returns raw binary data that must be converted to a decimal AC voltage. This is where pure computer science meets AC power theory.

What Assumption Fixes the Answer?

In pure base-2 math, the bit-width (8-bit, 12-bit, 16-bit) fixes the maximum decimal answer. However, in AC voltage measurement, the Reference Voltage (Vref) and the sensor step-down ratio are the assumptions that fix your final decimal voltage. If you are pushing past voltage and calculating real power (Watts) from those decimal readings, the Power Factor (PF) and the phase angle between the voltage and current waveforms become the mandatory fixing assumptions. Without them, your math is just guessing.

How the Conversion Shifts: 120V vs 230V vs 3-Phase

A 12-bit ADC yields binary values from 000000000000 to 111111111111 (decimal 0 to 4095). How that decimal 4095 maps to physical voltage shifts entirely based on your grid topology:

  • 120V Nominal Systems: The peak voltage is roughly 170V. Your sensor's onboard potentiometer is tuned so that the ADC's maximum decimal read (4095) maps to 170V. The scaling factor is 170 / 4095 = 0.0415V per bit.
  • 230V Nominal Systems: The peak voltage hits ~325V. You must adjust the sensor's voltage divider, shifting the decimal scaling factor so 4095 maps to 325V (0.0793V per bit). Applying a 120V scaling factor to a 230V grid will result in massive decimal under-reporting and potential ADC saturation.
  • 3-Phase Systems: You cannot use a single conversion channel. You must sample three distinct ADC channels and apply a 120-degree phase-shift offset to the decimal calculations. If you attempt to sum the raw decimal conversions of all three phases without vector math, the sine waves will cancel each other out near zero.

When the Conversion is Meaningless

Converting a single, instantaneous binary ADC sample into a decimal AC voltage is meaningless for determining usable mains voltage. AC is a continuous sine wave; a single snapshot might catch the zero-crossing (decimal 0) or the peak. You must sample hundreds of binary values over a full 360-degree cycle, convert them to decimal, square them, average them, and take the square root to find True RMS. Furthermore, converting decimal voltage and current into real power is entirely meaningless if the load's Power Factor (PF) is unknown, as you will only calculate Apparent Power (VA), which can be dangerously misleading for inductive loads like motors or transformers.

Practical Implementation: ESP32 ADC Scaling

The internal 12-bit SAR ADC on the ESP32 is notoriously non-linear at the extreme top and bottom of its range (near 0 and 4095). For precision AC mains decoding, experienced builders bypass the internal ADC and use an external TI ADS1115 16-bit ADC via I2C. The ADS1115 outputs a signed 16-bit integer, meaning you must handle two's complement binary for the negative half of the AC sine wave.

Here is the exact scaling math for an ADS1115 configured with a ±4.096V gain, reading a ZMPT101B sensor tuned for 230V RMS:

  1. Read Raw Binary/Hex: The I2C register returns a 16-bit signed value (e.g., decimal 24500 at the positive peak).
  2. Convert to Decimal Voltage: The ADS1115 resolution at ±4.096V is 0.125mV per bit. Multiply the decimal read by 0.000125 to get the secondary-side voltage.
  3. Apply Transformer Ratio: Multiply by the ZMPT101B's specific calibration constant (typically derived empirically, e.g., × 53.5) to yield the primary mains decimal voltage.
  4. Calculate RMS: Square each decimal sample, accumulate over 20ms (one 50Hz cycle), divide by the sample count, and take the square root. For deeper theory on this, refer to the All About Circuits RMS guide.
⚠️ Safety & Code Warning: Never connect ADC GPIO pins directly to AC mains. Always use an isolated sensor module (like ZMPT101B) or a step-down transformer. Verify isolation with a multimeter before energizing. Local electrical codes (NEC/IEC) dictate specific isolation and enclosure requirements for mains-voltage monitoring equipment.

Frequently Asked Questions

How do I convert binary to decimal in Arduino C++ without using built-in parsers?

If you are receiving raw binary strings over UART and need to avoid the overhead of strtol(), use bitwise shift operators. Initialize a decimal integer at 0. Iterate through your binary character array; for every '1', shift your accumulator left by 1 (val <<= 1) and add 1. For every '0', just shift left. This executes in a fraction of the time on an 8-bit ATmega328P compared to string-parsing libraries, which is critical when you are trying to catch high-frequency AC zero-crossings.

Why does my binary-to-decimal AC voltage reading fluctuate between 0 and 170?

This happens because you are reading instantaneous points on the AC sine wave rather than calculating True RMS. If your serial monitor prints a new decimal conversion every 10ms, you are essentially watching the sine wave peak and trough in real-time. To fix this, store the squared decimal values in an array over a full 16.67ms (60Hz) or 20ms (50Hz) window, average them, and apply the square root function (sqrt()) only once per cycle before printing to the serial monitor.

How do I handle signed binary (two's complement) when reading negative AC half-cycles?

When an external ADC like the ADS1115 measures the negative half of an AC wave, it returns a two's complement binary value. If you read the raw I2C bytes into an unsigned 16-bit integer (uint16_t), a negative voltage will appear as a massive positive decimal (e.g., 65000+). To fix this, cast the raw register data directly into a signed 16-bit integer (int16_t). The C++ compiler will automatically interpret the leading '1' bit as a negative sign, giving you the correct negative decimal value required for accurate RMS squaring.

For more details on ESP32-specific ADC behaviors and non-linearity workarounds, consult the official Espressif ADC API Documentation.