0.2.0 PCF8591

This commit is contained in:
rob tillaart 2023-02-23 16:01:06 +01:00
parent 23e4c50eab
commit 7fd36cbc53
13 changed files with 190 additions and 82 deletions

View File

@ -6,7 +6,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update

View File

@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6

View File

@ -10,7 +10,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:

View File

@ -6,13 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.2.0] - 2023-02-23
- fix#10 analogRead() for differential modi.
- add defines for 4 different modi
- add four comparator functions (wrappers).
- update readme.md
- update keywords.txt
- update GitHub actions
- update license 2023
- minor edits
----
## [0.1.3] - 2022-11-21
- add RP2040 to build-CI
- add changelog.md
- move code from .h to .cpp
- update unit test
## [0.1.2] - 2021-12-23
- update library.json
- update readme.md
@ -20,7 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- minor edits
## [0.1.1] - 2021-01-14
- added WireN
- added WireN
- improve error handling.
## [0.1.0] - 2021-01-04

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2022 Rob Tillaart
Copyright (c) 2020-2023 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

View File

@ -2,7 +2,7 @@
// FILE: PCF8591.cpp
// AUTHOR: Rob Tillaart
// DATE: 2020-03-12
// VERSION: 0.1.3
// VERSION: 0.2.0
// PURPOSE: I2C PCF8591 library for Arduino
// URL: https://github.com/RobTillaart/PCF8591
@ -50,6 +50,7 @@ bool PCF8591::begin(uint8_t sda, uint8_t scl, uint8_t val)
}
#endif
bool PCF8591::begin(uint8_t val)
{
_wire->begin();
@ -62,10 +63,11 @@ bool PCF8591::begin(uint8_t val)
bool PCF8591::isConnected()
{
_wire->beginTransmission(_address);
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
return( _error == PCF8591_OK);
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
return (_error == PCF8591_OK);
}
//////////////////////////////////////////////////////////
//
// ADC PART
@ -73,19 +75,19 @@ bool PCF8591::isConnected()
void PCF8591::enableINCR()
{
_control |= PCF8591_INCR_FLAG;
};
}
void PCF8591::disableINCR()
{
_control &= ~PCF8591_INCR_FLAG;
};
}
bool PCF8591::isINCREnabled()
{
return ((_control & PCF8591_INCR_FLAG) > 0);
};
}
uint8_t PCF8591::analogRead(uint8_t channel, uint8_t mode)
@ -95,44 +97,41 @@ uint8_t PCF8591::analogRead(uint8_t channel, uint8_t mode)
_error = PCF8591_MODE_ERROR;
return 0;
}
_control &= 0b01000100; // clear all except flags
_control &= 0b01000100; // clear all except flags
_control |= (mode << 4);
_error = PCF8591_CHANNEL_ERROR;
switch(mode)
{
case 0:
case PCF8591_FOUR_SINGLE_CHANNEL:
if (channel > 3) return 0;
_control |= channel;
break;
case 1:
case PCF8591_THREE_DIFFERENTIAL:
if (channel > 2) return 0;
_control |= (channel << 4);
break;
case 2:
case PCF8591_MIXED:
if (channel > 2) return 0;
_control |= (channel << 4);
break;
case 3:
case PCF8591_TWO_DIFFERENTIAL:
if (channel > 1) return 0;
_control |= (channel << 4);
break;
default:
return 0;
}
_control |= channel;
_error = PCF8591_OK;
// NOTE: one must read two values to get an up to date value.
// Page 8 datasheet.
// NOTE: one must read two values to get an up to date value.
// Page 8 datasheet.
_wire->beginTransmission(_address);
_wire->write(_control);
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
if (_error != 0) return PCF8591_I2C_ERROR;
if (_wire->requestFrom(_address, (uint8_t)2) != 2)
{
_error = PCF8591_I2C_ERROR;
return _adc[channel]; // known last value
return _adc[channel]; // return last known value
}
_wire->read();
_adc[channel] = _wire->read();
@ -142,14 +141,16 @@ uint8_t PCF8591::analogRead(uint8_t channel, uint8_t mode)
uint8_t PCF8591::analogRead4()
{
_control &= 0b01000100; // clear all except flags
// clear all except flags
// MODE == PCF8591_FOUR_SINGLE_CHANNEL.
_control &= 0b01000100;
uint8_t channel = 0;
_control |= channel;
enableINCR();
_wire->beginTransmission(_address);
_wire->write(_control);
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
_error = _wire->endTransmission(); // default == 0 == PCF8591_OK
if (_error != 0)
{
_error = PCF8591_I2C_ERROR;
@ -180,6 +181,36 @@ uint8_t PCF8591::lastRead(uint8_t channel)
};
// comparator calls need testing.
int PCF8591::readComparator_01()
{
int8_t v = analogRead(0, 3);
return v;
}
int PCF8591::readComparator_23()
{
int8_t v = analogRead(1, 3);
return v;
}
int PCF8591::readComparator_03()
{
int8_t v = analogRead(0, 1);
return v;
}
int PCF8591::readComparator_13()
{
int8_t v = analogRead(1, 1);
return v;
}
//////////////////////////////////////////////////////////
//
// DAC PART

View File

@ -3,7 +3,7 @@
// FILE: PCF8591.h
// AUTHOR: Rob Tillaart
// DATE: 2020-03-12
// VERSION: 0.1.3
// VERSION: 0.2.0
// PURPOSE: I2C PCF8591 library for Arduino
// URL: https://github.com/RobTillaart/PCF8591
@ -12,14 +12,20 @@
#include "Wire.h"
#define PCF8591_LIB_VERSION (F("0.1.3"))
#define PCF8591_LIB_VERSION (F("0.2.0"))
#define PCF8591_OK 0x00
#define PCF8591_PIN_ERROR 0x81
#define PCF8591_I2C_ERROR 0x82
#define PCF8591_MODE_ERROR 0x83
#define PCF8591_CHANNEL_ERROR 0x84
#define PCF8591_ADDRESS_ERROR 0x85
#define PCF8591_OK 0x00
#define PCF8591_PIN_ERROR 0x81
#define PCF8591_I2C_ERROR 0x82
#define PCF8591_MODE_ERROR 0x83
#define PCF8591_CHANNEL_ERROR 0x84
#define PCF8591_ADDRESS_ERROR 0x85
// datasheet figure 4 page 6
#define PCF8591_FOUR_SINGLE_CHANNEL 0x00 // default
#define PCF8591_THREE_DIFFERENTIAL 0x01
#define PCF8591_MIXED 0x02
#define PCF8591_TWO_DIFFERENTIAL 0x03
class PCF8591
@ -27,6 +33,7 @@ class PCF8591
public:
explicit PCF8591(const uint8_t address = 0x48, TwoWire *wire = &Wire);
// set initial value for DAC, default 0
#if defined (ESP8266) || defined(ESP32)
bool begin(uint8_t sda, uint8_t scl, uint8_t value = 0);
#endif
@ -42,18 +49,26 @@ public:
bool isINCREnabled();
// analogRead() returns the value.
uint8_t analogRead(uint8_t channel, uint8_t mode = 0);
// analogRead4() returns PCF8591_OK or an error code.
uint8_t analogRead4();
// mode 0 = PCF8591_FOUR_SINGLE_CHANNEL
uint8_t analogRead(uint8_t channel, uint8_t mode = 0);
// analogRead4() returns PCF8591_OK or an error code.
uint8_t analogRead4();
// access the 4 channels read with analogRead4()
uint8_t lastRead(uint8_t channel);
// datasheet par 8.2 figure 4
// not for PCF8591_MIXED mode.
// comparator calls need testing.
int readComparator_01(); // channel 0 mode 3
int readComparator_23(); // channel 1 mode 3
int readComparator_03(); // channel 0 mode 1
int readComparator_13(); // channel 1 mode 1
// DAC PART
void enableDAC();
void disableDAC();
bool isDACEnabled();
bool analogWrite(uint8_t value = 0); // returns true on success.
uint8_t lastWrite(); // returns last successful write

View File

@ -28,41 +28,77 @@ The library only supports it for the mode 0 (plain ADC, no differential).
The **lastRead()** function is needed to get access to the values.
First tests shows it is 2.6 x faster than 4 individual reads.
**analogRead4()** needs investigation in the future for the other modi.
## Interface
### Generic
```cpp
#include "PCF8591.h"
```
- **PCF8591(const uint8_t address, TwoWire \*wire = &Wire)** constructor with I2C address,
default is 0x48, optional set the WireN I2C bus.
- **bool begin(uint8_t sda, uint8_t scl, uint8_t value = 0)** set wire pins for ESP series.
Also set initial value for the DAC. Returns **true** if successful.
- **bool begin(uint8_t value = 0)** Set initial value for the DAC. Returns **true** if successful.
#### Constructor
- **PCF8591(const uint8_t address = 0x48, TwoWire \*wire = &Wire)** constructor with I2C address.
Default is 0x48, optional set the WireN I2C bus.
- **bool begin(uint8_t sda, uint8_t scl, uint8_t value = 0)** set wire pins for ESP series.
Also set initial value for the DAC.
Returns **true** if successful.
- **bool begin(uint8_t value = 0)** Set initial value for the DAC.
Returns **true** if successful.
- **bool isConnected()** test to see if chip can be reached.
### ADC channels
#### ADC channels
The PCF8591 has four 8 bit ADC channels. Values = 0..255.
- **void enableINCR()** used in analogRead4(). Could become private in the future.
- **void enableINCR()** used in analogRead4().
Could become private in the future.
- **void disableINCR()** idem.
- **bool isINCREnabled()** idem.
- **uint8_t analogRead(uint8_t channel, uint8_t mode = 0)** read one of the 4 analogue ports.
Default mode is single ports. For comparator modes test datasheet.
- **uint8_t analogRead4()** read all 4 channels in one call.
- **uint8_t analogRead(uint8_t channel, uint8_t mode = 0)** returns value of the analogue channel.
Return 0 in case of an error, so check **lastError()** to be verify validity.
Default mode is PCF8591_FOUR_SINGLE_CHANNEL, see table below.
For details comparator modes see datasheet figure 4 page 6.
- **uint8_t analogRead4()** read all 4 channels in one call.
Works in PCF8591_FOUR_SINGLE_CHANNEL mode only.
Uses **enableINCR()** to do that efficiently.
It is about 2.6 x faster than 4 individual **analogRead()**, although the latter
allows for optimized timing per channel.
Only 4x single ports mode supported for now, comparator modi needs investigation.
Returns **PCF8591_OK** or an error code.
It is about 2.6 times faster than 4 individual **analogRead()** calls.
The latter allows for optimized timing per channel and the order
in which the channels are read.
Use **lastRead()** to access the 4 values.
Returns **PCF8591_OK** or an error code if appropriate.
- **uint8_t lastRead(uint8_t channel)** get last read value from cache.
This cache is filled both by **analogRead()** and **analogRead4()**. See example sketch.
This cache is filled both by **analogRead()** and **analogRead4()**.
See example sketch.
### DAC channel
| ADC mode | Value | Notes |
|:------------------------------|:-------:|:----------|
| PCF8591_FOUR_SINGLE_CHANNEL | 0x00 | default |
| PCF8591_THREE_DIFFERENTIAL | 0x01 |
| PCF8591_MIXED | 0x02 |
| PCF8591_TWO_DIFFERENTIAL | 0x03 |
#### Comparator
Since 0.2.0 four direct comparator calls are added to make the code more explicit.
These four calls are in fact wrappers around the **analogRead()**.
These still need to be tested as I had no hardware available.
- **int readComparator_01()** == analogRead(channel = 0, mode = 3);
- **int readComparator_23()** == analogRead(channel = 1, mode = 3);
- **int readComparator_03()** == analogRead(channel = 0, mode = 1);
- **int readComparator_13()** == analogRead(channel = 1, mode = 1);
The values of the comparator calls are cached and can be accessed with **lastRead()**.
Be sure to select the right channel for **lastRead()**.
Note: these functions do never use PCF8591_MIXED (2) mode.
#### DAC channel
The PCF8591 has one 8 bit DAC. output value 0..255 == 0..Vref Volts (datasheet).
@ -71,16 +107,15 @@ The PCF8591 has one 8 bit DAC. output value 0..255 == 0..Vref Volts (datasheet).
- **bool isDACEnabled()** check the modus operandi.
- **bool analogWrite(uint8_t value = 0)** writes a value 0..255 to the DAC. Check datasheet for voltage.
Note, this is a real voltage not a PWM signal like **analogWrite()** on an UNO.
- **uint8_t lastWrite()** get last written value from cache.
- **uint8_t lastWrite()** get last value written (from cache).
### Error codes
#### Error codes
- **int lastError()** always check this value after a read / write to see if it was OK (== 0).
After the read the error value is reset to OK.
To elaborate
| error code | Value | Notes |
| Error code | Value | Notes |
|:------------------------|:-------:|:--------|
| PCF8591_OK | 0x00 |
| PCF8591_PIN_ERROR | 0x81 |
@ -97,21 +132,21 @@ See examples.
## Future
#### must
#### Must
- improve documentation
- test / verify comparator calls with hardware.
- datasheet (par.8.2 figure 4)
#### should
- add / improve comparator modi support, datasheet (par.8.2 figure 4)
- int16_t readComparator10()
- int16_t readComparator30() - return type correct?
- int16_t readComparator31()
- int16_t readComparator32()
- set modi and read.
#### Should
- add examples for comparator calls.
- schema?
#### could
- **analogRead4()** needs investigation for the other modi.
- Does it work?
- Is it user understandable?
- good example
#### Could
#### Wont

View File

@ -6,7 +6,7 @@
// URL: https://github.com/RobTillaart/PCF8591
//
// NOTE: output is written in markdown format of a table
// (so oeasy to include in the readme.md ;)
// (so easy to include in the readme.md ;)
// can be changed to tab based or comma based output
@ -152,4 +152,3 @@ void test_ADC_error()
// -- END OF FILE --

View File

@ -15,20 +15,35 @@ analogRead KEYWORD2
analogRead4 KEYWORD2
lastRead KEYWORD2
readComparator_01 KEYWORD2
readComparator_23 KEYWORD2
readComparator_03 KEYWORD2
readComparator_13 KEYWORD2
enableDAC KEYWORD2
disableDAC KEYWORD2
isDACEnabled KEYWORD2
analogWrite KEYWORD2
lastWrite KEYWORD2
lastError KEYWORD2
# Instances (KEYWORD2)
# Constants (LITERAL1)
PCF8591_LIB_VERSION LITERAL1
PCF8591_OK LITERAL1
PCF8591_PIN_ERROR LITERAL1
PCF8591_I2C_ERROR LITERAL1
PCF8591_MODE_ERROR LITERAL1
PCF8591_CHANNEL_ERROR LITERAL1
PCF8591_ADDRESS_ERROR LITERAL1
PCF8591_FOUR_SINGLE_CHANNEL LITERAL1
PCF8591_THREE_DIFFERENTIAL LITERAL1
PCF8591_MIXED LITERAL1
PCF8591_TWO_DIFFERENTIAL LITERAL1

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/PCF8591.git"
},
"version": "0.1.3",
"version": "0.2.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=PCF8591
version=0.1.3
version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=PCF8591 library for Arduino. Supports multiple I2C WireN bus.

View File

@ -97,4 +97,6 @@ unittest(test_DAC)
unittest_main()
// --------
// -- END OF FILE --