Misuratore Ampere / Volt / Continuità per pista Slot

Che è MISO, occupato dalla SPI
spostalo!

Errore da novizio! Per questo motivo scrivo molto nel forum :smiley:

Grazie mille davvero!!

Adesso risolto anche questo problema volevo cercare un modo per snellire e cancellare le tante funzioni che ho creato per la stampa attraverso l'uso di funzioni parametriche. Vediamo che cosa riesco a fare.

Te l'avevo detto che qualcuno piu "softwarista" avrebbe probabilmente trovato il problema meglio di me :wink:

ricki158:
... snellire e cancellare ...

Solo come suggerimento ... quando cancelli tutto per passare a finestre completamente diverse, che dovresti comunque riscrivere (tipo, quando fai impostazioni o selezioni), invece di usare le varie funzioni "clear", fai semplicemente il clear dell'intero lcd ... poi al massimo ristampi una sola volta le parti statiche ... in questo modo, sara' un po piu lento durante i passaggi di schermata, ma puoi eliminare tutte le varie funzioni "clear" dedicate (tanto adesso la cancellazione delle scritte durante il funzionamento normale la fai con l'ultimo sistema, dentro alle funzioni di scrittura, giusto ?) ... :wink:

Io per le funzioni "clear" avevo in mente un'altra cosa: tengo la funzione generale e inserisco come argomento il colore, che per le funzioni clear sarà il nero.

Buonasera a tutti!

Sotto consiglio di Silente sono passato a scrivere le funzioni inserendo i parametri che mi interessavano, generalizzando in questo modo le funzioni ed utilizzandone una per fare 4 stampe diverse. Che dire, il risultato è strepitoso perché sono passato dalle 1000 righe alle 500.

Oltretutto sono riuscito a capire come dare per parametro un oggetto (in questo caso i display) e sono riuscito a fare le stampe prima su un solo display e poi sull'altro. Devo dire che non cambia molto per quel che riguarda il flickering.

Ho aperto un topic nella sezione software per avere alcune delucidazioni appunto su come inserire alcuni parametri ed ho scoperto altre cose molto utili per far si che i propri codici funzionino :smiley:

Dopo aver fatto tutti questi passi da gigante posso dire di aver completato la parte di stampa sui display e di averla ottimizzata al massimo. Se avete altre idee vi prego parlatemene :smiley:

Visto che non vedevo l'ora di cominciare a misurare qualcosa, ho unito tutto (visto che funziona) al programma principale che svolge le letture e sono riuscito a farlo funzionare facendo qualche aggiustaggio.
Per il momento sto facendo le letture senza nessun tipo di media, così da velocizzare le letture.
Sembra funzionare!

Ho due problemi però:

-1: la variazione dei valori non viene cancellata nella maniera corretta;
-2: la stampa del valore massimo che cambia avviene soltanto nel canale in quel momento selezionato da varSel. La stampa però, perché invece il massimo viene salvato su tutti i canali in maniera diversa. Quindi sostanzialmente quando mi muovo con il tasto che cambia varSel mi si "aggiorna" la stampata del valore massimo.

Allego il codice, vorrei fare un video ma in questo momento non riesco.

Multimetro_Pista.ino (17.1 KB)

Buongiorno a tutti!
Dopo un po' di tempo riscrivo su questo topic. Sono riuscito a sistemare il codice e a migliorarlo ancora un pochino su certi aspetti. Adesso funziona tutto a dovere. Ho provato la lettura delle tensioni ed è corretta e abbastanza veloce. La parte di rilevatori di corrente non l'ho ancora finita perché non li abbiamo ancora installati ma ho provato "al banco" gli ACS, 3 su 4 hanno caratteristiche corrette mentre uno solo ha una sensitivity di 0.40 mV/A anziché 0.30 mV/A. Non si sa perché ma rimane lineare nella curva. Vabbé vuol dire che ne terrò conto nel software.
Nel frattempo mi è arrivata la scheda dalla Cina che ho già stagnato (mi son dimenticato di comprare solamente una morsettiera da stampato a 45° da 2 poli sennò sarebbe già finito), ho fatto la plancia del mobiletto e appena posso farò il mobiletto completo con una stampante 3D.
Per il momento funziona tutto e sono molto soddisfatto. Volevo ringraziarvi.

Buongiorno a tutti!
Finalmente ho ritrovato un po' di tempo per concludere questo progetto. Purtroppo però ho cantato vittoria troppo presto.

Ho installato tutto sulla scheda come sulla breadboard, ho però scambiato i pin RST CS e D/C dei due display, sempre mantenendoli digitali ma non MOSI, MISO e SCK. Questo per non incrociare i cavi che ho saldato al connettore per i display. Questa è l'unica modifica che ho fatto e naturalmente ho cambiato i #define del codice per quanto riguarda questi pin. Ho quindi provato per la prima volta la scheda arrivata dalla Cina.

I display si accendono ma viene stampato il codice presente nella funzione "setup" di Arduino, mentre il "loop" non parte proprio. Ho fatto un debug semplicemente inserendo un Serial.println("Pippo"); nel loop ma non c'è nessun tipo di comunicazione.

Mi sembra molto strana questa cosa. Ho provato varie schede Arduino funzionanti e mi danno tutte lo stesso problema, se però tengo la scheda "volante" il loop funziona regolarmente dal momento che leggo su seriale "Pippo".

Potrei aver cambiato il pin sul quale porto i 5v del regolatore di tensione rispetto alla breadboard, non ricordo, ma anziché portare la tensione a monte del regolatore la porto a valle. Però mi sembra comunque strano che soltanto il "loop" sia bloccato. Magari devo ponticellare l'alimentazione sulla scheda Arduino. Non ricordo, devo tornare indietro nel topic a rileggere il discorso, è passato un po' di tempo.

Escludo comunque un problema nel software, il problema è della scheda che ho fatto io sicuramente. Bisogna "soltanto" trovare dove! Ed avere un po' di tempo per mettersi sotto e trovarlo.

Per il resto sto disegnando il mobiletto in SolidWorks per farmelo stampare in 3D, viene carino.

Intanto assieme a MightyPegas stiamo vedendo di migliorare un pochino la libreria Adafruit per i convertitori analogico digitali ADC1015 / ADC1115. Praticamente con gli ADC1115 è possibile avere un campionamento più veloce (anche per i 1015) cambiando alcuni #define, li ho inseriti quindi nella libreria .h ma questi #define sono "bloccati" nella libreria .cpp. Vorrei fare qualcosa di "generico", aggiungendo possibilità alla libreria senza riscriverla. Mi spiego meglio magari con il codice.

Questo è il pacco di #define relativi alla velocità di campionamento nel file .h:

#define ADS1015_REG_CONFIG_DR_MASK      (0x00E0)  
#define ADS1015_REG_CONFIG_DR_128SPS    (0x0000)  // 128 samples per second
#define ADS1015_REG_CONFIG_DR_250SPS    (0x0020)  // 250 samples per second
#define ADS1015_REG_CONFIG_DR_490SPS    (0x0040)  // 490 samples per second
#define ADS1015_REG_CONFIG_DR_920SPS    (0x0060)  // 920 samples per second
#define ADS1015_REG_CONFIG_DR_1600SPS   (0x0080)  // 1600 samples per second (default)
#define ADS1015_REG_CONFIG_DR_2400SPS   (0x00A0)  // 2400 samples per second
#define ADS1015_REG_CONFIG_DR_3300SPS   (0x00C0)  // 3300 samples per second

Ai quali ho aggiunto:

#define ADS1115_REG_CONFIG_DR_MASK     	(0x00E0)
#define ADS1115_REG_CONFIG_DR_8SPS     	(0x0000)  // 8 samples per second
#define ADS1115_REG_CONFIG_DR_16SPS    	(0x0020)  // 16 samples per second
#define ADS1115_REG_CONFIG_DR_32SPS    	(0x0040)  // 32 samples per second
#define ADS1115_REG_CONFIG_DR_64SPS    	(0x0060)  // 64 samples per second
#define ADS1115_REG_CONFIG_DR_128SPS   	(0x0080)  // 128 samples per second (default)
#define ADS1115_REG_CONFIG_DR_250SPS   	(0x00A0)  // 250 samples per second
#define ADS1115_REG_CONFIG_DR_475SPS   	(0x00C0)  // 475 samples per second
#define ADS1115_REG_CONFIG_DR_860SPS   	(0x00E0)  // 860 samples per second

E fin qui tutto ok.
Nel file .cpp però tutte le funzioni hanno più o meno questa morfologia:

/**************************************************************************/
/*!
    @brief  Gets a single-ended ADC reading from the specified channel
*/
/**************************************************************************/
uint16_t Adafruit_ADS1015::readADC_SingleEnded(uint8_t channel) {
  if (channel > 3)
  {
    return 0;
  }
  
  // Start with default values
  uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)
                    ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)
                    ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)
                    ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)
                    ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)
                    ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

  // Set PGA/voltage range
  config |= m_gain;

  // Set single-ended input channel
  switch (channel)
  {
    case (0):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
      break;
    case (1):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
      break;
    case (2):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
      break;
    case (3):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
      break;
  }

  // Set 'start single-conversion' bit
  config |= ADS1015_REG_CONFIG_OS_SINGLE;

  // Write config register to the ADC
  writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);

  // Wait for the conversion to complete
  delay(m_conversionDelay);

  // Read the conversion results
  // Shift 12-bit results right 4 bits for the ADS1015
  return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;  
}

Quello che vorrei fare è impostare anziché ADS1015_REG_CONFIG_DR_1600SPS la velocità che voglio io senza per forza scrivere ADS1115_REG_CONFIG_DR_860SPS nel file .cpp, rendendo valida questa libreria solo in questo caso specifico e non in "generale".

Conseguentemente ho la possibilità di variare anche il tempo di delay che aspetto per la conversione. La differenza sostanzialmente tra usare l 1015 e il 1115 è che nel primo ho un delay di 1 mS mentre nel secondo ho un delay di 8 mS. Ma con 860 SPS posso scendere a 2 mS. Anche qui, vorrei riuscire a capire come fare affinché il delay si regoli automaticamente in base alla velocità di campionamento scelta. Anche perché così ad occhio, la libreria è scritta per valori di default, mentre se cambio valori devo farlo sia per la velocità di campionamento sia per il delay.

Chiedo informazioni su come fare poiché di librerie ne so veramente poco, ed ho anche poca immaginazione derivante da poca pratica :smiley: . Allego lo zip della libreria con il file .h al quale ho aggiunto le velocità per il 1115.

Grazie ragazzi!

Adafruit_ADS1X15-master.zip (12.7 KB)

Buongiorno a tutti!

L'Arduino continua a non far girare il "loop" e non ne so il motivo.
I 5v li porto al pin Vcc dell'Arduino Pro Micro (schema elettrico in allegato), cioè a valle del regolatore di tensione interno, esattamente come sulla breadboard, mi ritrovo però circa la stessa tensione (circa 0.1 - 0.2 V in meno) sul pin RAW che è quello in entrata al regolatore di tensione e che è alimentato dalla presa USB, che però non collego!
Sui pin digitali ed analogici mi ritrovo la tensione di alimentazione oppure delle tensioni da 1.20 V.

Non so proprio che pesci pigliare e come risolvere questo problema.
Come mai il "loop" non gira?

Ho proprio bisogno di un vostro aiuto!

Riccardo

Multimetro Pista SlotCar.pdf (46.5 KB)

Le tensioni di cui parli le trovi sia con la scheda inserita nell'altra, sia con la scheda disinserita ? ... non e' che usi per sbaglio uno dei pin di comunicazione per qualcos'altro ? (non controllare solo come hardware, anche nel software) ...

Allora…
Ti rispondo qui nel thread perché è una cosa di interesse generale…

Ho letto delle tue ultime peripezie per quanto riguarda la grafica, l'aggiornamento dei dati e il flickering e ho guardato il source.
Da subito ho visto che, pur ottenendo il risultato voluto, sbagliavi il sistema per cancellare il contenuto precedente.
Il sistema più veloce è la fillRect che, a seconda del chip della scheda, utilizza sistemi ottimizzati per scrivere sullo schermo. Nel tuo caso purtroppo il chip non ha di queste facilitazioni, ma la fillRect rimane comunque più veloce perché non deve comporre i caratteri leggendo dalla PGM_MEM e fare una marea di moltiplicazioni per rapportare al textSize, il tutto poi in aggiunta ad un'altra conversione float->ASCII.

Poi… andando a curiosare sulla libreria gfx (io ne usavo un'altra) ho trovato questo:

    // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
    // THIS IS ON PURPOSE AND BY DESIGN.  The background color feature
    // has typically been used with the 'classic' font to overwrite old
    // screen contents with new data.  This ONLY works because the
    // characters are a uniform size; it's not a sensible thing to do with
    // proportionally-spaced fonts with glyphs of varying sizes (and that
    // may overlap).  To replace previously-drawn text when using a custom
    // font, use the getTextBounds() function to determine the smallest
    // rectangle encompassing a string, erase the area with fillRect(),
    // then draw new text.  This WILL infortunately 'blink' the text, but
    // is unavoidable.  Drawing 'background' pixels will NOT fix this,
    // only creates a new set of problems.  Have an idea to work around
    // this (a canvas object type for MCUs that can afford the RAM and
    // displays supporting setAddrWindow() and pushColors()), but haven't
    // implemented this yet.

In pratica usando la fonte interna della libreria a dimensione fissa (quella che usi tu se non sbaglio) la libreria già di suo cancella il contenuto precedente in quanto scrive sia il colore in primo piano (il carattere) che lo sfondo. Naturalmente se il nuovo testo risulta più corto del precedente sulla destra ti potranno rimanere uno o più caratteri.
Ad esempio
scrivi "12.34"
e poi allo stesso punto scrivi "0.00"
sullo schermo avrai "0.004"

Ma questo è un problema facilmente risolvibile in diverse maniere.
Il sistema più semplice sarebbe stato tramite la sprintf che (anche se un po' lenta) con gli opportuni parametri avrebbe provveduto a tutto, ma purtroppo la sua implementazione in AVR GCC non supporta i float (e double).
Si deve ricorrere quindi alla dtostrf che trasforma un float/double in stringa (ma senza le opzioni di allineamento della sprintf).
In pratica devi stabilire a priori il numero di cifre max (nel caso dei volt ad es. 6 caratteri: 1 per il segno, 2 per i volt, 1 per il punto e 2 decimali).
Poi con la dtostrf trasformi il float in ascii dentro un buffer e conti i caratteri del risultato
Poi o posti il testo all'interno del buffer a dx e riempi a sx con gli spazi, oppure scrivi sullo schermo n spazi (la differenza tra il num. max di cifre e quelle che hai), calcoli le nuove coordinate e fai la print.

Quando cambi schermata (ad es. dai volt agli ampere) con la fillRect cancelli le aree interessate e scrivi i nuovi valori.

E ti liberi di una marea di codice :slight_smile:

Quindi il "riempiere un rettangolo" è più veloce del "coloro solo i pixel accesi in quel rettangolo" ?
Comunque la libreria di suo non cancella il testo precedente, per questo ho fatto funzioni generiche parametriche che chiamo inserendo il colore e da dove prendere i valori, così posso cancellare facilmente i caratteri.
Al momento l'unica cosa che varia velocemente e che ha un certo flickering sono i volt e gli ampere che aggiorno il più velocemente possibile. Per il resto non ho problemi. Vorrei cercare di risolvere questi problemi imprevisti, dopodiché potrei pensare ad un'ultima ottimizzazione delle stampate, così da migliorare ancor di più la visualizzazione. Grazie intanto!

ricki158:
Quindi il "riempiere un rettangolo" è più veloce del "coloro solo i pixel accesi in quel rettangolo" ?

in questo caso sì, perché ti risparmi tutto il lavoro di creazione del carattere da inviare e un'altra trasformazione float->ascii.

Poi guarda la differenza dei due loop principali della drawChar (richiamata per ogni carattere) e della fillRect (loop che nel nostro caso verrebbe eseguito 7*textSize volte)
Qualcosa mi dice che quello della fillRect sia più veloce :slight_smile:
Anche perchè la stessa drawChar nel caso textSize sia maggiore di 1 richiama la fillRect per ogni punto del carattere da ingrandire...

    for(int8_t i=0; i<6; i++ ) {
      uint8_t line;
      if(i < 5) line = pgm_read_byte(font+(c*5)+i);
      else      line = 0x0;
      for(int8_t j=0; j<8; j++, line >>= 1) {
        if(line & 0x1) {
          if(size == 1) drawPixel(x+i, y+j, color);
          else          fillRect(x+(i*size), y+(j*size), size, size, color);
        } else if(bg != color) {
          if(size == 1) drawPixel(x+i, y+j, bg);
          else          fillRect(x+i*size, y+j*size, size, size, bg);
        }
      }
  for (; x0<=x1; x0++) {
    if (steep) {
      drawPixel(y0, x0, color);
    } else {
      drawPixel(x0, y0, color);
    }
    err -= dy;
    if (err < 0) {
      y0 += ystep;
      err += dx;
    }

Comunque la libreria di suo non cancella il testo precedente, per questo ho fatto funzioni generiche parametriche che chiamo inserendo il colore e da dove prendere i valori, così posso cancellare facilmente i caratteri.

strano... da quel che si vede nel loop che ho postato, lo sfondo viene scritto... a patto che il colore sia impostato diverso da quello di primo piano...

Massimo

ricki158:
Comunque la libreria di suo non cancella il testo precedente, per questo ho fatto funzioni generiche parametriche che chiamo inserendo il colore e da dove prendere i valori, così posso cancellare facilmente i caratteri.

Credo di aver scoperto il motivo...
Della setTextColor ne esistono due versioni, con uno o due parametri.
Quella che usi tu (1 parametro) imposta lo sfondo e il primo piano allo stesso colore (modalità "trasparente") e quindi ogni volta che scrivi traccia il solo carattere senza toccare lo sfondo...
Dovresti usare la versione a 2 parametri setTextColor (fgcolor, bgcolor) per impostare entrambi i colori...

Massimo

Usando la versione a due parametri, vado a rallentare molto la stampata? Comunque interessante, perché a questo punto tutto il lavoro di ottimizzazione del codice non mi serve più e non devo cancellare ogni volta o ad ogni cambio di pagina! Ancora meno righe e forse poso eliminare un po' di funzioni parametriche o parametri di funzione.

ricki158:
Usando la versione a due parametri, vado a rallentare molto la stampata? Comunque interessante, perché a questo punto tutto il lavoro di ottimizzazione del codice non mi serve più e non devo cancellare ogni volta o ad ogni cambio di pagina! Ancora meno righe e forse poso eliminare un po' di funzioni parametriche o parametri di funzione.

Difficile a dirsi.
Prima in effetti scrivevi solo il carattere invece di tutto il quadretto che lo racchiudeva. Con questo sistema invece scriveresti molti più punti, ma faresti un solo passaggio invece di due e non dovrebbe più esserci il flickering.

Ottimizzando un po' il codice della drawChar per dimensioni >1 evitando di fargli fare call di call di call (sistema che hanno ideato per eventuale override da parte dei driver specifici dei chip ma che con il tuo display non ci sono) su 6 caratteri da scrivere a occhio si potrebbe recuperare 1 mS o più per ogni print...

Se poi fai il bravo, ti regalo un pezzetto di codice estratto dal mio display con il quale potresti ridurre tutte quelle pagine di display a poche righe :wink:
Occuperesti però più ram (che in parte recupereresti non dovendo più memorizzare i valori precedenti come fai ora)

Massimo

Adesso più che altro devo trovare come mai ci sono questi problemi di sincronia per far funzionare tutto.
Alla fine, come uno stupido, avevo un problema con le periferiche ADC1115 che erano girate al contrario e bloccavano il loop. Girandole nella maniera corretta però funziona comunque male. Com'è possibile che ci siano questi problemi passando da breadboard a basetta finale?

ricki158:
Adesso più che altro devo trovare come mai ci sono questi problemi di sincronia per far funzionare tutto.
Alla fine, come uno stupido, avevo un problema con le periferiche ADC1115 che erano girate al contrario e bloccavano il loop. Girandole nella maniera corretta però funziona comunque male. Com'è possibile che ci siano questi problemi passando da breadboard a basetta finale?

Bé, ma quante modifiche hai fatto sullo sketch?
Ti è rimasta una versione del programma di quando girava sulla breadboard?

Per il display, se puoi scambiare i connettori tra i due intanto puoi vedere se dipende dal display o da altro.
Se il problema si trasferisce da uno all'altro allora ricontrolla il collegamento dei segnali... Le piattine quando si saldano diventano delicate all'attaccatura sulla saldatura, si spezzano facilmente a causa delle piccole incisioni lasciate sui conduttori al momento della spellatura, e i connettori crimpati per le piattine non sono una certezza, può capitare un contatto difettoso...

Gli ADC1115 funzionano ancora entrambi?
Le sincronie se hai moduli o componenti che non rispondono correttamente è facile che vadano a pallino.

Massimo

Lo sketch che girava su breadboard è quello attuale, solamente con i #define dei display cambiati e con l'aggiornamento della libreria degli ADC1115.

Gli ADC1115 funzionano entrambi.

Appena mi è possibile controllo i cavi variando i connettori.

Ho provato a invertire i cavi. I cavi non hanno problemi, il secondo display fa la neve. Anche se collegato da solo.

ricki158:
Ho provato a invertire i cavi. I cavi non hanno problemi, il secondo display fa la neve. Anche se collegato da solo.

Se invertendo i cavi la neve resta, sai cosa significa, vero? :frowning: