gobot.io/x/gobot/v2@v2.1.0/drivers/gpio/motor_driver.go (about)

     1  package gpio
     2  
     3  import (
     4  	"gobot.io/x/gobot/v2"
     5  )
     6  
     7  // MotorDriver Represents a Motor
     8  type MotorDriver struct {
     9  	name             string
    10  	connection       DigitalWriter
    11  	SpeedPin         string
    12  	SwitchPin        string
    13  	DirectionPin     string
    14  	ForwardPin       string
    15  	BackwardPin      string
    16  	CurrentState     byte
    17  	CurrentSpeed     byte
    18  	CurrentMode      string
    19  	CurrentDirection string
    20  }
    21  
    22  // NewMotorDriver return a new MotorDriver given a DigitalWriter and pin
    23  func NewMotorDriver(a DigitalWriter, speedPin string) *MotorDriver {
    24  	return &MotorDriver{
    25  		name:             gobot.DefaultName("Motor"),
    26  		connection:       a,
    27  		SpeedPin:         speedPin,
    28  		CurrentState:     0,
    29  		CurrentSpeed:     0,
    30  		CurrentMode:      "digital",
    31  		CurrentDirection: "forward",
    32  	}
    33  }
    34  
    35  // Name returns the MotorDrivers name
    36  func (m *MotorDriver) Name() string { return m.name }
    37  
    38  // SetName sets the MotorDrivers name
    39  func (m *MotorDriver) SetName(n string) { m.name = n }
    40  
    41  // Connection returns the MotorDrivers Connection
    42  func (m *MotorDriver) Connection() gobot.Connection { return m.connection.(gobot.Connection) }
    43  
    44  // Start implements the Driver interface
    45  func (m *MotorDriver) Start() (err error) { return }
    46  
    47  // Halt implements the Driver interface
    48  func (m *MotorDriver) Halt() (err error) { return }
    49  
    50  // Off turns the motor off or sets the motor to a 0 speed
    51  func (m *MotorDriver) Off() (err error) {
    52  	if m.isDigital() {
    53  		err = m.changeState(0)
    54  	} else {
    55  		err = m.Speed(0)
    56  	}
    57  	return
    58  }
    59  
    60  // On turns the motor on or sets the motor to a maximum speed
    61  func (m *MotorDriver) On() (err error) {
    62  	if m.isDigital() {
    63  		err = m.changeState(1)
    64  	} else {
    65  		if m.CurrentSpeed == 0 {
    66  			m.CurrentSpeed = 255
    67  		}
    68  		err = m.Speed(m.CurrentSpeed)
    69  	}
    70  	return
    71  }
    72  
    73  // Min sets the motor to the minimum speed
    74  func (m *MotorDriver) Min() (err error) {
    75  	return m.Off()
    76  }
    77  
    78  // Max sets the motor to the maximum speed
    79  func (m *MotorDriver) Max() (err error) {
    80  	return m.Speed(255)
    81  }
    82  
    83  // IsOn returns true if the motor is on
    84  func (m *MotorDriver) IsOn() bool {
    85  	if m.isDigital() {
    86  		return m.CurrentState == 1
    87  	}
    88  	return m.CurrentSpeed > 0
    89  }
    90  
    91  // IsOff returns true if the motor is off
    92  func (m *MotorDriver) IsOff() bool {
    93  	return !m.IsOn()
    94  }
    95  
    96  // Toggle sets the motor to the opposite of it's current state
    97  func (m *MotorDriver) Toggle() (err error) {
    98  	if m.IsOn() {
    99  		err = m.Off()
   100  	} else {
   101  		err = m.On()
   102  	}
   103  	return
   104  }
   105  
   106  // Speed sets the speed of the motor
   107  func (m *MotorDriver) Speed(value byte) (err error) {
   108  	if writer, ok := m.connection.(PwmWriter); ok {
   109  		m.CurrentMode = "analog"
   110  		m.CurrentSpeed = value
   111  		return writer.PwmWrite(m.SpeedPin, value)
   112  	}
   113  	return ErrPwmWriteUnsupported
   114  }
   115  
   116  // Forward sets the forward pin to the specified speed
   117  func (m *MotorDriver) Forward(speed byte) (err error) {
   118  	err = m.Direction("forward")
   119  	if err != nil {
   120  		return
   121  	}
   122  	err = m.Speed(speed)
   123  	if err != nil {
   124  		return
   125  	}
   126  	return
   127  }
   128  
   129  // Backward sets the backward pin to the specified speed
   130  func (m *MotorDriver) Backward(speed byte) (err error) {
   131  	err = m.Direction("backward")
   132  	if err != nil {
   133  		return
   134  	}
   135  	err = m.Speed(speed)
   136  	if err != nil {
   137  		return
   138  	}
   139  	return
   140  }
   141  
   142  // Direction sets the direction pin to the specified speed
   143  func (m *MotorDriver) Direction(direction string) (err error) {
   144  	m.CurrentDirection = direction
   145  	if m.DirectionPin != "" {
   146  		var level byte
   147  		if direction == "forward" {
   148  			level = 1
   149  		} else {
   150  			level = 0
   151  		}
   152  		err = m.connection.DigitalWrite(m.DirectionPin, level)
   153  	} else {
   154  		var forwardLevel, backwardLevel byte
   155  		switch direction {
   156  		case "forward":
   157  			forwardLevel = 1
   158  			backwardLevel = 0
   159  		case "backward":
   160  			forwardLevel = 0
   161  			backwardLevel = 1
   162  		case "none":
   163  			forwardLevel = 0
   164  			backwardLevel = 0
   165  		}
   166  		err = m.connection.DigitalWrite(m.ForwardPin, forwardLevel)
   167  		if err != nil {
   168  			return
   169  		}
   170  		err = m.connection.DigitalWrite(m.BackwardPin, backwardLevel)
   171  		if err != nil {
   172  			return
   173  		}
   174  	}
   175  	return
   176  }
   177  
   178  func (m *MotorDriver) isDigital() bool {
   179  	return m.CurrentMode == "digital"
   180  }
   181  
   182  func (m *MotorDriver) changeState(state byte) (err error) {
   183  	m.CurrentState = state
   184  	if state == 1 {
   185  		m.CurrentSpeed = 255
   186  	} else {
   187  		m.CurrentSpeed = 0
   188  	}
   189  	if m.ForwardPin != "" {
   190  		if state == 1 {
   191  			err = m.Direction(m.CurrentDirection)
   192  			if err != nil {
   193  				return
   194  			}
   195  			if m.SpeedPin != "" {
   196  				err = m.Speed(m.CurrentSpeed)
   197  				if err != nil {
   198  					return
   199  				}
   200  			}
   201  		} else {
   202  			err = m.Direction("none")
   203  		}
   204  	} else {
   205  		err = m.connection.DigitalWrite(m.SpeedPin, state)
   206  	}
   207  
   208  	return
   209  }