Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: 812_hello PCF8591_test_LAAS
Revision 0:1116b0d151fc, committed 2013-09-21
- Comitter:
- wim
- Date:
- Sat Sep 21 19:25:09 2013 +0000
- Commit message:
- Extended functionality to include mbed type AnalogIn and AnalogOut; Fixed issue related to LPC812 I2C bug
Changed in this revision
| PCF8591.cpp | Show annotated file Show diff for this revision Revisions of this file |
| PCF8591.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8591.cpp Sat Sep 21 19:25:09 2013 +0000
@@ -0,0 +1,293 @@
+/* PCF8591 - I2C 8 bit 4 channel A/D and 8 bit 1 channel D/A converter
+ * Copyright (c) 2013 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8591.h"
+
+
+/** Create a PCF8591 AD and DA object using a specified I2C bus and slaveaddress
+ *
+ * @param I2C &i2c the I2C port to connect to
+ * @param char deviceAddress the address of the PCF8591
+ */
+PCF8591::PCF8591(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) {
+
+ _slaveAddress = deviceAddress;
+ _init();
+}
+
+
+#if(0)
+//These methods are disabled since they interfere with normal expected behaviour for mbed type Analog I/O
+//
+
+/** Set ADC mode
+ *
+ * @param adc_mode ADC Channel mode, valid Range (PCF8591_4S, PCF8591_3D, PCF8591_2S_1D, PCF8591_2D)
+ */
+void PCF8591::setADCMode(uint8_t mode){
+ uint8_t data[6];
+
+ _mode = _mode & ~PCF8591_2D; // Clear ADC mode bits
+
+ switch (mode) {
+ case PCF8591_4S:
+ _mode = _mode | PCF8591_4S;
+ break;
+ case PCF8591_3D:
+ _mode = _mode | PCF8591_3D;
+ break;
+ case PCF8591_2S_1D:
+ _mode = _mode | PCF8591_2S_1D;
+ break;
+ case PCF8591_2D:
+ _mode = _mode | PCF8591_2D;
+ break;
+ default:
+ _mode = _mode | PCF8591_4S;
+ break;
+ }
+
+ data[0] = _mode; // Control Reg
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 1);
+
+};
+
+/** Set DAC mode
+ *
+ * @param dac_mode DAC Channel mode, valid Range (false=disable, true=enable)
+ */
+void PCF8591::setDACMode(bool mode) {
+ uint8_t data[6];
+
+ if (mode)
+ _mode = _mode | PCF8591_AOUT; // Enable DAC output
+ else
+ _mode = _mode & ~PCF8591_AOUT; // Disable DAC output
+
+ data[0] = _mode; // Control Reg
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 1);
+
+};
+#endif
+
+
+/** Write Analog Output
+ *
+ * @param analogOut output value (0..255)
+ */
+void PCF8591::write(uint8_t analogOut) {
+ uint8_t data[6];
+
+ data[0] = _mode; // Control Reg
+ data[1] = analogOut; // DAC Channel
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 2);
+};
+
+/** Read Analog Channel
+ *
+ * @param Channel ADC channel, valid range PCF8591_ADC0, PCF8591_ADC1, PCF8591_ADC2 or PCF8591_ADC3
+ * @return value uint8_t AD converted value (0..255, representing 0V..Vcc)
+ */
+#if(0)
+// I2C block operations test
+// Causes problems with Ticker and printf on LPC812. No issues found on LPC1768
+uint8_t PCF8591::read(uint8_t channel) {
+// uint8_t data[6];
+ uint8_t data[6] = {123,123,123,123,123,123}; //test to check failed read
+
+ _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits
+ _mode = _mode | (channel & PCF8591_CHMSK); // Set ADC Channel bits
+
+ data[0] = _mode; // Init Control Reg
+
+ // write data to the device to select the ADC channel
+ _i2c->write(_slaveAddress, (char*) data, 1);
+
+ // read selected ADC channel
+ // note that first byte is a 'dummy' and should be ignored
+ _i2c->read(_slaveAddress, (char*) data, 2);
+ return data[1];
+};
+
+#else
+// I2C single byte operations test
+// No issues found on LPC812
+uint8_t PCF8591::read(uint8_t channel) {
+ uint8_t data[6];
+// uint8_t data[6] = {123,123,123,123,123,123}; //test to check failed read
+
+ _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits
+ _mode = _mode | (channel & PCF8591_CHMSK); // Set ADC Channel bits
+
+ data[0] = _mode; // Init Control Reg
+
+ // write data to the device to select the ADC channel
+ _i2c->start();
+ _i2c->write(_slaveAddress); // Slave write address
+ _i2c->write(data[0]);
+ _i2c->stop();
+
+ // read selected ADC channel
+ // note that first byte is a 'dummy' and should be ignored
+ _i2c->start();
+ _i2c->write(_slaveAddress | 0x01); // Slave read address
+ data[0]=_i2c->read(1); //ack
+ data[1]=_i2c->read(0); //nack
+ _i2c->stop();
+
+ return data[1];
+};
+
+#endif
+
+
+/** Initialise AD and DA driver
+ *
+ */
+void PCF8591::_init() {
+ uint8_t data[6];
+
+ _mode = PCF8591_CTRL_DEF; // Init mode
+
+ data[0] = _mode; // Init Control Reg
+ data[1] = 0x00; // Init DAC Channel to 0
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 2);
+};
+
+
+
+
+
+/** Create a PCF8591 AnalogOut object connected to the specified I2C bus and deviceAddress
+ *
+ */
+PCF8591_AnalogOut::PCF8591_AnalogOut(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) {
+
+ _slaveAddress = deviceAddress;
+ _init();
+}
+
+
+/** Write Analog Output
+ *
+ * @param analogOut value (0 .. 1.0)
+ */
+void PCF8591_AnalogOut::write(float analogOut) {
+ uint8_t data[6];
+
+ data[0] = _mode; // Control Reg
+
+ // DAC Channel
+ if (analogOut < 0.0) data[1] = 0;
+ else if (analogOut >= 1.0) data[1] = 255;
+ else data[1] = uint8_t (analogOut * 255.0);
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 2);
+};
+
+/** Operator = Analog Output
+ *
+ * @param analogOut value (0.0f .. 1.0f)
+ */
+PCF8591_AnalogOut& PCF8591_AnalogOut::operator= (float value){
+ write(value);
+ return *this;
+}
+
+
+/** Initialise DAC driver
+ *
+ */
+void PCF8591_AnalogOut::_init() {
+ uint8_t data[6];
+
+ _mode = PCF8591_CTRL_DEF; // Init mode
+
+ data[0] = _mode; // Init Control Reg
+ data[1] = 0x00; // Init DAC Channel to 0
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 2);
+};
+
+
+
+/** Create a PCF8591 AnalogIn object connected to the specified I2C bus and deviceAddress
+ *
+ */
+PCF8591_AnalogIn::PCF8591_AnalogIn(I2C *i2c, uint8_t channel, uint8_t deviceAddress) : _i2c(i2c) {
+
+ _slaveAddress = deviceAddress;
+ _channel = channel;
+ _init();
+}
+
+
+/** Read Analog input
+ *
+ * @return analogIn value (0 .. 1.0)
+ */
+float PCF8591_AnalogIn::read() {
+ uint8_t data[6];
+
+ data[0] = _mode; // Init Control Reg
+
+ // write data to the device to select the ADC channel
+ _i2c->start();
+ _i2c->write(_slaveAddress); // Slave write address
+ _i2c->write(data[0]);
+ _i2c->stop();
+
+ // read selected ADC channel
+ // note that first byte is a 'dummy' and should be ignored
+ _i2c->start();
+ _i2c->write(_slaveAddress | 0x01); // Slave read address
+ data[0]=_i2c->read(1); //ack
+ data[1]=_i2c->read(0); //nack
+ _i2c->stop();
+
+
+ // ADC Channel
+ return ((float) data[1] / 255.0);
+
+};
+
+
+/** Operator float Analog Input
+ *
+ * @return analogIn value (0 .. 1.0)
+ */
+PCF8591_AnalogIn::operator float(){
+ return (read());
+}
+
+
+/** Initialise ADC driver
+ *
+ */
+void PCF8591_AnalogIn::_init() {
+ uint8_t data[6];
+
+ _mode = PCF8591_CTRL_DEF; // Init mode
+ _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits
+ _mode = _mode | (_channel & PCF8591_CHMSK); // Set ADC Channel bits
+
+ data[0] = _mode; // Init Control Reg
+
+ // write data to the device
+ _i2c->write(_slaveAddress, (char*) data, 1);
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8591.h Sat Sep 21 19:25:09 2013 +0000
@@ -0,0 +1,221 @@
+/* PCF8591 - I2C 8 bit, 4 channel A/D and 8 bit, 1 channel D/A converter
+ * Copyright (c) 2013 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _PCF8591_H
+#define _PCF8591_H
+
+/** Driver for PCF8591 I2C I2C A/D and D/A converter
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "PCF8591.h"
+ *
+ * // I2C Communication
+ * I2C i2c_adcdac(p28,p27); // SDA, SCL for LPC1768
+ * //I2C i2c_adcdac(P0_10,P0_11); // SDA, SCL for LPC812
+ *
+ * //Declare a composite ADC and DAC device that may be used through public methods
+ * PCF8591 adc_dac(&i2c_adcdac); // I2C bus, Default PCF8591 Slaveaddress
+ *
+ * //Declare independent ADC and DAC objects that may be used similar to mbed AnalogIn and AnalogOut pins
+ * //PCF8591_AnalogOut anaOut(&i2c_bus);
+ * //
+ * //PCF8591_AnalogIn anaIn(&i2c_bus, PCF8591_ADC0);
+ *
+ *
+ * int main() {
+ * uint8_t count = 0;
+ * uint8_t analog;
+ *
+ * while(1) {
+ * wait(0.2);
+ * count++;
+ *
+ * // Composite device methods
+ * adc_dac.write(count); // write D/A value
+ * analog = adc_dac.read(PCF8591_ADC0); // read A/D value for Channel 0
+ *
+ * // mbed pin type methods
+ * //anaOut = (float)count / 255.0; // write D/A value using range 0.0f .. 1.0f
+ * //analog = anaIn * 33.0; // read A/D value for Channel 0 in (Volts*10)
+ * }
+ *
+ * }
+ * @endcode
+ */
+
+
+//Address Defines for PCF8591
+#define PCF8591_SA0 0x90
+#define PCF8591_SA1 0x92
+#define PCF8591_SA2 0x94
+#define PCF8591_SA3 0x96
+#define PCF8591_SA4 0x98
+#define PCF8591_SA5 0x9A
+#define PCF8591_SA6 0x9C
+#define PCF8591_SA7 0x9E
+
+//Register Defines for PCF8591
+#define PCF8591_CTRL 0x00
+#define PCF8591_ADR0 0x01
+#define PCF8591_ADR1 0x02
+#define PCF8591_ADR2 0x03
+#define PCF8591_ADR3 0x04
+#define PCF8591_DAR 0x01
+
+//Control Register Defines for PCF8591
+//AD Channels
+#define PCF8591_ADC0 0x00
+#define PCF8591_ADC1 0x01
+#define PCF8591_ADC2 0x02
+#define PCF8591_ADC3 0x03
+//AD Channel Mask
+#define PCF8591_CHMSK 0x03
+
+//Auto Increment flag (0=disable, 1=enable)
+#define PCF8591_AIF 0x04
+
+//AD Channels Input modes
+//4 Single Channels (Chan0=AIN0, Chan1=AIN0, Chan2=AIN0, Chan3=AIN0)
+#define PCF8591_4S 0x00
+//3 Diff Channels (Chan0=AIN0-AIN3, Chan1=AIN1-AIN3, Chan2=AIN2-AIN3)
+#define PCF8591_3D 0x10
+//2 Single Channels (Chan0=AIN0, Chan1=AIN1)
+//1 Diff Channel (Chan2=AIN2-AIN3)
+#define PCF8591_2S_1D 0x20
+//2 Diff Channels (Chan0=AIN0-AIN1, Chan1=AIN2-AIN3)
+#define PCF8591_2D 0x30
+//ChannelMode Mask
+#define PCF8591_CHMDMSK 0x30
+
+//Analog Output enable flag (0=disable, 1=enable)
+#define PCF8591_AOUT 0x40
+
+//Default Mode: ADC0, AutoIncr Off, 4 Single Chan, AnalogOut On
+#define PCF8591_CTRL_DEF (PCF8591_ADC0 | PCF8591_4S | PCF8591_AOUT)
+
+
+/** Create a PCF8591 object connected to the specified I2C bus and deviceAddress
+ *
+*/
+class PCF8591 {
+public:
+ /** Create a PCF8591 AD and DA object using a specified I2C bus and slaveaddress
+ *
+ * @param I2C &i2c the I2C port to connect to
+ * @param char deviceAddress the address of the PCF8591
+ */
+ PCF8591(I2C *i2c, uint8_t deviceAddress = PCF8591_SA0);
+
+#if(0)
+//These methods are disabled since they interfere with normal expected behaviour for mbed type Analog I/O
+//
+ /** Set ADC mode
+ *
+ * @param adc_mode ADC Channel mode, valid Range (PCF8591_4S, PCF8591_3D, PCF8591_2S_1D, PCF8591_2D)
+ */
+ void setADCMode(uint8_t mode);
+
+ /** Set DAC mode
+ *
+ * @param dac_mode DAC Channel mode, valid Range (false=disable, true=enable)
+ */
+ void setDACMode(bool mode);
+#endif
+
+/** Write Analog Output
+ *
+ * @param analogOut output value (0..255)
+ */
+ void write(uint8_t analogOut);
+
+/** Read Analog Channel
+ *
+ * @param Channel ADC channel, valid range PCF8591_ADC0, PCF8591_ADC1, PCF8591_ADC2 or PCF8591_ADC3
+ * @return value uint8_t AD converted value (0..255, representing 0V..Vcc)
+ */
+ uint8_t read(uint8_t channel);
+
+
+
+protected:
+ I2C *_i2c; //I2C bus reference
+ uint8_t _slaveAddress; //I2C Slave address of device
+ uint8_t _mode; //Device mode
+
+/** Initialise AD and DA driver
+ *
+ */
+ void _init();
+};
+
+
+/** Create a PCF8591 AnalogOut object connected to the specified I2C bus and deviceAddress
+ *
+*/
+class PCF8591_AnalogOut {
+public:
+ /** Create a PCF8591 Analogout object using a specified I2C bus and slaveaddress
+ *
+ * @param I2C &i2c the I2C port to connect to
+ * @param char deviceAddress the address of the PCF8591
+ */
+ PCF8591_AnalogOut(I2C *i2c, uint8_t deviceAddress = PCF8591_SA0);
+
+ void write(float value);
+ #ifdef MBED_OPERATORS
+ /** An operator shorthand for write()
+ */
+ PCF8591_AnalogOut& operator= (float value);
+ #endif
+
+protected:
+ I2C *_i2c; //I2C bus reference
+ uint8_t _slaveAddress; //I2C Slave address of device
+ uint8_t _mode; //Device mode
+
+/** Initialise DAC driver
+ *
+ */
+ void _init();
+};
+
+
+/** Create a PCF8591 AnalogIn object connected to the specified I2C bus and deviceAddress
+ *
+*/
+class PCF8591_AnalogIn {
+public:
+ /** Create a PCF8591 AnalogIn object using a specified I2C bus and slaveaddress
+ *
+ * @param I2C &i2c the I2C port to connect to
+ * @param channel ADC channel of the PCF8591
+ * @param char deviceAddress the address of the PCF8591
+ */
+ PCF8591_AnalogIn(I2C *i2c, uint8_t channel, uint8_t deviceAddress = PCF8591_SA0);
+
+ float read();
+ #ifdef MBED_OPERATORS
+ /** An operator shorthand for read()
+ */
+ operator float();
+ #endif
+
+protected:
+ I2C *_i2c; //I2C bus reference
+ uint8_t _slaveAddress; //I2C Slave address of device
+ uint8_t _mode; //Device mode
+ uint8_t _channel; //Channel
+
+/** Initialise DAC driver
+ *
+ */
+ void _init();
+};
+
+
+#endif
\ No newline at end of file
PCF8591 I2C ADC and DAC