[RISOLTO] Arduino UNO con MCP23017 distanza 20 Metri

Buongiorno a tutti,

qualche settimana fa avevo pubblicato un post nella sezione Software inerente a tale progetto ma è stato chiuso perché ho infranto il regolamento specificando che tale progetto veniva collegato ad un PLC che lavora con la tensione di 230V (qualsiasi utente non esperto poteva emulare il mio progetto)

Visto il consiglio dei moderatori, ho deciso di stravolgere il progetto e collegarlo ad una centrale antintrusione che ha una parte domotica e lavora con tensioni di 12Vcc.

Il progetto è una evoluzione dell’attuale che lavora con il famoso PLC a 230V (ma che non andrò minimamente a spiegare come funziona per non incorrere nella violazione)

Allego un PDF dove ho disegnato tramite Autocad lo schema con i componenti utilizzati.

Vorrei capire se ho sbagliato a collegare qualche componente in quanto in determinate situazioni l’integrato MCP23017 smette di comandare i Relé e sono costretto a spengere Arduino per almeno 10 minuti.

L’utilizzo dei Relé a 5V è obbligatorio in questo progetto perché la centrale di allarme lavora con le proprie tensioni sugli ingressi (1,5Vcc) ed i contatti devono essere a singolo bilanciamento con resistenza in serie al contatto dell’ingresso.
In pratica, sul comune del Relé ho il GND della centrale e su NC del Relé ho la resistenza da 1,8K che va all’ingresso della centrale (tra GND e Ingresso ci sono 1,5V della centrale).

Non potendo utilizzare le uscite digitali dell’ MCP23017 ho optato per i relé

Spero di non incorrere nuovamente nella violazione con lo schema allegato.

Grazie

Fabio

Pannello Arduino_1-Model.pdf (111 KB)

La I2C non funziona con 20m.
Ciao Uwe

Il bus I2C è un bus che nasce, come bene il sigificato dell'acronimo descrive (Inter-Integrated Circuit Bus), per mettere in comunicazione tra di loro circuiti integrati sullo stesso stampato. E' stato poi, nel settore amatoriale/dilettantesco, "mal utilizzato" per connettere anche cose non direttamente sulo stesso circuito, ma ... il fatto che non sia nato per tale scopo poi si fa sentire e, se lo si allunga troppo, il tutto ha un funzionamento instabile ed inaffidabile.

Se devi portarlo in giro, esistono apposiri circuiti "extender" da utilizzare, come il P82B715 che ti permettono di portare a distanza (anche 50 mt) detto bus.

Guglielmo

gpb01:
Il bus I2C è un bus che nasce, come bene il sigificato dell’acronimo descrive (Inter-Integrated Circuit Bus) …

Infatti nello schema sono inseriti i due extender e collegati con il cavo cat. 5e come da datasheet del costruttore.

sgamino:
Infatti nello schema sono inseriti i due extender e collegati con il cavo cat. 5e come da datasheet del costruttore.

Ok, chiedo scusa, mi ero basato solo sull'affermazione di Uwe e non avevo visto lo schema, quindi, lato I2C dovresti essere a posto; il problema potrebbe essere nel collegamento scheda relè ... hai le due alimentazioni separate, come sempre abbiamo descritto su qeusto forum quando si parla di schede relè? Che scheda relè usi (link)?

Guglielmo

gpb01:
Ok, chiedo scusa, mi ero basato solo sull'affermazione di Uwe e non avevo visto lo schema, quindi, lato I2C dovresti essere a posto; il problema potrebbe essere nel collegamento scheda relè ... hai le due alimentazioni separate, come sempre abbiamo descritto su qeusto forum quando si parla di schede relè? Che scheda relè usi (link)?

Guglielmo

Per le prove a banco (diciamo) non ho alimentazioni separate per i relé.
Al momento li alimento per come è nello schema, ossia da Arduino.

Avevo pensato che il fatto che alimentare 3 Relè con Arduino, più tutte le altre componenti poteva creare questo problema ed ecco perché volevo la vostra opinione.

I relé al momento della prova a banco sono singoli, mentre quelli che andrò ad utilizzare sono alimentati esternamente.

Se il problema del MCP che mi smette di controllare i relé è imputato ad un fattore di alimentazione sarei tranquillo e potrei installare il tutto con i relé alimentati esternamente.

Se invece il problema mi si ripropone anche con gli altri relé, mi trovo male perché dovrei smontare tutto e tornare al vecchio sistema.

Relé attuali

Relé alimentati esternamente

Per fare una cosa fatta bene ed evitare i disturbi (che possono bloccare Arduino), usa una doppia alimentazione secondo questo schema (©︎ Brunello):

In questo modo il tutto funzionerà a logica inversa ... pin HIGH = relè a riposo, pin LOW = relè eccitato.

Guglielmo

Domani faccio la prova con i relé definitivi (alimentati esternamente) e vedo cosa succede.

Grazie per le informazioni

Fabio

sgamino:
Domani faccio la prova con i relé definitivi (alimentati esternamente) e vedo cosa succede.

Ricorda che le due alimentazioni NON devono avere alcunchè in comune, nemmeno il GND !

Guglielmo

Buongiorno Guglielmo,
per motivi di tempo ho testato il progetto con i led invece che con la scheda relé alimentata esternamente.
Ho inserito 3 led Bianchi (alimentati sempre da Arduino) al posto dei relé e dopo un primo funzionamento iniziale è ricomparso il problema che MCP smette di comandare le uscite.

Il funzionamento è alquanto semplice,
ho 3 selettori, il primo fa la stagione e attiva tutto il programma compreso il relé 1, il secondo selettore fa la forzatura e abilita solamente il relé 3, il terzo attiva il relé 2.

Inserendo i Led pensavo di risolvere il problema degli assorbimenti ma i problemi compaiono ugualmente,

Inizio la prova facendo queste sequenze:

Selettore (Stagione = 6) in Inverno -----> Led 1 Acceso (mcp_sta = 10)
Selettore (Forza = 5) SU -----> Led 3 Acceso (mcp_forza = 12)
Selettore (Forza = 5) GIU -----> Led 3 Spento (mcp_forza = 12)
QUI TUTTO OK

Selettore (Stagione = 6) sempre in Inverno
Selettore (Clima = 3) SU -----> Led 2 Acceso (mcp_calore = 11)

A questo punto la valvola del riscaldamento si apre per il passaggio acqua e si chiude il contatto ausiliario che ha per la segnalazione, leggendolo con MCP (mcp_termo = 9) il Led Termo su Arduino si accende.

Qui ho fatto una condizione, se la sonda DS18B20 legge una temperatura inferiore a quella impostata, chiude anche il relé 3 che attiva l'apertura della valvola bollitore (mcp_forza = 12)

Se sposto il Selettore Clima in posizione GIU la valvola del riscaldamento si apre e a questo punto si verifica il problema che MCP smette di controllare le uscite spengendo in questo caso tutti i LED.

Per ripristinare il funzionamento devo spengere Arduino, attendere 1 minuto e Accenderlo nuovamente.
Se riprovo la sequenza, quando arrivo a ripeterla si ricrea lo stesso problema.

A questo punto oltre ad un fattore assorbimento, credo che il problema sia anche nel codice scritto.

Posto il codice così metto a disposizione di tutti il progetto completo per capire dove sia il problema che mi sta facendo impazzire.

Grazie

Fabio

Ecco il codice

#include <Adafruit_MCP23017.h>
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
Adafruit_MCP23017 mcp1;


LiquidCrystal_I2C lcd(0x27, 20, 4);
const int Stagione = 6;          // Selettore ESTATE/INVERNO collegato ad Arduino
const int Forza = 5;               // Selettore SU per Forzare acqua calda collegato ad Arduino
const int mcp_calore =  11;    // Relè 2 collegato a MCP23017
const int mcp_sta = 10;         // Relè 1 collegato a MCP23017
const int mcp_forza = 12;      // Relè 3 Selettore SU Forzatura calore collegato a MCP23017
const int ledforzato = 8;      // Se forzato accende LED Rosso collegato ad Arduino
const int mcp_bollitore = 8;  // Elettro Valvola Linea Bollitore collegato a MCP23017
const int mcp_termo = 9;      // Elettro Valvola Linea Riscaldamento collegato a MCP23017
const int Clima = 3;          // Termostato Ambiente per Riscaldamento Abitazione collegato ad Arduino
const int ledtermo = 9;       // Led Verde Stato Elettrovalvola Riscaldamento Abitazione 
const int ledboll = 10;       // Led Verde Stato Elettrovalvola Bollitore 
const int ledblu = 4;         // Led Blu Stato Stagione, acceso su Inverno

// Lettura Stato dei SELETTORI collegati ad Arduino

int statoForza = 0;
int statoStagione = 0;
int statoClima = 0;


// Linea dati DS18B20 al pin 7 di Arduino
#define ONE_WIRE_BUS 7

// Dichiaro il Pin del DHT e il modello DHT11
#define DHTPIN 2
#define DHTTYPE DHT11

// Imposta la comunicazione oneWire per comunicare con un dispositivo
OneWire oneWire(ONE_WIRE_BUS);

// Passaggio oneWire reference alla Dallas Temperature
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  // Dichiaro l'indirizzo dell'intergato MCP23017
  mcp1.begin(0);
  sensors.begin();
  dht.begin();
  lcd.init();
  lcd.backlight();
  Wire.begin();
  digitalWrite(SDA, 0);
  digitalWrite(SCL, 0);
  
  // Configuro i Pin USCITA
  mcp1.pinMode(mcp_calore, OUTPUT);    // Relè 2 su MCP23017
  mcp1.pinMode(mcp_sta, OUTPUT);       // Relè 1 su MCP23017
  mcp1.pinMode(mcp_forza, OUTPUT);     // Relè 3 su MCP23017
  pinMode(ledforzato, OUTPUT);         // Led ROSSO Forzatura su Arduino
  pinMode(ledtermo, OUTPUT);           // Led VERDE Valvola Termosifoni su Arduino
  pinMode(ledboll, OUTPUT);            // Led VERDE Valvola Bollitore su Arduino
  pinMode(ledblu, OUTPUT);             // Led Blu Stagione Inverno

  // Configuro i Pin INGRESSO
  pinMode(Forza, INPUT_PULLUP);               // Selettore SU per Forzatura su Arduino
  pinMode(Stagione, INPUT_PULLUP);            // Selettore SU per Inverno, GIU per Estate su Arduino
  pinMode(Clima, INPUT_PULLUP);        // Ingresso per Riscaldamento Ambiente da Termostato su Arduino
  mcp1.pinMode(mcp_bollitore, INPUT);  // Stato Elettrovalvola Linea Bollitore su MCP23017
  mcp1.pinMode(mcp_termo, INPUT);      // Stato Elettrovalvola Linea Riscaldamento su MCP23017

}

void loop(void) {

  statoForza = digitalRead(Forza);
  statoStagione = digitalRead(Stagione);
  statoClima = digitalRead(Clima);

  // Lettura Dallas
  sensors.requestTemperatures();

  // Lettura DHT11
  float t = dht.readTemperature();
  float f = dht.readTemperature(true);

  /*
     Chiedo se lo stato del Selettore Stagione su Arduino è su INVERNO per abilitare la Modalità INVERNO
     Se il selettore è in INVERNO invio su MCP23017 la richiesta di CHIUDERE il Relé 1
     Altrimenti il Relé 1 rimane aperto se lo stato era ESTATE
  */

  if (digitalRead(Stagione) == LOW)
  {
    mcp1.digitalWrite(mcp_sta, LOW);
    digitalWrite(ledblu, LOW);
  }
  else
  {
    mcp1.digitalWrite(mcp_sta, HIGH);
    digitalWrite(ledblu, HIGH);
  }

  /* Controllo il riscaldamento dell'abitazione tramite un termostato esterno alimentato a pile.
     Il contatto del termostato è collegato direttamente ad Arduino sul Pin "crono" con la PULL UP 
     configurata per risparmio cablaggi.
     Funziona solamente se è INVERNO
  */

  if (digitalRead(Clima) == LOW && digitalRead(Stagione) == HIGH)
  {
    mcp1.digitalWrite(mcp_calore, HIGH);

  }
  else
  {
    mcp1.digitalWrite(mcp_calore, LOW);

  }

  /*
     Prima verifica: Selettore di Forzatura in stato GIU (OFF), Prima e Seconda sonda DS18B20 sotto soglia temperatura, Elettrovalvola Riscaldamento Abitazione Aperta(Passaggio Acqua)
     Seconda verifica: Selettore di Forzatura in stato SU (ON), Selettore della Stagione su INVERNO
     Terza verifica: Selettore di Forzatura in stato GIU (OFF) o Prima sonda DS18B20 sopra soglia temperatura o Elettrovalvola Riscaldamento Abitazione Chiusa
  */
  if (digitalRead(Forza) == LOW && sensors.getTempCByIndex(0) <= 40 && sensors.getTempCByIndex(1) <= 40 && mcp1.digitalRead(mcp_termo) ==  LOW)
  {
    mcp1.digitalWrite(mcp_forza, HIGH); // Se la Prima verifica è tutta confermata, attivo il Relé 3 che farà aprire l'Elettrovalvola del Bollitore 
     
  }
  else if (digitalRead(Forza) == HIGH && digitalRead(Stagione) == HIGH)
  {
    mcp1.digitalWrite(mcp_forza, HIGH); // Se la Seconda verifica è tutta confermata, attivo il Relé 3 che apre l'Elettrovalvola del Bollitore per la forzatura dal selettore
    digitalWrite(ledforzato, HIGH);     // Attivo anche il LED Rosso per segnalarmi che ho attivato la forzatura
  }
  else if (digitalRead(Forza) == HIGH || sensors.getTempCByIndex(0) >= 70 || mcp1.digitalRead(mcp_termo) ==  HIGH)

  {
    mcp1.digitalWrite(mcp_forza, LOW);  // Se la Terza verifica trova un dato esatto, disattiva il Relé 3 che chiude l'Elettrovalvola del Bollitore
    digitalWrite(ledforzato, LOW);      // Disattivo il LED Rosso
  }

  if (mcp1.digitalRead(mcp_termo) ==  LOW)
  {
    digitalWrite(ledtermo, HIGH);  //Se la valvola del Riscaldamento Ambiente è aperta accendo il LED VERDE che mi segnala l'avvenuta apertura per il passaggio acqua
  }
  else
  {
    digitalWrite(ledtermo, LOW);
  }

  if (mcp1.digitalRead(mcp_bollitore) ==  LOW)
  {
    digitalWrite(ledboll, HIGH);  //Se la valvola del Bollitore è aperta accendo il LED VERDE che mi segnala l'avvenuta apertura per il passaggio acqua
  }
  else
  {
    digitalWrite(ledboll, LOW);
  }

  /*
    Nel Display 20x4 visualizzo le varie temperature,
    Caldaia sta per la temperatura dello stadio alto del Bollitore
    Solare sta per la temperatura dello stadio basso del Bollitore
    Mandata sta per la temperatura dell'acqua nel circuito del riscaldamento
    Casa sta per la temperatura dell'ambiente misurata dal DHT11 installato su Arduino
  */

  lcd.setCursor(0, 0);
  lcd.print("Caldaia  ");       // Temperatura del Primario Bollitore 
  lcd.print(sensors.getTempCByIndex(0));
  lcd.setCursor(0, 1);
  lcd.print("Solare   ");       // Temperatura del Solare Bollitore 
  lcd.print(sensors.getTempCByIndex(1));
  lcd.setCursor(0, 2);
  lcd.print("Mandata  ");       // Temperatura della Linea 
  lcd.print (sensors.getTempCByIndex(2));
  lcd.setCursor(0, 3);
  lcd.print(F("Casa     "));    // Temperatura dell'abitazione
  lcd.print(t);

 delay(100);              
}