10 - Output Devices

Group assignment:

Measure the power consumption of an output device.

The multimeter is everyone’s best friend. Important to have steady hands to determine the voltage drop and current usage. P=VI. Bueno.

More details can be found here:

https://academany.fabcloud.io/fabacademy/2025/labs/barcelona/students/group-assignments/

Individual assignment and learnings

DC Motor with a fan

I wanted to control the motor through the PWN, ramping the speed up and down in pulses with a simple circuit :

|

(VCC) ---> (Fan +)
|
[Drain]  (N-channel MOSFET)
|
[Source] --- GND
|
Pin 17 ---> [Gate] --- [Pull-down Resistor] ---> GND

Added a code to vary the max PWN value so the speed goes in waves :

#include <Arduino.h>

#define FAN_PIN 17         // GPIO pin connected to the MOSFET gate
#define PWM_FREQUENCY 1000  // PWM frequency in Hz
#define MAX_PWM 255         // Maximum PWM value (8-bit)

int pwmValue = 0;  // Initial PWM value
int rampSpeed = 5; // Speed of the ramp-up/down (lower is faster)
bool rampUp = true; // Flag to check whether we are ramping up or down

void setup() {
  pinMode(FAN_PIN, OUTPUT);  // Set the FAN_PIN as output
}

void loop() {
  // Write the current PWM value to the fan
  analogWrite(FAN_PIN, pwmValue);

  // Ramp up the PWM value gradually
  if (rampUp) {
    pwmValue += rampSpeed;
    if (pwmValue >= MAX_PWM) {
      pwmValue = MAX_PWM;
      rampUp = false;  // Start ramping down
    }
  }
  // Ramp down the PWM value gradually
  else {
    pwmValue -= rampSpeed;
    if (pwmValue <= 0) {
      pwmValue = 0;
      rampUp = true;  // Start ramping up
    }
  }
if (pwmValue >= MAX_PWM) {
  pwmValue = MAX_PWM;
  rampUp = false;
  delay(1000);  // Pause at full speed for 1 second
}

if (pwmValue <= 0) {
  pwmValue = 0;
  rampUp = true;
  delay(1000);  // Pause at 0 speed for 1 second
}
  delay(30);  // Delay for a smooth transition (adjust for speed of ramp)
}

Here is the video:

Passe Purée Electrique

Why?

Having worked in professional kitchens and cooking dinners for family, I really appreciate a good purée, tomato or curry sauce. A key step is to pass it through a passe purée, or when missing a sieve with the help of a metal spoon. This is fine in small quantities but more cumbersome as the number of guests increases.

In the pizzeria I worked puréeing the tomatoes would take 10 -15 minutes and was a nice little exercise, at least while I’m still young. Christmas dinner for 30 required mash potato, it was quite the task to passe purée!

In India, making the curry sauces silky smooth sometimes requires passing the curry sauce through a a blender and a sieve one cooked. The larger restaurants have a machine to do this, but it’s rather expensive, and overkill for smaller numbers.

Figure 1: traditional passe purée.

So this week, I’d like to design and make an electric passe purée, perhaps inspired from the clay paste printer, that uses a piston to push through the clay through a fine nozzle. However, this time having replaceable sieves in lieu of the nozzles.

Figure 2: First sketch of electric sieve

Figure 3: Components for the sieve

Unfortunately I won’t be able to print out the cylinder in the lab as none of the machines have been exclusively used for food safety, I’m therefore limited to standard sizes at the hardware store.

At first glance, standard plumbing seem best suited for this application.

Learning to use a Stepper motor with the Barduino

For this task I decided to use the DRV8825 Stepper Driver as we had it in the Lab here in BCN. I had a look on some forums but decided I would try my luck with Google Gemini this week.

Here is the conversation I had:

Circuit Diagram :

  +3.3V (Barduino)
   |
   |
 [Barduino]
/  |   |   \\
S1  S2  DIR  STEP
|   |   |    |
|   |   |    |
[Switch1] [Switch2]
\ /     \ /
|       |
|       |
PIN1    PIN12
|       |
[10kΩ]  [10kΩ]
|       |
GND ----------------------------------------->  Barduino GND
|
|
[DRV8825]
|   |   |   |
A1  A2  B1  B2 ----> Stepper Motor Windings
|
VMOT ----> +5V Power Supply
|
GND ----------------------------------------->  +5V Power Supply GND, Barduino GND
|
SLEEP/RESET ------> +3.3V

Above you have an image of this circuit put together with the help of a bread board and hereafter is the first attempt at the Barduino code to control the motor going forward and back:

const int switch1Pin = 1;  // Switch 1 is connected to GPIO pin 1
const int switch2Pin = 12; // Switch 2 is connected to GPIO pin 12
const int stepPin = 11;    // DRV8825 Step pin is connected to GPIO pin 11
const int dirPin = 18;     // DRV8825 Direction pin is connected to GPIO pin 18

void setup() {
  Serial.begin(115200);
  // Set pin modes for switches, step, and direction
  pinMode(switch1Pin, INPUT_PULLDOWN); // Use pull-down resistor for Switch 1
  pinMode(switch2Pin, INPUT_PULLDOWN); // Use pull-down resistor for Switch 2
  pinMode(stepPin, OUTPUT);           // Step pin is an output to send step pulses
  pinMode(dirPin, OUTPUT);           // Direction pin is an output to control motor direction
}

void loop() {
  // Read the states of the switches
  int switch1State = digitalRead(switch1Pin);
  int switch2State = digitalRead(switch2Pin);

  // Control motor direction and movement based on switch states
  if (switch1State == LOW && switch2State == HIGH) {
	  Serial.println("switch1State == LOW && switch2State == HIGH");
    // If Switch 1 is not pressed and Switch 2 is pressed, rotate clockwise
    digitalWrite(dirPin, HIGH); // Set direction to clockwise
    moveStepper(1);             // Move one step
  } else if (switch1State == HIGH && switch2State == LOW) {
    Serial.println("switch1State == HIGH && switch2State == LOW");
    // If Switch 1 is pressed and Switch 2 is not pressed, rotate counter-clockwise
    digitalWrite(dirPin, LOW);  // Set direction to counter-clockwise
    moveStepper(1);             // Move one step
  } else {
    // If both switches are pressed or neither is pressed, stop the motor
    return;
  }
}

// Function to move the stepper motor a specified number of steps
void moveStepper(int steps) {
  for (int i = 0; i < steps; i++) {
    // Generate a pulse on the step pin for each step
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000); // Adjust for motor speed
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000); // Adjust for motor speed
  }
}

Checking the driver data sheet before launching the code, we noticed that a capacitor was missing:

I managed to get the stepper turning in one direction, with the help of adding an LED flashing light when the button works. However, I have not managed to get it working in both direction as of yet.

Barduino turning the stepper in one direction.

Moving a stepper with the Koji v7 board and Xiao ESP32S3

I asked chatgpt the following prompt :

💡

So I currently have this code :
const int switch1Pin = 1; // Switch 1 is connected to GPIO pin 1
const int switch2Pin = 12; // Switch 2 is connected to GPIO pin 12
const int stepPin = 11; // DRV8825 Step pin is connected to GPIO pin 11
const int dirPin = 18; // DRV8825 Direction pin is connected to GPIO pin 18

void setup() {
Serial.begin(115200);
// Set pin modes for switches, step, and direction
pinMode(switch1Pin, INPUT_PULLDOWN); // Use pull-down resistor for Switch 1
pinMode(switch2Pin, INPUT_PULLDOWN); // Use pull-down resistor for Switch 2
pinMode(stepPin, OUTPUT); // Step pin is an output to send step pulses
pinMode(dirPin, OUTPUT); // Direction pin is an output to control motor direction
}

void loop() {
// Read the states of the switches
int switch1State = digitalRead(switch1Pin);
int switch2State = digitalRead(switch2Pin);

// Control motor direction and movement based on switch states
if (switch1State == LOW && switch2State == HIGH) {
Serial.println("switch1State == LOW && switch2State == HIGH");
// If Switch 1 is not pressed and Switch 2 is pressed, rotate clockwise
digitalWrite(dirPin, HIGH); // Set direction to clockwise
moveStepper(1); // Move one step
} else if (switch1State == HIGH && switch2State == LOW) {
Serial.println("switch1State == HIGH && switch2State == LOW");
// If Switch 1 is pressed and Switch 2 is not pressed, rotate counter-clockwise
digitalWrite(dirPin, LOW); // Set direction to counter-clockwise
moveStepper(1); // Move one step
} else {
// If both switches are pressed or neither is pressed, stop the motor
return;
}
}

// Function to move the stepper motor a specified number of steps
void moveStepper(int steps) {
for (int i = 0; i < steps; i++) {
// Generate a pulse on the step pin for each step
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000); // Adjust for motor speed
digitalWrite(stepPin, LOW);
delayMicroseconds(1000); // Adjust for motor speed
}
}

I want to modify it so that instead of a switch the direction of the motor is determined whether a potentiometer goes clockwise or anti-clockwise.

The pins for the DIR and STEP are D1 and D0 respectively. The CLK on the potentiometer is connected to D5 and DT is connected to D4.

The result :

You're using a rotary encoder, not a regular potentiometer. Rotary encoders have CLK (clock) and DT (data) pins that change state as you turn the knob — this allows you to detect direction (clockwise or counter-clockwise) and movement.

Here’s how to modify your code to read the encoder and control the stepper motor accordingly. We'll use interrupts to detect encoder rotation direction and then step the motor in real time.

Updated Code (for Rotary Encoder on D5 = CLK, D4 = DT; DIR = D1, STEP = D0):

// Rotary Encoder pins
const int clkPin = D5;  // CLK connected to D5
const int dtPin = D4;   // DT connected to D4

// Stepper motor pins
const int stepPin = D0; // STEP connected to D0
const int dirPin = D1;  // DIR connected to D1

volatile int lastClkState;
volatile bool rotateCW = false;
volatile bool rotateCCW = false;

void setup() {
  Serial.begin(115200);

  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  lastClkState = digitalRead(clkPin);

  // Optionally attach interrupt to CLK pin for more responsive turning
  attachInterrupt(digitalPinToInterrupt(clkPin), readEncoder, CHANGE);
}

void loop() {
  if (rotateCW) {
    rotateCW = false;
    Serial.println("Clockwise");
    digitalWrite(dirPin, HIGH);
    moveStepper(1);
  }

  if (rotateCCW) {
    rotateCCW = false;
    Serial.println("Counter-Clockwise");
    digitalWrite(dirPin, LOW);
    moveStepper(1);
  }
}

// Interrupt Service Routine for encoder
void readEncoder() {
  int clkState = digitalRead(clkPin);
  int dtState = digitalRead(dtPin);

  if (clkState != lastClkState) {
    if (dtState != clkState) {
      rotateCW = true;
    } else {
      rotateCCW = true;
    }
  }
  lastClkState = clkState;
}

void moveStepper(int steps) {
  for (int i = 0; i < steps; i++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
}

I need to modify the code as the Xiao pins are D0, D1, D4 and D5 (already modified in the code given above.

I had to find the correct combination of wires for the A1 A2 B1 and B2 pins on the driver so that the motor turns correctly. When in the wrong pins the motor can move but it is not in a controlled manner nor often in the desired direction, it almost shakes.

In order to find the correct order, I crossed 2 of the 4 wires together. If they are a pair they will add resistance to the turning of the motor when turning by hand otherwise it is loose. Once the first pair is found these are put in A1 and A2 then the other two in B1 and B2. The order doesn't seem to matter as long as they are a pair.

The stepper motor requires at least 8V otherwise it doesn't draw current. This was provided by a DC Lab Power Supply.

The reference voltage is set on the driver using a multimeter and a screwdriver to turn the screw on the driver. 0.7-0.9V worked appropriately. This sets an appropriate current limit.

Here is a video of me turning the rotary encoder and the stepper motor moving in one direction, then turning the rotary encoder in the opposite direction and the stepper motor turning in the other direction.

Success.