Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Time = unsigned long;
- using Pin = int8_t;
- constexpr Time kSecond = 1000;
- constexpr Time kMinute = 60 * kSecond;
- class Stepper28BYJ_48
- {
- public:
- static constexpr int8_t kPinCount = 4;
- static constexpr float kMinimumDelay = 2.0;
- static constexpr float kMotorStepsPerRevolution = 2048.0;
- Stepper28BYJ_48(const Pin a, const Pin b, const Pin c, const Pin d)
- :mPins{a,b,c,d}
- {
- for (size_t idx = 0; idx < kPinCount; ++idx) {
- pinMode(mPins[idx], OUTPUT);
- }
- powerOff();
- }
- // Performs a blocking rotation
- // -1.0 <= speed < 0 or 0 < speed <= 1.0
- // revolutions >= 0.0
- void rotate(const float speed, const float revolutions) const
- {
- if (speed == 0.0 || speed < -1.0 || speed > 1.0 || revolutions <= 0.0) {
- return;
- }
- // Possible improvement - we don't keep track of or know whether where we're starting meshes
- // with where we left off.
- const int32_t totalSteps = static_cast<int32_t>(revolutions * kMotorStepsPerRevolution);
- int currentStep = 0;
- for (int stepCount = 0; stepCount < totalSteps; ++stepCount) {
- outputStep(currentStep);
- delay(static_cast<Time>(kMinimumDelay / fabs(speed)));
- currentStep = nextStep(speed < 0.0, currentStep);
- }
- powerOff();
- }
- inline void powerOff() const
- {
- // Turns off all pins to avoid overheating while idling.
- outputStep(kPinCount);
- }
- void rotateDegrees(const float speed, const float degrees) const
- {
- rotate(speed, degrees / 360.0);
- }
- private:
- const Pin mPins[kPinCount];
- Pin nextStep(const bool direction, const Pin lastStep) const
- {
- return (lastStep + kPinCount + (direction ? 1 : -1)) % kPinCount;
- }
- void outputStep(const int step) const
- {
- for (int pinIndex = 0; pinIndex < kPinCount; ++pinIndex) {
- digitalWrite(mPins[pinIndex], step == pinIndex ? HIGH : LOW);
- }
- }
- };
- class Button
- {
- public:
- Button(const Pin pin)
- :mPin(pin)
- {
- // Use pullup and connect the other end of the button to ground. Input is high
- // all the time and only low when button is pressed.
- pinMode(mPin, INPUT_PULLUP);
- }
- bool pressed() const
- {
- return digitalRead(mPin) != HIGH;
- }
- private:
- const Pin mPin;
- };
- class MotionDetector
- {
- public:
- MotionDetector(const Pin pin)
- :mPin(pin)
- {
- pinMode(mPin, INPUT);
- // Wait for the motion detector to initialize
- delay(1 * kMinute);
- }
- bool motionDetected() const
- {
- return digitalRead(mPin) != LOW;
- }
- private:
- const Pin mPin;
- };
- class LED
- {
- public:
- LED(const Pin pin)
- :mPin(pin)
- {
- pinMode(mPin, OUTPUT);
- }
- void onIf(const bool on) const
- {
- digitalWrite(mPin, on ? HIGH : LOW);
- }
- private:
- const Pin mPin;
- };
- const Stepper28BYJ_48& flushStepper()
- {
- static const Stepper28BYJ_48 theStepper(6, 7, 8, 9);
- return theStepper;
- }
- const MotionDetector& motionDetector()
- {
- static const MotionDetector detector(10);
- return detector;
- }
- const LED& flushScheduledLed()
- {
- static const LED flushPending(14);
- return flushPending;
- }
- const LED& detectionPausedLed()
- {
- static const LED detectionPaused(15);
- return detectionPaused;
- }
- const Button& cancelButton()
- {
- static const Button cancelBtn(2);
- return cancelBtn;
- }
- void flush()
- {
- //static uint32_t flushCount = 0;
- //++flushCount;
- constexpr float speed = 0.25;
- flushStepper().rotate(speed, 1.0);
- }
- void setup()
- {
- // initialize statics
- flushStepper();
- motionDetector();
- detectionPausedLed();
- flushScheduledLed();
- cancelButton();
- }
- void loop()
- {
- #if 0
- // testing settings.
- constexpr Time kDelayBetweenDetectAndFlush = 5 * kSecond;
- constexpr Time kDelayBetweenFlushAndResumeDetection = 5 * kSecond;
- #else
- constexpr Time kDelayBetweenDetectAndFlush = 10 * kMinute;
- constexpr Time kDelayBetweenFlushAndResumeDetection = 10 * kMinute;
- #endif
- constexpr Time kNoFlushScheduled = 0;
- static Time nextScheduledFlushTime = kNoFlushScheduled;
- static Time detectionResumeTime = 0;
- flushScheduledLed().onIf(nextScheduledFlushTime != kNoFlushScheduled);
- detectionPausedLed().onIf(millis() < detectionResumeTime);
- if (millis() > detectionResumeTime && motionDetector().motionDetected()) {
- // We detected motion. Schedule a flush. Keep watching and pushing back flush time
- // as long as we detect movement.
- nextScheduledFlushTime = millis() + kDelayBetweenDetectAndFlush;
- }
- if (nextScheduledFlushTime != kNoFlushScheduled && millis() > nextScheduledFlushTime) {
- // Unschedule the flush.
- nextScheduledFlushTime = kNoFlushScheduled;
- flushScheduledLed().onIf(false);
- flush();
- // After a flush, ignore detections for a little while.
- detectionResumeTime = millis() + kDelayBetweenFlushAndResumeDetection;
- }
- if (cancelButton().pressed()) {
- nextScheduledFlushTime = kNoFlushScheduled;
- detectionResumeTime = millis() + 10 * kSecond;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement