Sensor Ramp

Some of you might be using ‘digital’ sensors or incoming ‘digital’ states that only report a simple ‘on’ or ‘off’ state – none of the analogue range of values that ultrasonic or some infrared rangefinders provide.

Examples of such ‘digital’ sensors are the PIR Motion Sensor, magnetic reed switches, or the basic pushbutton.

Other examples might be from datasets in IoTa that broadcast a simple binary state, such as car parking sensors or bike stations.

This simple algorithm is basically a counter that ramps up/down a variable over time. When the sensor is active (reports ‘on’) this variable slowly increases linearly. The opposite happens when the sensor is inactive (reports ‘off’).

graph TD; style E fill:#aaccff,stroke:#666,stroke-width:2px A{Is incoming value
TRUE/HIGH/1?} --yes--> C[increase/decrease value of sensorRamp] B{Is incoming value
FALSE/LOW/0?} --yes--> C C --> D[limit value of sensorRamp between RAMP_MIN and RAMP_MAX] D --> E[update sensorRamp]

What’s left is then up to you to make use of this variable. Code is heavily commented below, so read it through and adapt into your own existing project if needed.

For simplicity, this code intentionally excludes components related to connecting events and triggers from IoTa.


Libraries Used

(learn how to import them in the Build IDE):


Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
    SensorRamp: an easy signal filter for digital sensors

    This example code allows one to easily connect a DIGITAL sensor
    that can be used to LINEARLY increment/decrement a variable gradually.

    This is a general 'utility' script that requires tweaking to match
    each project's needs.

    In particular, look at RAMP_MIN, RAMP_MAX and RAMP_INCRE

    Also, modify the #define tags to the pins / values accordingly to
    your project's wiring.

    Check comments below for detailed explanation.

    The MIT License (MIT)
    Copyright © 2016 Chuan Khoo

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.
*/

// SYSTEM_THREAD(ENABLED);             // improve responsiveness of the Photon; comment out if you're having problems (and increase RAMP_INCRE below)

// SYSTEM_MODE(MANUAL);

#define SENSEPIN        D3          // say you have a digital PIR sensor connected to D3
#define DEBUGPIN        D2          // we'll use an LED connected on D2 (via a 330/220ohm resistor!) to visually observe the results of the ramp

#define RAMP_MIN        0           // the minimum value you want the ramp to drop down to
#define RAMP_MAX        800         // the maximum value you want the ramp to drop down to
#define RAMP_INCRE      0.015        // how fast you want the ramp to set the speed of the ramp, fractions allowed! try a range of 0.015 to 2

int mySensorVal = 0;                // placeholder that stores state of digital input
double sensorRamp = 0;              // the current value of the ramp; change this if you want a non-zero initial value
int rampDir = 0;                    // an up/down direction modifier used in the code; don't modify this


/////////// SETUP function
void setup() {
    Serial.begin(57600);             // using this to debug the status of the sensorRamp value
    pinMode(SENSEPIN, INPUT);       // if you're using a pushbutton, use INPUT_PULLDOWN instead of INPUT
    pinMode(DEBUGPIN, OUTPUT);               // debug LED just to see what's going on with our ramp, remove this if you don't need it

}

/////////// LOOP function
void loop() {

    // copy this into your loop function    
    mySensorVal = digitalRead(SENSEPIN);       // read state of sensor into mySensorVal

    if(mySensorVal) {       // if you wish to detect a reverse state, change to !mySensorVal
        rampDir = 1;
    } else {
        rampDir = -1;
    }
    updateRamp();
    // end copy


    Serial.printlnf("%i : %i", mySensorVal, (int)sensorRamp);

    // next, do whatever you need to do with the sensorRamp variable!
    // e.g. driving a MOSFET gate to alter the speed of a DC motor / brightness of 12V analog LED strip:
    // analogWrite(SOME_PWM_PIN, sensorRamp);
}

/////////// copy this entire updateRamp function into your own code
void updateRamp() {
    sensorRamp += rampDir * RAMP_INCRE;
    sensorRamp = constrain(sensorRamp, RAMP_MIN, RAMP_MAX);     // make sure the ramp value is kept within RAMP_MIN and RAMP_MAX

    int remap = map(sensorRamp, RAMP_MIN, RAMP_MAX, 0, 255);
    analogWrite(DEBUGPIN, remap);                     // debug LED just to see what's going on with our ramp, comment this out if you don't need it
}