0.1.0 AnalogUVSensor

This commit is contained in:
rob tillaart 2021-09-29 17:06:47 +02:00
parent 2ddca893ac
commit e8057ebd10
17 changed files with 650 additions and 0 deletions

View File

@ -0,0 +1,7 @@
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update
compliance: strict

View File

@ -0,0 +1,17 @@
---
name: Arduino CI
on: [push, pull_request]
jobs:
runTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -0,0 +1,18 @@
name: JSON check
on:
push:
paths:
- '**.json'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:
pattern: "\\.json$"

View File

@ -0,0 +1,76 @@
//
// FILE: AnalogUVSensor.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2021-09-25
// PURPOSE: AnalogUVSensor library
//
// HISTORY:
// 0.1.0 2021-09-25 initial version
#include "AnalogUVSensor.h"
AnalogUVSensor::AnalogUVSensor()
{
// defaults from UNO.
_analogPin = 14; // A0
_volts = 5;
_maxADC = 1023;
_powerPin = -1;
_invert = false;
}
void AnalogUVSensor::begin(uint8_t analogPin, float volts, uint16_t maxADC)
{
_analogPin = analogPin;
_volts = volts;
_maxADC = maxADC;
}
float AnalogUVSensor::read(uint8_t times)
{
uint32_t sum = 0;
for (int i = 0; i < times; i++)
{
sum += analogRead(_analogPin);
}
uint16_t milliVolt = sum * (_volts * 1000.0) / (times * _maxADC);
return mV2index(milliVolt);
}
float AnalogUVSensor::mV2index(uint16_t milliVolt)
{
if (milliVolt < 50) return 0.0;
// linear interpolation between 0..1
if (milliVolt < 227) return 0.0 + (1.0 * milliVolt - 50.0) / (227.0 - 50.0);
// linear interpolation between 1..11
// formula derived with spreadsheet.
return 0.0104865310 * milliVolt - 1.289154988;
}
char AnalogUVSensor::index2color(float index)
{
if (index <= 2) return 'G';
if (index <= 5) return 'Y';
if (index <= 7) return 'O';
if (index <= 10) return 'R';
return 'P';
}
void AnalogUVSensor::setPowerPin(uint8_t powerPin, bool invert)
{
_invert = invert;
_powerPin = powerPin;
pinMode(_powerPin, OUTPUT);
switchOn();
}
// -- END OF FILE --

View File

@ -0,0 +1,45 @@
#pragma once
//
// FILE: AnalogUVSensor.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2021-09-25
// PURPOSE: AnalogUVSensor library
//
// library for analogue UV sensor
//
#include "Arduino.h"
#define ANALOG_UVSENSOR_LIB_VERSION (F("0.1.0"))
class AnalogUVSensor
{
public:
AnalogUVSensor();
void begin(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023);
float read(uint8_t times = 1);
float mV2index(uint16_t milliVolt);
char index2color(float index);
// POWER
void setPowerPin(uint8_t powerPin, bool invert = false);
void switchOff() { digitalWrite(_powerPin, _invert ? HIGH : LOW); };
void switchOn() { digitalWrite(_powerPin, _invert ? LOW : HIGH); };
private:
uint8_t _analogPin;
float _volts;
uint16_t _maxADC;
uint8_t _powerPin;
bool _invert;
};
// -- END OF FILE --

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2021 Rob Tillaart
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.

View File

@ -0,0 +1,93 @@
# AnalogUVSensor
Arduino library for analogue UV sensor
## Description
![Foo](https://www.tinytronics.nl/shop/image/cache/catalog/products/product-003601/uv-light-sensor-module-200-370nm-80x80w.jpg)
Image courtesy Tinytronics
This small (type-less) UV-sensor is powered by 3.3 .. 5 V so it can be used by almost any microprocessor.
The sensor has an analogue output that is roughly linear with the UV-index (sunlight assumed, see notes)
| Voltage | UV index |
|:-------:|:--------:|
| <0.050 | 0 |
| 0.227 | 1 |
| 0.318 | 2 |
| 0.408 | 3 |
| 0.503 | 4 |
| 0.606 | 5 |
| 0.696 | 6 |
| 0.795 | 7 |
| 0.881 | 8 |
| 0.976 | 9 |
| 1.079 | 10 |
| 1.170> | 11 |
From this table the formula is derived (spreadsheet) which is pretty linear between UV 1 and 11.
### Notes
Note: The sensor is not calibrated and the table is indicative for sunlight (assumption!)
and therefore not suitable for e.g. medical or industrial usage.
Note: UV radiation will not go through glass, so inside you will most likely always read zero.
This may help to calibrate the zero level of the sensor.
Note: depending on the light source used, the table above is incorrect.
If one wants to use other values one need to fix this in the **mv2index()** function.
### Sensitivity
The sensor is sensitive for wavelengths from 200 - 370 nm, so mostly in UVB and UVA region and less in the UVC.
https://en.wikipedia.org/wiki/Ultraviolet
## Interface
- **AnalogUVSensor()** Constructor.
- **void begin(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023)**
set the parameters of the sensor, analogPin, volts and maxADC to specify the internal ADC. Volts and maxADC have a default so these can be omitted.
Note that one needs to reset these parameters if the settings of the internal ADC are
changed e.g. to INTERNAL_1V1 to change the accuracy.
- **float read(uint8_t times = 1)** Returns the UV index.
Read the analogue sensor one (or more) times to average the reading.
This can improve the accuracy of the reading.
- **float mV2index(uint16_t milliVolt)** Returns the UV index.
The conversion formula from milliVolt to the UV index used internally by the **read()** function.
This function can also be called with a voltage measured with an external ADC.
- **char index2color(float index)** Converts an index to the first letter of Green,
Yellow, Orange, Red or Purple. Can be used as indication on a user interface.
This function can also be called with an index from an other UV index sensor.
#### Power interface
Works only if setPowerPin is called properly.
- **void setPowerPin(uint8_t powerPin, bool invert = false)**
Can be used to control the power of the sensor e.g. for low power mode.
Optionally one can set the invert flag to **true** to invert the **HIGH LOW** levels e.g. when the analogue sensor is switched through a MOSFET.
- **void switchOff()** should switch off the power of the sensor.
- **void switchOn()** should switch on the power of the sensor.
### Future
- verify vs calibrated sensor
- investigate angle sensitivity e.g. if the UV light comes from an angle - cosine law.
- investigate response time to stabilize e.g. does it react fast on clouds.
- investigate with different light sources (UVled, TL, sunlight).
- investigate time needed to first (stable) measurement.
- **index2time()** calculate max exposure time? dangerous?
## Sponsor
The development of this library is sponsored by [TinyTronics, Netherlands](https://www.tinytronics.nl/shop/nl).

View File

@ -0,0 +1,48 @@
//
// FILE: UV_sensor.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-09-21
// example not using the library,
// sort of minimal version
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
}
void loop()
{
Serial.println(indexUV(A0, 5.0, 1023)); // assume UNO analogue port
delay(1000);
}
float indexUV(uint16_t pin, int16_t analog_max, float voltage_max)
{
uint16_t raw = analogRead(pin);
float millivolt = (voltage_max * raw * 1000) / analog_max;
if (millivolt < 50)
{
return 0.0;
}
if (millivolt < 227)
{
// linear interpolation between 0..1
float uvi = 0.0 + (millivolt - 50.0) / (227.0 - 50.0);
return uvi;
}
// linear interpolation between 1..11
// formula derived with spreadsheet.
float uvi = 0.0104865310 * millivolt - 1.289154988;
return uvi;
}
// -- END OF FILE --

View File

@ -0,0 +1,37 @@
//
// FILE: demUV.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo UV sensor
// DATE: 2021-09-25
#include "AnalogUVSensor.h"
AnalogUVSensor AUV;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ANALOG_UVSENSOR_LIB_VERSION: ");
Serial.println(ANALOG_UVSENSOR_LIB_VERSION);
AUV.begin(A0, 5.0, 1023);
}
void loop()
{
float uvi = AUV.read();
Serial.print("UVI: ");
Serial.print(uvi, 1);
Serial.print("\t");
Serial.println(AUV.index2color(uvi));
delay(1000);
}
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
//
// FILE: uvi_demo.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo UV sensor
// DATE: 2021-09-25
#include "AnalogUVSensor.h"
AnalogUVSensor AUV;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ANALOG_UVSENSOR_LIB_VERSION: ");
Serial.println(ANALOG_UVSENSOR_LIB_VERSION);
AUV.begin(A0, 5.0, 1023);
}
void loop()
{
float uvi = AUV.read();
Serial.print("UVI: ");
Serial.println(uvi, 1);
delay(1000);
}
// -- END OF FILE --

View File

@ -0,0 +1,41 @@
//
// FILE: uvi_demo_low_power.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo UV sensor
// DATE: 2021-09-25
#include "AnalogUVSensor.h"
AnalogUVSensor AUV;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ANALOG_UVSENSOR_LIB_VERSION: ");
Serial.println(ANALOG_UVSENSOR_LIB_VERSION);
AUV.begin(A0, 5.0, 1023);
AUV.setPowerPin(4);
AUV.switchOff();
}
void loop()
{
AUV.switchOn();
float uvi = AUV.read();
AUV.switchOff();
Serial.print("UVI: ");
Serial.println(uvi, 1);
delay(1000);
}
// -- END OF FILE --

View File

@ -0,0 +1,40 @@
//
// FILE: uvi_test.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo UV sensor
// DATE: 2021-09-25
#include "AnalogUVSensor.h"
AnalogUVSensor AUV;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ANALOG_UVSENSOR_LIB_VERSION: ");
Serial.println(ANALOG_UVSENSOR_LIB_VERSION);
AUV.begin(A0, 5.0, 1023);
for (uint16_t milliVolt = 0; milliVolt < 1210; milliVolt += 10)
{
Serial.print(milliVolt);
Serial.print("\t");
Serial.println(AUV.mV2index(milliVolt), 1);
}
Serial.println("\n Done...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,20 @@
# Syntax Coloring Map For AnalogUVsensor
# Data types (KEYWORD1)
AnalogUVSensor KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
read KEYWORD2
mV2index KEYWORD2
index2color KEYWORD2
setPowerPin KEYWORD2
switchOff KEYWORD2
switchOn KEYWORD2
# Constants (LITERAL1)
ANALOG_UVSENSOR_LIB_VERSION LITERAL1

View File

@ -0,0 +1,22 @@
{
"name": "AnalogUVSensor",
"keywords": "Analog UV sensor",
"description": "AnalogUVSensor library for Arduino. ",
"authors":
[
{
"name": "Rob Tillaart",
"email": "Rob.Tillaart@gmail.com",
"maintainer": true
}
],
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/AnalogUVSensor.git"
},
"version": "0.1.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,11 @@
name=AnalogUVSensor
version=0.1.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=AnalogUVSensor library for Arduino.
paragraph=UV index measurement
category=Sensors
url=https://github.com/RobTillaart/AnalogUVSensor
architectures=*
includes=AnalogUVSensor.h
depends=

View File

@ -0,0 +1,107 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2020-12-06
// PURPOSE: unit tests for the SHT31 temperature and humidity sensor
// https://github.com/RobTillaart/SHT31
// https://www.adafruit.com/product/2857
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
#include <ArduinoUnitTests.h>
#define A0 0
#include "Arduino.h"
#include "AnalogUVSensor.h"
unittest_setup()
{
}
unittest_teardown()
{
}
unittest(constructor)
{
fprintf(stderr, "VERSION: %s\n", ANALOG_UVSENSOR_LIB_VERSION);
AnalogUVSensor AUV;
AUV.begin(A0);
fprintf(stderr, "UV: %f\n", AUV.read());
assertEqualFloat(0.000000, AUV.read(), 0.01);
}
unittest(mv2index)
{
AnalogUVSensor AUV;
AUV.begin(A0);
float uvi;
for (uint16_t milliVolt = 0; milliVolt < 1200; milliVolt += 50)
{
uvi = AUV.mV2index(milliVolt);
fprintf(stderr, "%d\t %f\n", milliVolt, uvi);
}
assertEqualFloat(0.000000, AUV.mV2index(0), 0.01);
assertEqualFloat(0.000000, AUV.mV2index(50), 0.01);
assertEqualFloat(0.282486, AUV.mV2index(100), 0.01);
assertEqualFloat(0.847458, AUV.mV2index(200), 0.01);
assertEqualFloat(1.856804, AUV.mV2index(300), 0.01);
assertEqualFloat(2.905457, AUV.mV2index(400), 0.01);
assertEqualFloat(3.954111, AUV.mV2index(500), 0.01);
assertEqualFloat(5.002764, AUV.mV2index(600), 0.01);
assertEqualFloat(6.051417, AUV.mV2index(700), 0.01);
assertEqualFloat(7.100070, AUV.mV2index(800), 0.01);
assertEqualFloat(8.148723, AUV.mV2index(900), 0.01);
assertEqualFloat(9.197376, AUV.mV2index(1000), 0.01);
assertEqualFloat(10.24602, AUV.mV2index(1100), 0.01);
}
unittest(index2color)
{
AnalogUVSensor AUV;
AUV.begin(A0);
assertEqual('G', AUV.index2color(0));
assertEqual('G', AUV.index2color(1));
assertEqual('G', AUV.index2color(2));
assertEqual('Y', AUV.index2color(3));
assertEqual('Y', AUV.index2color(4));
assertEqual('Y', AUV.index2color(5));
assertEqual('O', AUV.index2color(6));
assertEqual('O', AUV.index2color(7));
assertEqual('R', AUV.index2color(8));
assertEqual('R', AUV.index2color(9));
assertEqual('R', AUV.index2color(10));
assertEqual('P', AUV.index2color(11));
}
unittest_main()
// -- END OF FILE --