If you need to convert the binary number to decimal for standard 8-bit microcontroller registers, the direct answer for the common byte 11010110 is 214. Whether you are parsing a GPIO port mask on an Arduino or reading an 8-bit I2C sensor register, base-2 to base-10 conversion is the foundational step before scaling that value to real-world electrical units. Below is the exact mathematical substitution, the assumptions that dictate your final integer, and how this math shifts when mapping binary ADC reads to AC mains voltages.

The Core Formula and Neighboring Values

The standard positional notation formula for converting an 8-bit unsigned binary string to decimal is:

D = (b7×128) + (b6×64) + (b5×32) + (b4×16) + (b3×8) + (b2×4) + (b1×2) + (b0×1)

Substituting our target values for 11010110:

  • (1×128) + (1×64) + (0×32) + (1×16) + (0×8) + (1×4) + (1×2) + (0×1)
  • 128 + 64 + 0 + 16 + 0 + 4 + 2 + 0 = 214

When debugging embedded systems, you rarely look at a single value in isolation. Here is a spec-sheet-table of neighboring values within a ±20% range (171 to 255) to help you spot off-by-one errors or bit-shift mistakes in your serial monitor output.

Binary (8-bit)DecimalHexCommon Use Case
101010111710xABLower threshold limit
101110011850xB9PWM duty cycle (~72%)
110101102140xD6Target GPIO mask / ADC byte
111100002400xF0Upper nibble mask
111111112550xFFMax 8-bit unsigned / All HIGH

What Assumptions Fix Your Decimal Answer?

Raw base-2 math assumes an unsigned integer. In embedded C++, the assumption that fixes your final decimal answer is the data type cast. If your compiler interprets 11010110 as a signed 8-bit integer (int8_t), the most significant bit (MSB) acts as a sign flag. Using Two's Complement, the decimal answer instantly shifts from 214 to -42.

Bench Tip: If your ESP32 serial monitor prints a negative number when you expect a value over 127, you are implicitly casting to a signed type. Force the compiler to treat the register as unsigned by declaring your variable as uint8_t or bitwise-ANDing it with 0xFF before printing.

Furthermore, endianness fixes the answer when dealing with 16-bit or 32-bit registers (like reading a 12-bit ADC value split across two 8-bit I2C bytes). If the sensor sends the Least Significant Byte (LSB) first, swapping the byte order will completely change your decimal output.

Scaling Binary to Mains: 120V vs 230V vs 3-Phase ADC Reads

In power electronics, converting a binary ADC read to a meaningful decimal voltage requires physical assumptions. The assumption that fixes your final real-world answer is the nominal voltage, the power factor (pf), and whether you are measuring single-phase vs 3-phase systems.

Let's look at how the decimal answer shifts when using an ESP32-WROOM-32's 12-bit ADC (0-4095 binary range) paired with a ZMPT101B voltage transformer module to measure AC mains.

  • 120V Nominal (North America): The peak voltage is ~170V. Your voltage divider scales this to the ESP32's 3.3V logic limit. A peak binary read of 111111111111 (4095) maps to 170V. A mid-point RMS calculation requires sampling the sine wave and converting the binary array to decimal to find the True RMS True RMS measurement.
  • 230V Nominal (EU/UK/AU): The peak voltage is ~325V. If you use the exact same hardware voltage divider without changing the scaling factor in your code, a binary read of 111111111111 (4095) now represents 325V. The decimal conversion math remains identical, but the multiplier applied to the decimal output shifts by a factor of 1.91.
  • 3-Phase Systems: When measuring phase-to-phase (e.g., L1 to L2) instead of phase-to-neutral, the voltage is multiplied by √3 (1.732). A 230V phase-to-neutral system yields 400V phase-to-phase. Your binary-to-decimal scaling constant must be updated to account for this phase shift, or your decimal output will read 73% lower than the actual line voltage.

Decision Tree: When Standard Conversion is Meaningless

Blindly applying the base-2 positional formula is meaningless if the binary string is not a standard integer. Use this decision-tree-table to determine the correct parsing method before attempting to convert the binary number to decimal.

Data Source / ProtocolBinary FormatWhy Standard Math FailsConcrete C++ Fix
DS3231 RTC Module (I2C)BCD (Binary Coded Decimal)Each nibble is 0-9, not 0-15. 0001 0101 is 15 in decimal, not 21.Use Wire.read() - 6 * (Wire.read() >> 4)
IEEE 754 Sensor (Modbus)32-bit FloatBits represent sign, exponent, and mantissa, not a linear integer.Use memcpy(&floatVar, &byteArray, 4)
UART Text StringASCII EncodedThe string "101" is three bytes (0x31 0x30 0x31), not the number five.Use strtol(charBuffer, NULL, 2)
Raw GPIO / I2C RegisterStandard Unsigned IntN/A - Standard math applies perfectly.Cast to uint8_t or uint16_t

Final Pick: If you are reading raw sensor registers or GPIO masks, always terminate your decision path by explicitly casting to uint8_t (for 8-bit) or uint16_t (for 12-bit ADC reads) to prevent the compiler from applying unwanted Two's Complement sign extensions.

FAQ: Edge Cases in Embedded Binary Math

Why does my ESP32 ADC binary read max out at 4095 even when I increase the voltage?

The ESP32's ADC is 12-bit, meaning the absolute maximum binary value is 111111111111 (4095 in decimal). If your input voltage exceeds the 3.3V VCC reference (or ~1.1V on some older WROOM revisions due to internal attenuation), the ADC saturates. You must add a hardware voltage divider to scale the input down before it hits the GPIO pin ESP32 ADC Oneshot Driver.

How do I handle the non-linearity of the ESP32 ADC near 0V and 3.3V?

Converting the binary number to decimal is mathematically perfect, but the physical silicon is not. The ESP32 ADC exhibits non-linearity at the extreme low and high ends of its range. To get accurate decimal voltage readings, avoid using the bottom 100 and top 100 decimal values. Design your voltage divider so your expected AC peak sits squarely in the 500 to 3500 decimal range.

What happens if I read a 12-bit ADC value into an 8-bit variable?

Truncation. If the ADC returns 101011001110 (2766 in decimal) and you store it in a uint8_t, the compiler chops off the top 4 bits. You are left with 11001110 (206 in decimal). Always use uint16_t for any ADC with a resolution higher than 8 bits.