gobot.io/x/gobot@v1.16.0/drivers/aio/analog_sensor_driver.go (about)

     1  package aio
     2  
     3  import (
     4  	"time"
     5  
     6  	"gobot.io/x/gobot"
     7  )
     8  
     9  // AnalogSensorDriver represents an Analog Sensor
    10  type AnalogSensorDriver struct {
    11  	name       string
    12  	pin        string
    13  	halt       chan bool
    14  	interval   time.Duration
    15  	connection AnalogReader
    16  	gobot.Eventer
    17  	gobot.Commander
    18  	rawValue int
    19  	value    float64
    20  	scale    func(input int) (value float64)
    21  }
    22  
    23  // NewAnalogSensorDriver returns a new AnalogSensorDriver with a polling interval of
    24  // 10 Milliseconds given an AnalogReader and pin.
    25  // The driver supports customizable scaling from read int value to returned float64.
    26  // The default scaling is 1:1. An adjustable linear scaler is provided by the driver.
    27  //
    28  // Optionally accepts:
    29  // 	time.Duration: Interval at which the AnalogSensor is polled for new information
    30  //
    31  // Adds the following API Commands:
    32  // 	"Read"      - See AnalogDriverSensor.Read
    33  // 	"ReadValue" - See AnalogDriverSensor.ReadValue
    34  func NewAnalogSensorDriver(a AnalogReader, pin string, v ...time.Duration) *AnalogSensorDriver {
    35  	d := &AnalogSensorDriver{
    36  		name:       gobot.DefaultName("AnalogSensor"),
    37  		connection: a,
    38  		pin:        pin,
    39  		Eventer:    gobot.NewEventer(),
    40  		Commander:  gobot.NewCommander(),
    41  		interval:   10 * time.Millisecond,
    42  		halt:       make(chan bool),
    43  		scale:      func(input int) (value float64) { return float64(input) },
    44  	}
    45  
    46  	if len(v) > 0 {
    47  		d.interval = v[0]
    48  	}
    49  
    50  	d.AddEvent(Data)
    51  	d.AddEvent(Value)
    52  	d.AddEvent(Error)
    53  
    54  	d.AddCommand("Read", func(params map[string]interface{}) interface{} {
    55  		val, err := d.Read()
    56  		return map[string]interface{}{"val": val, "err": err}
    57  	})
    58  
    59  	d.AddCommand("ReadValue", func(params map[string]interface{}) interface{} {
    60  		val, err := d.ReadValue()
    61  		return map[string]interface{}{"val": val, "err": err}
    62  	})
    63  
    64  	return d
    65  }
    66  
    67  // Start starts the AnalogSensorDriver and reads the sensor at the given interval.
    68  // Emits the Events:
    69  //	Data int - Event is emitted on change and represents the current raw reading from the sensor.
    70  //	Value float64 - Event is emitted on change and represents the current reading from the sensor.
    71  //	Error error - Event is emitted on error reading from the sensor.
    72  func (a *AnalogSensorDriver) Start() (err error) {
    73  	if a.interval == 0 {
    74  		// cyclic reading deactivated
    75  		return
    76  	}
    77  	var oldRawValue = 0
    78  	var oldValue = 0.0
    79  	go func() {
    80  		timer := time.NewTimer(a.interval)
    81  		timer.Stop()
    82  		for {
    83  			_, err := a.ReadValue()
    84  			if err != nil {
    85  				a.Publish(a.Event(Error), err)
    86  			} else {
    87  				if a.rawValue != oldRawValue && a.rawValue != -1 {
    88  					a.Publish(a.Event(Data), a.rawValue)
    89  					oldRawValue = a.rawValue
    90  				}
    91  				if a.value != oldValue && a.value != -1 {
    92  					a.Publish(a.Event(Value), a.value)
    93  					oldValue = a.value
    94  				}
    95  			}
    96  
    97  			timer.Reset(a.interval)
    98  			select {
    99  			case <-timer.C:
   100  			case <-a.halt:
   101  				timer.Stop()
   102  				return
   103  			}
   104  		}
   105  	}()
   106  	return
   107  }
   108  
   109  // Halt stops polling the analog sensor for new information
   110  func (a *AnalogSensorDriver) Halt() (err error) {
   111  	if a.interval == 0 {
   112  		// cyclic reading deactivated
   113  		return
   114  	}
   115  	a.halt <- true
   116  	return
   117  }
   118  
   119  // Name returns the AnalogSensorDrivers name
   120  func (a *AnalogSensorDriver) Name() string { return a.name }
   121  
   122  // SetName sets the AnalogSensorDrivers name
   123  func (a *AnalogSensorDriver) SetName(n string) { a.name = n }
   124  
   125  // Pin returns the AnalogSensorDrivers pin
   126  func (a *AnalogSensorDriver) Pin() string { return a.pin }
   127  
   128  // Connection returns the AnalogSensorDrivers Connection
   129  func (a *AnalogSensorDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) }
   130  
   131  // Read returns the current reading from the sensor without scaling
   132  func (a *AnalogSensorDriver) Read() (val int, err error) {
   133  	return a.connection.AnalogRead(a.Pin())
   134  }
   135  
   136  // SetScaler substitute the default 1:1 return value function by a new scaling function
   137  func (a *AnalogSensorDriver) SetScaler(scaler func(int) float64) {
   138  	a.scale = scaler
   139  }
   140  
   141  // ReadValue returns the current reading from the sensor
   142  func (a *AnalogSensorDriver) ReadValue() (val float64, err error) {
   143  	if a.rawValue, err = a.Read(); err != nil {
   144  		return
   145  	}
   146  	a.value = a.scale(a.rawValue)
   147  	return a.value, nil
   148  }
   149  
   150  // Value returns the last read value from the sensor
   151  func (a *AnalogSensorDriver) Value() float64 {
   152  	return a.value
   153  }
   154  
   155  // RawValue returns the last read raw value from the sensor
   156  func (a *AnalogSensorDriver) RawValue() int {
   157  	return a.rawValue
   158  }
   159  
   160  func AnalogSensorLinearScaler(fromMin, fromMax int, toMin, toMax float64) func(input int) (value float64) {
   161  	m := (toMax - toMin) / float64(fromMax-fromMin)
   162  	n := toMin - m*float64(fromMin)
   163  	return func(input int) (value float64) {
   164  		if input <= fromMin {
   165  			return toMin
   166  		}
   167  		if input >= fromMax {
   168  			return toMax
   169  		}
   170  		return float64(input)*m + n
   171  	}
   172  }