Skip to main content
Version: 3.2.2

Piston Tutorial

note

As of v3.1.0, example projects come with include/subsystems.hpp.  If you do not have this, create this file in include/.  Now open include/main.h, add #include "subsytems.hpp".  You're all caught up and can follow along below!  

Creating the Piston​

We want to create a piston and have it accessible by main.cpp and autons.cpp.  To do this we can create the piston in include/subsystems.hpp with the code below.  

#pragma once

#include "EZ-Template/api.hpp"
#include "api.h"

extern Drive chassis;

// Your motors, sensors, etc. should go here.  Below are examples

inline ez::Piston doinker('A');
// inline pros::Motor intake(1);
// inline pros::adi::DigitalIn limit_switch('A');

Button Control​

Two Buttons​

To move a piston we type

piston name.(true or false);

So to actuate the piston, we would type

doinker.set(true);  

EZ-Template has a controller object already made for you that you can access with master. You can read controller inputs with master.get_digital(DIGITAL_button).  With an if/else statement, we can have the piston extend when R1 is pressed, and retract when R2 is pressed.  

if (master.get_digital(DIGITAL_R1)) {
doinker.set(true);
}
else if (master.get_digital(DIGITAL_R2)) {
doinker.set(false);
}

EZ-Template also has a shortcut for two button control. Instead of the if/else block, you can use this instead. This will do the same thing as the code above.

doinker.set(master.get_digital(DIGITAL_R1), master.get_digital(DIGITAL_R2));

Adding this to opcontrol looks like this.

void opcontrol() {
// This is preference to what you like to drive on
chassis.drive_brake_set(MOTOR_BRAKE_COAST);

while (true) {
// Gives you some extras to make EZ-Template ezier
ez_template_extras();

chassis.opcontrol_tank(); // Tank control
// chassis.opcontrol_arcade_standard(ez::SPLIT); // Standard split arcade
// chassis.opcontrol_arcade_standard(ez::SINGLE); // Standard single arcade
// chassis.opcontrol_arcade_flipped(ez::SPLIT); // Flipped split arcade
// chassis.opcontrol_arcade_flipped(ez::SINGLE); // Flipped single arcade

// . . .
// Put more user control code here!
// . . .

doinker.set(master.get_digital(DIGITAL_R1), master.get_digital(DIGITAL_R2));

pros::delay(ez::util::DELAY_TIME); // This is used for timer calculations! Keep this ez::util::DELAY_TIME
}
}

Hold​

Sometimes you want a subsystem that only activates while a button is being held. You can do this by setting the piston to the button, with this code.

doinker.set(master.get_digital(DIGITAL_R1));

Adding this to opcontrol looks like this.

void opcontrol() {
// This is preference to what you like to drive on
chassis.drive_brake_set(MOTOR_BRAKE_COAST);

while (true) {
// Gives you some extras to make EZ-Template ezier
ez_template_extras();

chassis.opcontrol_tank(); // Tank control
// chassis.opcontrol_arcade_standard(ez::SPLIT); // Standard split arcade
// chassis.opcontrol_arcade_standard(ez::SINGLE); // Standard single arcade
// chassis.opcontrol_arcade_flipped(ez::SPLIT); // Flipped split arcade
// chassis.opcontrol_arcade_flipped(ez::SINGLE); // Flipped single arcade

// . . .
// Put more user control code here!
// . . .

doinker.set(master.get_digital(DIGITAL_R1));

pros::delay(ez::util::DELAY_TIME); // This is used for timer calculations! Keep this ez::util::DELAY_TIME
}
}

Toggle​

Toggles are one button that controls the state of the piston. Every time it is pressed, the piston does the opposite of what it currently is doing.

The code below does not work. You can try it and see why it doesn't work. Every time the code runs, the solenoid will trigger and create a "farting" noise.

if (master.get_digital(DIGITAL_R1)) {
doinker.set(!doinker.get());
}

The solution to this is to only allow that code to run when the button is pressed freshly.

if (master.get_digital_new_press(DIGITAL_R1)) {
doinker.set(!doinker.get());
}

EZ-Template has a shortcut for button toggles with pistons.

doinker.button_toggle(master.get_digital(DIGITAL_R1));

Adding this to opcontrol looks like this.

void opcontrol() {
// This is preference to what you like to drive on
chassis.drive_brake_set(MOTOR_BRAKE_COAST);

while (true) {
// Gives you some extras to make EZ-Template ezier
ez_template_extras();

chassis.opcontrol_tank(); // Tank control
// chassis.opcontrol_arcade_standard(ez::SPLIT); // Standard split arcade
// chassis.opcontrol_arcade_standard(ez::SINGLE); // Standard single arcade
// chassis.opcontrol_arcade_flipped(ez::SPLIT); // Flipped split arcade
// chassis.opcontrol_arcade_flipped(ez::SINGLE); // Flipped single arcade

// . . .
// Put more user control code here!
// . . .

doinker.button_toggle(master.get_digital(DIGITAL_R1));

pros::delay(ez::util::DELAY_TIME); // This is used for timer calculations! Keep this ez::util::DELAY_TIME
}
}

Using it in Autonomous​

Because the piston is created in subsystmes.hpp, we can access is in autonomous exactly the same way!

In the example below, the robot will actuate the piston after driving 6" and will retract once it's driven 24".  The piston will not actuate again until it starts to come back and will retract once it's back to where it started.  

void intake_autonomous() {
chassis.pid_drive_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait_until(6_in);
doinker.set(true);
chassis.pid_wait_quick_chain();
doinker.set(false);

chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait_quick_chain();

chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait_quick_chain();

chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();

doinker.set(true);
chassis.pid_drive_set(-24_in, DRIVE_SPEED, true);
chassis.pid_speed_max_set(DRIVE_SPEED);  
chassis.pid_wait();
doinker.set(false);
}

More Tutorials​

The PROS team has made a tutorial for programming a VEX clawbot.  You can find that here.