librerie I2C che bloccano il codice

...come da titolo vi chiedo qualche chiarimento sulle librerie I2C.
Il problema nasce dal fatto che un vecchio codice, anzi due, che giravano benissimo su un LCD 16x2 e poi 20x4 (già provvisto di modulo I2C) se collegati al vecchio modo, ora stanno dando problemi con le librerie I2C associate ai relativi moduli I2C.
I display sono perfettamente funzionanti con TUTTI i codici che ho e mi stanno dando problemi solo su uno che utilizzo come termometro a due sonde.
Su monitor seriale l'output è corretto come inserisco le librerie I2C e la Wire.h si "sputtana" tutto.
Qual'è il motivo??

Ciao,
la prima cosa che mi viene in mente quando ti si incasina tutto è che l'indirizzo dello slave con cui vuoi instaurare la comunicazione non sia corretto..

Ciao zemmo, prendo atto ma purtroppo non sono così tecnico da comprendere il significato dela tua indicazione e tantomento individuare il problema/soluzione.
Tieni conto che non gira solo su questo "semplice" programma termometro a due sonde mentre gira su tutti gli altri programmi. Nello specifico, ho due programmi termostato; uno che lavora sulla media dei valori (e con questo nessun problema) ed il secondo che lavora con un array (sul quale non lavora e incasina). Su output monitor seriale tutto ok fin quando non inserisco le linee relativa alle libreire I2C, wire e quant'altro.

ciao

ho letto e riletto il posto... ma non è ben chiaro il problema, o almeno non riesco a capirlo io :frowning:

se riesci a essere un po' più dettagliato nei procedimenti da te fatti allegando anche qualche pezzo di codice e un piccolo circuito farebbe comodo :slight_smile:

MD

ciao...cosa vuol dire "stanno dando problemi"?...errori in compilazione? quello che vedi nell'LCD non è coerente con quello che ti aspetti?...non scrive nulla?

per quanto scritto da zemmo...per farla semplice...I2C è un modo di trasmettere e richiedere informazioni a schede/componenti esterni ad arduino...siccome puoi averen più di uno connesso contemporaneamente un modo per far capire allo specifico componente che gli stai chiedendo qualche cosa è dare, in questo caso con configurazione hardware del modulo I2C del display, un indirizzo (ID) e specificare quest'indirizzo nei dati che invii.
c'è un programmino...mi sembra si chiami "I2C scanner"...ti dice che indirizzi sono collegati all'arduino

provvedo.
In parole...ho un semplice programma che mi fa da termometro con due sonde.
Funzionava regolarmente con un display LCD 16x2 QUANDO collegato con i vari PIN ed inseriti i relativi comandi/librerie.
Avendo a disposizione dei moduli I2C li ho montati sui display LCD che ho e che utilizzo senza problemi con altri programmi.
Bene...anzi male...una volta inserite le istruzioni/libreria I2C il programmma non gira più e si stranisce...lcd blinka, l'out put su monitor seriale sbarella.

ecco il codice: messo così gia regolarmente e mi da output su monitor seriale corretto ovviamnte NO lcd dato che è collegato un I2C.
Se attivo le prime tre linee (aggiornando i comandi nel setup) l'LCD non funziona e l'output su monitor seriale sfarfalla.

//#include <LiquidCrystal_I2C.h>
//#include <Wire.h>
//LiquidCrystal_I2C lcd(0x3f, 20, 4);  // LCD GRANDE

const int NRLETTURE = 10;    // numero letture
const int NRLETTURE2 = 10;
const int SensorPin = A0;    //variabile lettura sensore
const int SensorPin2 = A1;   // seconda variabileb sensore due

float valori[NRLETTURE];     //array con i valori
float valori2[NRLETTURE2];

int T_campionamento = 25;    // tempo campionamento
int T_campionamento2 = 25;

float sommaGradi, mediaGradi, sommaGradi2, mediaGradi2;

long previousMillis = 0;
long interval = 500;

#include <LiquidCrystal.h>             // include la libreria del display lcd
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //pin display LCD

void setup()
{
// lcd.init();        // set up the LCD's number of columns and rows:
// lcd.backlight();
   lcd.begin(20, 4); 
 // lcd.backlight();
  lcd.print("Created by: ");
  lcd.setCursor(0,2);
  lcd.print("ppregeo");
  Serial.begin(9600);      //inizializzo la seriale
 // analogReference(INTERNAL);  
 //delay(3000);
}
void loop()
{
  analogRead(SensorPin2);
  
  for ( int i = 0; i<=NRLETTURE;i++)
  {
    int sensorVal = analogRead(SensorPin);
    //float voltage = (sensorVal /1024.0) * 5.0; //dividendo per 1024.0 da una lettura inferiore.
    //float temperature = (voltage - .5) * 100;
    float temperature = (sensorVal * 4.30)/10;
    valori[i] = temperature;
    delay(T_campionamento);

    }
  sommaGradi = 0;                        // il primo valore deve essere sia zero, altrimenti poi sballa tutto
  for( int i = 0; i<=NRLETTURE; i++)     //ciclo che somma i valori dell'array
  { 
    sommaGradi = sommaGradi + valori[i];   //sommaGradi2 = sommaGradi2 + valori[i];
  // }
  mediaGradi = sommaGradi / NRLETTURE;   //media valori
  }
  analogRead(SensorPin);
  
  for ( int i = 0; i<=NRLETTURE2;i++)
  {
    int sensorVal2 = analogRead(SensorPin2);
    //float voltage2 = (sensorVal2 /1024.0) * 5.0;
    //float temperature2 = (voltage2 - .5) * 100;
    float temperature2 = (sensorVal2 * 4.30) /10;
    valori2[i] = temperature2;
    delay(T_campionamento2);
  }
  sommaGradi2 = 0;
  for( int i = 0; i<=NRLETTURE2; i++)        //ciclo che somma i valori dell'array
  { 
    sommaGradi2 = sommaGradi2 + valori2[i];
// }
  mediaGradi2 = sommaGradi2 / NRLETTURE2; //divido la somma dei valori per il loro numero (media)     
 }

  //--------------- prova delay ----------------
  //    unsigned long currentMillis = millis();
  //    if (currentMillis - previousMillis > interval)
  //    {
  //    previousMillis = currentMillis;
   
  //delay(T_campionamento);
  //--------------------------------------------

  Serial.print ("Temp mandata:    ");            //scrive sul display la parola "gradi"
  Serial.println (mediaGradi);
  Serial.print ("Temp ritorno:    ");
  Serial.println (mediaGradi2);
  Serial.print ("differenza:      ");
  Serial.println (mediaGradi-mediaGradi2);
  Serial.println ("---------------------------------------------");
     
  lcd.clear(); 
  lcd.print("In ");                   
  lcd.print(mediaGradi);               //scrivo la temperatura
  lcd.setCursor(0,1);
  lcd.print("Out ");
  lcd.print(mediaGradi2);
  lcd.setCursor(0,2);
  lcd.print("d ");
  lcd.print(mediaGradi - mediaGradi2);
}

@ ORSO... si l'LCD ha il corretto address...0x3f. gia verificato e cmd gia funzionanti con altri programmi.
l'LCD NON funziona proprio...nel migliore dei casi mi da solo la schermata del setup...ma non quella del ciclo loop. Ho provato anche ad isolarla con un void...ma nulla

Se usi uno di questi cosi possono avere un diverso indirizzo di default a seconda della versione dell'integrato che vedi al centro.
Quelli su cui mi sono imbattuto sono 0x27 e 0x3F, non so se ce ne sono altri con indirizzo di default andora differenti.
Usi la libreria LiquidCrystal_I2C?
La inizializzi così?
LiquidCrystal_I2C lcd(0x3F, 16, 2);
o in un modo simile? Il primo parametro è appunto l'indirizzo a cui il dispositivo risponde.

EDIT:
mi sono sovrapposto, prova con 0x27 se non sei sicuro dell'indirizzo.
Oppure usa lo scan i2c per capire che indirizzo può avere il tuo dispositivo.
Lo scan è banale, fa un for provando tutti gli indirizzi, quindi da 0 a 127 e fa

    Wire.beginTransmission(address);
    byte error = Wire.endTransmission();

se trova qualcosa che risponde nel modo corretto error risulta a 0.

...nessun problema di indirizzo. Funziona su altri programmi. inizializzazione gia sperimentata e funzionante

NON ho capito il problema ... ma .. non è che vuoi collegare in quel modo DUE LCD ? ? ?

Perché, in testa al programma vedo la #include <LiquidCrystal_I2C.h> con le sue cose e, scendendo, trovo una #include <LiquidCrystal.h> con le sue altre cose ... ::slight_smile:

Mi confermi che se usi una elimini completamente tutto quello che è dell'altra ?

Guglielmo

ciao Gug. Corretto ELIMINO quella che non viene utilizzata. Ho postato tutto il codice per completezza di informazione.
indirizzo 0x3f già verificato e LCD funzionante con altri progetti.
Come attivo le linee relative al I2C il programma si stranisce LCD non va e dati sballati.

@ maubarzi: i mod
uli I2C son quelli uno è montato di serie sul display l'altro l'ho montato io...ma ripeto NON funziona solo con questo programma

Ho letto male ho hai scritto che quello che scrivi nel setup esce e poi più nulla?
Questo taglierebbe la testa al toro riguardo l'inizializzazione del display e quindi il problema sarebbe sul loop.
Però sarebbe meglio postare il codice bacato e non quello funzionante, cioè quello con i2c e non l'altro

vince59: Mi fai uno schemino, anche a penna e poi lo fotografi, di tutti i collegamenti ?

Guglielmo

intanto te lo descrivo:

LM 35 (sonda1): 5vdcc; gnd; pin A0 (input);
LM 35 (sonda2): 5vdcc; gnd; pin A1 (input);

LCD DISPLAY (20x4 - dal modulo I2C montato di serie):
5vdcc;
gnd;
SDA -> pin A4;
SCL -> pin A5.
Ho provato anche gli altri due piedini di Arduino (gli utlimi due dopo AREF) che da quanto leggo dovrebbero essere paralleli di A4 ed A5. Ho anche provatop a spostare gli ingressi su A1 ed A2.

Attenzione....se attivo le righe di codice "no I2C" alle linee 7 ed 8 del codice si blocca/sbarella, se invece attivo le linee 26 e 27 funziona (SEMPRE e SOLO su monitor seriale).

Fosse un problema di "sequenza interna"?

questo codice, ad esempio funziona benissimo:

//DT Studio
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd 
 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.print("Hello,DT Studio!");
}

void loop()
{
}

vince59:
questo codice, ad esempio funziona benissimo

Ok, ora però mostraci il codice che NON funziona, ossia come l'hai modificato per I2C e vediamo.

Come dice mio figlio... ancora non capisco!
L'ultimo codice che hai postato funziona. Bene. Se aggiungi il loop non più?
Ma cosa aggiungi nel loop?

vince59:
Attenzione....se attivo le righe di codice "no I2C" alle linee 7 ed 8 del codice si blocca/sbarella, se invece attivo le linee 26 e 27 funziona (SEMPRE e SOLO su monitor seriale).

Qui mi perdo, perchè non hai postato anche tutta questa parte? Così uno che legge si trova il codice da analizzare e ci può ragionare sopra.
Scusa se sono così "tardo" ma non ho mica trovato le due righe 7 e 8 e non ho nemmeno capito ancora cosa vuol dire in pratica "blocca/sbarella".

vince59:
... Ho provato anche gli altri due piedini di Arduino (gli utlimi due dopo AREF) che da quanto leggo dovrebbero essere paralleli di A4 ed A5. Ho anche provatop a spostare gli ingressi su A1 ed A2 ...

Perdona, queste sono prove "senza senso", fatte a caso e non è così che si risolvono i problemi ...

A0 ed A1 vanno bene per le due sonde di temperatura, A4 ed A5 vanno bene per il bus I2C, quindi, se i collegamenti sono fatti bene (... senza falsi contatti), l'hardware è a posto ed il problema è altrove.

Come dice "docdoc" metti il codice esatto che utilizzi con il modulo LCD I2C.

Guglielmo

Mi scuso per non essere chiaro a tutti.
Questo è il codice che NON gira i nquanto iserite le linee relative a display I2C-

  1. l'LCD mostra solo la schermata di setup. Lampeggia un paio di volte e poi rimane acceso senza alcuna scritta.
  2. l'output su monitor seriale "sbarell"...i dati escono non nell'ordine delle linee di comando e si blocca.
    @ baumarzi...l'ultimo codice era relativo ad hello world era per dimostarre che le linee di codeice relative al display I2C in quel programma funzionano
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27, 16, 2);  // LCD PICCOLO
LiquidCrystal_I2C lcd(0x3f, 20, 4);  // LCD GRANDE

//#include <LiquidCrystal.h>             // include la libreria del display lcd
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //pin display LCD

const int NRLETTURE = 10;    
const int NRLETTURE2 = 10;
const int SensorPin = A0;    
const int SensorPin2 = A1;   

float valori[NRLETTURE];     
float valori2[NRLETTURE2];

int T_campionamento = 25;    
int T_campionamento2 = 25;

float sommaGradi, mediaGradi, sommaGradi2, mediaGradi2;

long previousMillis = 0;
long interval = 500;

//#include <LiquidCrystal.h>             
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

void setup()
{
 lcd.init();        
 lcd.backlight();
   lcd.begin(20, 4); 
  lcd.print("Created by: ");
  lcd.setCursor(0,2);
  lcd.print("ppregeo");
  Serial.begin(9600);     
 // analogReference(INTERNAL);  
 //delay(3000);
}
void loop()
{
  analogRead(SensorPin2);
  
  for ( int i = 0; i<=NRLETTURE;i++)
  {
    int sensorVal = analogRead(SensorPin);
    //float voltage = (sensorVal /1024.0) * 5.0; 
    //float temperature = (voltage - .5) * 100;
    float temperature = (sensorVal * 4.30)/10;
    valori[i] = temperature;
    delay(T_campionamento);

    }
  sommaGradi = 0;                       
  for( int i = 0; i<=NRLETTURE; i++)     
  { 
    sommaGradi = sommaGradi + valori[i];   //sommaGradi2 = sommaGradi2 + valori[i];
  // }
  mediaGradi = sommaGradi / NRLETTURE;   
  }
  analogRead(SensorPin);
  
  for ( int i = 0; i<=NRLETTURE2;i++)
  {
    int sensorVal2 = analogRead(SensorPin2);
    //float voltage2 = (sensorVal2 /1024.0) * 5.0;
    //float temperature2 = (voltage2 - .5) * 100;
    float temperature2 = (sensorVal2 * 4.30) /10;
    valori2[i] = temperature2;
    delay(T_campionamento2);
  }
  sommaGradi2 = 0;
  for( int i = 0; i<=NRLETTURE2; i++)        //ciclo che somma i valori dell'array
  { 
    sommaGradi2 = sommaGradi2 + valori2[i];
// }
  mediaGradi2 = sommaGradi2 / NRLETTURE2;      
 }

  Serial.print ("Temp mandata:    ");            
  Serial.println (mediaGradi);
  Serial.print ("Temp ritorno:    ");
  Serial.println (mediaGradi2);
  Serial.print ("differenza:      ");
  Serial.println (mediaGradi-mediaGradi2);
  Serial.println ("---------------------------------------------");
     
  lcd.clear(); 
  lcd.print("In ");                   
  lcd.print(mediaGradi);               
  lcd.setCursor(0,1);
  lcd.print("Out ");
  lcd.print(mediaGradi2);
  lcd.setCursor(0,2);
  lcd.print("d ");
  lcd.print(mediaGradi - mediaGradi2);
}

Allora, da un'occhiata "al volo" (magari stasera da casa posso vedere meglio), potrei anche sbagliare qualcosa, ma direi due cose:

  1. ma tu nel loop() non hai alcun delay(), quindi fai cld.clear() e tutto il resto ad una velocità che il display non regge. Scrivi su lcd solamente quando qualcosa CAMBIA, non tutto di seguito alla massima velocità! Considera che il display non è affatto veloce a seguire i cambiamenti (a parte la sua interfaccia I2C che ha comunque dei limiti) generalmente regge, nel senso che si "vede" quello che cambia, un paio di update al secondo o poco più. Per me tu qui ne fai MIGLIAIA al secondo. Intanto prova a mettere un delay(500) ad esempio e vedi che succede.

  2. Se scrivi tanta roba sulla seriale fai Serial.begin(115200); se metti solo 9600 potresti avere problemi (non c'è handshake hardware, se fai overflow del buffer ti perdi byte)

Mentre se usi la libreria non I2C funziona, giusto?
Hai la doppia cablatura sempre attiva giusto?
Puoi postare un esempio di output seriale per capire esattamente cosa vuol dire che escono in ordine strano?

Se non ho letto male il codice, il loop dovrebbe girare alla velocità della luce (ogni 50 millisecondi), non è che lcd.clear(); prevale su tutto il resto?
Mi pareva di essere incappato anche io in un problema analogo tempo fa e poi ho evitato il clear, semplicemente andavo sopra senza sbiancare sempre tutto.

EDIT:
@docdoc ci siamo sovrapposti, mi sa che abbiamo beccato il problema nel tuo punto 1.

Però questo significa che senza la libreria I2C non funzionasse lo stesso.

EDIT 2:
Io comunque non scrivevo sull'lcd alla velocità della luce ma un paio di volte al secondo al massimo e quando c'era qualcosa da aggiornare e non a raffica incontrollata.