0.6.1 MAX44009

This commit is contained in:
Rob Tillaart 2024-05-22 10:12:43 +02:00
parent 7c6b01e0e0
commit 1248e73967
18 changed files with 361 additions and 74 deletions

View File

@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.6.1] - 2024-05-17
- add **getCurrentDivisorRatio()**
- add **getAddress()** convenience
- add **max44009_performance.ino**.
- add **max44009_test_manual_mode.ino**.
- update readme.md
- update keywords.txt
- minor edits.
## [0.6.0] - 2023-10-02
- refactor constructor around I2C interface (simpler)
- remove **configure()**

View File

@ -2,10 +2,10 @@
// FILE: Max44009.h
// AUTHOR: Rob Tillaart
// VERSION: 0.6.0
// VERSION: 0.6.1
// DATE: 2010-??-??
// PURPOSE: library for MAX44009 lux sensor Arduino
// URL: https://github.com/RobTillaart/MAX44009
// breakout MAX44009 / GY-49
@ -33,7 +33,7 @@
#include "Arduino.h"
#define MAX44009_LIB_VERSION (F("0.6.0"))
#define MAX44009_LIB_VERSION (F("0.6.1"))
#define MAX44009_DEFAULT_ADDRESS 0x4A
#define MAX44009_ALT_ADDRESS 0x4B
@ -71,9 +71,13 @@ public:
Max44009(const uint8_t address = MAX44009_DEFAULT_ADDRESS, TwoWire *wire = &Wire);
bool isConnected();
uint8_t getAddress();
float getLux();
int getError();
// threshold must be between 0 and 188006
bool setHighThreshold(const float value); // returns false if value out of range
float getHighThreshold(void);
@ -82,11 +86,13 @@ public:
void setThresholdTimer(const uint8_t value); // 2 seems practical minimum
uint8_t getThresholdTimer();
void enableInterrupt() { write(MAX44009_INTERRUPT_ENABLE, 1); };
void disableInterrupt() { write(MAX44009_INTERRUPT_ENABLE, 0); };
bool interruptEnabled() { return read(MAX44009_INTERRUPT_ENABLE) & 0x01; };
uint8_t getInterruptStatus() { return read(MAX44009_INTERRUPT_STATUS) & 0x01; };
// check datasheet for detailed behaviour
void setConfiguration(uint8_t);
uint8_t getConfiguration();
@ -105,7 +111,9 @@ public:
// 110 12.5ms manual only
// 111 6.25ms manual only
void setManualMode(uint8_t CDR, uint8_t TIM);
int getIntegrationTime() { return 800 >> (getConfiguration() & 0x07); }; // ms
int getCurrentDivisorRatio(); // CDR 0/1
int getIntegrationTime(); // TIM in ms (rounded)
// TEST the math
float convertToLux(uint8_t datahigh, uint8_t datalow);

View File

@ -2,12 +2,11 @@
// FILE: max44009_interrupt.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2020-01-30
// URL: https://github.com/RobTillaart/MAX44009
#include "Wire.h"
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
@ -19,8 +18,10 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
myLux.setContinuousMode();
myLux.setHighThreshold(30);
@ -44,23 +45,29 @@ void loop()
{
lastDisplay += interval;
float lux = myLux.getLux();
int err = myLux.getError();
int st = myLux.getInterruptStatus();
if (err != 0)
int error = myLux.getError();
int status = myLux.getInterruptStatus();
if (error != 0)
{
Serial.print("Error:\t");
Serial.println(err);
Serial.println(error);
}
else
{
Serial.print("lux:\t");
Serial.print(lux);
if (st == 1) Serial.println("\tIRQ occurred");
else Serial.println();
if (status == 1)
{
Serial.println("\tIRQ occurred");
}
else
{
Serial.println();
}
}
}
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -0,0 +1,64 @@
//
// FILE: max44009_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// URL: https://github.com/RobTillaart/MAX44009
//
// This measurement is indicative for the I2C speed
// It might be affected by the intensity.
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
uint32_t start = 0;
uint32_t stop = 0;
int count = 0;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
myLux.setContinuousMode();
for (uint32_t clock = 100000; clock <= 800000; clock += 100000)
{
delay(1000); // wait for new measurement.
test(clock);
}
}
void test(uint32_t clock)
{
Wire.setClock(clock);
// time the measurement
start = micros();
float lux = myLux.getLux();
stop = micros();
// print results.
Serial.print(clock);
Serial.print("\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.print(lux);
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -2,12 +2,12 @@
// FILE: max44009_setAutomaticMode.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2020-01-30
// URL: https://github.com/RobTillaart/MAX44009
#include "Wire.h"
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
@ -19,6 +19,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
@ -33,19 +34,20 @@ void loop()
{
lastDisplay += interval;
float lux = myLux.getLux();
int err = myLux.getError();
int error = myLux.getError();
// in automatic mode TIM & CDR are automatic generated
// and read only (in manual mode they are set by the user
int conf = myLux.getConfiguration();
int CDR = (conf & 0x80) >> 3;
int TIM = (conf & 0x07);
// In automatic mode TIM and CDR are automatic generated
// and read only.
// In manual mode they are set by the user.
int config = myLux.getConfiguration();
int CDR = (config & 0x80) >> 3;
int TIM = (config & 0x07);
int integrationTime = myLux.getIntegrationTime();
if (err != 0)
if (error != 0)
{
Serial.print("Error:\t");
Serial.println(err);
Serial.println(error);
}
else
{
@ -64,5 +66,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
// FILE: max44009_setContinuousMode.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2020-01-30
// URL: https://github.com/RobTillaart/MAX44009
//
// note that lux values are repeated a number of times
// if read faster than the integration time.
@ -11,9 +11,9 @@
// NB the getLux() call takes a bit more than 1 millisecond
#include "Wire.h"
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
@ -28,6 +28,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
@ -42,14 +43,16 @@ void loop()
{
lastDisplay += interval;
count++;
// time the measurement
start = micros();
float lux = myLux.getLux();
stop = micros();
int err = myLux.getError();
if (err != 0)
int error = myLux.getError();
if (error != 0)
{
Serial.print("Error:\t");
Serial.println(err);
Serial.println(error);
}
else
{
@ -60,7 +63,10 @@ void loop()
Serial.println();
}
}
if (count == 5) myLux.clrContinuousMode();
if (count == 5)
{
myLux.clrContinuousMode();
}
if (count == 10)
{
count = 0;
@ -69,5 +75,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,11 +2,12 @@
// FILE: max44009_setManualMode.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2020-01-30
// URL: https://github.com/RobTillaart/MAX44009
#include "Wire.h"
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
@ -22,6 +23,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
@ -49,9 +51,9 @@ void loop()
}
}
// Change CDR and TIM every 5 seconds
// Note that the value of getLux() is affected
// for up to about a second.
// Change CDR and TIM every 5 seconds
// Note that the value of getLux() is affected
// for up to about a second.
if (millis() - lastChangeCDRTIM >= 5000)
{
lastChangeCDRTIM += 5000;
@ -70,5 +72,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -3,6 +3,7 @@
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2015-08-06
// URL: https://github.com/RobTillaart/MAX44009
//
// breakout MAX44009 / GY-49
//
@ -18,9 +19,9 @@
// 1 = 0x4B
#include "Wire.h"
#include "Max44009.h"
Max44009 myLux(0x4A);
uint32_t lastDisplay = 0;
@ -32,8 +33,10 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
Wire.setClock(100000);
}
@ -46,11 +49,11 @@ void loop()
{
lastDisplay += interval;
float lux = myLux.getLux();
int err = myLux.getError();
if (err != 0)
int error = myLux.getError();
if (error != 0)
{
Serial.print("Error:\t");
Serial.println(err);
Serial.println(error);
}
else
{
@ -61,4 +64,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -1,7 +1,28 @@
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
# Choosing to run compilation tests on 2 different Arduino platforms
# ESP32 specific application
platforms:
# - uno
# - leonardo
# - due
# - zero
# - leonardo
# - m4
- esp32
# - esp8266
# - mega2560
# - rpipico

View File

@ -3,6 +3,7 @@
// AUTHOR: Moritz Ulmer
// PURPOSE: demo of max44009 library
// DATE: 2020-01-19
// URL: https://github.com/RobTillaart/MAX44009
//
// NOTE: To select the alternative I2C address on the GY-49 breakout board,
// the A0 pin has to be set to 3V3. It is soldered to GND by default.
@ -10,12 +11,11 @@
// Made for ESP specific; does not work on UNO;
#include "Wire.h"
#include "Max44009.h"
// Don't begin I2C interface (Wire). Will be called in setup()
// Don't begin I2C interface (Wire). Will be called in setup()
Max44009 myLuxA(MAX44009_DEFAULT_ADDRESS, &Wire);
Max44009 myLuxB(MAX44009_ALT_ADDRESS, &Wire);
Max44009 myLuxC(MAX44009_DEFAULT_ADDRESS, &Wire1);
@ -30,6 +30,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin(19, 18);
Wire1.begin(22, 23);
@ -49,5 +50,5 @@ void loop() {
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -0,0 +1,81 @@
//
// FILE: max44009_test_manualmode.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// URL: https://github.com/RobTillaart/MAX44009
#include "Max44009.h"
Max44009 myLux(MAX44009_DEFAULT_ADDRESS, &Wire);
uint32_t lastDisplay = 0;
uint32_t lastChangeCDRTIM = 0;
uint8_t CDR = 0;
uint8_t TIM = 0;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
myLux.setManualMode(CDR, TIM);
}
void loop()
{
uint32_t interval = 100;
if (millis() - lastDisplay >= interval)
{
lastDisplay += interval;
float lux = myLux.getLux();
int err = myLux.getError();
if (err != 0)
{
Serial.print("Error:\t");
Serial.println(err);
}
else
{
Serial.print("lux:\t");
Serial.println(lux);
}
}
// Change CDR and TIM every 5 seconds
// Note that the value of getLux() is affected
// for up to about a second.
if (millis() - lastChangeCDRTIM >= 5000)
{
lastChangeCDRTIM += 5000;
TIM++;
if (TIM == 4)
{
TIM = 0;
CDR = (CDR + 1) & 1;
}
myLux.setManualMode(CDR, TIM);
Serial.print("CDR:\t");
Serial.print((int)CDR);
Serial.print("\t");
Serial.print(myLux.getCurrentDivisorRatio()); // read from config
Serial.print("\tTIM:\t");
Serial.print((int)TIM);
Serial.print("\t");
Serial.print(myLux.getIntegrationTime()); // read from config
Serial.print(" ms\n");
}
}
// -- END OF FILE --

View File

@ -2,12 +2,12 @@
// FILE: max44009_two_sensors.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo of max44009 library
// DATE: 2020-02-16
// URL: https://github.com/RobTillaart/MAX44009
#include "Wire.h"
#include "Max44009.h"
Max44009 LuxA(0x4A);
Max44009 LuxB(0x4B);
@ -21,8 +21,10 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX44009_LIB_VERSION: ");
Serial.println(MAX44009_LIB_VERSION);
Serial.println();
Wire.begin();
Wire.setClock(100000);
Serial.print("\n\tCOUNT\tLUXA\tLUXB\n");
@ -46,19 +48,19 @@ void loop()
Serial.print('\t');
float lux = LuxA.getLux();
int err = LuxA.getError();
if (err != 0) Serial.print(err);
else Serial.print(lux);
int error = LuxA.getError();
if (error != 0) Serial.print(error);
else Serial.print(lux);
Serial.print('\t');
lux = LuxB.getLux();
err = LuxB.getError();
if (err != 0) Serial.print(err);
else Serial.print(lux);
error = LuxB.getError();
if (error != 0) Serial.print(error);
else Serial.print(lux);
Serial.println();
}
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -6,6 +6,8 @@ Max44009 KEYWORD1
# Methods and Functions (KEYWORD2)
isConnected KEYWORD2
getAddress() KEYWORD2
getLux KEYWORD2
getError KEYWORD2
@ -25,10 +27,11 @@ setConfiguration KEYWORD2
getConfiguration KEYWORD2
setAutomaticMode KEYWORD2
setContinuousMode KEYWORD2
setManualMode KEYWORD2
clrContinuousMode KEYWORD2
getIntegrationTime KEYWORD2
setManualMode KEYWORD2
getIntegrationTime KEYWORD2
getCurrentDivisorRatio KEYWORD2
# Instances (KEYWORD2)

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Max44009.git"
},
"version": "0.6.0",
"version": "0.6.1",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=Max44009
version=0.6.0
version=0.6.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for MAX44009 I2C LUX sensor Arduino.

View File

@ -9,7 +9,8 @@
#include "Max44009.h"
// MAX44007 KEY VALUES
// MAX44009 KEY VALUES
#define MAX44009_MIN_LUX (0.045)
#define MAX44009_MAX_LUX (188006.0)
@ -31,6 +32,12 @@ bool Max44009::isConnected()
}
uint8_t Max44009::getAddress()
{
return _address;
}
float Max44009::getLux(void)
{
uint8_t datahigh = read(MAX44009_LUX_READING_HIGH);
@ -115,7 +122,7 @@ uint8_t Max44009::getConfiguration()
void Max44009::setAutomaticMode()
{
// CDR & TIM cannot be written in automatic mode
// CDR and TIM cannot be written in automatic mode
uint8_t config = read(MAX44009_CONFIGURATION);
config &= ~MAX44009_CFG_MANUAL;
write(MAX44009_CONFIGURATION, config);
@ -140,7 +147,7 @@ void Max44009::clrContinuousMode()
void Max44009::setManualMode(uint8_t CDR, uint8_t TIM)
{
if (CDR !=0) CDR = 1; // only 0 or 1
if (CDR !=0) CDR = 1; // only 0 or 1
if (TIM > 7) TIM = 7;
uint8_t config = read(MAX44009_CONFIGURATION);
config |= MAX44009_CFG_MANUAL;
@ -150,6 +157,22 @@ void Max44009::setManualMode(uint8_t CDR, uint8_t TIM)
}
int Max44009::getCurrentDivisorRatio()
{
uint8_t CDR = read(MAX44009_CONFIGURATION) & 0x08;
return CDR >> 3;
}
int Max44009::getIntegrationTime()
{
uint8_t TIM = read(MAX44009_CONFIGURATION) & 0x07;
return 800 >> TIM;
}
// datahigh = [eeee mmmm]
// datalow = [ mmmm]
float Max44009::convertToLux(uint8_t datahigh, uint8_t datalow)
{
uint8_t exponent = datahigh >> 4;
@ -168,7 +191,8 @@ bool Max44009::setThreshold(const uint8_t reg, const float value)
// CHECK RANGE OF VALUE
if ((value < 0.0) || (value > MAX44009_MAX_LUX)) return false;
uint32_t mantissa = round(value * (1.0 / MAX44009_MIN_LUX)); // compile time optimized.
// compile time optimized.
uint32_t mantissa = round(value * (1.0 / MAX44009_MIN_LUX));
uint8_t exponent = 0;
while (mantissa > 255)
{
@ -185,7 +209,8 @@ bool Max44009::setThreshold(const uint8_t reg, const float value)
float Max44009::getThreshold(uint8_t reg)
{
uint8_t datahigh = read(reg);
float lux = convertToLux(datahigh, 0x08); // 0x08 = correction for lost bits
// 0x08 = correction for lost bits
float lux = convertToLux(datahigh, 0x08);
return lux;
}

View File

@ -25,7 +25,7 @@ dynamic range from 0.045 lux to 188,000 lux.
#### MAX44007
The MAX44007 is an almost identical sensor that uses a step size of 0.025.
This implies that this library is not useable 1 to 1 for the MAX44007, however some parts will work/
This implies that this library is not useable 1 to 1 for the MAX44007, however some parts will work.
#### Related
@ -59,6 +59,51 @@ This implies that this library is not useable 1 to 1 for the MAX44007, however s
//
```
## I2C
#### Address
The MAX44009 can have 2 addresses:
- 0x4A = **MAX44009_DEFAULT_ADDRESS**
- 0x4B = **MAX44009_ALT_ADDRESS**
See schema above.
#### I2C 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
#### I2C Performance
Performance of the getLux function in microseconds.
| Clock | UNO | ESP32 | Notes |
|:--------:|:-------:|:-------:|:-------:|
| 100000 | | |
| 200000 | | |
| 300000 | | |
| 400000 | | |
| 500000 | | |
| 600000 | | |
TODO fill table.
## Interface
@ -71,6 +116,7 @@ This implies that this library is not useable 1 to 1 for the MAX44007, however s
- **Max44009(const uint8_t address = MAX44009_DEFAULT_ADDRESS, TwoWire \*wire = &Wire)** Constructor.
Optional address and optional I2C interface.\
- **bool isConnected()** returns true if the device address configured is available on I2C bus.
- **uint8_t getAddress()** returns device address. Convenience function.
NOTE: The user must call **Wire.begin()** or **Wire.begin(SDA, SCL)** in **setup()**.
@ -130,7 +176,7 @@ check datasheet for details
Check datasheet for details.
CCR = Current Divisor Ratio.
CDR = Current Divisor Ratio.
TIM = Integration time.
@ -141,7 +187,10 @@ Advantage is that the latest data is always available fast.
- **void clrContinuousMode()** uses less power so better for LOW power configurations.
- **void setManualMode(uint8_t CDR, uint8_t TIM)** Set the Current Divisor Ratio and the
integration time manually. Effectively disable automatic mode.
- **int getIntegrationTime()** returns the set integration time in milliseconds
- **int getIntegrationTime()** returns the set integration time in milliseconds.
Note these are rounded down (12 == 12.5 and 6 == 6.25) to minimize math.
- **int getCurrentDivisorRatio()** returns the set Current Divisor Ratio.
This is either 0 (full intensity) or 1 (1/8th intensity).
```
CDR = Current Divisor Ratio
@ -162,7 +211,7 @@ integration time manually. Effectively disable automatic mode.
### Test functions
Function for the conversion math, not meant to be used directly,
but by making them public they become testable.
but by making it public the math becomes testable.
- **float convertToLux(uint8_t dataHigh, uint8_t dataLow)** convert intern register
format to a LUX value.
@ -196,12 +245,17 @@ Pull ups on I2C bus are recommended.
#### Must
- improve documentation
- buy hardware
#### Should
- run performance test on UNO and ESP32.
#### Could
- merge MAX44007 / MAX44009 library in the future. (shared base class?)
- read data high and low in one call?
- convertToLux() overflow test, when exponent == 15.
#### Wont

View File

@ -32,7 +32,6 @@
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "Max44009.h"
@ -80,9 +79,9 @@ unittest(test_constructor)
Wire.begin();
assertEqual(MAX44009_OK, LuxA.getError());
assertTrue(LuxA.isConnected()); // TODO should be false...
assertTrue(LuxA.isConnected()); // TODO should be false...
// TODO more tests if WIRE works...
// TODO more tests if WIRE works...
}