Commit ec9a7043 authored by Buscicchio's avatar Buscicchio

Add project files.

parent bdc45b7a
This diff is collapsed.

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29503.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommDropper", "CommDropper.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4BA3BABF-904B-410C-B922-26F3EC06F277}
EndGlobalSection
EndGlobal
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Misc Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>xml;json;txt;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="src\arduino folders read me.txt">
<Filter>Misc Files</Filter>
</None>
<None Include="CommDropper.ino" />
<None Include="State_FMS.ino" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="__vm\.CommDropper.vsarduino.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libraries\FiniteStateMachine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libraries\Pins.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libraries\JC_Button_mod.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libraries\DynamixelSerial_STM32.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="libraries\FiniteStateMachine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libraries\JC_Button_mod.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libraries\DynamixelSerial_STM32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
const byte FSM_NUMBER_OF_STATES = 10;
State FSM_state_BootUp = State(Enter_BootUp, Update_BootUp, Exit_BootUp);
State FSM_state_StandBy = State(Enter_StandBy, Update_StandBy, Exit_StandBy);
State FSM_state_Start_Cal = State(update_Start_Cal);
State FSM_state_Top_Cal = State(Enter_Top_Cal, Update_Top_Cal, Exit_Top_Cal);
State FSM_state_Bottom_Cal = State(Enter_Bottom_Cal, Update_Bottom_Cal, Exit_Bottom_Cal);
State FSM_state_faulted = State(Update_Faulted);
//DROPP
State FSM_state_Start_Drop = State(Enter_Start_Drop, Update_Start_Drop, Exit_Start_Drop);
//LOAD
State FSM_state_Finish_Load = State(Enter_Finish_Load, Update_Finish_Load, Exit_Finish_Load);
State FSM_state_Wait_For_Load = State(Enter_Wait_For_Load, Update_Wait_For_Load, Exit_Wait_For_Load);
State FSM_state_Start_Load = State(Enter_Start_Load, Update_Start_Load, Exit_Start_Load);
FSM FSM_stateMachine = FSM(FSM_state_BootUp); //initialize state machine, start in state: noop
void processStateMachine() {
//THIS LINE IS CRITICAL
//do not remove the stateMachine.update() call, it is what makes this program 'tick'
FSM_stateMachine.update();
}
void Enter_BootUp() {
nh.loginfo("System BootUp");
}
void Update_BootUp() {
//if (FSM_stateMachine.timeInCurrentState() > 1000); {}
//servo_initialization();
FSM_stateMachine.transitionTo(FSM_state_StandBy);
}
void Exit_BootUp() {
nh.loginfo("System BootUp");
}
void Enter_StandBy() {
nh.loginfo("I am in StandBy. ");
servo_pos_msg.data = Dynamixel.readPosition(BIG_SERVO.ID);
}
void Update_StandBy() {
//Wait for user to press button to initiate Calibration
//nh.loginfo("I am in Update_StandBy. ");
//CALIBRATION
if (command.cal_cmd == true || Cal_Button.pressedFor(LONG_PRESS)) { FSM_stateMachine.transitionTo(FSM_state_Start_Cal); }
//DROP
if (DROPPER.Is_Calibrated == true && (command.drop_cmd == true || Drop_Button.pressedFor(LONG_PRESS))) { FSM_stateMachine.transitionTo(FSM_state_Start_Drop); }
//LOAD
if (DROPPER.Is_Calibrated == true && (command.load_cmd == true || Load_Button.pressedFor(LONG_PRESS))) { FSM_stateMachine.transitionTo(FSM_state_Start_Load); }
}
void Exit_StandBy() {
nh.loginfo("I am in leaving_StandBy. ");
}
/*
#pragma region INITIALIZING STATE
void EnteringInitializingState() {
//CommDropperInitialize();
}
void UpdateInitializingState() {
//Wait for all servos to reach position
if (all_servos_in_position == true) {
FSM_stateMachine.transitionTo(FSM_state_Start_Calibration);
}
}
#pragma endregion*/
#pragma region CALIBRATION
void update_Start_Cal() {
nh.loginfo("Starting Calibration");
FSM_stateMachine.transitionTo(FSM_state_Top_Cal);
DROPPER.Is_Calibrated = false;
BIG_SERVO.goal_speed = CALIBRATION_SPEED;
}
#pragma region CALIBRATION TOP STATE
void Enter_Top_Cal() {
nh.loginfo("I am in calibration TOP. ");
//bottom_hardstop_found = false;
//Move main servo down to fin bottom hardstop
BIG_SERVO.goal_position_deg = BIG_SERVO.fake_top_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.goal_position_deg, BIG_SERVO.goal_speed);
}
void Update_Top_Cal() {
//Chek_For_Timeout_fault();
if (Top_Hardstop.isPressed()) {
//has reached bottom hardstop, set this as bottom position
nh.loginfo("Top hard stop pressed");
servo_pos_msg.data = Dynamixel.readPosition(BIG_SERVO.ID);
BIG_SERVO.top_position = Add_offset_top(BIG_SERVO.position_deg, HARDSTOP_OFFSET); // Sign?
BIG_SERVO.goal_position_deg = BIG_SERVO.top_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.goal_position_deg, BIG_SERVO.goal_speed); // Asks the servo to stay in position
FSM_stateMachine.transitionTo(FSM_state_Bottom_Cal);
}
}
void Exit_Top_Cal() {
}
#pragma endregion
#pragma region CALIBRATION BOTTOM STATE
void Enter_Bottom_Cal() {
nh.loginfo("I am in calibration BOTTOM. ");
BIG_SERVO.goal_position_deg = BIG_SERVO.fake_bottom_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.goal_position_deg, BIG_SERVO.goal_speed);
}
void Update_Bottom_Cal() {
//Chek_For_Timeout_fault();
if (Bottom_Hardstop.isPressed()) {
//has reached bottom hardstop, set this as bottom position
nh.loginfo("Bottom hard stop pressed");
servo_pos_msg.data = Dynamixel.readPosition(BIG_SERVO.ID);
BIG_SERVO.bottom_position = Add_offset_bottom(BIG_SERVO.position_deg , HARDSTOP_OFFSET ); // Sign?
BIG_SERVO.goal_position_deg = BIG_SERVO.bottom_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.goal_position_deg, BIG_SERVO.goal_speed);
FSM_stateMachine.transitionTo(FSM_state_StandBy);
}
}
void Exit_Bottom_Cal() {
DROPPER.Is_Calibrated = true;
BIG_SERVO.rest_position = Add_offset_top(BIG_SERVO.top_position, HARDSTOP_OFFSET);
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.rest_position, BIG_SERVO.goal_speed);
//command.cal_cmd = false;
nh.loginfo("Calibration Finished!");
}
#pragma endregion
#pragma endregion
void Update_Faulted() {
//
// Send out error messages
//
}
#pragma region DROP STATE
void Enter_Start_Drop() {
nh.loginfo("Dropping the radio!");
BIG_SERVO.goal_speed = NOMINAL_SPEED;
BIG_SERVO.goal_position_deg = BIG_SERVO.bottom_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.bottom_position, BIG_SERVO.goal_speed);
}
void Update_Start_Drop() {
if (BIG_SERVO.has_reached_goal == true) {
nh.loginfo("Dropping the radio!");
Dynamixel.move(SMALL_SERVO[command.drop_radio].ID, SMALL_SERVO[command.drop_radio].open_position);
if (DROPPER.all_servos_in_position == true) {
FSM_stateMachine.transitionTo(FSM_state_StandBy);
}
}
}
void Exit_Start_Drop() {
nh.loginfo("Radio dropped");
BIG_SERVO.goal_speed = NOMINAL_SPEED;
BIG_SERVO.goal_position_deg = BIG_SERVO.rest_position;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.bottom_position, BIG_SERVO.goal_speed);
}
#pragma endregion
#pragma region LOAD STATE
//State FSM_state_Start_Load = State(Enter_Start_Load, Update_Start_Load, Exit_Start_Load);
void Enter_Start_Load() {
nh.loginfo("Starting load sequence!");
BIG_SERVO.has_reached_goal = false;
BIG_SERVO.goal_position_deg = BIG_SERVO.rest_position;
BIG_SERVO.goal_speed = NOMINAL_SPEED;
Dynamixel.moveSpeed(BIG_SERVO.ID, BIG_SERVO.goal_position_deg, BIG_SERVO.goal_speed);
}
void Update_Start_Load() {
if (BIG_SERVO.has_reached_goal == true)
{
nh.loginfo("Opening small servos");
for (size_t i = 0; i < NUMBER_OF_RADIOS; i++)
{
SMALL_SERVO[i].goal_position_deg = SMALL_SERVO[i].open_position;
Dynamixel.move(SMALL_SERVO[i].ID, SMALL_SERVO[i].goal_position_deg);
}
FSM_stateMachine.transitionTo(FSM_state_Wait_For_Load);
}
}
void Exit_Start_Load() {
nh.loginfo("Small servos are open. Load radios!");
}
//State FSM_state_Wait_For_Load = State(Enter_Wait_For_Load, Update_Wait_For_Load, Exit_Wait_For_Load);
void Enter_Wait_For_Load() {
//
}
void Update_Wait_For_Load() {// Togle load command or press the button for confirm radio loaded.
if (command.load_cmd == false || Load_Button.pressedFor(LONG_PRESS)) {
for (size_t i = 0; i < NUMBER_OF_RADIOS; i++)
{
SMALL_SERVO[i].goal_position_deg = SMALL_SERVO[i].close_position;
Dynamixel.move(SMALL_SERVO[i].ID, SMALL_SERVO[i].goal_position_deg);
}
FSM_stateMachine.transitionTo(FSM_state_Finish_Load);
}
}
void Exit_Wait_For_Load() {
nh.loginfo("Load radio!");
}
//State FSM_state_Finish_Load = State(Enter_Finish_Load, Update_Finish_Load, Exit_Finish_Load);
void Enter_Finish_Load() {
//
}
void Update_Finish_Load() {// Togle load command or press the button for confirm radio loaded.
for (size_t i = 0; i < NUMBER_OF_RADIOS; i++)
{
// TO DO: Check radio presence?
}
FSM_stateMachine.transitionTo(FSM_state_StandBy);
}
void Exit_Finish_Load() {
nh.loginfo("Radios have been loaded");
}
#pragma endregion
#pragma region CALIBRATION TIMEOUT
void Chek_For_Timeout_fault() {
if (FSM_stateMachine.timeInCurrentState() > 20000) { //10secs as timeout
FSM_stateMachine.immediateTransitionTo(FSM_state_faulted);
}
}
#pragma endregion
//FSM USEFUL FUNCTIONS!
int Add_offset_top(int Position, int Offset) { //( int Position
/*if (temp > 0) { temp = temp - HARDSTOP_OFFSET; }
else {
temp = temp + HARDSTOP_OFFSET;
}
return temp;*/
return Position + Offset;
}
int Add_offset_bottom(int Position, int Offset) {
/*if (temp > 0) { temp = temp + HARDSTOP_OFFSET; }
else {
temp = temp - HARDSTOP_OFFSET;
}
return temp;*/
return Position - Offset;
}
void servo_initialization() {
BIG_SERVO.error = Dynamixel.ledStatus(BIG_SERVO.ID, ON); //turn LED on for Dyna 1 (MX106)
SMALL_SERVO[0].error = Dynamixel.ledStatus(SMALL_SERVO[0].ID, ON); //turn LED on for Dyna 2 (AX-12A)
SMALL_SERVO[1].error = Dynamixel.ledStatus(SMALL_SERVO[1].ID, ON);
SMALL_SERVO[2].error = Dynamixel.ledStatus(SMALL_SERVO[2].ID, ON);
SMALL_SERVO[3].error = Dynamixel.ledStatus(SMALL_SERVO[3].ID, ON);
SMALL_SERVO[4].error = Dynamixel.ledStatus(SMALL_SERVO[4].ID, ON);
SMALL_SERVO[5].error = Dynamixel.ledStatus(SMALL_SERVO[5].ID, ON);
BIG_SERVO.initial_position = Dynamixel.readPosition(BIG_SERVO.ID);
if (BIG_SERVO.error != 0) {
nh.logerror("Communication with the big servo failed!");
DROPPER.Is_Faulted = true;
}
for (int i = 0; i < NUMBER_OF_DROPPERS; i++)
{
if (SMALL_SERVO[i].error != 0) {
nh.logerror("Communication with one/some of the dropper/s failed!");
DROPPER.Is_Faulted = true;
}
}
if (DROPPER.Is_Faulted == true) {
nh.logerror("Servos initialization failed!");
}
if (DROPPER.Is_Faulted == false) {
//FSM_stateMachine.transitionTo(FSM_state_StandBy);
nh.logerror("Communication with servos established!");
}
}
\ No newline at end of file
/*
Editor: https://www.visualmicro.com/
This file is for intellisense purpose only.
Visual micro (and the arduino ide) ignore this code during compilation. This code is automatically maintained by visualmicro, manual changes to this file will be overwritten
The contents of the _vm sub folder can be deleted prior to publishing a project
All non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!).
Note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again
Hardware: Nucleo-32, Platform=stm32, Package=STM32
*/
#if defined(_VMICRO_INTELLISENSE)
#ifndef _VSARDUINO_H_
#define _VSARDUINO_H_
#define _VMDEBUG 1
#define STM32F3xx
#define ARDUINO 10809
#define ARDUINO_NUCLEO_F303K8
#define ARDUINO_ARCH_STM32
#define STM32F303x8
#define HAL_UART_MODULE_ENABLED
#define __cplusplus 201103L
#define __inline__
#define __asm__(x)
#define __extension__
#define __ATTR_PURE__
#define __ATTR_CONST__
#define __inline__
#define __volatile__
#define __GNUC__ 6
#define __GNUC_MINOR__ 3
#define __GNUC_PATCHLEVEL__ 0
#define _Static_assert(x)
#undef __cplusplus
#define __cplusplus 201103L
typedef bool _Bool;
#define __ARMCC_VERSION 400678
#define __attribute__(noinline)
#include "arduino.h"
#include <PinNamesVar.h>
#include <variant.h>
#include <variant.cpp>
#undef cli
#define cli()
#include "CommDropper.ino"
#include "State_FMS.ino"
#endif
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
||
|| @file FiniteStateMachine.cpp
|| @version 1.7
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Provide an easy way of making finite state machines
|| #
||
|| @license
|| | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version
|| | 2.1 of the License.
|| |
|| | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|| | Lesser General Public License for more details.
|| |
|| | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|| #
||
*/
#include "FiniteStateMachine.h"
//FINITE STATE
State::State( void (*updateFunction)() ){
userEnter = 0;
userUpdate = updateFunction;
userExit = 0;
}
State::State( void (*enterFunction)(), void (*updateFunction)(), void (*exitFunction)() ){
userEnter = enterFunction;
userUpdate = updateFunction;
userExit = exitFunction;
}
//what to do when entering this state
void State::enter(){
if (userEnter){
userEnter();
}
}
//what to do when this state updates
void State::update(){
if (userUpdate){
userUpdate();
}
}
//what to do when exiting this state
void State::exit(){
if (userExit){
userExit();
}
}
//END FINITE STATE
//FINITE STATE MACHINE
FiniteStateMachine::FiniteStateMachine(State& current){
needToTriggerEnter = true;
currentState = nextState = &current;
stateChangeTime = 0;
}
FiniteStateMachine& FiniteStateMachine::update() {
//simulate a transition to the first state
//this only happens the first time update is called
if (needToTriggerEnter) {
currentState->enter();
needToTriggerEnter = false;
} else {
if (currentState != nextState){
immediateTransitionTo(*nextState);
}
currentState->update();
}
return *this;
}
FiniteStateMachine& FiniteStateMachine::transitionTo(State& state){
nextState = &state;
stateChangeTime = millis();
return *this;
}
FiniteStateMachine& FiniteStateMachine::immediateTransitionTo(State& state){
currentState->exit();
currentState = nextState = &state;
currentState->enter();
stateChangeTime = millis();
return *this;
}
//return the current state
State& FiniteStateMachine::getCurrentState() {
return *currentState;
}
//check if state is equal to the currentState
boolean FiniteStateMachine::isInState( State &state ) const {
if (&state == currentState) {
return true;
} else {
return false;
}
}
unsigned long FiniteStateMachine::timeInCurrentState() {
millis() - stateChangeTime;
}
//END FINITE STATE MACHINE
/*
||
|| @file FiniteStateMachine.h
|| @version 1.7
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Provide an easy way of making finite state machines
|| #
||
|| @license
|| | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version
|| | 2.1 of the License.
|| |
|| | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|| | Lesser General Public License for more details.
|| |
|| | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|| #
||
*/
#ifndef FINITESTATEMACHINE_H
#define FINITESTATEMACHINE_H
#include <Arduino.h>
#define NO_ENTER (0)
#define NO_UPDATE (0)
#define NO_EXIT (0)
#define FSM FiniteStateMachine
//define the functionality of the states
class State {
public:
State( void (*updateFunction)() );
State( void (*enterFunction)(), void (*updateFunction)(), void (*exitFunction)() );
//State( byte newId, void (*enterFunction)(), void (*updateFunction)(), void (*exitFunction)() );
//void getId();
void enter();
void update();
void exit();
private:
//byte id;
void (*userEnter)();
void (*userUpdate)();
void (*userExit)();
};
//define the finite state machine functionality
class FiniteStateMachine {
public:
FiniteStateMachine(State& current);
FiniteStateMachine& update();
FiniteStateMachine& transitionTo( State& state );
FiniteStateMachine& immediateTransitionTo( State& state );
State& getCurrentState();
boolean isInState( State &state ) const;
unsigned long timeInCurrentState();
private:
bool needToTriggerEnter;
State* currentState;
State* nextState;
unsigned long stateChangeTime;
};
#endif
/*
|| @changelog
|| | 1.7 2010-03-08- Alexander Brevig : Fixed a bug, constructor ran update, thanks to René Pressé
|| | 1.6 2010-03-08- Alexander Brevig : Added timeInCurrentState() , requested by sendhb
|| | 1.5 2009-11-29- Alexander Brevig : Fixed a bug, introduced by the below fix, thanks to Jon Hylands again...
|| | 1.4 2009-11-29- Alexander Brevig : Fixed a bug, enter gets triggered on the first state. Big thanks to Jon Hylands who pointed this out.
|| | 1.3 2009-11-01 - Alexander Brevig : Added getCurrentState : &State
|| | 1.3 2009-11-01 - Alexander Brevig : Added isInState : boolean, requested by Henry Herman
|| | 1.2 2009-05-18 - Alexander Brevig : enter and exit bug fix
|| | 1.1 2009-05-18 - Alexander Brevig : Added support for cascaded calls
|| | 1.0 2009-04-13 - Alexander Brevig : Initial Release
|| #
*/
\ No newline at end of file
// Arduino Button Library
// https://github.com/JChristensen/JC_Button
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
#include "JC_Button_mod.h"
/*----------------------------------------------------------------------*
/ initialize a Button object and the pin it's connected to. *
/-----------------------------------------------------------------------*/
void Button::begin()
{
pinMode(m_pin, m_puEnable ? INPUT_PULLUP : INPUT);
m_state = digitalRead(m_pin);
if (m_invert) m_state = !m_state;
m_time = millis();
m_lastState = m_state;
m_changed = false;
m_lastChange = m_time;
}
/*----------------------------------------------------------------------*
/ returns the state of the button, true if pressed, false if released. *
/ does debouncing, captures and maintains times, previous state, etc. *
/-----------------------------------------------------------------------*/
bool Button::read()
{
uint32_t ms = millis();
bool pinVal = digitalRead(m_pin);
if (m_invert) pinVal = !pinVal;
if (ms - m_lastChange < m_dbTime)
{
m_changed = false;
}
else
{
m_lastState = m_state;
m_state = pinVal;
m_changed = (m_state != m_lastState);
if (m_changed) m_lastChange = ms;
}
m_time = ms;
return m_state;
}
/*----------------------------------------------------------------------*
* isPressed() and isReleased() check the button state when it was last *
* read, and return false (0) or true (!=0) accordingly. *