mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-22 23:56:13 +01:00
9dacd24d27
* Add <D SERVO vpin position> command Allow a PWM servo to be driven to any arbitrary position. * Enhancements for HAL drivers Add state change notification for external GPIO module drivers; Allow drivers to be installed statically by declaration (as an alternative to the 'create' call). * Create IO_HCSR04.h HAL driver for HC-SR04 ultrasonic distance sensor (sonar). * Enable servo commands in NO-HAL mode, but return error. Avoid compile errors in RMFT.cpp when compiled with basic HAL by including the Turnout::createServo function as a stub that returns NULL. * Update IO_HCSR04.h Minor changes * Change <D SERVO> Give the <D SERVO> command an optional parameter of the profile. For example, <D SERVO 100 200 3> will slowly move the servo on pin 100 to PWM position corresponding to 200. If omitted, the servo will move immediately (no animation). * IODevice (HAL) changes 1) Put new devices on the end of the chain instead of the beginning. This will give better performance for devices created first (ArduinoPins and extender GPIO devices, typically). 2) Remove unused functions. * Update IO_HCSR04.h Allow thresholds for ON and OFF to be separately configured at creation. * Update IODevice.cpp Fix compile error on IO_NO_HAL minimal HAL version. * Update IO_PCA9685.cpp Remove unnecessary duplicated call to min() function.
101 lines
4.1 KiB
C++
101 lines
4.1 KiB
C++
/*
|
|
* © 2020, Chris Harlow. All rights reserved.
|
|
*
|
|
* This file is part of Asbelos DCC API
|
|
*
|
|
* This is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* It 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef Sensor_h
|
|
#define Sensor_h
|
|
|
|
#include "Arduino.h"
|
|
#include "IODevice.h"
|
|
|
|
// Uncomment the following #define statement to use callback notification
|
|
// where the driver supports it.
|
|
// The principle of callback notification is to avoid the Sensor class
|
|
// having to poll the device driver cyclically for input values, and then scan
|
|
// for changes. Instead, when the driver scans the inputs, if it detects
|
|
// a change it invokes a callback function in the Sensor class. In the current
|
|
// implementation, the advantages are limited because (a) the Sensor class
|
|
// performs debounce checks, and (b) the Sensor class does not have a
|
|
// static reference to the output stream for sending <Q>/<q> messages
|
|
// when a change is detected. These restrictions mean that the checkAll()
|
|
// method still has to iterate through all of the Sensor objects looking
|
|
// for changes.
|
|
#define USE_NOTIFY
|
|
|
|
struct SensorData {
|
|
int snum;
|
|
VPIN pin;
|
|
uint8_t pullUp;
|
|
};
|
|
|
|
class Sensor{
|
|
// The sensor list is a linked list where each sensor's 'nextSensor' field points to the next.
|
|
// The pointer is null in the last on the list.
|
|
// To partition the sensor into those sensors which require polling through cyclic calls
|
|
// to 'IODevice::read(vpin)', and those which support callback on change, 'firstSensor'
|
|
// points to the start of the overall list, and 'lastSensor' points to the end of the list
|
|
// (the last sensor object). This structure allows sensors to be added to the start or the
|
|
// end of the list easily. So if an input pin supports change notification, it is placed at the
|
|
// end of the list. If not, it is placed at the beginning. And the pointer 'firstPollSensor'
|
|
// is set to the first of the sensor objects that requires scanning. Thus, we can iterate
|
|
// through the whole list, or just through the part that requires scanning.
|
|
|
|
public:
|
|
SensorData data;
|
|
struct {
|
|
uint8_t active:1;
|
|
uint8_t inputState:1;
|
|
uint8_t latchDelay:6;
|
|
}; // bit 7=active; bit 6=input state; bits 5-0=latchDelay
|
|
|
|
static Sensor *firstSensor;
|
|
#ifdef USE_NOTIFY
|
|
static Sensor *firstPollSensor;
|
|
static Sensor *lastSensor;
|
|
#endif
|
|
// readingSensor points to the next sensor to be polled, or null if the poll cycle is completed for
|
|
// the period.
|
|
static Sensor *readingSensor;
|
|
|
|
// Constructor
|
|
Sensor();
|
|
Sensor *nextSensor;
|
|
void setState(int state);
|
|
static void load();
|
|
static void store();
|
|
static Sensor *create(int id, VPIN vpin, int pullUp);
|
|
static Sensor* get(int id);
|
|
static bool remove(int id);
|
|
static void checkAll(Print *stream);
|
|
static void printAll(Print *stream);
|
|
static unsigned long lastReadCycle; // value of micros at start of last read cycle
|
|
static const unsigned int cycleInterval = 10000; // min time between consecutive reads of each sensor in microsecs.
|
|
// should not be less than device scan cycle time.
|
|
static const unsigned int minReadCount = 1; // number of additional scans before acting on change
|
|
// E.g. 1 means that a change is ignored for one scan and actioned on the next.
|
|
// Max value is 63
|
|
|
|
#ifdef USE_NOTIFY
|
|
static bool pollSignalPhase;
|
|
static void inputChangeCallback(VPIN vpin, int state);
|
|
static bool inputChangeCallbackRegistered;
|
|
#endif
|
|
|
|
}; // Sensor
|
|
|
|
#endif
|