Laplace and Z-Transform Arduino PID controller

 In my previous post on using Laplace and Z-Transform for building PID controller with Arduino. In that post I provided the schematic but did not explain. So I am writing this note on the hardware interfacing aspect.

🧰 Part 1: Hardware Interfacing in Proteus

The MOTOR-ENCODER component in Proteus is used here, which simulates a DC motor with an optical encoder. Here's how to wire it to an Arduino:

✅ MOTOR-ENCODER Pin Description

PinConnect ToDescription
++12V SupplyMotor power supply
MOSFET DrainConnect to low side of MOSFET
Q1Arduino pin 9Encoder Channel A (quadrature)
Q2Arduino pin 10Encoder Channel B (quadrature)
IDXArduino pin 11Index pulse (optional)
(GND/VCC)Automatically poweredEncoder logic power (internally)

✅ MOSFET Driver (IRF540N)

Control motor speed with an IRF540N N-channel MOSFET:

MOSFET PinConnect To
GateArduino pin 5 via 220Ω
Drain terminal of motor
SourceGND
Gate→GND10kΩ pull-down resistor

✅ Power Supply

  • Motor side: +12V → + terminal of motor.

  • Arduino: USB or +5V regulated.

  • Important: Connect all GNDs together (Arduino GND, MOSFET Source, motor GND).

🔌 Interconnection Diagram


Arduino Encoder with Z transform algorithm

🧾 Part 2: Arduino Code Explanation

  • Reading encoder Q1 and Q2 as quadrature inputs to determine rotation direction and position.

  • Running a PID controller every 100 ms to regulate speed based on encoder feedback.

  • Outputting PWM to pin 5, which controls the IRF540N MOSFET (and thus the motor power).


// PID constants
float Kp = 1.2, Ki = 0.5, Kd = 0.05;
float T = 0.1; // Sampling time = 100 ms

float e[3] = {0}; // PID error buffer
float u = 0;      // PWM output

int setSpeed = 10; // target speed in counts per 100 ms

const int pwmPin = 5;   // MOSFET gate for motor control
const int Q1Pin = 9;    // Encoder Q1
const int Q2Pin = 10;   // Encoder Q2
const int IDXPin = 11;  // Encoder Index pulse (optional)

volatile long encoderCount = 0;
long lastEncoderCount = 0;

unsigned long lastTime = 0;

// Track last Q1/Q2 to detect direction
int lastQ1 = 0;
int lastQ2 = 0;

void setup() {
  pinMode(pwmPin, OUTPUT);
  pinMode(Q1Pin, INPUT);
  pinMode(Q2Pin, INPUT);
  pinMode(IDXPin, INPUT); // Optional

  Serial.begin(9600);
  Serial.println("Proteus DC Motor Encoder PID Control");
}

void loop() {
  // Quadrature decoding (called frequently to detect movement)
  updateEncoder();

  // PID loop every 100 ms
  if (millis() - lastTime >= T * 1000) {
    lastTime = millis();

    e[2] = e[1];
    e[1] = e[0];

    // Speed = encoder ticks since last sample
    long currentCount = encoderCount;
    int feedback = currentCount - lastEncoderCount;
    lastEncoderCount = currentCount;

    e[0] = setSpeed - feedback;

    float du = Kp * (e[0] - e[1]) + Ki * T * e[0] + Kd / T * (e[0] - 2 * e[1] + e[2]);
    u += du;
    u = constrain(u, 0, 255);

    analogWrite(pwmPin, (int)u);

    // Display information
    Serial.print("Position: ");
    Serial.print(encoderCount);
    Serial.print(" | Speed: ");
    Serial.print(feedback);
    Serial.print(" | PWM: ");
    Serial.print((int)u);

    // Optional: display Q1, Q2, IDX state
    Serial.print(" | Q1Q2IDX: ");
    Serial.print(digitalRead(Q1Pin));
    Serial.print(digitalRead(Q2Pin));
    Serial.println(digitalRead(IDXPin));
  }
}

// Quadrature decoder
void updateEncoder() {
  int q1 = digitalRead(Q1Pin);
  int q2 = digitalRead(Q2Pin);

  // Detect rising edge on Q1 and determine direction from Q2
  if (q1 != lastQ1) {
    if (q1 == 1) {
      if (q2 == 0) encoderCount++;  // CW
      else encoderCount--;          // CCW
    }
  }

  // Save last states
  lastQ1 = q1;
  lastQ2 = q2;
}

✅ What You Can Observe in Proteus

SignalWhere to Watch
Encoder pulsesOscilloscope or logic probe on Q1/Q2
PWM dutyPin 5 (MOSFET gate)
Motor behaviorMotor symbol animation
Encoder countArduino serial monitor

🔚 Summary

  • Use Q1 and Q2 for quadrature decoding — no interrupts needed for moderate speed simulation.

  • Use PID to regulate motor speed by adjusting PWM output.

  • Connect Q1/Q2 to Arduino pins 9 and 10 as inputs.

  • Use pin 5 as PWM output to gate of IRF540N MOSFET.

  • Ensure all grounds are common in simulation.


Post a Comment

Previous Post Next Post