PCF8591: un expander i2c I/O analogico
Libreria per utilizzare l’integrato pcf8591 tramite protocollo i2c con arduino e esp8266.
Questo integrato può controllare fino a 4 ingressi analogici e una uscita analogica, utile per misurare la tensione leggere i valori di termistor o controllare l’intensità di led.
Può leggere e scrivere valori analogici con solo 2 fili (perfetto per ESP-01).
Cerco di semplificare l’uso di questo IC, riducendo al minimo le operazioni da fare.
Come funziona il protocollo I2c
Il protocollo I2C funziona con due fili, l’SDA (dati) e SCL (clock).
Questi pin sono open-drain, e sono in pull-up con delle resistenze.
Di solito c’è un master e uno o più slave sulla linea, anche se possono esserci più master, ma ne parleremo in altra occasione.
Entrambi i master e gli slave possono trasmettere o ricevere dati, pertanto un dispositivo può trovarsi in uno di questi quattro stati: trasmissione master, ricezione master, trasmissione slave, ricezione slave.
Modulo o IC
Qui l'IC AliExpressQui il module Module Temperature Illumination - pcf8591 smd - pcf8591
Libreria
Puoi trovare la mia libreria qui .
Download
Fai clic sul pulsante DOWNLOADS nell’angolo in alto a destra, rinominare la cartella non compressa PCF8591.
Verificare che la cartella PCF8591 contenga PCF8591.cpp e PCF8591.h.
Collocare la cartella della libreria PCF8591 come / librerie / cartella.
Potrebbe essere necessario creare la sottocartella librerie se è la tua prima libreria.
Riavvia l’IDE.
Uso
Sul costruttore è necessario passare l’indirizzo I2C, è possibile utilizzare i pins A0, A1, A2 per cambiare l’indirizzo, potete trovare il valore specifico qui (per verificare l’indirizzo potete usare questa guida I2cScanner)
PCF8591(uint8_t address);
per l’esp8266 se vuoi specificare i pin SDA e SCL puoi usare questo:
PCF8591(uint8_t address, uint8_t sda, uint8_t scl);
Per gli esp32 puoi passare direttamente il TwoWire così da poter selezionare il secondo canale i2c: [updated 29/04/2019]
// Instantiate Wire for generic use at 400kHz
TwoWire I2Cone = TwoWire(0);
// Instantiate Wire for generic use at 100kHz
TwoWire I2Ctwo = TwoWire(1);
PCF8591 pcf8591(&I2Ctwo, PCF8591_I2C_ADDRESS);
// PCF8591 pcf8591(&I2Ctwo, PCF8591_I2C_ADDRESS, 21, 22);
Leggere valori
Come puoi vedere dall’immagine questo integrato ha 4 ingressi analogici e 1 uscita
Quindi per leggere tutti gli input analogici con un comando puoi fare così (i valori vanno da 0 a 255):
PCF8591::AnalogInput ai = pcf8591.analogReadAll();
Serial.print(ai.ain0);
Serial.print(" - ");
Serial.print(ai.ain1);
Serial.print(" - ");
Serial.print(ai.ain2);
Serial.print(" - ");
Serial.println(ai.ain3);
se vuoi leggere un singolo ingresso o canale analogico:
int ana = pcf8591.analogRead(AIN0); // read analog 0
Leggi un valore da un canale
Questo IC ha varie modalità di lettura, ed è possibile utilizzare l’ingresso analogico o il canale analogico (puoi leggere i singoli valori con una chiamata a valore o gli AND logici dei valori).
Per esempio per leggere il valore dal canale 0 in “Two differential” devi fare:
int ana = pcf8591.analogRead(CHANNEL0, TWO_DIFFERENTIAL_INPUT); // read analog 0
Scrivi un valore
Se vuoi scrivere un valore analogico puoi fare così (il valore va da 0 a 255):
pcf8591.analogWrite(128);
Caratteristiche aggiuntive
Ho aggiunto delle utilità che permettono di leggere o screvere una tensione: per il calcolo della tensione è necessario passare alcuni parametri:
- microcontrollerReferenceVoltage: se a true ricava la tensione dal microcontrollore (solo AVR no esp8266 per esp 3.3v è fisso)
- referenceVoltage : se microcontrollerReferenceVoltage è false è necessario passare la relativa tensione
void voltageWrite(float value, bool microcontrollerReferenceVoltage = true, float referenceVoltage = 5.0);
float voltageRead(uint8_t analogPin, bool microcontrollerReferenceVoltage = true, float referenceVoltage = 5.0);
Un esempio:
pcf8591.voltageWrite(2.7); // 2.7Volts output
delay(3000);
float ana0V = pcf8591.voltageRead(AIN0); // Read voltage from analog 0
Serial.println(ana0V);
Schema di esempio
Esempi aggiuntivi
Nel tempo vari contributori mi hanno aiutato a creare nuove features ed esempi. Vado a mostrarveli qui:
Generare un segnale sinusoidale
Dalla Francia Yves Pelletier ha creato un esempio che genera un’onda sinusoidale dall’analog output
/*
* PCF8591 Analog Port Expand
* Production of a sinusoïdal signal using a PCF8591 module
*
* by Yves Pelletier <http://electroniqueamateur.blogspot.com>
*
* http://electroniqueamateur.blogspot.com/2019/01/pcf8591-et-esp8266-ou-arduino.html
*
*
* PCF8574 ----- Esp32
* A0 ----- GRD
* A1 ----- GRD
* A2 ----- GRD
* SDA ----- A4
* SCL ----- A5
*
*
*/
#include "PCF8591.h" // bibliothèque https://github.com/xreef/PCF8591_library
#define PCF8591_I2C_ADDRESS 0x48 //adresse i2c du module PCF8591
PCF8591 pcf8591(PCF8591_I2C_ADDRESS);
int compteur;
void setup()
{
pcf8591.begin();
}
void loop(){
pcf8591.analogWrite(100 + 100 * sin(2*3.1416*compteur/200) ); // sinus
// pcf8591.analogWrite(compteur ); // dent de scie
compteur++;
if (compteur > 200){
compteur = 0;
}
delay(1);
}
Esp32 leds blink usando il canale i2c secondario
/*
* PCF8591 Analog Port Expand
* Read all analog pins and write value on analog ouput
*
* by Mischianti Renzo <https://mischianti.org>
*
* https://mischianti.org/pcf8591-i2c-analog-i-o-expander/
*
*
* PCF8574 ----- Esp32
* A0 ----- GRD
* A1 ----- GRD
* A2 ----- GRD
* SDA ----- 21
* SCL ----- 22
*
*
*/
#include "Arduino.h"
#include "PCF8591.h"
#define PCF8591_I2C_ADDRESS 0x48
// Instantiate Wire for generic use at 400kHz
TwoWire I2Cone = TwoWire(0);
// Instantiate Wire for generic use at 100kHz
TwoWire I2Ctwo = TwoWire(1);
// Set i2c address
//PCF8591 pcf8591(&I2Ctwo, PCF8591_I2C_ADDRESS);
PCF8591 pcf8591(&I2Ctwo, 0x20, 21, 22);
void setup()
{
Serial.begin(115200);
I2Cone.begin(16,17,400000); // SDA pin 16, SCL pin 17, 400kHz frequency
pcf8591.begin();
}
void loop()
{
PCF8591::AnalogInput ai = pcf8591.analogReadAll();
Serial.print(ai.ain0);
Serial.print(" - ");
Serial.print(ai.ain1);
Serial.print(" - ");
Serial.print(ai.ain2);
Serial.print(" - ");
Serial.println(ai.ain3);
delay(3000);
int ana = pcf8591.analogRead(AIN0);
Serial.print("AIN0 --> ");
Serial.println(ana);
ana = pcf8591.analogRead(AIN1);
Serial.print("AIN1 --> ");
Serial.println(ana);
ana = pcf8591.analogRead(AIN2);
Serial.print("AIN2 --> ");
Serial.println(ana);
ana = pcf8591.analogRead(AIN3);
Serial.print("AIN3 --> ");
Serial.println(ana);
delay(3000);
pcf8591.analogWrite(0);
delay(3000);
pcf8591.analogWrite(128);
delay(3000);
pcf8591.analogWrite(255);
delay(3000);
}