Browse Source

Interrupt handling routines for sensors

fastled
Xose Pérez 6 years ago
parent
commit
90a7f7f6d2
6 changed files with 112 additions and 28 deletions
  1. +2
    -0
      code/espurna/config/sensors.h
  2. +1
    -13
      code/espurna/sensor.ino
  3. +68
    -3
      code/espurna/sensors/BaseSensor.h
  4. +1
    -1
      code/espurna/sensors/EmonADS1X15Sensor.h
  5. +2
    -4
      code/espurna/sensors/EmonSensor.h
  6. +38
    -7
      code/espurna/sensors/EventSensor.h

+ 2
- 0
code/espurna/config/sensors.h View File

@ -2,6 +2,8 @@
// SENSORS
// -----------------------------------------------------------------------------
#define SENSOR_DEBUG 0 // Debug sensors (always to 0 in prod)
#define SENSOR_READ_INTERVAL 6000 // Read data from sensors every 6 seconds
#define SENSOR_REPORT_EVERY 10 // Report every this many readings
#define SENSOR_USE_INDEX 0 // Use the index in topic (i.e. temperature/0)


+ 1
- 13
code/espurna/sensor.ino View File

@ -190,17 +190,6 @@ void _sensorPost() {
}
}
// -----------------------------------------------------------------------------
// Interrupts
// -----------------------------------------------------------------------------
#if EVENTS_SUPPORT
unsigned char _event_sensor_id = 0;
void _isrEventSensor() {
_sensors[_event_sensor_id]->InterruptHandler();
}
#endif // EVENTS_SUPPORT
// -----------------------------------------------------------------------------
// Sensor initialization
// -----------------------------------------------------------------------------
@ -293,9 +282,8 @@ void _sensorInit() {
EventSensor * sensor = new EventSensor();
sensor->setGPIO(EVENTS_PIN, EVENTS_PIN_MODE);
sensor->setDebounceTime(EVENTS_DEBOUNCE);
sensor->setinterruptMode(EVENTS_INTERRUPT_MODE);
_sensorRegister(sensor);
_event_sensor_id = sensorCount() - 1;
attachInterrupt(EVENTS_PIN, _isrEventSensor, EVENTS_INTERRUPT_MODE);
}
#endif


+ 68
- 3
code/espurna/sensors/BaseSensor.h View File

@ -38,6 +38,8 @@ typedef enum magnitude_t {
} magnitude_t;
#define GPIO_NONE 0x99
#define SENSOR_ERROR_OK 0 // No error
#define SENSOR_ERROR_OUT_OF_RANGE 1 // Result out of sensor range
#define SENSOR_ERROR_WARM_UP 2 // Sensor is warming-up
@ -55,9 +57,6 @@ class BaseSensor {
// Destructor
~BaseSensor() {}
// General interrupt handler
virtual void InterruptHandler() {}
// Initialization method, must be idempotent
virtual void begin() {}
@ -91,11 +90,77 @@ class BaseSensor {
// Number of available slots
unsigned char count() { return _count; }
// Handle interrupt calls
virtual void handleInterrupt(unsigned char gpio) {}
// Interrupt attach callback
void attached(unsigned char gpio) {
#if SENSOR_DEBUG
Serial.printf("[SENSOR] GPIO%d interrupt attached to %s\n", gpio, name().c_str());
#endif
}
// Interrupt detach callback
void detached(unsigned char gpio) {
#if SENSOR_DEBUG
Serial.printf("[SENSOR] GPIO%d interrupt detached from %s\n", gpio, name().c_str());
#endif
}
protected:
// Attach interrupt
void attach(BaseSensor * instance, unsigned char gpio, unsigned char mode);
// Detach interrupt
void detach(unsigned char gpio);
int _error = 0;
unsigned char _count = 0;
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
BaseSensor * _isr_sensor_instance[16] = {NULL};
void _sensor_isr(unsigned char gpio) {
if (_isr_sensor_instance[gpio]) {
_isr_sensor_instance[gpio]->handleInterrupt(gpio);
}
}
void _sensor_isr_0() { _sensor_isr(0); }
void _sensor_isr_2() { _sensor_isr(2); }
void _sensor_isr_4() { _sensor_isr(4); }
void _sensor_isr_5() { _sensor_isr(5); }
void _sensor_isr_12() { _sensor_isr(12); }
void _sensor_isr_13() { _sensor_isr(13); }
void _sensor_isr_14() { _sensor_isr(14); }
void _sensor_isr_15() { _sensor_isr(15); }
void (*_sensor_isrs[16])() = {
_sensor_isr_0, NULL, _sensor_isr_2, NULL, _sensor_isr_4, _sensor_isr_5,
NULL, NULL, NULL, NULL, NULL, NULL,
_sensor_isr_12, _sensor_isr_13, _sensor_isr_14, _sensor_isr_15
};
void BaseSensor::attach(BaseSensor * instance, unsigned char gpio, unsigned char mode) {
detach(gpio);
if (_sensor_isrs[gpio]) {
_isr_sensor_instance[gpio] = instance;
attachInterrupt(gpio, _sensor_isrs[gpio], mode);
instance->attached(gpio);
}
}
void BaseSensor::detach(unsigned char gpio) {
if (_isr_sensor_instance[gpio]) {
detachInterrupt(gpio);
_isr_sensor_instance[gpio]->detached(gpio);
_isr_sensor_instance[gpio] = NULL;
}
}

+ 1
- 1
code/espurna/sensors/EmonADS1X15Sensor.h View File

@ -291,7 +291,7 @@ class EmonADS1X15Sensor : public EmonSensor {
}
config |= ((channel + 4) << 12); // Set single-ended input channel (0x4000 - 0x7000)
#if EMON_DEBUG
#if SENSOR_DEBUG
Serial.printf("[EMON] ADS1X115 Config Registry: %04X\n", config);
#endif


+ 2
- 4
code/espurna/sensors/EmonSensor.h View File

@ -8,8 +8,6 @@
#include "Arduino.h"
#include "BaseSensor.h"
#define EMON_DEBUG 0
class EmonSensor : public BaseSensor {
public:
@ -65,7 +63,7 @@ class EmonSensor : public BaseSensor {
m = s * i;
}
#if EMON_DEBUG
#if SENSOR_DEBUG
Serial.print("[EMON] Current ratio: "); Serial.println(ratio);
Serial.print("[EMON] Ref. Voltage: "); Serial.println(ref);
Serial.print("[EMON] ADC Counts: "); Serial.println(_adc_counts);
@ -120,7 +118,7 @@ class EmonSensor : public BaseSensor {
current = (double) (int(current * _multiplier) - 1) / _multiplier;
if (current < 0) current = 0;
#if EMON_DEBUG
#if SENSOR_DEBUG
Serial.print("[EMON] Total samples: "); Serial.println(_samples);
Serial.print("[EMON] Total time (ms): "); Serial.println(time_span);
Serial.print("[EMON] Sample frequency (Hz): "); Serial.println(1000 * _samples / time_span);


+ 38
- 7
code/espurna/sensors/EventSensor.h View File

@ -20,11 +20,19 @@ class EventSensor : public BaseSensor {
_count = 1;
}
~EventSensor() {
detachInterrupt(_gpio);
}
void setGPIO(unsigned char gpio, int mode = INPUT) {
_gpio = gpio;
pinMode(_gpio, mode);
}
void setinterruptMode(unsigned long mode) {
_mode = mode;
}
void setDebounceTime(unsigned long debounce) {
_debounce = debounce;
}
@ -33,12 +41,11 @@ class EventSensor : public BaseSensor {
// Sensors API
// ---------------------------------------------------------------------
void InterruptHandler() {
static unsigned long last = 0;
if (millis() - last > _debounce) {
_events = _events + 1;
last = millis();
}
// Initialization method, must be idempotent
// Defined outside the class body
void begin() {
if (_interrupt_gpio != GPIO_NONE) detach(_interrupt_gpio);
attach(this, _gpio, _mode);
}
// Descriptive name of the sensor
@ -50,6 +57,7 @@ class EventSensor : public BaseSensor {
// Descriptive name of the slot # index
String slot(unsigned char index) {
(void) index;
return name();
}
@ -73,6 +81,27 @@ class EventSensor : public BaseSensor {
return 0;
}
// Handle interrupt calls
void handleInterrupt(unsigned char gpio) {
(void) gpio;
static unsigned long last = 0;
if (millis() - last > _debounce) {
_events = _events + 1;
last = millis();
}
}
// Interrupt attach callback
void attached(unsigned char gpio) {
BaseSensor::attached(gpio);
_interrupt_gpio = gpio;
}
// Interrupt detach callback
void detached(unsigned char gpio) {
BaseSensor::detached(gpio);
if (_interrupt_gpio == gpio) _interrupt_gpio = GPIO_NONE;
}
protected:
@ -81,7 +110,9 @@ class EventSensor : public BaseSensor {
// ---------------------------------------------------------------------
volatile unsigned long _events = 0;
unsigned long _debounce = 0;
unsigned long _debounce = EVENTS_DEBOUNCE;
unsigned char _gpio;
unsigned char _interrupt_gpio = GPIO_NONE;
unsigned char _mode;
};

Loading…
Cancel
Save