0.1.0 LTR390_DFR

This commit is contained in:
Rob Tillaart 2024-05-09 18:25:55 +02:00
parent 0fe93f2c99
commit cf8200a3e8
17 changed files with 944 additions and 0 deletions

View File

@ -0,0 +1,30 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
# - due
# - zero
# - leonardo
- m4
- esp32
- esp8266
# - mega2560
- rpipico
libraries:
- "printHelpers"

View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart
custom: "https://www.paypal.me/robtillaart"

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- 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
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- 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
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: json-syntax-check
uses: limitusus/json-syntax-check@v2
with:
pattern: "\\.json$"

View File

@ -0,0 +1,13 @@
# Change Log LTR390_DFR
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.0] - 2024-04-29
- initial version

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2024 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,343 @@
#pragma once
//
// FILE: LTR390_DFR.h
// AUTHOR: Rob Tillaart
// DATE: 2024-04-29
// VERSION: 0.1.0
// PURPOSE: Arduino library for the I2C LTR390 UV sensor (DF Robotics edition).
// URL: https://github.com/RobTillaart/LTR390_DFR
#include "Arduino.h"
#include "Wire.h"
#define LTR390_DFR_LIB_VERSION (F("0.1.0"))
// LTR390 ERROR CODES
// TODO
// DF_ROBOTICS LTR390 REGISTERS (16 bits)
#define LTR390_PID 0x00
#define LTR390_ADDRESS 0x02
#define LTR390_FIRMWARE 0x05
#define LTR390_PART_ID 0x06
#define LTR390_ALS_DATA_0 0x07
#define LTR390_ALS_DATA_1 0x08
#define LTR390_UVS_DATA_0 0x09
#define LTR390_UVS_DATA_1 0x0A
#define LTR390_GAIN 0x0B
#define LTR390_INT_CONFIG 0x0C
#define LTR390_ALS_UVS_THRES_UP_0 0x0D
#define LTR390_ALS_UVS_THRES_UP_1 0x0E
#define LTR390_ALS_UVS_THRES_LOW_0 0x0F
#define LTR390_ALS_UVS_THRES_LOW_1 0x10
#define LTR390_ALS_UVS_THRES_VAR_DATA 0x11
#define LTR390_ALS_UVS_MEAS_RATE 0x12
#define LTR390_MAIN_CTRL 0x13
class LTR390_DFR
{
public:
LTR390_DFR(TwoWire *wire = &Wire)
{
_address = 0x1C; // Fixed 0x1C = 28 = DF_ROBOTICS
_wire = wire;
_gain = 3.0; // default
_time = 0.1; // default 18 bit, 100 ms.
_UVsensitivity = 1.0;
}
bool begin()
{
return isConnected();
}
bool isConnected()
{
_wire->beginTransmission(_address);
return (_wire->endTransmission() == 0);
}
uint8_t getAddress()
{
return _address;
}
//////////////////////////////////////////////
//
// MAIN CONTROL
//
void setALSMode()
{
writeRegister(LTR390_MAIN_CTRL, 0x02);
}
void setUVSMode()
{
writeRegister(LTR390_MAIN_CTRL, 0x0A);
}
uint8_t reset()
{
writeRegister(LTR390_MAIN_CTRL, 0x10);
delay(100);
return readRegister(LTR390_MAIN_CTRL);
}
//////////////////////////////////////////////
//
// PART_ID
//
uint8_t getPartID()
{
uint8_t reg = readRegister(LTR390_PART_ID);
return reg >> 4;
}
uint8_t getRevisionID()
{
uint8_t reg = readRegister(LTR390_PART_ID);
return reg & 0x0F;
}
//////////////////////////////////////////////
//
// GET DATA
//
uint32_t getALSData()
{
return readRegister(8) * 65536UL + readRegister(7);
}
// page 22 datasheet
float getLux(float wfac = 1)
{
float lux = 0.6 * getALSData() /( _gain * _time);
if (wfac > 1) lux *= wfac;
return lux;
}
uint32_t getUVSData()
{
return readRegister(10) * 65536UL + readRegister(9);
}
// page 22 datasheet
float getUVI(float wfac = 1)
{
float uvi = getUVSData() / _UVsensitivity;
if (wfac > 1) uvi *= wfac;
return uvi;
}
//////////////////////////////////////////////
//
// MEASUREMENT CONFIGURATION
//
// experimental...
//
// TODO does not work as expected yet
//
void setGain(uint8_t gain) // 0..4
{
uint16_t value = gain;
if (value > 4) value = 4;
writeRegister(LTR390_GAIN, value);
_gain = 1;
if (value == 1) _gain = 3;
if (value == 2) _gain = 6;
if (value == 3) _gain = 9;
if (value == 4) _gain = 18;
}
uint8_t getGain()
{
uint16_t reg = readRegister(LTR390_GAIN);
return reg & 0x07;
}
// resolution = 0..5 See datasheet P14.
// time = 0..7 See datasheet P14.
void setMeasurement(uint8_t resolution, uint8_t time)
{
uint16_t value = (resolution << 4) | time;
writeRegister(LTR390_ALS_UVS_MEAS_RATE, value);
_time = 2.000;
if (time == 0) _time = 0.025;
if (time == 1) _time = 0.050;
if (time == 2) _time = 0.100;
if (time == 3) _time = 0.200;
if (time == 4) _time = 0.500;
if (time == 5) _time = 1.000;
}
uint8_t getResolution()
{
uint16_t reg = readRegister(LTR390_ALS_UVS_MEAS_RATE);
return (reg >> 4) & 0x07;
}
uint8_t getTime()
{
uint16_t reg = readRegister(LTR390_ALS_UVS_MEAS_RATE);
return reg & 0x07;
}
/*
//////////////////////////////////////////////
//
// MAIN STATUS
// TODO elaborate - need split? or masks?
//
uint8_t getStatus()
{
uint8_t reg = readRegister(LTR390_MAIN_STATUS);
return reg & 0x38;
}
*/
/*
//////////////////////////////////////////////
//
// INTERRUPT
//
int setInterruptConfig(uint8_t value)
{
return writeRegister(LTR390_INT_CFG, value);
}
uint8_t getInterruptConfig()
{
return readRegister(LTR390_INT_CFG);
}
int setInterruptPersist(uint8_t value)
{
return writeRegister(LTR390_INT_PST, value);
}
uint8_t getInterruptPersist()
{
return readRegister(LTR390_INT_PST);
}
*/
/*
//////////////////////////////////////////////
//
// THRESHOLD
//
void setHighThreshold(uint32_t value)
{
writeRegister(LTR390_ALS_UVS_THRES_UP_0, value & 0xFF);
value >>= 8;
writeRegister(LTR390_ALS_UVS_THRES_UP_1, value & 0xFF);
value >>= 8;
writeRegister(LTR390_ALS_UVS_THRES_UP_2, value & 0x0F);
}
uint32_t getHighThreshold()
{
uint32_t value = readRegister(LTR390_ALS_UVS_THRES_UP_2) & 0x0F;
value <<= 8;
value += readRegister(LTR390_ALS_UVS_THRES_UP_1);
value <<= 8;
value += readRegister(LTR390_ALS_UVS_THRES_UP_0);
return value;
}
void setLowThreshold(uint32_t value)
{
writeRegister(LTR390_ALS_UVS_THRES_LOW_0, value & 0xFF);
value >>= 8;
writeRegister(LTR390_ALS_UVS_THRES_LOW_1, value & 0xFF);
value >>= 8;
writeRegister(LTR390_ALS_UVS_THRES_LOW_2, value & 0x0F);
}
uint32_t getLowThreshold()
{
uint32_t value = readRegister(LTR390_ALS_UVS_THRES_LOW_2) & 0x0F;
value <<= 8;
value += readRegister(LTR390_ALS_UVS_THRES_LOW_1);
value <<= 8;
value += readRegister(LTR390_ALS_UVS_THRES_LOW_0);
return value;
}
*/
//////////////////////////////////////////////
//
// PRIVATE TODO move.
//
int writeRegister(uint8_t reg, uint16_t value)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->write(value & 0xFF);
_wire->write(value >> 8);
int n = _wire->endTransmission();
if (n != 0)
{
// Serial.print("write:\t");
// Serial.println(n);
}
return n;
}
uint16_t readRegister(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
int n = _wire->endTransmission();
if (n != 0)
{
// Serial.print("read:\t");
// Serial.println(n);
return n;
}
n = _wire->requestFrom(_address, (uint8_t)2);
if (n != 2)
{
// Serial.print("requestFrom: \t");
// Serial.print(n);
return n;
}
uint16_t data = _wire->read();
return data + _wire->read() * 256;
}
private:
TwoWire * _wire;
uint8_t _address;
// for LUX math
float _gain;
float _time;
float _UVsensitivity;
};
// -- END OF FILE --

View File

@ -0,0 +1,141 @@
[![Arduino CI](https://github.com/RobTillaart/LTR390_DFR/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/LTR390_DFR/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/LTR390_DFR/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/LTR390_DFR/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/LTR390_DFR/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/LTR390_DFR.svg)](https://github.com/RobTillaart/LTR390_DFR/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/LTR390_DFR/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/LTR390_DFR.svg?maxAge=3600)](https://github.com/RobTillaart/LTR390_DFR/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/LTR390_DFR.svg)](https://registry.platformio.org/libraries/robtillaart/LTR390_DFR)
# LTR390_DFR
Arduino library for the I2C LTR390 UV sensor (DF Robotics edition).
## Description
**Experimental**
This library is to read the LTR390 UV sensor on the DF Robotics
break-out board.
Operating voltage range: **3.0V .. 5.0V** (tolerant).
## I2C
The break-out has an address of 0x1C == 28 decimal.
#### I2C Speed
The device should work on 100 kHz and 400 kHz I2C bus.
To be tested.
#### Multiplexing
Sometimes you need to control more devices than possible with the default
address range the device provides.
This is possible with an I2C multiplexer e.g. TCA9548 which creates up
to eight channels (think of it as I2C subnets) which can use the complete
address range of the device.
Drawback of using a multiplexer is that it takes more administration in
your code e.g. which device is on which channel.
This will slow down the access, which must be taken into account when
deciding which devices are on which channel.
Also note that switching between channels will slow down other devices
too if they are behind the multiplexer.
- https://github.com/RobTillaart/TCA9548
#### Related
- https://github.com/RobTillaart/LTR390_RT (native LTR390)
- https://github.com/RobTillaart/LTR390_DFR (DF Robotics variant)
## Interface TODO elaborate...
```cpp
#include "LTR390_DFR.h"
```
#### Constructor
- **LTR390_DFR(TwoWire \* wire = &Wire)** Constructor
with optional Wire interface.
- **bool begin()** returns true if device 0x1C can be seen on the I2C bus.
- **bool isConnected()** returns true if device 0x1C can be seen on I2C bus.
- **uint8_t getAddress()** returns 0x1C, fixed address, for convenience.
#### Main control
- **void setALSMode()**
- **void setUVSMode()**
- **void reset()** blocks for 100 ms.
#### Measurement configuration
- **void setGain(uint8_t gain)** gain = 0..4,
- **uint8_t getGain()** returns set value.
- **void setMeasurement(uint8_t resolution, uint8_t time)**
- **uint8_t getResolution()**
- **uint8_t getTime()**
#### Part and revision ID
- **uint8_t getPartID()** returns 11.
- **uint8_t getRevisionID()** returns 2.
#### Get data
- **uint32_t getALSData()**
- **float getLUX(float wfac = 1)** wfac = window factor,
- **uint32_t getUVSData()**
- **float getUVI(float wfac = 1)** wfac = window factor,
## Future
#### Must
- Elaborate and improve documentation a lot.
- add tables, ranges etc.
- test with right hardware.
- keep in sync with LTR390_RT when possible
#### Should
- add examples
- fix / elaborate TODO's in code.
- status and error codes
- interrupts and thresholds
- add setUVsensitivity()
#### Could
- add error handling
- unit test ==> test examples
#### Wont
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

View File

@ -0,0 +1,56 @@
//
// FILE: LTR390_ALS_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test basic behaviour and performance
// URL: https://github.com/RobTillaart/LTR390_DFR
//
// can be used with plotter.
#include "LTR390_DFR.h"
LTR390_DFR uv;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
Serial.print("LTR390_DFR_LIB_VERSION: ");
Serial.println(LTR390_DFR_LIB_VERSION);
Serial.println();
Wire.begin();
uv.begin();
while (uv.isConnected() == false)
{
Serial.println("Could not connect, fix and reboot");
delay(1000);
}
Serial.println("Device found.");
Serial.print("RESET:\t");
Serial.println(uv.reset());
Serial.print("PARTID:\t");
Serial.println(uv.getPartID());
Serial.print("REVID:\t");
Serial.println(uv.getRevisionID());
uv.setALSMode();
delay(1000);
Serial.println("End setup...");
}
void loop()
{
delay(1000);
Serial.println(uv.getALSData());
}
// -- END OF FILE --

View File

@ -0,0 +1,52 @@
//
// FILE: LTR390_UV_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test basic behaviour and performance
// URL: https://github.com/RobTillaart/LTR390
#include "LTR390_DFR.h"
LTR390_DFR uv;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
Serial.print("LTR390_DFR_LIB_VERSION: ");
Serial.println(LTR390_DFR_LIB_VERSION);
Serial.println();
Wire.begin();
if (uv.begin() == false)
{
Serial.println("Could not connect, fix and reboot");
}
else
{
Serial.println("Device found.");
}
Serial.print("PARTID:\t");
Serial.println(uv.getPartID());
Serial.print("REVID:\t");
Serial.println(uv.getRevisionID());
uv.setUVSMode();
Serial.println("\ndone...");
}
void loop()
{
delay(1000);
Serial.println(uv.getUVSData());
}
// -- END OF FILE --

View File

@ -0,0 +1,67 @@
//
// FILE: LTR390_dump_registers.ino
// AUTHOR: Rob Tillaart
// PURPOSE: dump
// URL: https://github.com/RobTillaart/LTR390_DFR
#include "LTR390_DFR.h"
LTR390_DFR uv;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
Serial.print("LTR390_DFR_LIB_VERSION: ");
Serial.println(LTR390_DFR_LIB_VERSION);
Serial.println();
Wire.begin();
Wire.setClock(100000);
if (uv.begin() == false)
{
Serial.println("Could not connect, fix and reboot");
}
else
{
Serial.println("Device found.");
}
// register range according to DFrobotics
for (uint8_t reg = 0x00; reg < 0x14; reg++)
{
Serial.print(reg, HEX);
Serial.print("\t");
Serial.print(uv.readRegister(reg), HEX);
Serial.print("\t(");
Serial.print(uv.readRegister(reg));
Serial.print(")\n");
}
Serial.println();
Serial.println("\ndone...");
// select mode
// uv.setUVSMode();
uv.setALSMode();
}
void loop()
{
// Serial.print("ALS:\t");
// Serial.println(uv.getALSData());
// delay(1000);
// Serial.print("UVS:\t");
// Serial.println(uv.getUVSData());
// delay(1000);
}
// -- END OF FILE --

View File

@ -0,0 +1,50 @@
//
// FILE: LTR390_getLux.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test basic behaviour and performance
// URL: https://github.com/RobTillaart/LTR390_DFR
//
// can be used with plotter.
#include "LTR390_DFR.h"
LTR390_DFR uv;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
Serial.print("LTR390_DFR_LIB_VERSION: ");
Serial.println(LTR390_DFR_LIB_VERSION);
Serial.println();
Wire.begin();
uv.begin();
while (uv.isConnected() == false)
{
Serial.println("Could not connect, fix and reboot");
delay(1000);
}
Serial.println("Device found.");
uv.setALSMode();
Serial.println("RAW, LUX");
}
void loop()
{
delay(1000);
Serial.print(uv.getALSData());
Serial.print("\t");
Serial.println(uv.getLux());
}
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
# Syntax Colouring Map For LTR390_DFR
# Data types (KEYWORD1)
LTR390_DFR KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
isConnected KEYWORD2
getAddress KEYWORD2
setALSMode KEYWORD2
setUVSMode KEYWORD2
reset KEYWORD2
getPartID KEYWORD2
getRevisionID KEYWORD2
getALSData KEYWORD2
getLUX KEYWORD2
getUVSData KEYWORD2
getUVI KEYWORD2
setGain KEYWORD2
getGain KEYWORD2
setMeasurement KEYWORD2
getResolution KEYWORD2
getTime KEYWORD2
# Constants (LITERAL1)
LTR390_DFR_LIB_VERSION LITERAL1

View File

@ -0,0 +1,23 @@
{
"name": "LTR390_DFR",
"keywords": "UV, LUX",
"description": "Arduino library for the I2C LTR390 UV sensor. (DF Robotics edition)",
"authors":
[
{
"name": "Rob Tillaart",
"email": "Rob.Tillaart@gmail.com",
"maintainer": true
}
],
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/LTR390_DFR.git"
},
"version": "0.1.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
"headers": "LTR390_DFR.h"
}

View File

@ -0,0 +1,11 @@
name=LTR390_DFR
version=0.1.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for the I2C LTR390 UV sensor (DF Robotics edition).
paragraph=
category=Sensors
url=https://github.com/RobTillaart/LTR390_DFR
architectures=*
includes=LTR390_DFR.h
depends=

View File

@ -0,0 +1,51 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2024-04-29
// PURPOSE: unit tests for the LTR390 library
// URL: https://github.com/RobTillaart/LTR390_DFR
//
// supported assertions
// https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
// assertNotNull(actual)
#include <ArduinoUnitTests.h>
#include "LTR390_DFR.h"
unittest_setup()
{
fprintf(stderr, "LTR390_DFR_LIB_VERSION: %s\n", (char *) LTR390_DFR_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constructor)
{
LTR390_DFR dev;
assertEqual(0x1C, dev.getAddress());
}
unittest_main()
// -- END OF FILE --