It is simple to use PCF8591 Library (ADC / DAC converter) for LPC800MAX
Fork of PCF8591 by
PCF8591.cpp@0:1116b0d151fc, 2013-09-21 (annotated)
- Committer:
- wim
- Date:
- Sat Sep 21 19:25:09 2013 +0000
- Revision:
- 0:1116b0d151fc
Extended functionality to include mbed type AnalogIn and AnalogOut; Fixed issue related to LPC812 I2C bug
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wim | 0:1116b0d151fc | 1 | /* PCF8591 - I2C 8 bit 4 channel A/D and 8 bit 1 channel D/A converter |
wim | 0:1116b0d151fc | 2 | * Copyright (c) 2013 Wim Huiskamp |
wim | 0:1116b0d151fc | 3 | * |
wim | 0:1116b0d151fc | 4 | * Released under the MIT License: http://mbed.org/license/mit |
wim | 0:1116b0d151fc | 5 | * |
wim | 0:1116b0d151fc | 6 | * version 0.2 Initial Release |
wim | 0:1116b0d151fc | 7 | */ |
wim | 0:1116b0d151fc | 8 | #include "mbed.h" |
wim | 0:1116b0d151fc | 9 | #include "PCF8591.h" |
wim | 0:1116b0d151fc | 10 | |
wim | 0:1116b0d151fc | 11 | |
wim | 0:1116b0d151fc | 12 | /** Create a PCF8591 AD and DA object using a specified I2C bus and slaveaddress |
wim | 0:1116b0d151fc | 13 | * |
wim | 0:1116b0d151fc | 14 | * @param I2C &i2c the I2C port to connect to |
wim | 0:1116b0d151fc | 15 | * @param char deviceAddress the address of the PCF8591 |
wim | 0:1116b0d151fc | 16 | */ |
wim | 0:1116b0d151fc | 17 | PCF8591::PCF8591(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) { |
wim | 0:1116b0d151fc | 18 | |
wim | 0:1116b0d151fc | 19 | _slaveAddress = deviceAddress; |
wim | 0:1116b0d151fc | 20 | _init(); |
wim | 0:1116b0d151fc | 21 | } |
wim | 0:1116b0d151fc | 22 | |
wim | 0:1116b0d151fc | 23 | |
wim | 0:1116b0d151fc | 24 | #if(0) |
wim | 0:1116b0d151fc | 25 | //These methods are disabled since they interfere with normal expected behaviour for mbed type Analog I/O |
wim | 0:1116b0d151fc | 26 | // |
wim | 0:1116b0d151fc | 27 | |
wim | 0:1116b0d151fc | 28 | /** Set ADC mode |
wim | 0:1116b0d151fc | 29 | * |
wim | 0:1116b0d151fc | 30 | * @param adc_mode ADC Channel mode, valid Range (PCF8591_4S, PCF8591_3D, PCF8591_2S_1D, PCF8591_2D) |
wim | 0:1116b0d151fc | 31 | */ |
wim | 0:1116b0d151fc | 32 | void PCF8591::setADCMode(uint8_t mode){ |
wim | 0:1116b0d151fc | 33 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 34 | |
wim | 0:1116b0d151fc | 35 | _mode = _mode & ~PCF8591_2D; // Clear ADC mode bits |
wim | 0:1116b0d151fc | 36 | |
wim | 0:1116b0d151fc | 37 | switch (mode) { |
wim | 0:1116b0d151fc | 38 | case PCF8591_4S: |
wim | 0:1116b0d151fc | 39 | _mode = _mode | PCF8591_4S; |
wim | 0:1116b0d151fc | 40 | break; |
wim | 0:1116b0d151fc | 41 | case PCF8591_3D: |
wim | 0:1116b0d151fc | 42 | _mode = _mode | PCF8591_3D; |
wim | 0:1116b0d151fc | 43 | break; |
wim | 0:1116b0d151fc | 44 | case PCF8591_2S_1D: |
wim | 0:1116b0d151fc | 45 | _mode = _mode | PCF8591_2S_1D; |
wim | 0:1116b0d151fc | 46 | break; |
wim | 0:1116b0d151fc | 47 | case PCF8591_2D: |
wim | 0:1116b0d151fc | 48 | _mode = _mode | PCF8591_2D; |
wim | 0:1116b0d151fc | 49 | break; |
wim | 0:1116b0d151fc | 50 | default: |
wim | 0:1116b0d151fc | 51 | _mode = _mode | PCF8591_4S; |
wim | 0:1116b0d151fc | 52 | break; |
wim | 0:1116b0d151fc | 53 | } |
wim | 0:1116b0d151fc | 54 | |
wim | 0:1116b0d151fc | 55 | data[0] = _mode; // Control Reg |
wim | 0:1116b0d151fc | 56 | |
wim | 0:1116b0d151fc | 57 | // write data to the device |
wim | 0:1116b0d151fc | 58 | _i2c->write(_slaveAddress, (char*) data, 1); |
wim | 0:1116b0d151fc | 59 | |
wim | 0:1116b0d151fc | 60 | }; |
wim | 0:1116b0d151fc | 61 | |
wim | 0:1116b0d151fc | 62 | /** Set DAC mode |
wim | 0:1116b0d151fc | 63 | * |
wim | 0:1116b0d151fc | 64 | * @param dac_mode DAC Channel mode, valid Range (false=disable, true=enable) |
wim | 0:1116b0d151fc | 65 | */ |
wim | 0:1116b0d151fc | 66 | void PCF8591::setDACMode(bool mode) { |
wim | 0:1116b0d151fc | 67 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 68 | |
wim | 0:1116b0d151fc | 69 | if (mode) |
wim | 0:1116b0d151fc | 70 | _mode = _mode | PCF8591_AOUT; // Enable DAC output |
wim | 0:1116b0d151fc | 71 | else |
wim | 0:1116b0d151fc | 72 | _mode = _mode & ~PCF8591_AOUT; // Disable DAC output |
wim | 0:1116b0d151fc | 73 | |
wim | 0:1116b0d151fc | 74 | data[0] = _mode; // Control Reg |
wim | 0:1116b0d151fc | 75 | |
wim | 0:1116b0d151fc | 76 | // write data to the device |
wim | 0:1116b0d151fc | 77 | _i2c->write(_slaveAddress, (char*) data, 1); |
wim | 0:1116b0d151fc | 78 | |
wim | 0:1116b0d151fc | 79 | }; |
wim | 0:1116b0d151fc | 80 | #endif |
wim | 0:1116b0d151fc | 81 | |
wim | 0:1116b0d151fc | 82 | |
wim | 0:1116b0d151fc | 83 | /** Write Analog Output |
wim | 0:1116b0d151fc | 84 | * |
wim | 0:1116b0d151fc | 85 | * @param analogOut output value (0..255) |
wim | 0:1116b0d151fc | 86 | */ |
wim | 0:1116b0d151fc | 87 | void PCF8591::write(uint8_t analogOut) { |
wim | 0:1116b0d151fc | 88 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 89 | |
wim | 0:1116b0d151fc | 90 | data[0] = _mode; // Control Reg |
wim | 0:1116b0d151fc | 91 | data[1] = analogOut; // DAC Channel |
wim | 0:1116b0d151fc | 92 | |
wim | 0:1116b0d151fc | 93 | // write data to the device |
wim | 0:1116b0d151fc | 94 | _i2c->write(_slaveAddress, (char*) data, 2); |
wim | 0:1116b0d151fc | 95 | }; |
wim | 0:1116b0d151fc | 96 | |
wim | 0:1116b0d151fc | 97 | /** Read Analog Channel |
wim | 0:1116b0d151fc | 98 | * |
wim | 0:1116b0d151fc | 99 | * @param Channel ADC channel, valid range PCF8591_ADC0, PCF8591_ADC1, PCF8591_ADC2 or PCF8591_ADC3 |
wim | 0:1116b0d151fc | 100 | * @return value uint8_t AD converted value (0..255, representing 0V..Vcc) |
wim | 0:1116b0d151fc | 101 | */ |
wim | 0:1116b0d151fc | 102 | #if(0) |
wim | 0:1116b0d151fc | 103 | // I2C block operations test |
wim | 0:1116b0d151fc | 104 | // Causes problems with Ticker and printf on LPC812. No issues found on LPC1768 |
wim | 0:1116b0d151fc | 105 | uint8_t PCF8591::read(uint8_t channel) { |
wim | 0:1116b0d151fc | 106 | // uint8_t data[6]; |
wim | 0:1116b0d151fc | 107 | uint8_t data[6] = {123,123,123,123,123,123}; //test to check failed read |
wim | 0:1116b0d151fc | 108 | |
wim | 0:1116b0d151fc | 109 | _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits |
wim | 0:1116b0d151fc | 110 | _mode = _mode | (channel & PCF8591_CHMSK); // Set ADC Channel bits |
wim | 0:1116b0d151fc | 111 | |
wim | 0:1116b0d151fc | 112 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 113 | |
wim | 0:1116b0d151fc | 114 | // write data to the device to select the ADC channel |
wim | 0:1116b0d151fc | 115 | _i2c->write(_slaveAddress, (char*) data, 1); |
wim | 0:1116b0d151fc | 116 | |
wim | 0:1116b0d151fc | 117 | // read selected ADC channel |
wim | 0:1116b0d151fc | 118 | // note that first byte is a 'dummy' and should be ignored |
wim | 0:1116b0d151fc | 119 | _i2c->read(_slaveAddress, (char*) data, 2); |
wim | 0:1116b0d151fc | 120 | return data[1]; |
wim | 0:1116b0d151fc | 121 | }; |
wim | 0:1116b0d151fc | 122 | |
wim | 0:1116b0d151fc | 123 | #else |
wim | 0:1116b0d151fc | 124 | // I2C single byte operations test |
wim | 0:1116b0d151fc | 125 | // No issues found on LPC812 |
wim | 0:1116b0d151fc | 126 | uint8_t PCF8591::read(uint8_t channel) { |
wim | 0:1116b0d151fc | 127 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 128 | // uint8_t data[6] = {123,123,123,123,123,123}; //test to check failed read |
wim | 0:1116b0d151fc | 129 | |
wim | 0:1116b0d151fc | 130 | _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits |
wim | 0:1116b0d151fc | 131 | _mode = _mode | (channel & PCF8591_CHMSK); // Set ADC Channel bits |
wim | 0:1116b0d151fc | 132 | |
wim | 0:1116b0d151fc | 133 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 134 | |
wim | 0:1116b0d151fc | 135 | // write data to the device to select the ADC channel |
wim | 0:1116b0d151fc | 136 | _i2c->start(); |
wim | 0:1116b0d151fc | 137 | _i2c->write(_slaveAddress); // Slave write address |
wim | 0:1116b0d151fc | 138 | _i2c->write(data[0]); |
wim | 0:1116b0d151fc | 139 | _i2c->stop(); |
wim | 0:1116b0d151fc | 140 | |
wim | 0:1116b0d151fc | 141 | // read selected ADC channel |
wim | 0:1116b0d151fc | 142 | // note that first byte is a 'dummy' and should be ignored |
wim | 0:1116b0d151fc | 143 | _i2c->start(); |
wim | 0:1116b0d151fc | 144 | _i2c->write(_slaveAddress | 0x01); // Slave read address |
wim | 0:1116b0d151fc | 145 | data[0]=_i2c->read(1); //ack |
wim | 0:1116b0d151fc | 146 | data[1]=_i2c->read(0); //nack |
wim | 0:1116b0d151fc | 147 | _i2c->stop(); |
wim | 0:1116b0d151fc | 148 | |
wim | 0:1116b0d151fc | 149 | return data[1]; |
wim | 0:1116b0d151fc | 150 | }; |
wim | 0:1116b0d151fc | 151 | |
wim | 0:1116b0d151fc | 152 | #endif |
wim | 0:1116b0d151fc | 153 | |
wim | 0:1116b0d151fc | 154 | |
wim | 0:1116b0d151fc | 155 | /** Initialise AD and DA driver |
wim | 0:1116b0d151fc | 156 | * |
wim | 0:1116b0d151fc | 157 | */ |
wim | 0:1116b0d151fc | 158 | void PCF8591::_init() { |
wim | 0:1116b0d151fc | 159 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 160 | |
wim | 0:1116b0d151fc | 161 | _mode = PCF8591_CTRL_DEF; // Init mode |
wim | 0:1116b0d151fc | 162 | |
wim | 0:1116b0d151fc | 163 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 164 | data[1] = 0x00; // Init DAC Channel to 0 |
wim | 0:1116b0d151fc | 165 | |
wim | 0:1116b0d151fc | 166 | // write data to the device |
wim | 0:1116b0d151fc | 167 | _i2c->write(_slaveAddress, (char*) data, 2); |
wim | 0:1116b0d151fc | 168 | }; |
wim | 0:1116b0d151fc | 169 | |
wim | 0:1116b0d151fc | 170 | |
wim | 0:1116b0d151fc | 171 | |
wim | 0:1116b0d151fc | 172 | |
wim | 0:1116b0d151fc | 173 | |
wim | 0:1116b0d151fc | 174 | /** Create a PCF8591 AnalogOut object connected to the specified I2C bus and deviceAddress |
wim | 0:1116b0d151fc | 175 | * |
wim | 0:1116b0d151fc | 176 | */ |
wim | 0:1116b0d151fc | 177 | PCF8591_AnalogOut::PCF8591_AnalogOut(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) { |
wim | 0:1116b0d151fc | 178 | |
wim | 0:1116b0d151fc | 179 | _slaveAddress = deviceAddress; |
wim | 0:1116b0d151fc | 180 | _init(); |
wim | 0:1116b0d151fc | 181 | } |
wim | 0:1116b0d151fc | 182 | |
wim | 0:1116b0d151fc | 183 | |
wim | 0:1116b0d151fc | 184 | /** Write Analog Output |
wim | 0:1116b0d151fc | 185 | * |
wim | 0:1116b0d151fc | 186 | * @param analogOut value (0 .. 1.0) |
wim | 0:1116b0d151fc | 187 | */ |
wim | 0:1116b0d151fc | 188 | void PCF8591_AnalogOut::write(float analogOut) { |
wim | 0:1116b0d151fc | 189 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 190 | |
wim | 0:1116b0d151fc | 191 | data[0] = _mode; // Control Reg |
wim | 0:1116b0d151fc | 192 | |
wim | 0:1116b0d151fc | 193 | // DAC Channel |
wim | 0:1116b0d151fc | 194 | if (analogOut < 0.0) data[1] = 0; |
wim | 0:1116b0d151fc | 195 | else if (analogOut >= 1.0) data[1] = 255; |
wim | 0:1116b0d151fc | 196 | else data[1] = uint8_t (analogOut * 255.0); |
wim | 0:1116b0d151fc | 197 | |
wim | 0:1116b0d151fc | 198 | // write data to the device |
wim | 0:1116b0d151fc | 199 | _i2c->write(_slaveAddress, (char*) data, 2); |
wim | 0:1116b0d151fc | 200 | }; |
wim | 0:1116b0d151fc | 201 | |
wim | 0:1116b0d151fc | 202 | /** Operator = Analog Output |
wim | 0:1116b0d151fc | 203 | * |
wim | 0:1116b0d151fc | 204 | * @param analogOut value (0.0f .. 1.0f) |
wim | 0:1116b0d151fc | 205 | */ |
wim | 0:1116b0d151fc | 206 | PCF8591_AnalogOut& PCF8591_AnalogOut::operator= (float value){ |
wim | 0:1116b0d151fc | 207 | write(value); |
wim | 0:1116b0d151fc | 208 | return *this; |
wim | 0:1116b0d151fc | 209 | } |
wim | 0:1116b0d151fc | 210 | |
wim | 0:1116b0d151fc | 211 | |
wim | 0:1116b0d151fc | 212 | /** Initialise DAC driver |
wim | 0:1116b0d151fc | 213 | * |
wim | 0:1116b0d151fc | 214 | */ |
wim | 0:1116b0d151fc | 215 | void PCF8591_AnalogOut::_init() { |
wim | 0:1116b0d151fc | 216 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 217 | |
wim | 0:1116b0d151fc | 218 | _mode = PCF8591_CTRL_DEF; // Init mode |
wim | 0:1116b0d151fc | 219 | |
wim | 0:1116b0d151fc | 220 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 221 | data[1] = 0x00; // Init DAC Channel to 0 |
wim | 0:1116b0d151fc | 222 | |
wim | 0:1116b0d151fc | 223 | // write data to the device |
wim | 0:1116b0d151fc | 224 | _i2c->write(_slaveAddress, (char*) data, 2); |
wim | 0:1116b0d151fc | 225 | }; |
wim | 0:1116b0d151fc | 226 | |
wim | 0:1116b0d151fc | 227 | |
wim | 0:1116b0d151fc | 228 | |
wim | 0:1116b0d151fc | 229 | /** Create a PCF8591 AnalogIn object connected to the specified I2C bus and deviceAddress |
wim | 0:1116b0d151fc | 230 | * |
wim | 0:1116b0d151fc | 231 | */ |
wim | 0:1116b0d151fc | 232 | PCF8591_AnalogIn::PCF8591_AnalogIn(I2C *i2c, uint8_t channel, uint8_t deviceAddress) : _i2c(i2c) { |
wim | 0:1116b0d151fc | 233 | |
wim | 0:1116b0d151fc | 234 | _slaveAddress = deviceAddress; |
wim | 0:1116b0d151fc | 235 | _channel = channel; |
wim | 0:1116b0d151fc | 236 | _init(); |
wim | 0:1116b0d151fc | 237 | } |
wim | 0:1116b0d151fc | 238 | |
wim | 0:1116b0d151fc | 239 | |
wim | 0:1116b0d151fc | 240 | /** Read Analog input |
wim | 0:1116b0d151fc | 241 | * |
wim | 0:1116b0d151fc | 242 | * @return analogIn value (0 .. 1.0) |
wim | 0:1116b0d151fc | 243 | */ |
wim | 0:1116b0d151fc | 244 | float PCF8591_AnalogIn::read() { |
wim | 0:1116b0d151fc | 245 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 246 | |
wim | 0:1116b0d151fc | 247 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 248 | |
wim | 0:1116b0d151fc | 249 | // write data to the device to select the ADC channel |
wim | 0:1116b0d151fc | 250 | _i2c->start(); |
wim | 0:1116b0d151fc | 251 | _i2c->write(_slaveAddress); // Slave write address |
wim | 0:1116b0d151fc | 252 | _i2c->write(data[0]); |
wim | 0:1116b0d151fc | 253 | _i2c->stop(); |
wim | 0:1116b0d151fc | 254 | |
wim | 0:1116b0d151fc | 255 | // read selected ADC channel |
wim | 0:1116b0d151fc | 256 | // note that first byte is a 'dummy' and should be ignored |
wim | 0:1116b0d151fc | 257 | _i2c->start(); |
wim | 0:1116b0d151fc | 258 | _i2c->write(_slaveAddress | 0x01); // Slave read address |
wim | 0:1116b0d151fc | 259 | data[0]=_i2c->read(1); //ack |
wim | 0:1116b0d151fc | 260 | data[1]=_i2c->read(0); //nack |
wim | 0:1116b0d151fc | 261 | _i2c->stop(); |
wim | 0:1116b0d151fc | 262 | |
wim | 0:1116b0d151fc | 263 | |
wim | 0:1116b0d151fc | 264 | // ADC Channel |
wim | 0:1116b0d151fc | 265 | return ((float) data[1] / 255.0); |
wim | 0:1116b0d151fc | 266 | |
wim | 0:1116b0d151fc | 267 | }; |
wim | 0:1116b0d151fc | 268 | |
wim | 0:1116b0d151fc | 269 | |
wim | 0:1116b0d151fc | 270 | /** Operator float Analog Input |
wim | 0:1116b0d151fc | 271 | * |
wim | 0:1116b0d151fc | 272 | * @return analogIn value (0 .. 1.0) |
wim | 0:1116b0d151fc | 273 | */ |
wim | 0:1116b0d151fc | 274 | PCF8591_AnalogIn::operator float(){ |
wim | 0:1116b0d151fc | 275 | return (read()); |
wim | 0:1116b0d151fc | 276 | } |
wim | 0:1116b0d151fc | 277 | |
wim | 0:1116b0d151fc | 278 | |
wim | 0:1116b0d151fc | 279 | /** Initialise ADC driver |
wim | 0:1116b0d151fc | 280 | * |
wim | 0:1116b0d151fc | 281 | */ |
wim | 0:1116b0d151fc | 282 | void PCF8591_AnalogIn::_init() { |
wim | 0:1116b0d151fc | 283 | uint8_t data[6]; |
wim | 0:1116b0d151fc | 284 | |
wim | 0:1116b0d151fc | 285 | _mode = PCF8591_CTRL_DEF; // Init mode |
wim | 0:1116b0d151fc | 286 | _mode = _mode & ~PCF8591_CHMSK; // Clear ADC Channel bits |
wim | 0:1116b0d151fc | 287 | _mode = _mode | (_channel & PCF8591_CHMSK); // Set ADC Channel bits |
wim | 0:1116b0d151fc | 288 | |
wim | 0:1116b0d151fc | 289 | data[0] = _mode; // Init Control Reg |
wim | 0:1116b0d151fc | 290 | |
wim | 0:1116b0d151fc | 291 | // write data to the device |
wim | 0:1116b0d151fc | 292 | _i2c->write(_slaveAddress, (char*) data, 1); |
wim | 0:1116b0d151fc | 293 | }; |