Skip to content

Commit

Permalink
Merge pull request #257 from oss-slu/255-implement-motor-control-func…
Browse files Browse the repository at this point in the history
…tionality

DC Motor Support
  • Loading branch information
yrlmanoharreddy authored Oct 6, 2024
2 parents 8ebb08e + f73181a commit 0f805ac
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.opensourcewithslu.components.controllers;

import com.opensourcewithslu.outputdevices.MotorHelper;
import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.pwm.Pwm;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/motor")
public class MotorController {
private final MotorHelper MotorHelper;

public MotorController(@Named("motor") Pwm motor, @Named("pin1") DigitalOutput pin1,
@Named("pin2") DigitalOutput pin2) {
this.MotorHelper = new MotorHelper(motor, pin1, pin2);
}

@Get("/enable")
public void enableDCMotor() {
MotorHelper.enable();
}

@Get("/disable")
public void disableDCMotor() {
MotorHelper.disable();
}

@Get("/setSpeed/{speed}")
public void setSpeed(double speed) {
MotorHelper.setSpeed(speed);
}

@Get("/setClockwise/{clockwise}")
public void setClockwise(boolean clockwise) {
MotorHelper.setClockwise(clockwise);
}

@Get("/switchDirection")
public void switchDirection() {
MotorHelper.switchDirection();
}
}
//end::ex[]
13 changes: 9 additions & 4 deletions components/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,20 @@ pi4j:
provider: pigpio-pwm
initial: 0
shutdown: 0
motor:
name: Motor
address: 18
pwmType: SOFTWARE
provider: pigpio-pwm
initial: 0
shutdown: 0
fan:
name: FAN
address: 18
pwm-type: SOFTWARE
provider: pigpio-pwm
initial: 0
shutdown: 0
provider: pigpio-pwm
pwm-type: hardware


# end::pwm[]

# tag::i2c[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.opensourcewithslu.outputdevices;

import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.pwm.Pwm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Helper class to control a DC motor using PWM (Pulse Width Modulation).
* This class provides methods to enable, disable, and set the speed of a motor.
*/
public class MotorHelper {

private static Logger log = LoggerFactory.getLogger(MotorHelper.class);
private static final int FREQUENCY = 50; // Frequency for PWM signal in Hz.
private boolean isEnabled = false; // State tracking variable for the motor.
private final Pwm motor; // PWM interface for the motor.
private final DigitalOutput pin1; // GPIO pin 1 for motor direction.
private final DigitalOutput pin2; // GPIO pin 2 for motor direction.
private boolean isClockwise = true; // Direction of the motor.

/**
* Constructs a new MotorHelper.
*
* @param motor A PWM interface to control the motor.
* @param pin1 A DigitalOutput interface for the first GPIO pin.
* @param pin2 A DigitalOutput interface for the second GPIO pin.
*/
//tag::const[]
public MotorHelper(Pwm motor, DigitalOutput pin1, DigitalOutput pin2)
//end::const[]
{
this.motor = motor;
this.pin1 = pin1;
this.pin2 = pin2;
}

/**
* Enables the DC motor by setting an initial duty cycle and frequency.
* The motor remains disabled until this method is called.
*/
//tag::[method]
public void enable()
//end::[method]
{
log.info("Enabling DC motor");
motor.on(0, FREQUENCY); // Initializes PWM signal with 0% duty cycle.
isEnabled = true;
}

/**
* Disables the motor, effectively stopping any ongoing PWM signal.
*/
//tag::[method]
public void disable()
//end::[method]
{
log.info("Disabling DC motor");
motor.off(); // Stops the PWM signal.
isEnabled = false;
}

/**
* Sets the speed of the DC motor.
* This method calculates the necessary pulse width and duty cycle to achieve the specified speed.
*
* @param speed the target speed for the motor, as a percentage between 0 and 1.
*/
//tag::[method]
public void setSpeed(double speed)
//end::[method]
{
if (!isEnabled) {
log.info("You must enable the DC motor first.");
return;
}

if (speed < 0 || speed > 100) {
log.info("You must enter a speed between 0 and 100.");
return;
}

log.info("Setting motor speed to {}%", speed);

motor.on(speed, FREQUENCY);
}

/**
* Sets the direction of the DC motor.
*
* @param clockwise whether the motor should rotate clockwise.
*/
//tag::[method]
public void setClockwise(boolean clockwise)
//end::[method]
{
if (!isEnabled) {
log.info("You must enable the DC motor first.");
return;
}

log.info("Setting motor direction clockwise to {}", clockwise);
if (clockwise) {
pin1.high();
pin2.low();
} else {
pin1.low();
pin2.high();
}

isClockwise = clockwise;
}

/**
* Switches the direction of the motor.
*/
//tag::[method]
public void switchDirection()
//end::[method]
{
setClockwise(!isClockwise);
}

/**
* Sets the logger object.
*
* @param log Logger object to set the logger to.
*/
public void setLog(Logger log) {
this.log = log;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package com.opensourcewithslu.outputdevices;

import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.pwm.Pwm;
import org.junit.jupiter.api.*;
import org.slf4j.Logger;

import static org.mockito.Mockito.*;

public class MotorHelperTest {
DigitalOutput pin1 = mock(DigitalOutput.class);
DigitalOutput pin2 = mock(DigitalOutput.class);
Pwm motor = mock(Pwm.class);
MotorHelper motorHelper = new MotorHelper(motor, pin1, pin2);
Logger log = mock(Logger.class);

@BeforeEach
public void openMocks() {
motorHelper.setLog(log);
}

@Test
void enables() {
motorHelper.enable();
verify(motor).on(0, 50);
verify(log).info("Enabling DC motor");
}

@Test
void disables() {
motorHelper.disable();
verify(motor).off();
verify(log).info("Disabling DC motor");
}

@Test
void setSpeedWorksWhenEnabled() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setSpeed(10);
verify(motor).on(10.0d, 50);
verify(log).info("Setting motor speed to {}%", 10.0d);
}

@Test
void setSpeedFailsWhenDisabled() {
motorHelper.setSpeed(10);
verify(log).info("You must enable the DC motor first.");
verify(motor, never()).on(10.0d, 50);
verify(log, never()).info("Setting motor speed to {}%", 10);
}

@Test
void setSpeedFailsWhenSpeedIsNegative() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setSpeed(-10);
verify(log).info("You must enter a speed between 0 and 100.");
verify(motor, never()).on(-10.0d, 50);
verify(log, never()).info("Setting speed to {}%", -10.0d);
}

@Test
void setSpeedFailsWhenSpeedIsAbove100() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setSpeed(110);
verify(log).info("You must enter a speed between 0 and 100.");
verify(motor, never()).on(110.0d, 50);
verify(log, never()).info("Setting motor speed to {}%", 110.0d);
}

@Test
void setClockwiseTrueWorksWhenEnabled() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setClockwise(true);
verify(pin1).high();
verify(pin2).low();
verify(log).info("Setting motor direction clockwise to {}", true);
}

@Test
void setClockwiseFalseWorksWhenEnabled() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setClockwise(false);
verify(pin1).low();
verify(pin2).high();
verify(log).info("Setting motor direction clockwise to {}", false);
}

@Test
void setClockwiseFailsWhenDisabled() {
motorHelper.setClockwise(true);
verify(log).info("You must enable the DC motor first.");
verify(pin1, never()).high();
verify(pin2, never()).low();
verify(log, never()).info("Setting motor direction clockwise to {}", true);
}

@Test
void switchDirectionFromClockwiseWorksWhenEnabled() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setClockwise(true);
motorHelper.switchDirection();
verify(pin1).low();
verify(pin2).high();
verify(log).info("Setting motor direction clockwise to {}", false);
}

@Test
void switchDirectionToClockwiseWorksWhenEnabled() {
motorHelper.enable();
verify(log).info("Enabling DC motor");
motorHelper.setClockwise(false);
motorHelper.switchDirection();
verify(pin1).high();
verify(pin2).low();
verify(log).info("Setting motor direction clockwise to {}", false);
}

@Test
void switchDirectionFailsWhenDisabled() {
motorHelper.switchDirection();
verify(log).info("You must enable the DC motor first.");
verify(pin1, never()).high();
verify(pin1, never()).low();
verify(pin2, never()).high();
verify(pin2, never()).low();
verify(log, never()).info("Setting motor direction clockwise to {}", true);
verify(log, never()).info("Setting motor direction clockwise to {}", false);
}
}

0 comments on commit 0f805ac

Please sign in to comment.