Math Functions

Lesson 86: Using cos() Function

Learn how cos() works with radians to build wave motion, periodic signals, and angle-based control logic.

Progress indicator

Lesson 86 of 86

Learning Objectives

  • Understand what cos() calculates and why it naturally creates smooth periodic signals.
  • Learn cos() syntax and correct angle input usage in radians.
  • Understand radians vs degrees and apply correct conversion formulas.
  • Use cos() output safely for PWM/animation by normalizing and scaling ranges.
  • Avoid common mistakes like wrong units, missing normalization, and unstable timing steps.
  • Read cosine-based LED behavior as a predictable waveform instead of random brightness changes.

Concept Explanation

What is cos()

cos() computes cosine of an angle. Cosine is a trigonometric function that produces smooth repeating values in the range -1 to 1.

This periodic behavior makes cos() useful for wave-based motion, brightness breathing effects, and cyclic control logic.

Think of cosine like a virtual wave generator inside your code. As your angle moves forward, cosine gives a value that rises and falls smoothly. That smooth rise/fall is exactly what we want for natural LED fades and repeated motion curves.

cos() Syntax

Basic syntax: cos(angleInRadians)

  • cos(0) returns 1
  • cos(PI / 2) returns near 0
  • cos(PI) returns -1

Full cosine cycle completes when angle moves from 0 to 2 * PI.

How cos() Works

  1. Take angle input (in radians).
  2. Compute cosine from trigonometric math routine.
  3. Return a floating-point value between -1 and 1.

As angle changes gradually, output also changes smoothly. That is why cosine is ideal for natural-looking transitions.

Important idea: cosine does not increase forever. It repeats in cycles. One full cycle is from 0 to 2 * PI, then the pattern repeats.

Radians vs Degrees

cos() expects radians, not degrees. Convert degrees with: radians = degrees * PI / 180.0.

  • 0 degrees = 0 rad
  • 90 degrees = PI/2 rad
  • 180 degrees = PI rad

If you pass degree numbers directly, your output shape and timing will look wrong. Most beginner cosine bugs come from unit mismatch.

cos() Return Value

Return range is from -1.0 to 1.0. For hardware outputs like PWM (0..255), normalize the value first.

Example normalization: (cosValue + 1.0) * 0.5 gives 0.0..1.0.

Then scale to output domain: normalized * 255.0 for PWM.

Without normalization, negative values can produce invalid LED output. Converting ranges correctly is the key bridge from math to hardware control.

When to Use cos()

  • Wave-style LED brightness animation.
  • Periodic control movement and timing patterns.
  • Angle-based geometry or motion formulas.
  • Smooth cyclic modulation instead of abrupt step-based changes.

Real-life ESP32 example: use cos() to create a breathing status LED that fades in and out smoothly, instead of blinking ON/OFF sharply.

Example Code

This example uses cos() to generate a smooth PWM wave for LED fading.

const int LED_PIN = 2;
float angleRad = 0.0;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  // Increase angle in radians.
  angleRad = angleRad + 0.25;
  if (angleRad > 6.283185) { // 2 * PI
    angleRad = 0.0;
  }

  float wave = cos(angleRad); // range: -1.0 to 1.0
  float normalized = (wave + 1.0) * 0.5; // range: 0.0 to 1.0
  int pwmValue = (int)(normalized * 255.0);
  pwmValue = constrain(pwmValue, 0, 255);

  analogWrite(LED_PIN, pwmValue);

  Serial.print("angle(rad): ");
  Serial.print(angleRad, 2);
  Serial.print(" | cos: ");
  Serial.print(wave, 3);
  Serial.print(" | pwm: ");
  Serial.println(pwmValue);

  delay(120);
}

Example Code Explanation

  1. angleRad is increased in fixed radian step for consistent waveform progression.
  2. After crossing 2*PI, angle resets to keep the cycle repeating.
  3. cos(angleRad) generates smooth periodic value in -1..1 domain.
  4. Output is normalized into 0..1 so negative cosine values become usable for PWM.
  5. Normalized value is scaled to 0..255 and constrained for hardware safety.
  6. analogWrite() sets LED brightness from the cosine-derived pwmValue.
  7. Serial logs show angle, trig output, and pwm for debugging and tuning.
  8. The LED appears brightest when cosine is near 1, medium around 0, and dimmest near -1 after normalization and scaling.
  9. delay(120) controls update speed; smaller delay gives smoother motion but uses more update cycles.

What Happens Inside

  1. CPU reads current angleRad from memory.
  2. CPU performs floating-point addition to increment the angle.
  3. Range guard checks if angle crossed 2 * PI; if yes, angle resets to 0.
  4. Math library computes cosine for that angle and returns a float in -1..1.
  5. Program remaps that float into 0..1 using normalization math.
  6. Program scales to 0..255 and converts to integer PWM value.
  7. Safety clamp via constrain() prevents out-of-range output.
  8. PWM register is updated through analogWrite(), changing LED duty cycle.
  9. Serial monitor prints live values so you can debug waveform behavior.
  10. Loop repeats forever, creating a continuous breathing LED pattern.
Real-life analogy: imagine turning a dimmer knob in tiny smooth steps again and again. Cosine provides those smooth steps mathematically, and PWM converts them into visible brightness.

Common Mistakes with cos()

  • Passing degree values directly without converting to radians.
  • Using cos() output directly for PWM without normalization.
  • Forgetting to wrap/reset angle, causing floating drift over very long runs.
  • Using too large angle step, producing jerky output instead of smooth waves.
  • Ignoring update interval, causing flicker or unstable visual behavior.

Best Practices for cos()

  • Keep angle in radians and document conversion when needed.
  • Normalize trig output before mapping to hardware ranges.
  • Use consistent step size and delay for stable wave animations.
  • Tune step and delay together to match desired smoothness and speed.
  • Print debug values during setup/tuning, then reduce logs for runtime performance.

Try it now

Open the simulator workspace and observe how cosine values map into smooth LED brightness changes.

Run in Simulator