12 Stepper Motors: Drivers and Motion
More
Depth: Practitioner
Progress saves as you read. Mark sections complete as you go; your progress appears in the sidebar.
12.1 Overview
This section: Overview — This first route builds counted motion from motor fundamentals through drivers, current, and acceleration.
This first route builds counted motion from motor fundamentals through drivers, current, and acceleration.
This is part 1 of 2. Continue with Stepper Motors: Precision and Reliability for the second focused route.
12.2 Start With the Story
This section: Start With the Story — Picture a label feeder that must move one sheet, stop at the print line, and return home after a jam.
Prove the Motion, Not Just the Pulse Count
Picture a label feeder that must move one sheet, stop at the print line, and return home after a jam. An actuator is a part that turns an electrical command into physical action. Here the action is counted rotation, but a count sent by the controller is not proof that the shaft or label moved.
Write the full motion promise. Name the travel, load, speed, power source, driver, home point, safe end stops, and owner. State whether a missed step only spoils a label or could hurt a person or machine.
Test a cold start, a warm driver, a sudden load, a fast change of speed, a blocked shaft, lost power, and a restart away from home. Measure the final position and current as well as the command count. Check that the machine finds home again and reports a miss instead of carrying an unknown position forward.
Keep immediate travel limits outside a remote service. The local machine must stop safely even when its dashboard or wider network is late.
This opening does not choose a motor size or promise that open-loop counting is always enough. Practitioner turns load and travel into a driver and motion plan. Under the Hood examines coil current, step shapes, resonance, heat, torque loss, and when feedback is needed.
Use a short motion check. Run one slow move, one fast move, one blocked move, and one restart away from home. Record the command, current, final place, heat, miss, and recovery. Repeat it after the load or speed changes.
Imagine a feeder that must move a gate exactly 12 millimetres, then return to the same home point every time. The actuator story is not “make the shaft spin”; it is “count motion, avoid missed steps, hold position, and recover if the load slips.”
Stepper motors fit that story when discrete movement and repeatability matter. The driver current, acceleration ramp, homing method, torque margin, and missed-step evidence are part of the actuator, not optional extras.
- Stepper Motor Operation: A brushless DC motor that moves in discrete angular steps by sequentially energizing coils; each step is a fixed angle (0.9, 1.8, or 3.6 degrees typically); enables precise open-loop position control without a position sensor
- Step Modes: Full step (commonly two phases energized): coarse resolution and higher torque than one-phase wave drive; half step (alternating one and two phases): twice the command resolution with varying torque; microstepping (controlled currents in adjacent phases): finer command resolution, not guaranteed positional accuracy. TI stepper drive guide
- Stepper Motor Driver IC: Dedicated ICs (A4988, DRV8825, TMC2208) that handle the coil energization sequence, current limiting, and microstepping; accept simple STEP/DIR logic signals from the MCU, simplifying firmware to just controlling pulse rate and direction
- H-Bridge Driver Boundary: Bipolar steppers need bridge switches that reverse current through each coil; older dual H-bridge chips such as L293D expose the coil-pair logic directly, while modern chopper drivers hide that switching behind STEP/DIR pins
- Holding Torque: The torque a stepper motor exerts when powered but stationary to resist external forces trying to move the shaft; enables passive position holding without a brake; drops significantly when power is removed (detent torque is much lower)
- Steps Per Revolution: The number of full steps to complete one full rotation; a standard 200-step motor (1.8 degree per step) needs 200 steps for 360 degrees; with 16x microstepping, this becomes 3200 microsteps per revolution
- Resonance and Mid-Frequency Instability: At certain speeds, the step frequency matches the rotor’s natural mechanical resonance frequency, causing vibration, noise, and missed steps; mitigated by microstepping, mechanical damping, or driving through the resonant speed range quickly
- Reference Current (Vref) Setting: Stepper drivers like A4988 and DRV8825 require setting the maximum coil current via a potentiometer (Vref); incorrect Vref causes overheating (too high) or insufficient torque and missed steps (too low); calculate from motor’s rated current per phase
- Acceleration Profiles: Ramping step frequency from low to high (acceleration) and high to low (deceleration) prevents step loss at high speeds; the maximum speed without losing steps depends on load, current setting, and supply voltage; libraries like AccelStepper implement acceleration and deceleration with trapezoidal speed profiles
Learning Objectives
This section: Learning Objectives
- Describe stepper motor construction and differentiate full-step, half-step, and microstepping sequences
- Control stepper motors with ULN2003 and A4988/DRV8825 drivers
- Implement acceleration profiles to prevent missed steps
- Apply the AccelStepper library to generate smooth trapezoidal motion profiles
- Configure microstepping for increased resolution
- Calculate torque, resolution, and travel time when sizing stepper motors for precision applications
A stepper motor moves in tiny, precise clicks — like the second hand on a clock ticking from one mark to the next. Each electrical pulse makes the motor rotate by exactly one small step (often just 1.8 degrees). By counting these steps, you always know exactly where the motor is positioned without needing any additional sensors. This is why stepper motors are used in 3D printers and CNC machines where precise movement is essential.
This chapter has four connected stops:
- First you build the mental model: discrete steps, open-loop counting, construction, and driver role.
- Then you turn that model into control wiring: ULN2003 sequences and STEP/DIR driver control.
- Next you size a real motion: microstepping, torque margin, current limits, and acceleration profiles.
- Finally you test the failure modes: missed steps, overheating, precision limits, and the evidence needed before trusting the axis.
Checkpoints recap the main decisions. Deep dives, calculators, and labs are optional breathers for testing the numbers.
12.3 Stepper Motor Fundamentals
This section: Stepper Motor Fundamentals — Stepper motors move in discrete steps, providing precise position control without feedback sensors (open-loop control).
Stepper motors move in discrete steps, providing precise position control without feedback sensors (open-loop control).
Think of a stepper motor like a clock’s second hand that can only move to specific tick marks. Here’s what happens with each electrical pulse:
Step 1: Energize First Coil - Electricity flows through coil A, creating a magnetic field that pulls the rotor’s permanent magnet teeth to align with coil A’s poles. The rotor snaps to position 0°.
Step 2: Switch to Next Coil - Coil A turns off, coil B turns on. The magnetic field shifts 90°, and the rotor follows, snapping to position 90° (or 1.8° for a 200-step motor).
Step 3: Continue the Sequence - By energizing coils in order (A → B → C → D → A…), the rotor steps around the circle precisely. Each pulse = one fixed angular movement.
Real-World Analogy: Imagine a gear with 200 teeth locked between 4 electromagnets positioned around a circle. Turn on the north electromagnet, and the gear’s nearest tooth snaps to it. Turn off north, turn on east — the gear rotates exactly one tooth. No encoder needed; you count pulses and know the exact position.
Why No Feedback Needed? Each step is mechanically fixed by the motor’s tooth count and coil positions. Send 100 pulses → rotor moves exactly 100 steps (unless it skips due to overload).
Characteristics:
- Precise angular positioning (typically 1.8 deg/step = 200 steps/rev)
- Open-loop control (no encoder needed)
- High holding torque at standstill
- Step-by-step movement (can be jerky at low speeds)
- Higher power consumption than servos
12.3.1 Construction And Motor-Type Selection
Do not select a stepper from the package photo alone. The useful design question is whether the physical job needs counted position, continuous speed, integrated feedback, or a simple angle command, then whether the motor, driver, supply, wiring, and software can carry the required torque.
A small permanent-magnet stepper exposes the same construction ideas that appear in larger hybrid steppers: rotor cups or toothed rotor poles attached to a permanent-magnet shaft, stator coils and poles around that rotor, shaft bearings that keep the rotor aligned, and a housing plus wire harness that bring the coil phases to the driver. The driver board is not optional decoration; it translates low-power controller signals into the coil current sequence that makes the rotor align one step at a time.
Use this comparison as a first-pass selection record before choosing a part:
| Candidate | Typical fit | Selection caution |
|---|---|---|
| Stepper motor | Low-cost counted positioning, high repeatability, and holding torque where medium speed is acceptable. | Needs a driver, current setting, acceleration ramp, and homing or feedback when missed steps matter. |
| DC motor | Low-cost, high-speed continuous rotation for fans, wheels, pumps, and simple mechanisms. | Without an encoder or process feedback it gives speed effort, not position proof. |
| DC motor with encoder | Higher-speed motion where actual speed, distance, or position must be measured. | The motor driver may stay simple, but encoder wiring, evidence handling, and control software become part of the design. |
| Servo motor | Compact angle control with built-in feedback for moderate speed and torque jobs. | Rotation range, stall torque, supply current, mounting, and end stops must match the linkage. |
For all four choices, check supply voltage, running and startup current, torque margin, driver rating, mechanical stops, and the evidence that proves the output moved as intended.
A NEMA 17 stepper with 200 steps/revolution moves per step. With a lead screw (2mm pitch), one full rotation moves the carriage mm, so each step moves mm = 10 micrometers. At 1/16 microstepping (3200 steps/rev), resolution becomes mm = 0.625 micrometers per microstep. To move 50mm requires full steps. At 800 steps/s, travel time is s.
This section:
Checkpoint: Counted Motion
You now know:
- A common stepper gives 200 full steps per revolution, so one full step is 1.8 degrees.
- With a 2 mm lead screw, one 200-step revolution moves 2 mm, so one full step moves 0.01 mm.
- At 1/16 microstepping, the same 200-step motor exposes 3200 commanded microsteps per revolution, but torque margin still decides whether the load actually follows.
The counting math is only useful if the electronics can reverse and limit coil current correctly. The next section makes that driver boundary explicit.
12.3.2 H-Bridge Driver Boundary
A stepper driver is the power spine between the microcontroller and the motor coils. The controller pins are only logic signals; the driver contains transistor switches that route real coil current from the motor supply. Current through a coil creates a magnetic field, and changing the current path changes the field that pulls the rotor toward the next aligned position.
For a bipolar stepper, think of the driver as two H-bridges: one bridge for coil X and one bridge for coil Y. Driving one diagonal switch pair sends current through a coil in one direction; driving the opposite diagonal pair reverses that current and swaps the coil’s north/south polarity. That is the physical reason a sequence of logic states makes the rotor rotate instead of merely energizing a random winding.
Older dual H-bridge chips make that boundary visible. On an L293D-style part, VCC1 powers the logic side, VCC2 powers the motor side, EN-1,2 and EN-3,4 enable the two bridge channels, and the outputs connect to coil X and coil Y. The controller must share ground with the driver logic, but it must not supply the motor current directly.
One simple full-step bridge sequence can be recorded like this:
| Step | X | Xbar | Y | Ybar | Physical result |
|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 1 | Coil X and coil Y are driven in their first polarity pair. |
| 2 | 1 | 0 | 0 | 1 | Coil X reverses while coil Y stays in the first polarity. |
| 3 | 1 | 0 | 1 | 0 | Coil Y reverses, advancing the magnetic alignment again. |
| 4 | 0 | 1 | 1 | 0 | Coil X reverses back while coil Y holds the second polarity. |
Different driver boards rename the pins, but the review question is the same: which device owns coil current, which supply powers the motor, which logic pins choose bridge polarity, and what proof shows the sequence rotates the shaft without overheating the driver.
12.3.3 Step Sequences
Full-Step Sequence (28BYJ-48 with ULN2003):
| Step | IN1 | IN2 | IN3 | IN4 |
|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 0 |
| 2 | 0 | 1 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 |
| 4 | 0 | 0 | 0 | 1 |
Half-Step Sequence (smoother, double resolution):
| Step | IN1 | IN2 | IN3 | IN4 |
|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 0 |
| 2 | 1 | 1 | 0 | 0 |
| 3 | 0 | 1 | 0 | 0 |
| 4 | 0 | 1 | 1 | 0 |
| 5 | 0 | 0 | 1 | 0 |
| 6 | 0 | 0 | 1 | 1 |
| 7 | 0 | 0 | 0 | 1 |
| 8 | 1 | 0 | 0 | 1 |
You have now seen the coil sequence directly. The next two examples show how that same idea appears in the small 28BYJ-48 hobby motor and the higher-current NEMA 17 driver stack.
12.4 28BYJ-48 with ULN2003
This section: 28BYJ-48 with ULN2003 — Read across the forms as engineering evidence.
The photographs below make stepper motor (28byj-48 with uln2003 driver) a physical comparison: look for changes in package, exposed interfaces, mounting, scale, and service access before treating the forms as interchangeable.
Read across the forms as engineering evidence. They share a capability name, but packaging and installation change the electrical, mechanical, environmental, and maintenance constraints.
The 28BYJ-48 is a popular small stepper for hobby projects. Inspect Figure 12.1 to see the motor and driver as a matched current-path pair before using the library example.
In Figure 12.1, follow the coloured winding leads into the ULN2003 channels, then return to the geared output shaft. Sequencing the windings creates steps, while the gearbox trades speed for torque and changes the effective steps per output revolution used in the code.
Specifications:
- Full steps per output revolution: 2048 nominally (with a 64:1 gearbox)
- Operating voltage: 5V DC
- Current: 200-300mA
- Full-step angle: 11.25 deg/64 = 0.18 deg nominally; gearbox ratio may vary and needs calibration
#include <AccelStepper.h>
// 28BYJ-48 at nominal 64:1, HALF4WIRE = 4096 half-steps per output revolution
AccelStepper stepper(AccelStepper::HALF4WIRE, 19, 5, 18, 17);
const int STEPS_PER_REV = 4096;
void setup() {
Serial.begin(115200);
stepper.setMaxSpeed(1000); // Steps per second
stepper.setAcceleration(500); // Steps per second^2
Serial.println("Commands: 0-360 = angle, h = home, f = full rotation");
}
void loop() {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input == "h") {
stepper.moveTo(0); // Home
} else if (input == "f") {
stepper.move(STEPS_PER_REV); // Full rotation
} else {
int angle = input.toInt();
if (angle >= 0 && angle <= 360) {
stepper.moveTo((long)angle * STEPS_PER_REV / 360); // Go to angle
Serial.printf("Moving to %d degrees\n", angle);
}
}
}
stepper.run(); // Must be called frequently — handles acceleration
}
12.5 NEMA 17 with A4988/DRV8825
This section: NEMA 17 with A4988/DRV8825 — For higher performance, NEMA 17 steppers with A4988 or DRV8825 drivers are a common choice.
For higher performance, NEMA 17 steppers with A4988 or DRV8825 drivers are a common choice. Inspect Figure 12.2 before copying a current setting, because the frame size identifies mechanical mounting rather than the winding’s electrical rating.
In the photo Figure 12.2, locate the square mounting face, shaft, and four-wire lead. Those features establish the mechanical interface and two-phase connection, but not a universal current limit; the actual winding current and driver cooling requirements must come from the motor and driver data.
Carry that distinction into the specifications: first confirm step angle and phase current from the actual motor, then set the A4988 or DRV8825 current limit, choose microstepping for the motion requirement, and test supply sag and driver temperature under the real acceleration profile. The frame label alone answers none of those electrical questions.
NEMA 17 Specifications:
- Steps per revolution: 200 (1.8 deg/step)
- Holding torque: around 40 N·cm (about 4 kgf·cm) for the example motor; check the chosen motor datasheet
- Phase current and winding voltage: use the chosen motor datasheet (for example, 1.7 A/phase at 2.8 V for Pololu #2267)
- Driver supply: may be 12–24 V with a compatible current-limited driver; set the phase-current limit to the motor rating
A4988 Driver Features:
- Microstepping: 1, 1/2, 1/4, 1/8, 1/16
- Current limit adjustment
- Sleep mode for power saving
- Step/direction interface
Microstepping Settings:
| MS1 | MS2 | MS3 | Resolution | Steps/Rev |
|---|---|---|---|---|
| 0 | 0 | 0 | Full step | 200 |
| 1 | 0 | 0 | 1/2 step | 400 |
| 0 | 1 | 0 | 1/4 step | 800 |
| 1 | 1 | 0 | 1/8 step | 1600 |
| 1 | 1 | 1 | 1/16 step | 3200 |
#include <AccelStepper.h>
#define STEP_PIN 25
#define DIR_PIN 26
#define ENABLE_PIN 27
// NEMA 17 with 1/16 microstepping = 3200 steps per revolution
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
const int STEPS_PER_REV = 3200;
void setup() {
Serial.begin(115200);
pinMode(ENABLE_PIN, OUTPUT);
digitalWrite(ENABLE_PIN, LOW); // Enable driver (active LOW)
stepper.setMaxSpeed(3000); // Steps per second
stepper.setAcceleration(1000); // Steps per second^2
Serial.println("NEMA 17 Stepper Ready");
}
void loop() {
if (Serial.available()) {
char cmd = Serial.read();
switch(cmd) {
case 'f': // Forward one revolution
stepper.move(STEPS_PER_REV);
break;
case 'b': // Backward one revolution
stepper.move(-STEPS_PER_REV);
break;
case 'h': // Home position
stepper.moveTo(0);
break;
case 's': // Stop
stepper.stop();
break;
case 'd': // Disable (power saving)
digitalWrite(ENABLE_PIN, HIGH);
break;
case 'e': // Enable
digitalWrite(ENABLE_PIN, LOW);
break;
}
}
stepper.run();
}
This section:
Checkpoint: Driver Choice
You now know:
- A 28BYJ-48 uses 2048 nominal full steps or 4096 nominal half-steps per output revolution at a 64:1 gearbox ratio; calibrate the actual motor.
- ULN2003-style boards expose the coil sequence; A4988 and DRV8825 boards hide it behind STEP, DIR, and current-limit settings.
- A NEMA 17 at 1/16 microstepping changes a 200-step revolution into 3200 commanded microsteps, but the current limit and supply voltage still set the usable torque.
This section:
12.6 Acceleration Profiles
This section: Acceleration Profiles — Treat acceleration as a torque-budget sequence rather than a cosmetic smoothing option.
Treat acceleration as a torque-budget sequence rather than a cosmetic smoothing option. Start from rest, where the driver must build phase current and overcome static friction. Increase step rate only while the motor’s available torque remains above load torque, reflected inertia, and friction. Hold the requested cruise rate inside the motor’s falling torque-speed envelope, then decelerate early enough that the load does not carry the rotor past commanded steps. A light bench shaft may tolerate an abrupt command that a lead screw, camera carriage, or valve cannot. Test the worst payload and supply voltage, record missed-step or homing evidence, and reduce acceleration before reducing position verification. This connects the profile directly to the chapter’s warning that commanded step count is not proof of achieved motion.
Steppers cannot instantly change speed. Attempting to start at full speed causes missed steps because the rotor can’t keep up with the magnetic field changes.
Trapezoidal velocity profile:
- Acceleration phase: Gradually increase speed
- Constant velocity: Maintain max speed during travel
- Deceleration: Gradually decrease speed to prevent overshoot
The AccelStepper library handles this automatically!
Scenario: You need to move a 3D printer’s Z-axis platform weighing 2 kg through 200 mm of travel using a lead screw with 8 mm pitch (one revolution = 8 mm linear travel).
Step 1 — Calculate required revolutions:
- Total travel: 200 mm
- Lead screw pitch: 8 mm/rev
- Revolutions needed: 200 / 8 = 25 revolutions
Step 2 — Calculate required steps (NEMA 17 at 1/16 microstepping):
- Steps per revolution: 200 full steps x 16 microsteps = 3,200
- Total steps: 25 x 3,200 = 80,000 steps
Step 3 — Calculate linear resolution:
- Resolution per microstep: 8 mm / 3,200 = 0.0025 mm (2.5 micrometers)
- This exceeds typical 3D printing needs (50-100 micrometers per layer)
Step 4 — Calculate required torque:
- Force to lift 2 kg: F = m x g = 2 x 9.81 = 19.62 N
- Lead screw torque: T = F x pitch / (2 x pi x efficiency)
- Assuming 40% efficiency: T = 19.62 x 0.008 / (2 x 3.14159 x 0.4) = 0.0625 Nm = 6.25 Ncm
- With a 2× design margin: 12.5 N cm; choose a NEMA 17 motor only after checking its actual torque-speed curve exceeds this demand at the intended speed.
Step 5 — Estimate travel time at 1,000 steps/sec max speed with 500 steps/sec^2^ acceleration:
- Acceleration time to max speed: t_accel = v_max / a = 1000 / 500 = 2 seconds
- Acceleration distance: s_accel = 1/2 × a × t^2^ = 0.5 x 500 x 4 = 1,000 steps
- Deceleration distance: s_decel = 1,000 steps (same)
- Constant-speed distance: 80,000 - 2,000 = 78,000 steps
- Constant-speed time: t_const = 78,000 / 1000 = 78 seconds
- Total time: 2 seconds (accel) + 78 seconds (constant) + 2 seconds (decel) = 82 seconds for 200 mm travel
Stepper motors provide open-loop positioning, but many IoT applications combine them with closed-loop PID controllers for higher reliability. When a stepper drives a process variable (temperature via a mixing valve, flow rate via a metering pump), the PID controller commands position changes while the stepper executes them precisely. See PID Control Fundamentals for the control theory behind this pairing.
// Manual trapezoidal profile (if not using AccelStepper)
void moveWithAcceleration(int targetSteps, int maxSpeed, int acceleration) {
int currentSpeed = 0;
int position = 0;
int direction = (targetSteps > 0) ? 1 : -1;
targetSteps = abs(targetSteps);
// Calculate distances for accel/decel phases
int accelSteps = (maxSpeed * maxSpeed) / (2 * acceleration);
int decelSteps = accelSteps;
int constSteps = targetSteps - accelSteps - decelSteps;
if (constSteps < 0) {
// Can't reach max speed, use triangular profile
accelSteps = targetSteps / 2;
decelSteps = targetSteps - accelSteps;
constSteps = 0;
maxSpeed = sqrt(2 * acceleration * accelSteps);
}
// Acceleration phase
for (int i = 1; i <= accelSteps; i++) {
currentSpeed = sqrt(2 * acceleration * i);
step(direction);
delayMicroseconds(1000000 / currentSpeed);
}
// Constant speed phase
for (int i = 0; i < constSteps; i++) {
step(direction);
delayMicroseconds(1000000 / maxSpeed);
}
// Deceleration phase
for (int i = decelSteps; i > 0; i--) {
currentSpeed = sqrt(2 * acceleration * i);
step(direction);
delayMicroseconds(1000000 / currentSpeed);
}
}
This section:
Checkpoint: Motion Budget
You now know:
- The worked Z-axis example needs 25 revolutions, or 80,000 microsteps, to move 200 mm with an 8 mm lead screw at 1/16 microstepping.
- The chapter’s 2 kg load, 40% screw efficiency, and 2× design margin give 12.5 N cm; check the chosen motor’s torque-speed curve at the required travel speed.
- The 1,000 steps/s and 500 steps/s^2 profile gives 82 seconds for the 200 mm move, so travel time is part of the actuator evidence.
This section: — Sizing the move is not the finish line.
Sizing the move is not the finish line. The same current and speed choices create the common failure modes that follow.
12.7 Common Pitfalls
This section: Common Pitfalls
The Mistake: Setting the stepper driver current limit to the motor’s rated current (e.g., 2.0A) without considering that stepper motors are rated for maximum holding torque at stall, not continuous operation.
Why It Happens: Datasheets list “rated current per phase” which represents the maximum the motor can handle when stationary with proper heat sinking.
The Fix: Start with 70-80% of rated current (e.g., 1.4-1.6A for a 2.0A motor) and increase only if torque is insufficient. Monitor motor temperature after 30 minutes of continuous operation - the case should not exceed 70-80C.
The Mistake: Assuming a stepper motor will always reach the commanded position without feedback, then discovering position errors accumulate over time.
Why It Happens: Stepper motors are marketed as “precise” (1.8 deg/step), creating false confidence. In reality, missed steps from overloading, mechanical binding, or acceleration too fast cause cumulative drift.
The Fix: For precision applications, add encoder verification or use limit switches for homing/calibration routines.
12.8 Continue to Part 2
This section: Continue to Part 2 — Continue with Stepper Motors: Precision and Reliability.
Continue with Stepper Motors: Precision and Reliability.
Find help
3 reviewed answers.
Where should I start in a module?
Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.
Modules and pathsReviewed
What can I try when a project does not work?
Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.
When you are stuckReviewed
How do interactive examples work?
Use the interactive guide to check how examples and simulations work before changing your project.
Interactive examples guideReviewed
