初始化提交
This commit is contained in:
228
arduino-cli/libraries/PCF8591/PCF8591.cpp
Normal file
228
arduino-cli/libraries/PCF8591/PCF8591.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/**
|
||||
* PCF8591 Analog Port Expand
|
||||
* https://www.mischianti.org/2019/01/03/pcf8591-i2c-analog-i-o-expander/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Renzo Mischianti www.mischianti.org All right reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "PCF8591.h"
|
||||
#include "Wire.h"
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param address: i2c address
|
||||
*/
|
||||
PCF8591::PCF8591(uint8_t address){
|
||||
_wire = &Wire;
|
||||
|
||||
_address = address;
|
||||
};
|
||||
#if !defined(__AVR) && !defined(__STM32F1__)
|
||||
/**
|
||||
*
|
||||
* @param address: i2c address
|
||||
* @param sda: sda pin
|
||||
* @param scl: scl pin
|
||||
*/
|
||||
PCF8591::PCF8591(uint8_t address, uint8_t sda, uint8_t scl){
|
||||
_wire = &Wire;
|
||||
|
||||
_address = address;
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
};
|
||||
|
||||
#ifdef ESP32
|
||||
/**
|
||||
* Constructor
|
||||
* @param address: i2c address
|
||||
*/
|
||||
PCF8591::PCF8591(TwoWire *pWire, uint8_t address){
|
||||
_wire = pWire;
|
||||
|
||||
_address = address;
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param address: i2c address
|
||||
* @param sda: sda pin
|
||||
* @param scl: scl pin
|
||||
*/
|
||||
PCF8591::PCF8591(TwoWire *pWire, uint8_t address, uint8_t sda, uint8_t scl){
|
||||
_wire = pWire;
|
||||
|
||||
_address = address;
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* wake up i2c controller
|
||||
*/
|
||||
void PCF8591::begin(){
|
||||
#ifndef __AVR
|
||||
_wire->begin(_sda, _scl);
|
||||
#else
|
||||
// Default pin for AVR some problem on software emulation
|
||||
// #define SCL_PIN _scl
|
||||
// #define SDA_PIN _sda
|
||||
_wire->begin();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all analog input in one trasmission
|
||||
* @param readType read datasheet for info
|
||||
* SINGLE_ENDED_INPUT
|
||||
* TREE_DIFFERENTIAL_INPUT
|
||||
* TWO_SINGLE_ONE_DIFFERENTIAL_INPUT
|
||||
* TWO_DIFFERENTIAL_INPUT
|
||||
* @return
|
||||
*/
|
||||
struct PCF8591::AnalogInput PCF8591::analogReadAll(byte readType){
|
||||
DEBUG_PRINTLN("Begin trasmission");
|
||||
_wire->beginTransmission(_address); // wake up PCF8591
|
||||
|
||||
byte operation = AUTOINCREMENT_READ | readType | (_outputStatus&OUTPUT_MASK);
|
||||
|
||||
DEBUG_PRINTLN("Write operation");
|
||||
_wire->write(operation); // control byte: reads ADC0 then auto-increment
|
||||
DEBUG_PRINTLN("End write (If code stop here add pullup resistor on SDA SCL)");
|
||||
_wire->endTransmission(); // end tranmission
|
||||
DEBUG_PRINTLN("Request response");
|
||||
_wire->requestFrom(_address, (uint8_t)5);
|
||||
|
||||
/*uint8_t control =*/_wire->read();
|
||||
analogInput.ain0=_wire->read();
|
||||
analogInput.ain1=_wire->read();
|
||||
analogInput.ain2=_wire->read();
|
||||
analogInput.ain3=_wire->read();
|
||||
|
||||
return analogInput;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read one specified channel
|
||||
* @param channel channel or analog identify (if readType is SINGLE_ENDED_INPUT)
|
||||
* @param readType read datasheet for info
|
||||
* SINGLE_ENDED_INPUT
|
||||
* TREE_DIFFERENTIAL_INPUT
|
||||
* TWO_SINGLE_ONE_DIFFERENTIAL_INPUT
|
||||
* TWO_DIFFERENTIAL_INPUT
|
||||
* @return
|
||||
*/
|
||||
uint8_t PCF8591::analogRead(uint8_t channel, byte readType){
|
||||
DEBUG_PRINTLN("Begin trasmission");
|
||||
_wire->beginTransmission(_address); // wake up PCF8591
|
||||
|
||||
byte operation = channel | readType| (_outputStatus&OUTPUT_MASK);
|
||||
|
||||
DEBUG_PRINTLN("Write operation");
|
||||
_wire->write(operation); // control byte: reads ADC0 then auto-increment
|
||||
DEBUG_PRINTLN("End write (If code stop here add pullup resistor on SDA SCL)");
|
||||
_wire->endTransmission(); // end tranmission
|
||||
DEBUG_PRINTLN("Request response");
|
||||
_wire->requestFrom(_address, (uint8_t)2);
|
||||
/*uint8_t control = */_wire->read();
|
||||
uint8_t ana=_wire->read();
|
||||
|
||||
return ana;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read voltage of analog input
|
||||
* @param analogPin (Analog identifier)
|
||||
* @param microcontrollerReferenceVoltage get voltage from microcontroller voltage (only AVR no esp8266 for esp 3.3v fixed)
|
||||
* @param referenceVoltage if microcontrollerReferenceVoltage false take this value
|
||||
* @return
|
||||
*/
|
||||
float PCF8591::voltageRead(uint8_t analogPin, bool microcontrollerReferenceVoltage, float referenceVoltage){
|
||||
float voltageRef = referenceVoltage;
|
||||
if (microcontrollerReferenceVoltage) voltageRef = PCF8591::readVcc()/1000.0;
|
||||
float ana = PCF8591::analogRead(analogPin);
|
||||
return ana*voltageRef/255;
|
||||
};
|
||||
/**
|
||||
* To write votlage on output
|
||||
* @param value voltage to write
|
||||
* @param microcontrollerReferenceVoltage get voltage from microcontroller voltage (only AVR no esp8266 for esp 3.3v fixed)
|
||||
* @param referenceVoltage if microcontrollerReferenceVoltage false take this value
|
||||
*/
|
||||
void PCF8591::voltageWrite(float value, bool microcontrollerReferenceVoltage, float referenceVoltage){
|
||||
if (microcontrollerReferenceVoltage) referenceVoltage = PCF8591::readVcc()/1000.0;
|
||||
uint8_t ana = value*255/referenceVoltage;
|
||||
PCF8591::analogWrite(ana);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write value on output pin
|
||||
* @param value votlage in volts
|
||||
*/
|
||||
void PCF8591::analogWrite(uint8_t value){
|
||||
_outputStatus = ENABLE_OUTPUT;
|
||||
DEBUG_PRINTLN("Begin trasmission");
|
||||
_wire->beginTransmission(_address);
|
||||
DEBUG_PRINTLN("Write operation");
|
||||
_wire->write(ENABLE_OUTPUT); // sets the PCF8591 into a DA mode
|
||||
DEBUG_PRINTLN("Write value");
|
||||
_wire->write(value); // sets the output
|
||||
DEBUG_PRINTLN("End write (If code stop here add pullup resistor on SDA SCL)");
|
||||
_wire->endTransmission();
|
||||
};
|
||||
|
||||
long PCF8591::readVcc(void) {
|
||||
#ifdef __AVR
|
||||
// Read 1.1V reference against AVcc
|
||||
// set the reference to Vcc and the measurement to the internal 1.1V reference
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#else
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
|
||||
delay(2); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (bit_is_set(ADCSRA, ADSC))
|
||||
; // measuring
|
||||
|
||||
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
|
||||
uint8_t high = ADCH; // unlocks both
|
||||
|
||||
long result = (high << 8) | low;
|
||||
|
||||
result = 1083630L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
|
||||
// scale_constant = internal1.1Ref * 1023 * 1000
|
||||
// internal1.1Ref = 1.1 * Vcc1 (per voltmeter) / Vcc2 (per readVcc() function)
|
||||
return result; // Vcc in millivolts
|
||||
#else
|
||||
// float vdd = readVcc(); // ESP.getVdd33(); //ESP.getVcc();
|
||||
return 3300;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user