YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
gp2y1010au0f_drv.cpp
1/*
2 * gp2y1010au0fdrv.cpp
3 *
4 * Created on: 27.01.2017
5 * Author: aterstegge
6 */
7
8#include "gp2y1010au0f_drv.h"
9
10gp2y1010au0f_drv::gp2y1010au0f_drv(adc_channel &adc,
11 gpio_interface &led,
12 timer_interface &timer,
13 float factor)
14 : _adc(adc), _ir_led(led), _timer(timer), _voltage_factor(factor) {
15
16 // HW initialization
17 _ir_led.gpioMode(GPIO::OUTPUT | GPIO::INIT_LOW);
18 _timer.setCallback([this]() {
19 process_state();
20 });
21
22 // initialize members
23 _raw_sum = 0;
24 _measurements = 0;
25 _counter = 0;
26 _volt = 0.0f;
27 _volt_min = 1.0f;
28 _volt_max = 2.5f;
29 _dust = 0.0f;
30 _callback = 0;
31 _state = STOP_MEASURE;
32}
33
34void gp2y1010au0f_drv::start_measure(uint16_t m, void (*callback)(gp2y1010au0f_drv *)) {
35 _callback = callback;
36 _raw_sum = 0.0;
37 _measurements = m;
38 _counter = m;
39 _state = START_MEASURE;
40 _timer.start();
41 process_state();
42}
43
44gp2y1010au0f_drv::~gp2y1010au0f_drv() {
45 _ir_led.gpioMode(GPIO::INPUT);
46 _timer.stop();
47}
48
49void gp2y1010au0f_drv::process_state() {
50 switch (_state) {
51 case START_MEASURE: {
52 // delay measurement, switch on IR LED
53 _timer.setPeriod(DELAY, TIMER::ONE_SHOT);
54 // set new state
55 _state = DO_MEASURE;
56 // switch on IR LED
57 _ir_led.gpioWrite(HIGH);
58 break;
59 }
60 case DO_MEASURE: {
61 // start the timer for after-measurement delay
62 _timer.setPeriod(T - DELAY, TIMER::ONE_SHOT);
63 // read out raw adc value
64 _raw_sum += _adc.adcReadRaw();
65 // switch off IR LED
66 _ir_led.gpioWrite(LOW);
67 // check if we need another measurement
68 _counter--;
69 if (_counter) {
70 // delay until next measurement
71 _timer.setPeriod(T - DELAY, TIMER::ONE_SHOT);
72 // set new state
73 _state = START_MEASURE;
74 } else {
75 _timer.stop();
76 _state = STOP_MEASURE;
77 process_state();
78 }
79 break;
80 }
81 case STOP_MEASURE: {
82 // do measure post-processing:
83 // 1. mean raw ADC value
84 _raw_sum /= _measurements;
85 // 2. calculate voltage
86 _volt = _adc.rawToVoltage(_raw_sum) * _voltage_factor;
87 // 3. evaluate max/min values
88 if (_volt < _volt_min) _volt_min = _volt;
89 if (_volt > _volt_max) _volt_max = _volt;
90 // 4. calculate dust
91 _dust = voltage_to_dust(_volt);
92 // Use callback to write value
93 _callback(this);
94
95 //if (_volt_min < 0.6) _volt_min += 0.01;
96 //if (_volt_max > 3.0) _volt_max -= 0.01;
97 break;
98 }
99 }
100}
101
102// This method is based on the output voltage
103// graph in the data sheet. It interpolates the
104// the graph with two linear sections.
105// Output range and unit is: 0..800 ug/m3
106float gp2y1010au0f_drv::voltage_to_dust(float VO) {
107 float v1 = _volt_min + 0.05f;
108 float v2 = _volt_max - 0.2f;
109
110 if (VO < v1) return 0.0f;
111 if (VO < v2) {
112 VO -= v1;
113 return 500.0f / (v2 - v1) * VO;
114 }
115 if (VO < _volt_max) {
116 VO -= v2;
117 return 300.0f / (_volt_max - v2) * VO + 500.0f;
118 }
119 return 800.0f;
120}
121