PIN analogici

Buongiorno a tutti,

Per comodità di circuito ho usato dei PIN analogici (precisamente A2 ed A3) per leggere la pressione di un pulsante dichiarandoli correttamente come INPUT.

La parte del programma non funzionava in modo corretto, leggendo i PIN come il pulsante venisse mantenuto sempre premuto (allego schema - la resistenza è da 12 Kohm in quanto l’unica disponibile).

Ho risolto empiricamente il problema settando i PIN come OUTPUT, ed il programma funziona.

Qualcuno potrebbe spiegarmi il perché del comportamento riscontrato? NON volendo/potendo cambiare il PIN quali problemi possono sorgere?

Grazie + saluti

Enrico

Untitled Sketch 2_schem.pdf (327 KB)

Quando i pin erano impostati come INPUT il valore letto era sempre 1023 indipendentemente dalla pressione esercitata e 0 quando invece il pulsante era a "riposo" ?

In ogni caso i pin analogici non vengono mai inizializzati nel setup tramite la funzione pinMode() , nel tuo caso ad esempio basta che tu li legga con la funzione analogRead() .
Il tuo problema deriva dal fatto che FORSE i pin Analogici di default sono già impostati come INPUT e andando a modificare la loro natura ad es pinMode(A0, INPUT) porti ad un funzionamento non aspettato del pin, quello che mi viene da supporre è la seguente ipotesi:
Assumiamo che INPUT = operatore algebrico meno (-)
OUTPUT = operatore algebrico (+)
assumendo che di default i pin analogici siano impostati come INPUT riassegnandoli l'INPUT con la funzione pinMode() vengono trasformati in OUTPUT, come nella matematica dove meno per meno fà più; mentre se gli assegniamo il valore OUTPUT tramite la funzione pinMode() il pin rimane sempre INPUT il che è sempre coerente con l'analogia matematica dove meno per più fà meno meno.
Non so se mi sono spiegato in ogni caso tutto ciò è solo un ipotesi che cerca di dare una logica al comportamento apparentemente anomalo dei tuoi pin analogici, in ogni caso non so se quello che ho detto è corretto ne quanto si avvicina alla reale risposta giusta ripeto è solo un ipotesi.

Grazie

Comunque è strano, ipotizzando di star parlando di una board con ATMEGA328 (ArduinoUNO) i pin analogici si possono usare esattamente come gli altri digitali. In effetti tutti i pin sono digitali, ma alcuni hanno una funzione alternativa, A0-1-2-3-4-5 possono anche funzionare come ingressi analogici, A4-5 possono anche funzionare come bus I2C.

Quindi o c'è un errore nel programma, o c'è un errore nei collegamenti, o si parla di un altro processore, o c'è un guasto :stuck_out_tongue:

Quindi o c'è un errore nel programma, o c'è un errore nei collegamenti, o si parla di un altro processore, o c'è un guasto

Non so che dire, la parte del programma è semplice, si tratta di cambiare stato ad una variabile; il processore è un Arduino micro pro AT328P, per quanto riguarda il guasto/collegamenti errati non mi spiego il fatto che un comune cambio da INPUT a OUTPUT permetta al sistema di funzionare.

Saluti

Enrico

Tanto meno ce lo spieghiamo noi, senza vedere il codice...

Tanto meno ce lo spieghiamo noi, senza vedere il codice...

Ecco le parti del codice contenenti i PIN incriminati.

Come si può vedere è moltp semplice, forse per questo non riesco a trovare l'errore!

int PulsDisplay = A3;
int PulsSet = A2;

void setup() {
  // put your setup code here, to run once:
  pinMode(PulsDisplay, OUTPUT);
  pinMode(PulsSet, OUTPUT);

}

void loop() {   // Loop and print the time every second.
  if ((digitalRead(PulsDisplay)) && (StatoSet == 0)) {
    if ( (millis() - t_debounce) > debounce_delay) {
      StatoDisplay = !StatoDisplay;
    }
    t_debounce = millis();
  }
}

Saluti

Solo tu sai che cosa stai facendo... Una porta impostata come uscita come può leggere lo stato del pulsante???!!!
Ricontrolla le connessioni.

Solo tu sai che cosa stai facendo... Una porta impostata come uscita come può leggere lo stato del pulsante???!!!
Ricontrolla le connessioni.

Ho riprodotto su una piastra millefori il circuito, in quanto la mia esperienza con arduino è molto limitata e le mie conoscenze di elettronica sono puramente empiriche. Ho quindi caricato il programma seguente su un UNO:

const int led1 = A2;
int PulsDisplay = A0;
bool StatoDisplay = 0;
long t_debounce = 0;
long debounce_delay = 500;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(PulsDisplay, OUTPUT);
}

void loop() {
  if (digitalRead(PulsDisplay))  {
    if ( (millis() - t_debounce) > debounce_delay) {
      StatoDisplay = !StatoDisplay;
    }
    t_debounce = millis();
  }
  if ( StatoDisplay == 1){
    digitalWrite(led1,HIGH);
  }else {
    digitalWrite(led1,LOW);
  } 
}

Come vedi è molto semplice per cui difficilmente ci sono problemi di collegamenti.

Quindi ho premuto il pulsante collegato al PIN A0 e definito come OUTPUT e …. parafrasando il Galileo nazionale … "Eppur si accende!!!" e, premendo una seconda volta si spegne!!

Purtroppo non posso allegare il video in quanto occupa troppa memoria.

Ho fatto quindi una riprova settando il PIN come INPUT e funziona.

Ritornando alla mia prima richiesta ritengo quindi si tratti di un problema legato al microPro o che l'ipotesi di Rankstrait sia corretta,

Saluti

Anche se un pin è impostato come uscita, dopo averlo impostato a livello alto o basso con digitalWrite puoi leggerne lo stato con digitalRead. Il problema è che quando è impostato come uscita ha un'impedenza bassa, anziché quasi infinita come quando è impostato come ingresso. Ciò vuol dire che se è a livello basso e lo forzi al positivo con un pulsante, leggi livello alto, ma scorre una corrente molto elevata, più o meno come se fosse a livello alto e tu lo cortocircuitassi a massa! Capisci che non è una cosa buona! Se non si danneggia è solo grazie alla limitazione di corrente interna sulle uscite, altrimenti si brucerebbe irrimediabilmente uno dei due mosfet che pilotano l'uscita. Con Arduino Uno puoi permetterti qualche "distrazione" simile, perché l'atmega328p è ben protetto, ma con altri microcontrollori devi stare attento, perché si bruciano molto più facilmente.

Perfetto, capito il concetto.

Grazie per i chiarimenti, ricontrollerò ancora una volta tutto il circuito per trovare l'inghippo. Probabilmente una saldatura non perfetta.

Saluti.

Enrico

Buongiorno a tutti

Ritorno su questo vecchio argomento in quanto proprio non riesco a risolverlo in modo corretto.

I pulsanti collegati ai PIN A2 e A3, se definiti come INPUT, non attendono la pressione del pulsante ma funzionano come se fossero sempre premuti; il funzionamento è regolare se definiti come OUTPUT.

Ritengo si tratti di un problema di programma in quanto ho rifatto tutti i collegamenti e cambiato il Mini Pro.

Allego l’intero programma e lo schema del circuito sperando che qualcuno abbia la pazienza di leggerlo ed, eventualmente, correggerlo. Tra l’altro anche collegando direttamente i PIN relativi al punto dei numeri ai 5V non si accendono. E’ perché gli altri sono collegati all’integrato? (Non ricevono direttamente il GND).

#include <stdio.h>
#include <DS1302.h>

int orario;
int data;

// Pin RTC
const int kCePin   = 2;  // Chip Enable
const int kIoPin   = 3;  // Input/Output
const int kSclkPin = 4;  // Serial Clock

const int led1 = 8;

// Pin integrati
#define DATA_PIN 7
#define LATCH_PIN 6
#define CLOCK_PIN 5

// Pin pulsanti visualizzazione/set
#define PulsDisplay A3
#define PulsSet A2

int StatoDisplay = 0;   // visualizza ora o data
int StatoSet = 0;

// Variabili scelta correzioni
int Set_Ore;
int Set_Min;
int Set_Gg;
int Set_Mesi;

// Variabili corrette
int corOre = 0;
int corMinuti = 0;
int corData = 0;
int corMese = 0;

// Variabili correzioni
int modOre = 0;
int modMinuti = 0;
int modData = 0;
int modMese = 0;

long t_debounce = 0;
long debounce_delay = 500;

// Variabili display
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;

// Variabili comandi display
unsigned long e;
unsigned long f;
unsigned long g;
unsigned long h;

unsigned long values[] = {
  //gfedcba
  0x7E, // 0
  0xC,  // 1
  0xB6, // 2
  0x9F, // 3
  0xCD, // 4
  0xDA, // 5
  0xFA, // 6
  0xE,  // 7
  0xFE, // 8
  0xDE, // 9
  0x0,  // tutto spento
};

DS1302 rtc(kCePin, kIoPin, kSclkPin);

void printTime() {
  Time t = rtc.time();

  // Array temporaneo inserimento valori data/ora
  char buf[50];

  Set_Ore = t.hr;
  Set_Min = t.min;
  Set_Gg = t.date;
  Set_Mesi = t.mon;

  corOre = t.hr + modOre;
  corMinuti = t.min + modMinuti ;
  corData = t.date + modData;
  corMese = t.mon + modMese;

  snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
           t.yr, corMese, corData,
           corOre, corMinuti, t.sec);

  // Controllo a video
  Serial.println(buf);

  orario = (corOre * 100) + corMinuti;
  data = (corData * 100) + corMese;
}

void setup() {
  Serial.begin(9600);
  Serial.println("Versione caricata 13");
  pinMode(DATA_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);

  pinMode(led1, OUTPUT);
  pinMode(PulsDisplay, OUTPUT);
  pinMode(PulsSet, OUTPUT);

  // Initializzazione data/ora
  //rtc.writeProtect(false);
  //rtc.halt(false);

  // Sunday, April 23, 2020 at 15:07:00.
  //Time t(2020, 04, 23, 15, 07, 00, Time::kSunday);

  // Memorizzazione valori inseriti
  //rtc.time(t);
}

void loop() {
  // Lampeggio Led
  if (digitalRead(led1) == HIGH)  {
    digitalWrite(led1, LOW);
  } else {
    digitalWrite(led1, HIGH);
  }

  //Visualizzazione ora/data
  if ((digitalRead(PulsDisplay)) && (StatoSet == 0)) {
    if ( (millis() - t_debounce) > debounce_delay) {
      StatoDisplay = !StatoDisplay;
      t_debounce = millis();
    }
  }
  printTime();
  nuovoSet();
  modValori();
  vis_dati();

  delay(1000);
}

void writeRegister(unsigned long value) {
  digitalWrite(LATCH_PIN, LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, value >> 24);
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, value >> 16);
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, value >> 8);
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, value);
  digitalWrite(LATCH_PIN, HIGH);
}

void vis_dati() {
  a = values[h];
  b = values[g];
  d = values[f];
  c = values[e];

  unsigned long dati = d;
  dati = (dati << 8) | c;
  dati = (dati << 8) | b;
  dati = (dati << 8) | a;

  writeRegister(dati << 0);
}

void ora() {
  e = (orario / 1000);
  f = (orario - (e * 1000)) / 100;
  g = (orario - (e * 1000) - (f * 100)) / 10;
  h = (orario - (e * 1000) - (f * 100) - (g * 10));
}

void DispData() {
  e = (data / 1000);
  f = (data - (e * 1000)) / 100;
  g = (data - (e * 1000) - (f * 100)) / 10;
  h = (data - (e * 1000) - (f * 100) - (g * 10));
}

void ModificaOra() {
  g = ((corOre ) / 10);
  h = ((corOre ) - (g * 10));
  e = 10;
  f = 10;
}

void ModificaMin() {
  g = ((corMinuti  ) / 10);
  h = ((corMinuti  ) - (g * 10));
  e = 10;
  f = 10;
}

void ModificaData() {
  g = ((corData ) / 10);
  h = ((corData ) - (g * 10));
  e = 10;
  f = 10;
}

void ModificaMese() {
  g = (corMese  / 10);
  h = corMese - (g * 10);
  e = 10;
  f = 10;
}

void  modValori() {
  switch (StatoSet) {
    case (0): // fine delle modifiche
      if (StatoDisplay == 1) {
        DispData();
      } else {
        ora();
      }
      break;

    case (1): // incrementa il valore delle ore
      while (StatoSet == 1) {
        nuovoSet();
        ModificaOra(); // visualizzo su disply i minuti
        vis_dati();

        //incremento le ore premendo PulsDisplay
        if (digitalRead(PulsDisplay)) {
          if ( (millis() - t_debounce) > debounce_delay) {
            if (corOre == 23) {
              modOre = 24 - (Set_Ore + 24);
            } else {
              modOre = modOre + 1;
            }
            corOre = Set_Ore + modOre;
          }
          t_debounce = millis();
        }
      }
      break;

    case (2): // incrementa il valore dei minuti
      while (StatoSet == 2) {
        nuovoSet();
        ModificaMin(); // visualizzo su disply i minuti
        vis_dati();
        //incremento i minuti premendo PulsDisplay
        if (digitalRead(PulsDisplay)) {
          if ( (millis() - t_debounce) > debounce_delay) {
            if (corMinuti == 59) {
              modMinuti = 60 - (Set_Min + 60);
            } else {
              modMinuti = modMinuti + 1;
            }
            corMinuti = Set_Min + modMinuti;
          }
          t_debounce = millis();
        }
      }
      break;

    case (3): // incrementa il valore della data
      while (StatoSet == 3) {
        nuovoSet();       
        ModificaData(); // visualizzo su disply la data
        vis_dati();
        //incremento la data premendo PulsDisplay
        if (digitalRead(PulsDisplay)) {
          if ( (millis() - t_debounce) > debounce_delay) {
            if (corData == 31) {
              modData = 31 - (Set_Gg + 30);
            } else {
              modData = modData + 1;
            }
            corData = Set_Gg + modData;
          }
          t_debounce = millis();
        }
      }
      break;

    case (4): // incrementa il valore dei mesi
      while (StatoSet == 4) {
        nuovoSet();
        ModificaMese();// visualizzo su disply il mese
        vis_dati();
        //incremento i mesi premendo PulsDisplay
        if (digitalRead(PulsDisplay)) {
          if ( (millis() - t_debounce) > debounce_delay) {
            if (corMese == 12) {
              modMese = 12 - (Set_Mesi + 11);
            } else {
              modMese = modMese + 1;
            }
            corMese = Set_Mesi + modMese;
          }
          t_debounce = millis();
        }
      }
      break;
  }
}

void nuovoSet()
{
  if (digitalRead(PulsSet)) {
    if ( (millis() - t_debounce) > debounce_delay) {
      StatoSet = StatoSet + 1;
      if (StatoSet > 4) {
        StatoSet = 0;
      }
      t_debounce = millis();
    }
  }
}

//******************************FINE*****************************************

Grazie per ogni eventuale aiuto.

Enrico

Orologio_schem.pdf (1.91 MB)