Signed binary is a digital representation system that uses the most significant bit (MSB) as a sign indicator and typically employs Two's Complement math to encode both positive and negative integers within a fixed bit-width. When you write firmware for an ESP32 or Arduino to read physical sensors, understanding this concept is not just an academic exercise. It dictates whether your control loop correctly reads a regenerative braking current of -10A or hallucinates a massive positive surge of 65526A, which will immediately trigger a false overcurrent fault and shut down your system.

The Core Mechanics: Two's Complement vs. Unsigned

In standard unsigned binary, every bit represents a positive power of two. An 8-bit register can hold values from 0 to 255. However, physical circuits frequently measure bipolar phenomena: temperatures below freezing, batteries discharging versus charging, or motors spinning forward versus reverse. To represent negative numbers without adding a dedicated "minus sign" wire to every data bus, digital systems use the MSB as a sign flag.

Think of a mechanical car odometer that rolls backwards. If you are at 000000 and roll back one mile, the dials flip over to 999999. In a 3-digit base-10 system, 999 effectively represents -1. Two's complement works exactly like this in base-2, allowing the microcontroller's Arithmetic Logic Unit (ALU) to use the exact same addition circuitry for both addition and subtraction.

Binary Representation Ranges and Bit Patterns
Data Type Bit Width Value Range Hex / Binary Example (-10)
Unsigned Integer (uint8_t) 8-bit 0 to 255 N/A (Cannot represent -10)
Signed Integer (int8_t) 8-bit -128 to +127 0xF6 / 11110110
Unsigned Integer (uint16_t) 16-bit 0 to 65,535 N/A (Cannot represent -10)
Signed Integer (int16_t) 16-bit -32,768 to +32,767 0xFFF6 / 1111111111110110
Signed Integer (int32_t) 32-bit -2.14B to +2.14B 0xFFFFFFF6

Notice how the negative value -10 requires all the higher-order bits to be set to 1 when expanded from 8-bit to 16-bit. This is called sign extension, and failing to account for it is the root cause of 90% of signed binary bugs in embedded C++.

Worked Example: Bidirectional Current Sensing with the INA219

Let us look at a real-world scenario using the Texas Instruments INA219 bidirectional current and power monitor. This IC is ubiquitous in battery management systems (BMS) and solar charge controllers because it can measure current flowing in both directions.

The INA219 stores its current measurement in a 16-bit signed Two's Complement I2C register. Suppose your shunt resistor is calibrated such that the Least Significant Bit (LSB) represents 1mA. Your motor controller enters a regenerative braking state, pushing -2.5A (or -2500mA) back into the battery pack.

The Math:
Target Value: -2500
16-bit Signed Binary: 11110110 00111100
Hexadecimal: 0xF63C

The Firmware Bug: If your Arduino or ESP32 code reads this I2C register into an unsigned 16-bit integer (uint16_t) instead of a signed one (int16_t), the microcontroller ignores the sign bit. It interprets 0xF63C as the positive decimal value 63,036. Your firmware now believes the motor is drawing 63 Amps. Your PID control loop will panic, assume a dead short, and instantly shut off the MOSFETs.

The Fix: Always declare the receiving variable as a signed integer. Furthermore, when manually combining two 8-bit I2C bytes into a 16-bit variable, cast the MSB to a signed type before bit-shifting, or use a union to let the compiler handle the Two's Complement mapping safely.

// Incorrect: Results in 63036 for negative currents
uint16_t raw_current = (Wire.read() << 8) | Wire.read();

// Correct: Preserves the Two's Complement sign bit
int16_t raw_current = (int16_t)((Wire.read() << 8) | Wire.read());

Where You Meet Signed Binary in Practice

Understanding what signed binary changes in a real circuit comes down to recognizing which sensors cross a zero-threshold. If a sensor only measures magnitude (like a basic light dependent resistor), unsigned is fine. If it measures direction or relative difference, you are dealing with signed data.

  • Temperature Sensors (e.g., DS18B20, LM75): These output signed 16-bit or 12-bit values. When the ambient temperature drops below 0°C, the MSB flips to 1. If your weather station code uses unsigned math, a winter night at -5°C will be logged as a boiling 4091°C.
  • IMUs and Accelerometers (e.g., MPU6050): Gyroscopes and accelerometers output signed 16-bit integers for the X, Y, and Z axes. Tilt the board left, you get a positive integer; tilt it right, the value crosses zero into negative territory.
  • H-Bridge Motor Control: When generating PWM signals for an H-bridge, a signed error signal from a PID controller tells the firmware which direction to drive the current. A positive error drives the high-side MOSFETs on the left; a negative error drives the right.

Common Confusions and Firmware Pitfalls

The most frequent error hobbyists make is confusing Two's Complement with Sign-Magnitude representation. In Sign-Magnitude, the MSB is literally just a minus sign attached to a normal binary number (e.g., 10000001 means -1). While intuitive for humans, Sign-Magnitude creates two distinct zeros (+0 and -0) and requires complex, separate hardware circuitry for subtraction. Two's Complement has only one zero and allows the ALU to simply add numbers together, even when subtracting. For a deeper dive into the hardware logic gates that make this possible, All About Circuits provides an excellent breakdown of binary arithmetic at the silicon level.

Another massive pitfall is Integer Promotion in C/C++. As detailed in the C++ reference on arithmetic types, when you perform math on 8-bit signed integers (int8_t), the compiler automatically promotes them to standard 16-bit or 32-bit int types to prevent overflow during the calculation. If you bit-shift a negative 8-bit value without explicitly casting it back down, the sign bit extends into the higher bytes, resulting in wildly incorrect math.

Frequently Asked Questions

Q: What is signed binary in one sentence?
A: Signed binary is a fixed-width digital encoding method that uses the most significant bit to indicate polarity and Two's Complement math to represent negative integers.

Q: What does it change in a real circuit or installation?
A: It dictates how microcontrollers, ADCs, and digital sensors parse bipolar physical data (like reverse current or sub-zero temperatures), preventing massive positive calculation errors when physical values drop below zero.

Q: What do people commonly confuse it with?
A: Makers frequently confuse Two's Complement with Sign-Magnitude encoding, or they fail to distinguish between signed integer underflow and unsigned integer overflow when writing C++ firmware for 8-bit and 16-bit registers.