mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-01 02:41:48 +00:00
Add examples for DMA, DutyCycle, DutyCycleEncoder and AddressableLED (#2100)
This commit is contained in:
committed by
Peter Johnson
parent
5891628112
commit
500c43fb84
@@ -33,6 +33,15 @@ class AddressableLED : public ErrorBase {
|
||||
b = _b;
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method to set all values of the LED.
|
||||
*/
|
||||
void SetLED(int r, int g, int b) {
|
||||
this->r = r;
|
||||
this->g = g;
|
||||
this->b = b;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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 <array>
|
||||
|
||||
#include <frc/AddressableLED.h>
|
||||
#include <frc/TimedRobot.h>
|
||||
#include <frc/smartdashboard/SmartDashboard.h>
|
||||
|
||||
class Robot : public frc::TimedRobot {
|
||||
// PWM port 0
|
||||
// Must be a PWM header, not MXP or DIO
|
||||
frc::AddressableLED m_led{0};
|
||||
std::array<frc::AddressableLED::LEDData, 12> m_ledBuffer; // Reuse the buffer
|
||||
int m_count = 0;
|
||||
|
||||
public:
|
||||
void RobotInit() override {
|
||||
// Default to a length of 12, start empty output
|
||||
// Length is expensive to set, so only set it once, then just update data
|
||||
m_led.SetLength(12);
|
||||
m_led.SetData(m_ledBuffer);
|
||||
m_led.Start();
|
||||
}
|
||||
|
||||
void RobotPeriodic() override {
|
||||
// Zero out all LEDs
|
||||
for (auto& ledData : m_ledBuffer) {
|
||||
ledData.SetLED(0, 0, 0);
|
||||
}
|
||||
|
||||
// Set 1 single LED to red
|
||||
m_ledBuffer[m_count].SetLED(50, 0, 0);
|
||||
|
||||
// Continue moving LED
|
||||
m_count++;
|
||||
if (m_count >= 12) m_count = 0;
|
||||
|
||||
// Buffer must be written to update.
|
||||
m_led.SetData(m_ledBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef RUNNING_FRC_TESTS
|
||||
int main() { return frc::StartRobot<Robot>(); }
|
||||
#endif
|
||||
82
wpilibcExamples/src/main/cpp/examples/DMA/cpp/Robot.cpp
Normal file
82
wpilibcExamples/src/main/cpp/examples/DMA/cpp/Robot.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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 <frc/AnalogInput.h>
|
||||
#include <frc/DMA.h>
|
||||
#include <frc/DMASample.h>
|
||||
#include <frc/DigitalOutput.h>
|
||||
#include <frc/Encoder.h>
|
||||
#include <frc/TimedRobot.h>
|
||||
#include <frc/smartdashboard/SmartDashboard.h>
|
||||
|
||||
class Robot : public frc::TimedRobot {
|
||||
frc::DMA m_dma; // DMA object
|
||||
|
||||
// DMA needs a trigger, can use an output as trigger.
|
||||
// 8 Triggers exist per DMA object, can be triggered on any
|
||||
// DigitalSource.
|
||||
frc::DigitalOutput m_dmaTrigger{2};
|
||||
|
||||
// Analog input to read with DMA
|
||||
frc::AnalogInput m_analogInput{0};
|
||||
|
||||
// Encoder to read with DMA
|
||||
frc::Encoder m_encoder{0, 1};
|
||||
|
||||
public:
|
||||
void RobotInit() override {
|
||||
// Trigger on falling edge of dma trigger output
|
||||
m_dma.SetExternalTrigger(&m_dmaTrigger, false, true);
|
||||
|
||||
// Add inputs we want to read via DMA
|
||||
m_dma.AddAnalogInput(&m_analogInput);
|
||||
m_dma.AddEncoder(&m_encoder);
|
||||
m_dma.AddEncoderPeriod(&m_encoder);
|
||||
|
||||
// Make sure trigger is set to off.
|
||||
m_dmaTrigger.Set(true);
|
||||
|
||||
// Start DMA. No triggers or inputs can be added after this call
|
||||
// unless DMA is stopped.
|
||||
m_dma.StartDMA(1024);
|
||||
}
|
||||
|
||||
void RobotPeriodic() override {
|
||||
// Manually Trigger DMA read
|
||||
m_dmaTrigger.Set(false);
|
||||
|
||||
// Need to create a sample.
|
||||
frc::DMASample sample;
|
||||
int32_t remaining = 0;
|
||||
int32_t status = 0;
|
||||
// Update our sample. remaining is the number of samples remaining in the
|
||||
// buffer status is more specfic error messages if readStatus is not OK.
|
||||
// Wait 1ms if buffer is empty
|
||||
HAL_DMAReadStatus readStatus =
|
||||
sample.Update(&m_dma, 1_ms, &remaining, &status);
|
||||
|
||||
if (readStatus == HAL_DMA_OK) {
|
||||
// Status value in all these reads should be checked, a non 0 value means
|
||||
// value could not be read
|
||||
|
||||
// If DMA is good, values exist
|
||||
auto encoderDistance = sample.GetEncoderDistance(&m_encoder, &status);
|
||||
// Period is not scaled, and is a raw value
|
||||
auto encoderPeriod = sample.GetEncoderPeriodRaw(&m_encoder, &status);
|
||||
auto analogVoltage =
|
||||
sample.GetAnalogInputVoltage(&m_analogInput, &status);
|
||||
|
||||
frc::SmartDashboard::PutNumber("Distance", encoderDistance);
|
||||
frc::SmartDashboard::PutNumber("Period", encoderPeriod);
|
||||
frc::SmartDashboard::PutNumber("Input", analogVoltage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef RUNNING_FRC_TESTS
|
||||
int main() { return frc::StartRobot<Robot>(); }
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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 <frc/DigitalInput.h>
|
||||
#include <frc/DutyCycle.h>
|
||||
#include <frc/DutyCycleEncoder.h>
|
||||
#include <frc/TimedRobot.h>
|
||||
#include <frc/smartdashboard/SmartDashboard.h>
|
||||
|
||||
class Robot : public frc::TimedRobot {
|
||||
frc::DigitalInput m_input{0}; // Input channel
|
||||
|
||||
// Duty cycle encoder
|
||||
frc::DutyCycleEncoder m_dutyCycleEncoder{m_input};
|
||||
|
||||
public:
|
||||
void RobotInit() override {
|
||||
// Set to 0.5 units per rotation
|
||||
m_dutyCycleEncoder.SetDistancePerRotation(0.5);
|
||||
}
|
||||
|
||||
void RobotPeriodic() override {
|
||||
// Connected can be checked, and uses the frequency of the encoder
|
||||
auto connected = m_dutyCycleEncoder.IsConnected();
|
||||
|
||||
// Duty Cycle Frequency in Hz
|
||||
auto frequency = m_dutyCycleEncoder.GetFrequency();
|
||||
|
||||
// Output of encoder
|
||||
auto output = m_dutyCycleEncoder.Get();
|
||||
|
||||
// Output scaled by DistancePerPulse
|
||||
auto distance = m_dutyCycleEncoder.GetDistance();
|
||||
|
||||
frc::SmartDashboard::PutBoolean("Connected", connected);
|
||||
frc::SmartDashboard::PutNumber("Frequency", frequency);
|
||||
frc::SmartDashboard::PutNumber("Output", output.to<double>());
|
||||
frc::SmartDashboard::PutNumber("Distance", distance);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef RUNNING_FRC_TESTS
|
||||
int main() { return frc::StartRobot<Robot>(); }
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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 <frc/DigitalInput.h>
|
||||
#include <frc/DutyCycle.h>
|
||||
#include <frc/TimedRobot.h>
|
||||
#include <frc/smartdashboard/SmartDashboard.h>
|
||||
|
||||
class Robot : public frc::TimedRobot {
|
||||
frc::DigitalInput m_input{0}; // Input channel
|
||||
frc::DutyCycle m_dutyCycle{m_input}; // Duty cycle input
|
||||
|
||||
public:
|
||||
void RobotInit() override {}
|
||||
|
||||
void RobotPeriodic() override {
|
||||
// Duty Cycle Frequency in Hz
|
||||
auto frequency = m_dutyCycle.GetFrequency();
|
||||
|
||||
// Output of duty cycle, ranging from 0 to 1
|
||||
// 1 is fully on, 0 is fully off
|
||||
auto output = m_dutyCycle.GetOutput();
|
||||
|
||||
frc::SmartDashboard::PutNumber("Frequency", frequency);
|
||||
frc::SmartDashboard::PutNumber("Duty Cycle", output);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef RUNNING_FRC_TESTS
|
||||
int main() { return frc::StartRobot<Robot>(); }
|
||||
#endif
|
||||
@@ -428,5 +428,45 @@
|
||||
"foldername": "TankDriveXboxController",
|
||||
"gradlebase": "cpp",
|
||||
"commandversion": 1
|
||||
},
|
||||
{
|
||||
"name": "Duty Cycle Encoder",
|
||||
"description": "Demonstrates the use of the Duty Cycle Encoder class",
|
||||
"tags": [
|
||||
"Getting Started with C++"
|
||||
],
|
||||
"foldername": "DutyCycleEncoder",
|
||||
"gradlebase": "cpp",
|
||||
"commandversion": 2
|
||||
},
|
||||
{
|
||||
"name": "Duty Cycle Input",
|
||||
"description": "Demonstrates the use of the Duty Cycle class",
|
||||
"tags": [
|
||||
"Getting Started with C++"
|
||||
],
|
||||
"foldername": "DutyCycleInput",
|
||||
"gradlebase": "cpp",
|
||||
"commandversion": 2
|
||||
},
|
||||
{
|
||||
"name": "Addressable LED",
|
||||
"description": "Demonstrates the use of the Addressable LED class",
|
||||
"tags": [
|
||||
"Getting Started with C++"
|
||||
],
|
||||
"foldername": "AddressableLED",
|
||||
"gradlebase": "cpp",
|
||||
"commandversion": 2
|
||||
},
|
||||
{
|
||||
"name": "DMA",
|
||||
"description": "Demonstrates the use of the DMA class",
|
||||
"tags": [
|
||||
"Advanced C++"
|
||||
],
|
||||
"foldername": "DMA",
|
||||
"gradlebase": "cpp",
|
||||
"commandversion": 2
|
||||
}
|
||||
]
|
||||
|
||||
@@ -37,4 +37,13 @@ public class AddressableLEDBuffer {
|
||||
m_buffer[(index * 4) + 2] = (byte) r;
|
||||
m_buffer[(index * 4) + 3] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer length.
|
||||
*
|
||||
* @return the buffer length
|
||||
*/
|
||||
public int getLength() {
|
||||
return m_buffer.length / 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.addressableled;
|
||||
|
||||
import edu.wpi.first.wpilibj.RobotBase;
|
||||
|
||||
/**
|
||||
* Do NOT add any static variables to this class, or any initialization at all.
|
||||
* Unless you know what you are doing, do not modify this file except to
|
||||
* change the parameter class to the startRobot call.
|
||||
*/
|
||||
public final class Main {
|
||||
private Main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization function. Do not perform any initialization here.
|
||||
*
|
||||
* <p>If you change your main robot class, change the parameter type.
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
RobotBase.startRobot(Robot::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.addressableled;
|
||||
|
||||
import edu.wpi.first.wpilibj.AddressableLED;
|
||||
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
|
||||
import edu.wpi.first.wpilibj.TimedRobot;
|
||||
|
||||
public class Robot extends TimedRobot {
|
||||
private AddressableLED m_led;
|
||||
private AddressableLEDBuffer m_ledBuffer;
|
||||
private int m_count;
|
||||
|
||||
@Override
|
||||
public void robotInit() {
|
||||
// PWM port 0
|
||||
// Must be a PWM header, not MXP or DIO
|
||||
m_led = new AddressableLED(0);
|
||||
|
||||
// Default to a length of 12, start empty output
|
||||
// Length is expensive to set, so only set it once, then just update data
|
||||
m_led.setLength(12);
|
||||
|
||||
// Reuse buffer
|
||||
m_ledBuffer = new AddressableLEDBuffer(12);
|
||||
|
||||
m_led.setData(m_ledBuffer);
|
||||
m_led.start();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void robotPeriodic() {
|
||||
// Zero out all LEDS
|
||||
for (int i = 0; i < m_ledBuffer.getLength(); i++) {
|
||||
m_ledBuffer.setLED(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Set 1 single LED to red
|
||||
m_ledBuffer.setLED(m_count, 50, 0, 0);
|
||||
|
||||
// Continue moving LED
|
||||
m_count++;
|
||||
if (m_count >= 12) {
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
// Buffer must be written to update.
|
||||
m_led.setData(m_ledBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.dutycycleencoder;
|
||||
|
||||
import edu.wpi.first.wpilibj.RobotBase;
|
||||
|
||||
/**
|
||||
* Do NOT add any static variables to this class, or any initialization at all.
|
||||
* Unless you know what you are doing, do not modify this file except to
|
||||
* change the parameter class to the startRobot call.
|
||||
*/
|
||||
public final class Main {
|
||||
private Main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization function. Do not perform any initialization here.
|
||||
*
|
||||
* <p>If you change your main robot class, change the parameter type.
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
RobotBase.startRobot(Robot::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.dutycycleencoder;
|
||||
|
||||
import edu.wpi.first.wpilibj.DigitalInput;
|
||||
import edu.wpi.first.wpilibj.DutyCycleEncoder;
|
||||
import edu.wpi.first.wpilibj.TimedRobot;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
|
||||
|
||||
@SuppressWarnings({"PMD.SingularField"})
|
||||
public class Robot extends TimedRobot {
|
||||
private DigitalInput m_input;
|
||||
private DutyCycleEncoder m_dutyCycleEncoder;
|
||||
|
||||
@Override
|
||||
public void robotInit() {
|
||||
m_input = new DigitalInput(0);
|
||||
m_dutyCycleEncoder = new DutyCycleEncoder(m_input);
|
||||
|
||||
// Set to 0.5 units per rotation
|
||||
m_dutyCycleEncoder.setDistancePerRotation(0.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void robotPeriodic() {
|
||||
// Connected can be checked, and uses the frequency of the encoder
|
||||
boolean connected = m_dutyCycleEncoder.isConnected();
|
||||
|
||||
// Duty Cycle Frequency in Hz
|
||||
int frequency = m_dutyCycleEncoder.getFrequency();
|
||||
|
||||
// Output of encoder
|
||||
double output = m_dutyCycleEncoder.get();
|
||||
|
||||
// Output scaled by DistancePerPulse
|
||||
double distance = m_dutyCycleEncoder.getDistance();
|
||||
|
||||
SmartDashboard.putBoolean("Connected", connected);
|
||||
SmartDashboard.putNumber("Frequency", frequency);
|
||||
SmartDashboard.putNumber("Output", output);
|
||||
SmartDashboard.putNumber("Distance", distance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.dutycycleinput;
|
||||
|
||||
import edu.wpi.first.wpilibj.RobotBase;
|
||||
|
||||
/**
|
||||
* Do NOT add any static variables to this class, or any initialization at all.
|
||||
* Unless you know what you are doing, do not modify this file except to
|
||||
* change the parameter class to the startRobot call.
|
||||
*/
|
||||
public final class Main {
|
||||
private Main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization function. Do not perform any initialization here.
|
||||
*
|
||||
* <p>If you change your main robot class, change the parameter type.
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
RobotBase.startRobot(Robot::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 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.examples.dutycycleinput;
|
||||
|
||||
import edu.wpi.first.wpilibj.DigitalInput;
|
||||
import edu.wpi.first.wpilibj.DutyCycle;
|
||||
import edu.wpi.first.wpilibj.TimedRobot;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
|
||||
|
||||
@SuppressWarnings({"PMD.SingularField"})
|
||||
public class Robot extends TimedRobot {
|
||||
private DigitalInput m_input;
|
||||
private DutyCycle m_dutyCycle;
|
||||
|
||||
@Override
|
||||
public void robotInit() {
|
||||
m_input = new DigitalInput(0);
|
||||
m_dutyCycle = new DutyCycle(m_input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void robotPeriodic() {
|
||||
// Duty Cycle Frequency in Hz
|
||||
int frequency = m_dutyCycle.getFrequency();
|
||||
|
||||
// Output of duty cycle, ranging from 0 to 1
|
||||
// 1 is fully on, 0 is fully off
|
||||
double output = m_dutyCycle.getOutput();
|
||||
|
||||
SmartDashboard.putNumber("Frequency", frequency);
|
||||
SmartDashboard.putNumber("Duty Cycle", output);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -449,5 +449,38 @@
|
||||
"gradlebase": "java",
|
||||
"mainclass": "Main",
|
||||
"commandversion": 1
|
||||
},
|
||||
{
|
||||
"name": "Duty Cycle Encoder",
|
||||
"description": "Demonstrates the use of the Duty Cycle Encoder class",
|
||||
"tags": [
|
||||
"Getting Started with Java"
|
||||
],
|
||||
"foldername": "dutycycleencoder",
|
||||
"gradlebase": "java",
|
||||
"mainclass": "Main",
|
||||
"commandversion": 2
|
||||
},
|
||||
{
|
||||
"name": "Duty Cycle Input",
|
||||
"description": "Demonstrates the use of the Duty Cycle class",
|
||||
"tags": [
|
||||
"Getting Started with Java"
|
||||
],
|
||||
"foldername": "dutycycleinput",
|
||||
"gradlebase": "java",
|
||||
"mainclass": "Main",
|
||||
"commandversion": 2
|
||||
},
|
||||
{
|
||||
"name": "Addressable LED",
|
||||
"description": "Demonstrates the use of the Addressable LED class",
|
||||
"tags": [
|
||||
"Getting Started with Java"
|
||||
],
|
||||
"foldername": "addressableled",
|
||||
"gradlebase": "java",
|
||||
"mainclass": "Main",
|
||||
"commandversion": 2
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user