Add Nidec Brushless motor. (#705)

This commit is contained in:
Peter Johnson
2017-11-08 23:40:01 -08:00
committed by GitHub
parent f34c736fb2
commit f3cd883c5c
4 changed files with 457 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "NidecBrushless.h"
#include <HAL/HAL.h>
#include "LiveWindow/LiveWindow.h"
using namespace frc;
/**
* Constructor.
*
* @param pwmChannel The PWM channel that the Nidec Brushless controller is
* attached to. 0-9 are on-board, 10-19 are on the MXP port
* @param dioChannel The DIO channel that the Nidec Brushless controller is
* attached to. 0-9 are on-board, 10-25 are on the MXP port
*/
NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
: m_safetyHelper(this), m_dio(dioChannel), m_pwm(pwmChannel) {
m_safetyHelper.SetExpiration(0.0);
m_safetyHelper.SetSafetyEnabled(false);
// the dio controls the output (in PWM mode)
m_dio.SetPWMRate(15625);
m_dio.EnablePWM(0.5);
// the pwm enables the controller
m_pwm.SetRaw(0xffff);
LiveWindow::GetInstance()->AddActuator("Nidec Brushless", pwmChannel, this);
HAL_Report(HALUsageReporting::kResourceType_NidecBrushless, pwmChannel);
}
/**
* Set the PWM value.
*
* <p>The PWM value is set using a range of -1.0 to 1.0, appropriately scaling
* the value for the FPGA.
*
* @param speed The speed value between -1.0 and 1.0 to set.
*/
void NidecBrushless::Set(double speed) {
m_speed = speed;
m_dio.UpdateDutyCycle(0.5 + 0.5 * (m_isInverted ? -speed : speed));
m_safetyHelper.Feed();
}
/**
* Get the recently set value of the PWM.
*
* @return The most recently set value for the PWM between -1.0 and 1.0.
*/
double NidecBrushless::Get() const { return m_speed; }
void NidecBrushless::SetInverted(bool isInverted) { m_isInverted = isInverted; }
bool NidecBrushless::GetInverted() const { return m_isInverted; }
/**
* Write out the PID value as seen in the PIDOutput base object.
*
* @param output Write out the PWM value as was found in the PIDController
*/
void NidecBrushless::PIDWrite(double output) { Set(output); }
/**
* Set the safety expiration time.
*
* @param timeout The timeout (in seconds) for this motor object
*/
void NidecBrushless::SetExpiration(double timeout) {
m_safetyHelper.SetExpiration(timeout);
}
/**
* Return the safety expiration time.
*
* @return The expiration time value.
*/
double NidecBrushless::GetExpiration() const {
return m_safetyHelper.GetExpiration();
}
/**
* Check if the motor is currently alive or stopped due to a timeout.
*
* @return a bool value that is true if the motor has NOT timed out and should
* still be running.
*/
bool NidecBrushless::IsAlive() const { return m_safetyHelper.IsAlive(); }
/**
* Stop the motor. This is called by the MotorSafetyHelper object
* when it has a timeout for this PWM and needs to stop it from running.
*/
void NidecBrushless::StopMotor() { Disable(); }
/**
* Check if motor safety is enabled.
*
* @return True if motor safety is enforced for this object
*/
bool NidecBrushless::IsSafetyEnabled() const {
return m_safetyHelper.IsSafetyEnabled();
}
void NidecBrushless::SetSafetyEnabled(bool enabled) {
m_safetyHelper.SetSafetyEnabled(enabled);
}
void NidecBrushless::GetDescription(llvm::raw_ostream& desc) const {
desc << "Nidec " << GetChannel();
}
void NidecBrushless::Disable() { m_dio.UpdateDutyCycle(0.5); }
/**
* Gets the channel number associated with the object.
*
* @return The channel number.
*/
int NidecBrushless::GetChannel() const { return m_pwm.GetChannel(); }
/*
* Live Window code, only does anything if live window is activated.
*/
std::string NidecBrushless::GetSmartDashboardType() const {
return "Nidec Brushless";
}
void NidecBrushless::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
if (subtable) {
m_valueEntry = subtable->GetEntry("Value");
UpdateTable();
} else {
m_valueEntry = nt::NetworkTableEntry();
}
}
void NidecBrushless::UpdateTable() {
if (m_valueEntry) {
m_valueEntry.SetDouble(Get());
}
}
void NidecBrushless::StartLiveWindowMode() {
Set(0); // Stop for safety
if (m_valueEntry) {
m_valueListener = m_valueEntry.AddListener(
[=](const nt::EntryNotification& event) {
if (!event.value->IsDouble()) return;
Set(event.value->GetDouble());
},
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
}
}
void NidecBrushless::StopLiveWindowMode() {
Set(0); // Stop for safety
if (m_valueListener != 0) {
m_valueEntry.RemoveListener(m_valueListener);
m_valueListener = 0;
}
}

View File

@@ -0,0 +1,73 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <string>
#include "DigitalOutput.h"
#include "LiveWindow/LiveWindowSendable.h"
#include "MotorSafety.h"
#include "MotorSafetyHelper.h"
#include "PWM.h"
#include "SpeedController.h"
#include "networktables/NetworkTableEntry.h"
namespace frc {
/**
* Nidec Brushless Motor.
*/
class NidecBrushless : public SpeedController,
public MotorSafety,
public LiveWindowSendable {
public:
NidecBrushless(int pwmChannel, int dioChannel);
~NidecBrushless() = default;
// SpeedController interface
void Set(double speed) override;
double Get() const override;
void SetInverted(bool isInverted) override;
bool GetInverted() const override;
void Disable() override;
void StopMotor() override;
// PIDOutput interface
void PIDWrite(double output) override;
// MotorSafety interface
void SetExpiration(double timeout) override;
double GetExpiration() const override;
bool IsAlive() const override;
void SetSafetyEnabled(bool enabled) override;
bool IsSafetyEnabled() const override;
void GetDescription(llvm::raw_ostream& desc) const override;
int GetChannel() const;
// Sendable interface
void InitTable(std::shared_ptr<nt::NetworkTable> subtable) override;
std::string GetSmartDashboardType() const override;
// LiveWindowSendable interface
void UpdateTable() override;
void StartLiveWindowMode() override;
void StopLiveWindowMode() override;
private:
MotorSafetyHelper m_safetyHelper;
bool m_isInverted = false;
DigitalOutput m_dio;
PWM m_pwm;
double m_speed = 0.0;
nt::NetworkTableEntry m_valueEntry;
int m_valueListener;
};
} // namespace frc

View File

@@ -0,0 +1,213 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
import edu.wpi.first.wpilibj.hal.HAL;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
/**
* Nidec Brushless Motor.
*/
public class NidecBrushless implements SpeedController, MotorSafety, LiveWindowSendable {
private final MotorSafetyHelper m_safetyHelper;
private boolean m_isInverted = false;
private DigitalOutput m_dio;
private PWM m_pwm;
private volatile double m_speed = 0.0;
/**
* Constructor.
*
* @param pwmChannel The PWM channel that the Nidec Brushless controller is attached to.
* 0-9 are on-board, 10-19 are on the MXP port
* @param dioChannel The DIO channel that the Nidec Brushless controller is attached to.
* 0-9 are on-board, 10-25 are on the MXP port
*/
public NidecBrushless(final int pwmChannel, final int dioChannel) {
m_safetyHelper = new MotorSafetyHelper(this);
m_safetyHelper.setExpiration(0.0);
m_safetyHelper.setSafetyEnabled(false);
// the dio controls the output (in PWM mode)
m_dio = new DigitalOutput(dioChannel);
m_dio.setPWMRate(15625);
m_dio.enablePWM(0.5);
// the pwm enables the controller
m_pwm = new PWM(pwmChannel);
m_pwm.setRaw(0xffff);
LiveWindow.addActuator("Nidec Brushless", pwmChannel, this);
HAL.report(tResourceType.kResourceType_NidecBrushless, pwmChannel);
}
/**
* Set the PWM value.
*
* <p>The PWM value is set using a range of -1.0 to 1.0, appropriately scaling the value for the
* FPGA.
*
* @param speed The speed value between -1.0 and 1.0 to set.
*/
@Override
public void set(double speed) {
m_speed = speed;
m_dio.updateDutyCycle(0.5 + 0.5 * (m_isInverted ? -speed : speed));
m_safetyHelper.feed();
}
/**
* Get the recently set value of the PWM.
*
* @return The most recently set value for the PWM between -1.0 and 1.0.
*/
@Override
public double get() {
return m_speed;
}
@Override
public void setInverted(boolean isInverted) {
m_isInverted = isInverted;
}
@Override
public boolean getInverted() {
return m_isInverted;
}
/**
* Write out the PID value as seen in the PIDOutput base object.
*
* @param output Write out the PWM value as was found in the PIDController
*/
@Override
public void pidWrite(double output) {
set(output);
}
/**
* Set the safety expiration time.
*
* @param timeout The timeout (in seconds) for this motor object
*/
@Override
public void setExpiration(double timeout) {
m_safetyHelper.setExpiration(timeout);
}
/**
* Return the safety expiration time.
*
* @return The expiration time value.
*/
@Override
public double getExpiration() {
return m_safetyHelper.getExpiration();
}
/**
* Check if the motor is currently alive or stopped due to a timeout.
*
* @return a bool value that is true if the motor has NOT timed out and should still be running.
*/
@Override
public boolean isAlive() {
return m_safetyHelper.isAlive();
}
/**
* Stop the motor. This is called by the MotorSafetyHelper object
* when it has a timeout for this PWM and needs to stop it from running.
*/
@Override
public void stopMotor() {
disable();
}
/**
* Check if motor safety is enabled.
*
* @return True if motor safety is enforced for this object
*/
@Override
public boolean isSafetyEnabled() {
return m_safetyHelper.isSafetyEnabled();
}
@Override
public void setSafetyEnabled(boolean enabled) {
m_safetyHelper.setSafetyEnabled(enabled);
}
@Override
public String getDescription() {
return "Nidec " + getChannel();
}
@Override
public void disable() {
m_dio.updateDutyCycle(0.5);
}
/**
* Gets the channel number associated with the object.
*
* @return The channel number.
*/
public int getChannel() {
return m_pwm.getChannel();
}
/*
* Live Window code, only does anything if live window is activated.
*/
@Override
public String getSmartDashboardType() {
return "Nidec Brushless";
}
private NetworkTableEntry m_valueEntry;
private int m_valueListener;
@Override
public void initTable(NetworkTable subtable) {
if (subtable != null) {
m_valueEntry = subtable.getEntry("Value");
updateTable();
} else {
m_valueEntry = null;
}
}
@Override
public void updateTable() {
if (m_valueEntry != null) {
m_valueEntry.setDouble(get());
}
}
@Override
public void startLiveWindowMode() {
set(0); // Stop for safety
m_valueListener = m_valueEntry.addListener((event) -> set(event.value.getDouble()),
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
}
@Override
public void stopLiveWindowMode() {
set(0); // Stop for safety
m_valueEntry.removeListener(m_valueListener);
m_valueListener = 0;
}
}

View File

@@ -107,6 +107,7 @@ public class FRCNetComm extends JNIWrapper {
int kResourceType_PDP = 59;
int kResourceType_PCM = 60;
int kResourceType_PigeonIMU = 61;
int kResourceType_NidecBrushless = 62;
}
/**