Tinkercad Pid Control 【RECENT】

class PID 
  public:
    float Kp, Ki, Kd;
    float setpoint, input, output;
    float outMin, outMax;
PID(float p, float i, float d, float minOut, float maxOut) 
  Kp = p; Ki = i; Kd = d;
  outMin = minOut; outMax = maxOut;
  integral = 0.0;
  prevError = 0.0;
  prevTime = 0.0;
  firstRun = true;
float compute(float currentInput) 

private: float integral, prevError; unsigned long prevTime; bool firstRun; ;

Open Tinkercad and start a new Circuits project. Drag these components onto the breadboard:

Note: Since Tinkercad lacks a physical heater, we will simulate the plant (the heating/cooling physics) using a variable inside the Arduino code. The LED brightness will represent the "power" applied to the heater.

Add a button that, when pressed, applies a "load" by subtracting 50 from the feedback pot value (or adding a constant offset to the error). This tests how well your PID rejects disturbances.

Most PID tutorials jump straight to hardware: an Arduino Uno, a DC motor with an encoder, an H-bridge, and a pile of jumper wires. If something goes wrong (oscillations, smoke, a loose wire), debugging is a nightmare for a beginner.

Tinkercad eliminates those barriers:

In other words, Tinkercad is the ideal PID sandbox.

Open the code editor. We will write a basic PID class from scratch (no library) to understand the mechanics.

// Tinkercad PID Position Control for DC Motor
double setpoint = 0;   // Desired angle (0-1023 from pot)
double input = 0;      // Actual angle from feedback pot
double output = 0;      // PWM signal (-255 to 255) sent to motor
double lastError = 0;
double integral = 0;

// PID Gains - Start with P only double Kp = 5.0; double Ki = 0.5; double Kd = 0.8;

// Timing unsigned long lastTime = 0; double dt = 0.1; // seconds

// Motor pins const int pwmPin = 9; const int dirPin = 8;

void setup() Serial.begin(9600); pinMode(pwmPin, OUTPUT); pinMode(dirPin, OUTPUT); tinkercad pid control

// Initialize setpoint from pot (we'll update in loop)

double computePID(double setp, double inp, double dt) double error = setp - inp;

// Proportional term double Pout = Kp * error;

// Integral term with anti-windup (clamp) integral += error * dt; double Iout = Ki * integral;

// Derivative term (on error, not measurement) double derivative = (error - lastError) / dt; double Dout = Kd * derivative;

// PID output double outputRaw = Pout + Iout + Dout; lastError = error; class PID public: float Kp, Ki, Kd; float

// Constrain output to -255 to 255 (PWM range) if (outputRaw > 255) outputRaw = 255; if (outputRaw < -255) outputRaw = -255;

return outputRaw;

void motorDrive(double cmd) if (cmd >= 0) digitalWrite(dirPin, HIGH); // Forward analogWrite(pwmPin, cmd); else digitalWrite(dirPin, LOW); // Reverse analogWrite(pwmPin, -cmd);

void loop() // Read setpoint (0 to 1023) setpoint = analogRead(A0);

// Read feedback position (0 to 1023 from "coupled" pot) input = analogRead(A1);

// Time delta for derivative and integral unsigned long now = millis(); double deltaTime = (now - lastTime) / 1000.0; if (deltaTime > 0.05) // Run PID every 50ms output = computePID(setpoint, input, deltaTime); motorDrive(output); lastTime = now; Open Tinkercad and start a new Circuits project

// Debug serial plotter data
Serial.print(setpoint);
Serial.print(" ");
Serial.print(input);
Serial.print(" ");
Serial.println(output);