001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.hal.FRCNetComm.tResourceType; 010import edu.wpi.first.hal.HAL; 011import edu.wpi.first.util.sendable.Sendable; 012import edu.wpi.first.util.sendable.SendableBuilder; 013import edu.wpi.first.util.sendable.SendableRegistry; 014 015/** 016 * Handle operation of an analog accelerometer. The accelerometer reads acceleration directly 017 * through the sensor. Many sensors have multiple axis and can be treated as multiple devices. Each 018 * is calibrated by finding the center value over a period of time. 019 */ 020public class AnalogAccelerometer implements Sendable, AutoCloseable { 021 private AnalogInput m_analogChannel; 022 private double m_voltsPerG = 1.0; 023 private double m_zeroGVoltage = 2.5; 024 private final boolean m_allocatedChannel; 025 026 /** Common initialization. */ 027 private void initAccelerometer() { 028 HAL.report(tResourceType.kResourceType_Accelerometer, m_analogChannel.getChannel() + 1); 029 SendableRegistry.addLW(this, "Accelerometer", m_analogChannel.getChannel()); 030 } 031 032 /** 033 * Create a new instance of an accelerometer. 034 * 035 * <p>The constructor allocates desired analog channel. 036 * 037 * @param channel The channel number for the analog input the accelerometer is connected to 038 */ 039 public AnalogAccelerometer(final int channel) { 040 this(new AnalogInput(channel), true); 041 SendableRegistry.addChild(this, m_analogChannel); 042 } 043 044 /** 045 * Create a new instance of Accelerometer from an existing AnalogChannel. Make a new instance of 046 * accelerometer given an AnalogChannel. This is particularly useful if the port is going to be 047 * read as an analog channel as well as through the Accelerometer class. 048 * 049 * @param channel The existing AnalogInput object for the analog input the accelerometer is 050 * connected to 051 */ 052 public AnalogAccelerometer(final AnalogInput channel) { 053 this(channel, false); 054 } 055 056 private AnalogAccelerometer(final AnalogInput channel, final boolean allocatedChannel) { 057 requireNonNullParam(channel, "channel", "AnalogAccelerometer"); 058 m_allocatedChannel = allocatedChannel; 059 m_analogChannel = channel; 060 initAccelerometer(); 061 } 062 063 /** Delete the analog components used for the accelerometer. */ 064 @Override 065 public void close() { 066 SendableRegistry.remove(this); 067 if (m_analogChannel != null && m_allocatedChannel) { 068 m_analogChannel.close(); 069 } 070 m_analogChannel = null; 071 } 072 073 /** 074 * Return the acceleration in Gs. 075 * 076 * <p>The acceleration is returned units of Gs. 077 * 078 * @return The current acceleration of the sensor in Gs. 079 */ 080 public double getAcceleration() { 081 if (m_analogChannel == null) { 082 return 0.0; 083 } 084 return (m_analogChannel.getAverageVoltage() - m_zeroGVoltage) / m_voltsPerG; 085 } 086 087 /** 088 * Set the accelerometer sensitivity. 089 * 090 * <p>This sets the sensitivity of the accelerometer used for calculating the acceleration. The 091 * sensitivity varies by accelerometer model. There are constants defined for various models. 092 * 093 * @param sensitivity The sensitivity of accelerometer in Volts per G. 094 */ 095 public void setSensitivity(double sensitivity) { 096 m_voltsPerG = sensitivity; 097 } 098 099 /** 100 * Set the voltage that corresponds to 0 G. 101 * 102 * <p>The zero G voltage varies by accelerometer model. There are constants defined for various 103 * models. 104 * 105 * @param zero The zero G voltage. 106 */ 107 public void setZero(double zero) { 108 m_zeroGVoltage = zero; 109 } 110 111 @Override 112 public void initSendable(SendableBuilder builder) { 113 builder.setSmartDashboardType("Accelerometer"); 114 builder.addDoubleProperty("Value", this::getAcceleration, null); 115 } 116}