From ea6ea57bd82d380997b1ae70b7d7e483489fed52 Mon Sep 17 00:00:00 2001 From: Ryan Greenblatt Date: Mon, 6 Aug 2018 12:28:11 -0400 Subject: [PATCH 1/2] Added c++ and Java setgetyawexample --- C++/PigeonSetGetYawC++/.cproject | 293 ++++++++++++++++++ C++/PigeonSetGetYawC++/.project | 28 ++ .../.settings/language.settings.xml | 36 +++ .../org.eclipse.cdt.managedbuilder.core.prefs | 13 + C++/PigeonSetGetYawC++/build.properties | 11 + C++/PigeonSetGetYawC++/build.xml | 28 ++ C++/PigeonSetGetYawC++/src/Robot.cpp | 59 ++++ Java/PigeonSetGetYaw/.classpath | 13 + Java/PigeonSetGetYaw/.project | 18 ++ Java/PigeonSetGetYaw/build.properties | 4 + Java/PigeonSetGetYaw/build.xml | 30 ++ .../org/usfirst/frc/team217/robot/Robot.java | 65 ++++ 12 files changed, 598 insertions(+) create mode 100644 C++/PigeonSetGetYawC++/.cproject create mode 100644 C++/PigeonSetGetYawC++/.project create mode 100644 C++/PigeonSetGetYawC++/.settings/language.settings.xml create mode 100644 C++/PigeonSetGetYawC++/.settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100644 C++/PigeonSetGetYawC++/build.properties create mode 100644 C++/PigeonSetGetYawC++/build.xml create mode 100644 C++/PigeonSetGetYawC++/src/Robot.cpp create mode 100644 Java/PigeonSetGetYaw/.classpath create mode 100644 Java/PigeonSetGetYaw/.project create mode 100644 Java/PigeonSetGetYaw/build.properties create mode 100644 Java/PigeonSetGetYaw/build.xml create mode 100644 Java/PigeonSetGetYaw/src/org/usfirst/frc/team217/robot/Robot.java diff --git a/C++/PigeonSetGetYawC++/.cproject b/C++/PigeonSetGetYawC++/.cproject new file mode 100644 index 00000000..0d0f985b --- /dev/null +++ b/C++/PigeonSetGetYawC++/.cproject @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/C++/PigeonSetGetYawC++/.project b/C++/PigeonSetGetYawC++/.project new file mode 100644 index 00000000..f463142c --- /dev/null +++ b/C++/PigeonSetGetYawC++/.project @@ -0,0 +1,28 @@ + + + PigeonSetGetYawC++ + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + edu.wpi.first.wpilib.plugins.core.nature.FRCProjectNature + + diff --git a/C++/PigeonSetGetYawC++/.settings/language.settings.xml b/C++/PigeonSetGetYawC++/.settings/language.settings.xml new file mode 100644 index 00000000..15011dc2 --- /dev/null +++ b/C++/PigeonSetGetYawC++/.settings/language.settings.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/C++/PigeonSetGetYawC++/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/C++/PigeonSetGetYawC++/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 00000000..a3c33656 --- /dev/null +++ b/C++/PigeonSetGetYawC++/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/CPATH/delimiter=; +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/CPATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/CPLUS_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/CPLUS_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/C_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/append=true +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/appendContributed=true +environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/LIBRARY_PATH/delimiter=; +environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/append=true +environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.cross.exe.debug.1104744751/appendContributed=true diff --git a/C++/PigeonSetGetYawC++/build.properties b/C++/PigeonSetGetYawC++/build.properties new file mode 100644 index 00000000..f51b8ca2 --- /dev/null +++ b/C++/PigeonSetGetYawC++/build.properties @@ -0,0 +1,11 @@ +# Build information +out=FRCUserProgram +src.dir=src +build.dir=build +out.exe=Debug/${out} + +# Simulation +simulation.world.file=/usr/share/frcsim/worlds/GearsBotDemo.world + +# Use the current C++ library by default +cpp-version=current diff --git a/C++/PigeonSetGetYawC++/build.xml b/C++/PigeonSetGetYawC++/build.xml new file mode 100644 index 00000000..42dd3555 --- /dev/null +++ b/C++/PigeonSetGetYawC++/build.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/C++/PigeonSetGetYawC++/src/Robot.cpp b/C++/PigeonSetGetYawC++/src/Robot.cpp new file mode 100644 index 00000000..34f96ccc --- /dev/null +++ b/C++/PigeonSetGetYawC++/src/Robot.cpp @@ -0,0 +1,59 @@ +#include +#include "ctre/Phoenix.h" +#include "Joystick.h" +#include + +class Robot: public frc::IterativeRobot { +public: + //This can be changed to an pigeon plugged into a talon with a ribbon cable by instantating a talon + //and passing that talon object into the pigeon constructor. + + PigeonIMU * _imu = new PigeonIMU(3); + + Joystick * _joystick = new Joystick(0); + + bool _lastButton1 = false; + bool _lastButton2 = false; + bool _lastButton3 = false; + + double _lastSetYaw = 0; + + void TeleopInit() { + _imu->SetYaw(0); + } + + void TeleopPeriodic() { + + //Set or Add yaw in degrees based on joystick + double yaw = 180 * _joystick->GetRawAxis(1); + + if(_joystick->GetRawButton(1) && !_lastButton1) { + double ypr_deg[] = {0, 0, 0}; + + _imu->GetYawPitchRoll(ypr_deg); + printf("yaw: %f last set yaw: %f\n", ypr_deg[0], _lastSetYaw); + } + + if(_joystick->GetRawButton(2) && !_lastButton2) { + _imu->SetYaw(yaw, 30); + _lastSetYaw = yaw; + printf("Set yaw to: %f\n", yaw); + } + + if(_joystick->GetRawButton(3) && !_lastButton3) { + double ypr_deg[] = {0, 0, 0}; + + _imu->GetYawPitchRoll(ypr_deg); + + _imu->AddYaw(yaw, 30); + + _lastSetYaw = ypr_deg[0] + yaw; + printf("Added %f to yaw\n", yaw); + } + _lastButton1 = _joystick->GetRawButton(1); + _lastButton2 = _joystick->GetRawButton(2); + _lastButton3 = _joystick->GetRawButton(3); + } +}; + +START_ROBOT_CLASS(Robot) diff --git a/Java/PigeonSetGetYaw/.classpath b/Java/PigeonSetGetYaw/.classpath new file mode 100644 index 00000000..9d41f0ec --- /dev/null +++ b/Java/PigeonSetGetYaw/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Java/PigeonSetGetYaw/.project b/Java/PigeonSetGetYaw/.project new file mode 100644 index 00000000..c7186819 --- /dev/null +++ b/Java/PigeonSetGetYaw/.project @@ -0,0 +1,18 @@ + + + PigeonSetGetYaw + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + edu.wpi.first.wpilib.plugins.core.nature.FRCProjectNature + + diff --git a/Java/PigeonSetGetYaw/build.properties b/Java/PigeonSetGetYaw/build.properties new file mode 100644 index 00000000..6b9a9891 --- /dev/null +++ b/Java/PigeonSetGetYaw/build.properties @@ -0,0 +1,4 @@ +# Project specific information +package=org.usfirst.frc.team217.robot +robot.class=${package}.Robot +simulation.world.file=/usr/share/frcsim/worlds/GearsBotDemo.world \ No newline at end of file diff --git a/Java/PigeonSetGetYaw/build.xml b/Java/PigeonSetGetYaw/build.xml new file mode 100644 index 00000000..76fd29a6 --- /dev/null +++ b/Java/PigeonSetGetYaw/build.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Java/PigeonSetGetYaw/src/org/usfirst/frc/team217/robot/Robot.java b/Java/PigeonSetGetYaw/src/org/usfirst/frc/team217/robot/Robot.java new file mode 100644 index 00000000..9b4fe949 --- /dev/null +++ b/Java/PigeonSetGetYaw/src/org/usfirst/frc/team217/robot/Robot.java @@ -0,0 +1,65 @@ +/** + * @brief A quick example on getting and setting the yaw of a pigeon + * + * This assumes the pigeon is directly connected over CAN. This example prints to console and requires the use of a + * gamepad. + */ +package org.usfirst.frc.team217.robot; + +import com.ctre.phoenix.sensors.PigeonIMU; + +import edu.wpi.first.wpilibj.IterativeRobot; +import edu.wpi.first.wpilibj.Joystick; + +public class Robot extends IterativeRobot { + + //This can be changed to an pigeon plugged into a talon with a ribbon cable by instantating a talon + //and passing that talon object into the pigeon constructor. + + PigeonIMU _imu = new PigeonIMU(3); + + Joystick _joystick = new Joystick(0); + + boolean _lastButton1 = false; + boolean _lastButton2 = false; + boolean _lastButton3 = false; + + double _lastSetYaw = 0; + + public void teleopInit() { + _imu.setYaw(0); + } + + public void teleopPeriodic() { + + //Set or Add yaw in degrees based on joystick + double yaw = 180 * _joystick.getRawAxis(1); + + if(_joystick.getRawButton(1) && !_lastButton1) { + double[] ypr_deg = {0, 0, 0}; + + _imu.getYawPitchRoll(ypr_deg); + System.out.printf("yaw: %f last set yaw: %f\n", ypr_deg[0], _lastSetYaw); + } + + if(_joystick.getRawButton(2) && !_lastButton2) { + _imu.setYaw(yaw, 30); + _lastSetYaw = yaw; + System.out.printf("Set yaw to: %f\n", yaw); + } + + if(_joystick.getRawButton(3) && !_lastButton3) { + double[] ypr_deg = {0, 0, 0}; + + _imu.getYawPitchRoll(ypr_deg); + + _imu.addYaw(yaw, 30); + + _lastSetYaw = ypr_deg[0] + yaw; + System.out.printf("Added %f to yaw\n", yaw); + } + _lastButton1 = _joystick.getRawButton(1); + _lastButton2 = _joystick.getRawButton(2); + _lastButton3 = _joystick.getRawButton(3); + } +} From 1621ad73f1329d8c1a4a7fc6a26f084329f678ef Mon Sep 17 00:00:00 2001 From: Ryan Greenblatt Date: Mon, 6 Aug 2018 13:39:44 -0400 Subject: [PATCH 2/2] Added C# example --- HERO C#/PigeonGetSetYaw/LICENSE | 22 +++ .../PigeonGetSetYaw/PigeonGetSetYaw.csproj | 50 ++++++ HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.sln | 27 ++++ HERO C#/PigeonGetSetYaw/Program.cs | 89 ++++++++++ .../Properties/AssemblyInfo.cs | 25 +++ HERO C#/PigeonGetSetYaw/README.md | 152 ++++++++++++++++++ 6 files changed, 365 insertions(+) create mode 100644 HERO C#/PigeonGetSetYaw/LICENSE create mode 100644 HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.csproj create mode 100644 HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.sln create mode 100644 HERO C#/PigeonGetSetYaw/Program.cs create mode 100644 HERO C#/PigeonGetSetYaw/Properties/AssemblyInfo.cs create mode 100644 HERO C#/PigeonGetSetYaw/README.md diff --git a/HERO C#/PigeonGetSetYaw/LICENSE b/HERO C#/PigeonGetSetYaw/LICENSE new file mode 100644 index 00000000..ba84b74b --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/LICENSE @@ -0,0 +1,22 @@ +/** + * Phoenix Software License Agreement + * + * Copyright (C) Cross The Road Electronics. All rights + * reserved. + * + * Cross The Road Electronics (CTRE) licenses to you the right to + * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and + * Phoenix Software API Libraries ONLY when in use with CTR Electronics hardware products. + * + * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT + * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF + * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS + * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE + * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER + * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT + * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE + */ \ No newline at end of file diff --git a/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.csproj b/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.csproj new file mode 100644 index 00000000..62549cf7 --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.csproj @@ -0,0 +1,50 @@ + + + + PigeonGetSetYaw + Exe + Top + {b69e3092-b931-443c-abe7-7e7b65f2a37f};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 9.0.21022 + 2.0 + {FD578599-D937-45DE-8426-8A0496775D6B} + v4.4 + $(MSBuildExtensionsPath32)\Microsoft\.NET Micro Framework\ + Cross Link HERO .NETMF_Mini-USB + USB + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + False + + + False + False + + + + + + \ No newline at end of file diff --git a/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.sln b/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.sln new file mode 100644 index 00000000..da36e86c --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/PigeonGetSetYaw.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PigeonGetSetYaw", "PigeonGetSetYaw.csproj", "{FD578599-D937-45DE-8426-8A0496775D6B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FD578599-D937-45DE-8426-8A0496775D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD578599-D937-45DE-8426-8A0496775D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD578599-D937-45DE-8426-8A0496775D6B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {FD578599-D937-45DE-8426-8A0496775D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD578599-D937-45DE-8426-8A0496775D6B}.Release|Any CPU.Build.0 = Release|Any CPU + {FD578599-D937-45DE-8426-8A0496775D6B}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C42EC366-E98E-4DCC-B494-0500E6601A0B} + EndGlobalSection +EndGlobal diff --git a/HERO C#/PigeonGetSetYaw/Program.cs b/HERO C#/PigeonGetSetYaw/Program.cs new file mode 100644 index 00000000..1ecded0f --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/Program.cs @@ -0,0 +1,89 @@ +/** + * A quick example on getting and setting the yaw of a pigeon + * + * This assumes the pigeon is directly connected over CAN. This example prints to console and requires the use of a + * gamepad. + */ + +using CTRE.Phoenix; +using Microsoft.SPOT; +using CTRE.Phoenix.Controller; +using CTRE.Phoenix.Sensors; +using System.Threading; + +namespace PigeonGetSetYaw +{ + public class Program + { + static RobotApplication _robotApp = new RobotApplication(); + + public static void Main() + { + _robotApp.init(); + + while (true) + { + _robotApp.run(); + + Thread.Sleep(10); + } + } + } + + public class RobotApplication + { + /* any system wide initializations here */ + PigeonIMU _imu = new PigeonIMU(3); + GameController _joystick = new GameController(UsbHostDevice.GetInstance()); + + bool _lastButton1 = false; + bool _lastButton2 = false; + bool _lastButton3 = false; + + float _lastSetYaw = 0; + + public void init() + { + _imu.SetYaw(0, 30); + } + + + /* loop forever */ + public void run() + { + //Set or Add yaw in degrees based on joystick + float yaw = 180 * _joystick.GetAxis(0); + if (_joystick.GetButton(1) && !_lastButton1) + { + float[] ypr_deg = { 0, 0, 0 }; + _imu.GetYawPitchRoll(ypr_deg); + Debug.Print("yaw: " + ypr_deg[0].ToString() + " last set yaw: " + _lastSetYaw.ToString()); + } + + if (_joystick.GetButton(2) && !_lastButton2) + { + _imu.SetYaw(yaw, 30); + _lastSetYaw = yaw; + Debug.Print("Set yaw to: " + yaw.ToString()); + } + + if (_joystick.GetButton(3) && !_lastButton3) + { + float[] ypr_deg = { 0, 0, 0 }; + + _imu.GetYawPitchRoll(ypr_deg); + + _imu.AddYaw(yaw, 30); + + _lastSetYaw = ypr_deg[0] + yaw; + Debug.Print("Added " + yaw.ToString() + " to yaw"); + } + _lastButton1 = _joystick.GetButton(1); + _lastButton2 = _joystick.GetButton(2); + _lastButton3 = _joystick.GetButton(3); + + } + } + + +} diff --git a/HERO C#/PigeonGetSetYaw/Properties/AssemblyInfo.cs b/HERO C#/PigeonGetSetYaw/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..d2d05b91 --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HERO Robot Application")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HERO Robot Application")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HERO C#/PigeonGetSetYaw/README.md b/HERO C#/PigeonGetSetYaw/README.md new file mode 100644 index 00000000..72c568ff --- /dev/null +++ b/HERO C#/PigeonGetSetYaw/README.md @@ -0,0 +1,152 @@ +# CANifier Demo +The CANifier Demo project is an example that demonstrates some of the use cases of the CANifier. The CANifier is a CAN-controlled multipurpose LED and General Purpose Input/Output (GPIO) controller. It supports a variety of sensors that communicate through Quadrature, Limit Switch, SPI, I2c, and PWM Input/Output. With the Three low-side outputs, we are able to control any common RGB LED strip. The project also uses PWM inputs to communicate with a LIDAR Lite V3 sensor. Lastly, this project provides insight on how the new CTRE framework works and gives an example to how classes, schedulers, and organization works. + +# The Project's Hardware +This example project requires a [CANifier][2], [LIDAR Lite V3][3], [gamepad][4], RoboRIO, PWM motor controller, any common RGB LED Strip, and power source such as a power supply. + +It is recommended that the user should test the CANifier in isolation prior to installation. It would also be the best opportunity for the user to field-upgrade the CANifier, test peripherals, and ensure wiring is correct. + +For transmitting signals, the CANifier is connected to both the LED strip and PWM motor controller. The LED Strip is wired to the CANifier's four pins on the labeled, A, B, C, and V+, which can be seen below in Figure 1. + +#### Figure 1: LED strip wired to the CANifier, R to A, G to B, B to C, and + to V+. +![alt text][LED Strip] + +The PWM motor controller’s PWM signal is wired directly to the CANifier. Wire the PWM motor controller’s ground to one of the ground pins available and connect the PWM wire (typically denoted by a white wire) to one of the 3 PWM outputs. As of Phoenix Toolsuite 5.0.3.3 Installer, PWM I/O pin 4 can only be used an input. + +For retrieving signals, the project has a LIDAR Lite V3 Distance Sensor communicating with the CANifier through PWM. To wire the LIDAR Lite V3 to the CANifier, follow the steps below and use the Figure 2 as a guide. Note: The LIDAR Lite V3 is not required to use the example, but only enhances the user’s experience. + +#### Figure 2: LIDAR Lite V3 wired to the CANifier. Steps with order explained in table. +![alt text][LIDAR] + +The CANifier can then be connected to the RoboRIO through CAN. Once all connections to the CANifier has been made, it is recommended that it be insulted in a 1" heat shrink tubing as seen below in the Figure 3. + +#### Figure 3: Heat shrink to insulate CANifier from shorts +![alt text][Insulation] + +##### Further instructions on how to use and wire the CANifier can be found within the documentation, which can be found here. [http://www.ctr-electronics.com/can-can-canifier-driver-led-driver-gpio.html#product_tabs_technical_resources] + +### Example Setup +Below is a sample setup containing all the hardware required. A PWM motor controller was not available for use at the time, so we modified the TalonSRX to become a PWM motor Controller. Below in Figure 4, we have the physical setup used to run the CANifier Demo project. + +#### Figure 4: Example Setup of all the hardware connected to each other +![alt text][Setup] + +# The Project's Software +Before deploying the project to the RoboRIO, we need to make sure we have the correct firmware. The example was built using CTRE's Alpha build of the Phoenix Framework, which can be found on the [HERO's technical resources page][5]. Once the installer has been ran, it will be important to ensure all hardware has been flashed with the latest firmware. As of this example's release it uses CANifier firmware 0.9 and HERO firmware 1.0.1.0. + +Once all hardware has been updated and libraries has been installed, User may deploy the example project to the RoboRIO. The project operates in three modes, which are explained below. +### Animate LED Strip +This is the default LED strip control mode, which will automatically start when the robot is enabled. All it does is ramp through the outer rim of the HSV color wheel at half brightness and is converted into RGB within the TaskHSV class. User can enter this mode by pressing button 6 (Right bumper) on the gamepad. +### Direct Control LED Strip +In this mode, user can control the LED strip by using the gamepad joysticks. It takes the x and y values from the gamepad and finds both the angle and magnitude, which will represent the hue and saturation on the HSV color wheel, with a constant brightness. User can enter mode by pressing button 5 (Left bumper) on the gamepad. +### LIDAR Control LED Strip +In this mode, user can control the LED strip by using the LIDAR Lite V3. The TaskMeasurePulseSensors retrieves the PWM signals from the LIDAR. Depending on how far the object is, the LED strip will illuminate at a different hue with fixed saturation and brightness. Green represents the closest with blue being the furthest. User can enter this mode by pressing button 7 (Left-trigger) on the gamepad. + +#### Figure 5: LIDAR being used to provide hue based on distance detected +![alt text][More Pretty] + +### The PWM Motor Controller +The PWM motor controller will only be controlled if a gamepad is connected as shown below. Because of the Talon being used as PWM motor controller, the Watchdog will not be able to safely disable the motor, thus we have an in line check as shown in the code block below. The PWM motor controller only looks at the Y value from the gamepad and can go forward and backwards. +```c# + bool gamepadOk = false; + + /* keep feeding watchdog to enable motors */ + if (Hardware.gamepad.GetConnectionStatus() == CTRE.UsbDeviceConnection.Connected) + { + /* keep talons enabled */ + CTRE.Watchdog.Feed(); + /* take note if gamepad is present */ + gamepadOk = true; + } + + if (gamepadOk) + { + Platform.Schedulers.PeriodicTasks.Start(Platform.Tasks.taskPWMmotorController); + } + else + { + Platform.Schedulers.PeriodicTasks.Stop(Platform.Tasks.taskPWMmotorController); + } +``` +#### Figure 6: PWM motor controller going forward is backwards as shown by the LED colors (It is a talon used as a PWM motor controller) +![alt text][Final Image] + +The new Phoenix Framework has been designed to allow users to create tasks to enter them within a scheduler to create a more organized workspace. Take notice that all tasks were created under the Task folder and entered into a list within the Tasks class under the Platform namespace as seen in the code below. TaskMainLoop was the task in charge of selecting which LED strip mode to operate in. +```c# + public static class Tasks + { + /* Subsystem tasks. A task could be all the functionality of a substem like a robot arm, + * or could be an individual action appy to a subsytem, such as up reading a gamepad and applying it to the drivcetrain. + * Use 'public static' because these are single objects. + */ + + public static TaskAnimateLEDStrip taskAnimateLEDStrip = new TaskAnimateLEDStrip(); + public static TaskDirectControlLEDStrip taskDirectControlArm = new TaskDirectControlLEDStrip(); + public static TaskPWMmotorController taskPWMmotorController = new TaskPWMmotorController(); + public static TaskMeasurePulseSensors taskMeasurePulseSensors = new TaskMeasurePulseSensors(); + public static TaskLIDAR_ControlLEDStrip taskLIDAR_ControlLEDStrip = new TaskLIDAR_ControlLEDStrip(); + public static TaskHSV taskHSV_ControlLedStrip = new TaskHSV(); + + + + public static TaskMainLoop taskMainLoop = new TaskMainLoop(); + + + /* insert all Tasks below in the Full List so they get auto inserted, see Program.cs to see how this works.*/ + public static ILoopable[] FullList = { + taskAnimateLEDStrip, + taskDirectControlArm, + taskPWMmotorController, + taskMeasurePulseSensors, + taskLIDAR_ControlLEDStrip, + taskHSV_ControlLedStrip, + taskMainLoop, + }; + } +``` + +Using the list created, the main Robot class then adds each task to the concurrent scheduler. +```c# + /* add all the periodic tasks */ + foreach (ILoopable task in Platform.Tasks.FullList) + Schedulers.PeriodicTasks.Add(task) +``` + +Once all tasks were added to the concurrent scheduler, we then continuously process the concurrent scheduler that then processes each of the tasks. +```c# + /* loop forever */ + while (true) + { + Schedulers.PeriodicTasks.Process(); + + /* dump some tasks and subsystems into the console output */ + // Debug.Print(Platform.Tasks.taskDirectControlArm.ToString() + " " + + // Platform.Tasks.taskAnimateLEDStrip.ToString()); + Debug.Print(Platform.Tasks.taskMeasurePulseSensors.ToString()); + + Thread.Sleep(5); + } +``` + +# Troubleshoot +### CANifier or Gamepad not recognized? +This may be due to having mismatched device ID's to the software. Users have two options. They may change the device ID to match the software or provide the correct device ID within the Hardware class under the Platform namespace. +```c# + /* The hardware objects. Use 'public static' because these are single objects. */ + public static class Hardware + { + public static CANifier canifier = new CANifier(0); + + public static GameController gamepad = new GameController(CTRE.UsbHostDevice.GetInstance(0), 0); + } +``` + [2]: http://www.ctr-electronics.com/can-can-canifier-driver-led-driver-gpio.html + [3]: https://www.sparkfun.com/products/14032 + [4]: http://www.andymark.com/product-p/am-2064.htm + [5]: http://www.ctr-electronics.com/hro.html#product_tabs_technical_resources + [LED Strip]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/Java/CANifier%20Demo/Documentation/Capture2.PNG + [LIDAR]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/Java/CANifier%20Demo/Documentation/Capture.PNG + [Insulation]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/Java/CANifier%20Demo/Documentation/IMG_20171011_103615.jpg + [Setup]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/HERO%20C%23/CANifier%20Demo/Documentation/IMG_20171011_142031_01.jpg + [More Pretty]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/Java/CANifier%20Demo/Documentation/IMG_20171011_125250.jpg + [Final Image]: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/gh-doc/Java/CANifier%20Demo/Documentation/IMG_20171011_130436.jpg