PCF8591: un expander i2c I/O analogico

Spread the love

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

pcf8591 IC
Qui l'IC AliExpress
pcf8592 module

Qui 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

pcf8591 pinout

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);
}
/*
 * 	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);
}

Spread the love

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *