presentazione, display a 7 segmenti e varie...

Ciao a tutti ,

sono da poco un possessore di un arduino 2009 (mi è arrivato giovedì scorso). Sono completamente a digiuno di elettronica nonostante i miei 31 anni, però me la cavo con la programmazione. Ho collegato un display a 7 segmenti ( di 2 cifre ) ad arduino, riesco a visualizzare le cifre ma non capisco perchè se il display è alimentato a 5v non riesco a fare l'upload del codice, mentre con i 3.3v non ho problemi. Arduino è alimentato via usb tramite un hub a cui sono collegate altre periferiche, è un problema di basso voltaggio ? Uso i pin dallo 0 al 14 per i segmenti, e i 5v per gli anodi comuni, non collego i pin dei puntini. Il display è collegato senza resistenze di alcun genere, rischio che si bruci ? Dal datasheet di questo non ho capito a quanto deve essere alimentato, se qualcuno volesse darci un'occhiata, il modello è ROHM LB-6710 (ricavato da un vecchio televisore MIVAR)

Parlando di arduino invece, vorrei sapere a cosa serve il pulsantino sulla board, se è possibile pilotarlo ( ma dai tutorial che ho visto, credo di no) e perchè sono presenti 2 GND vicino al 5v ( sono 2 gnd, vero ? )

In ultimo vorrei sapere se esiste in zona roma e dintorni un negozio che venda arduino oppure è solamente disponibile on-line ? Non ho preso lo starter-kit ed ora sto rosicando come pochi, so benissimo che sono componenti che si trovano facilmente ma qui in zona i negozi di elettronica fanno prezzi assurdi e acquistare lo starter kit online mi sembra eccessivo visto i notevoli 12? di spese di spedizione.

Grazie.

Ciao e benvenuto nel mondo dei micro :) Iniziamo dall'aspetto del controllo dei display: utilizzare tutte le uscite per accendere dei display è un vero spreco, perchè se ci pensi un attimo è possibile pilotare i 7 segmenti (e se vuoi anche il punto) con 7 uscite (8 con il punto) e 1 uscita per ogni digit, per un totale di 9 pin nel tuo caso (10 con il punto). In pratica si tratta di accendere un display alla volta così rapidamente che l'occhio li vede sempre accesi (ovvero con un ciclo che stia al di sotto del venticinquesimo di secondo).

Questa particolare gestione (detta multipexer), oltre a risparmiare in collegamenti (tutti i segmenti a devono essere collegati assieme, così come tutti i b, e così via..), permette un risparmio nei consumi.

Infatti il tuo problema può effettivamente essere dovuto all'eccessivo carico dovuto al consumo di ben 14 led accesi contemporaneamente (e senza una resistenza per ciascuno almeno da 220[ch937] rischi di far saltare tutti i led..).

Se poi vuoi spingerti oltre nella gestione del multiplexeing puoi addirittura accendere un segmento alla volta in un ciclo abbastanza veloce da non far scorgere all'occhio il farfallio (e in questo caso puoi anche omettere la resistenza perchè il lampo di luce per ogni segmento deve essere chiaramente molto intenso ma è abbastanza corto da scongiurare che il led si fulmini). Così arrivi ad accendere i tuoi display con il consumo di un solo led.. ;)

Per quello che poi concerne il problema dei costi di spedizione purtroppo non ti posso essere di aiuto.. io ad esempio per ridurre i costi mi sono acquistato un set completo con tutti i valori di resistenze su eBay, e per molto altro coltivo l'arte del recupero da vecchi apparecchi elettronici (che sono una vera fonte quasi inesauribile).

Grazie per le varie informazioni.
In pratica il multiplexing sarebbe una sorta di POV. Interessante.
Ma come lo metto in pratica ?
Potresti descrivermi pin per pin ?

utilizzare tutte le uscite per accendere dei display è un vero spreco, perchè se ci pensi un attimo è possibile pilotare i 7 segmenti (e se vuoi anche il punto) con 7 uscite (8 con il punto) e 1 uscita per ogni digit, per un totale di 9 pin nel tuo caso (10 con il punto).

Ossia i pin dallo 0 al 7 controllano i 14 segmenti, il pin 8 per i punti, il pin 9 e il pin 10 per i digit (ossia quelli che vanno ai 5v) ?
Attualmente i digit sono entrambi collegati ai 5v perchè le cifre i numeri da 0 a 9 sono visualizzati con lo zero davanti ( 00, 01, 02…)

E per il codice ? Attualmente io uso questo:

/* */
const boolean digits[] =
                          {
                            1, 1, 1, 1, 1, 1, 0, /* 0 */
                            0, 1, 1, 0, 0, 0, 0, /* 1 */
                            1, 0, 1, 1, 0, 1, 1, /* 2 */
                            1, 1, 1, 1, 0, 0, 1, /* 3 */
                            0, 1, 1, 0, 1, 0, 1, /* 4 */
                            1, 1, 0, 1, 1, 0, 1, /* 5 */
                            1, 1, 0, 1, 1, 1, 1, /* 6 */
                            0, 1, 1, 1, 0, 0, 0, /* 7 */
                            1, 1, 1, 1, 1, 1, 1, /* 8 */
                            1, 1, 1, 1, 1, 0, 1, /* 9 */
                          };

/* */
void draw_number(const byte number) {
  byte i;
  byte n;
  static byte old_n = 1;
  
  n = number % 10;
  for ( i = 0; i < 7; i++ ) {
    digitalWrite(i, !digits[i + (n*7)]);
  }
  
  n = number / 10;
  if ( n != old_n ) {
    for ( i = 7; i < 14; i++ ) {
        digitalWrite(i, !digits[i-7 + (n*7)]);
    }
    old_n = n;
  }
}

/* */
void setup() {
  byte i;
  
  for ( i = 0; i < 14; i++ ) {
    pinMode(i, OUTPUT);
  }
}

/* */
void loop() {
  byte i;

  for ( i = 0; i < 100; i++ ) {
    draw_number(i);
    delay(1000);
  }
}

Grazie per l’aiuto.

facciamola più semplice...

i pin dallo 0 al 7 pilotano i segmenti (punto incluso) di entrambi i display, e quindi devi collegare ogni segmento uguale di ciascun display con una delle uscite (es.: pin 0 -> a, 1->b, ... 7->punto). i pin 8 e 9 sono i "selettori" dei display.

Considera che ogni uscita di Arduino ha capacità sia di fornire corrente (source) che di riceverne (sink), e se guardi le specifiche del processore (datasheet: http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf) vedi anche i limiti consentiti per ogni pin.

Ora prima di proseguire: vuoi fare il multipexing semplice (per digit) o completo (per digit e per segmento)??

p.s. per il codice prima proviamo a vedere se riesci a scrivere qualcosa di tuo, eventualmente poi ti posto qualcosa di completo, ok?

ok il codice me lo scrivo da solo!

Ora prima di proseguire: vuoi fare il multipexing semplice (per digit) o completo (per digit e per segmento)??

...mmm cosa cambia ? Io sono interessato a visualizzare le cifre...al momento facciamolo semplice, poi semmai provo da solo ad implementare il completo...

Considera che ogni uscita di Arduino ha capacità sia di fornire corrente (source) che di riceverne (sink), e se guardi le specifiche del processore (datasheet: http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf) vedi anche i limiti consentiti per ogni pin.

In pratica setti il modo tramite pinMode(X, [INPUT|OUTPUT]), giusto ? Perchè questa nota, non capisco in che modo è implicata. Le uscite digitali possono essere solamente LOW e HIGH, mentre ad esempio se volessi usare un potenziomentro dovrei usare quelle marcate PWM.

Ma si scrive multipexing o multipLexing ? Oppure vanno bene entrambi ?

ma proprio non hai la possibilità di fare un psu da 5v a parte per il display?

ma proprio non hai la possibilità di fare un psu da 5v a parte per il display?

Sono a digiuno di elettronica, psu sta per “Power Supply Unit” ?
Perchè dovrei alimentare il display esternamente ?

Ora prima di proseguire: vuoi fare il multipexing semplice (per digit) o completo (per digit e per segmento)??

…mmm cosa cambia ?
Io sono interessato a visualizzare le cifre…al momento facciamolo semplice, poi semmai provo da solo ad implementare il completo…

il termine corretto è Multiplexing … è stato solo un mio errore di scrittura (se non sbagliassi ogni tanto da qualche parte mi sentirei un mostro ;D )

Il multiplexing per digit vuol dire che accendi un digit completo (sino a 8 led/segmenti) alla volta, per segmento invece accendi sempre e solo un led/segmento alla volta.

n pratica setti il modo tramite pinMode(X, [INPUT|OUTPUT]), giusto ?
Perchè questa nota, non capisco in che modo è implicata. Le uscite digitali possono essere solamente LOW e HIGH, mentre ad esempio se volessi usare un potenziomentro dovrei usare quelle marcate PWM

Non è quello che volevo dirti…
In sostanza se colleghi un led tra due pin, ad esempio il 4 e il 5, poi imposti entrambi come USCITE (nota bene, entrambe uscite) hai questo risultato:

pin 4 pin 5 stato led
0 0 spento
1 0 acceso se catodo comune*
0 1 acceso se anodo comune*
1 1 spento

*o viceversa a seconda di come hai collegato il led ai pin (con almeno una resistenza da 220[ch937] da una parte).

In pratica ottieni un funzione di XOR (or esclusivo) e questo perchè la corrente esce dal pin a 1 e rientra dal pin a 0, ed essendo il LED di fatto un diodo la corrente passa solo attraverso una direzione.

Tutto chiaro?

P.S: spero di aver spiegato bene, anche io non sono un “elettronico” ma principalmente un programmatore, ma dopo tanti anni di scrittura di firmware certi concetti mi sono entranti in mente da soli :stuck_out_tongue:

si, grazie,

stasera appena torno a casa proverò qualcosa.

ok, fatto!
Funziona!

Nel caso di suggerimenti, posto il codice.
Grazie a tutti.
(anche se per quanto riguarda il pulsante di arduino non mi ha risposto nessuno. Domanda stupida ?)

/* 0 to 9 */
const byte digits[] = { 64, 121, 18, 48, 41, 36, 4, 113, 0, 32 };
                        
/* */
void draw_number(const byte number) {
  byte i;
  byte digit1;
  byte digit2;
  
  digit1 = number / 10;
  digit2 = number % 10;
  
  for ( i = 0; i < 150; i++ ) {
    PORTD = digits[digit1];
    PORTB = 1;
    delay(1);
    PORTD = digits[digit2];
    PORTB = 2;
    delay(1);
  }
}

/* */
void setup() {
  DDRD = 127;  /* pins 0 to 6, output */
  DDRB = 3;    /* pins 8 to 9, output */
}

/* */
void loop() {
  byte i;

  for ( i = 0; i < 100; i++ ) {
    draw_number(i);
  }
}

Il pulsante? che pulsante :o

Ah si… se guardavi lo schema del tuo Arduino 2009 (http://arduino.cc/en/uploads/Main/arduino-duemilanove-schematic.pdf) ti saresti accorto che S1 è il pulsante di reset :wink:

Non può avere altri scopi ed è molto comodo se un programma ti si blocca in un loop infinito e vuoi rivedere cosa accade prima…

Ah si.. se guardavi lo schema del tuo Arduino 2009 (http://arduino.cc/en/uploads/Main/arduino-duemilanove-schematic.pdf) ti saresti accorto che S1 è il pulsante di reset

...e se ero capace a leggerlo non facevo una domanda tanto scontata!

A parte gli scherzi, nel codice, che timings mi consigli di usare ? Un'altra domanda, visto che sei cosi disponibile approfitto, girovagando sul web ho visto un codice che usa

delay(0.5);

ma dalla reference si legge che la funzione delay accetta un unsigned long come parametro, quindi 0.5 dovrebbe essere troncato a 0, ossia verrebbe delay(0); che non credo abbia effetto...invece il codice senza quel comando non funziona...perchè ? Sinceramente non ho provato se delay(0) dia gli stessi risultati anche perchè, per me, delay(0) non dovrebbe avere nessun effetto...

...e se ero capace a leggerlo non facevo una domanda tanto sconta

Scusa.. non avevo considerato questo aspetto... (per il quale comunque ti consiglio vivamente di cercare di comprendere qualcosa altrimenti con Arduino non vai molto lontano :P )

Per il timing il problema è che la programmazione di un microprocessore non è come quella di un normale computer, dove le risorse a disposizione sono quasi infinite, e perciò e fondamentale comprendere l'uso e il funzionamento delle periferiche interne, come ad esempio i Timer, che nel tuo caso potrebbero essere la miglior risposta alla tua domanda.

Ma principalmente quello che si dovrebbe sempre tenere presente nella programmazione di firmware (che è quello di cui discutiamo qui) è che di solito una funzione come quella di mostrare dei valori su di un display è una parte di un programma che magari rileva i valori da sonde e/o attiva o aziona relè, motori e quant'altro. Il tutto con dei feedback che spesso necessitano di una tale precisione nel timing che anche dove e come gestire un display può diventare una scelta fondamentale.

Tutto questo per dirti che dipende da cosa vuoi far fare ad Arduino... se si tratta solo di accendere dei led (o segmenti) il problema è secondario, basta che se sei in multiplexing la velocità di scansione non sia inferiore al 25mo/30mo di secondo.

Per quanto riguarda la tua osservazione su Delay() direi che può trattarsi anche di un piccolo errore di chi ha scritto il programma che hai visto, perchè è come chiedere alla funzione di fare un ritardo di 1/2 millisecondo quando la funzione accetta da 1 a 1000 millisencondi ;) Il fatto però che il codice possa funzionare solo perchè esiste quella chiamata alla funzione delay (che forse poteva benissimo essere anche delay(0); ) è dovuta al fatto che è la chiamata di per se che usa cicli macchina e quindi genera un ritardo, e probabilmente è stato calcolato da qualcuno che equivale appunto a 0.5 millisencondi (e se qualcuno che legge è al corrente della cosa si faccia avanti ;) )

grazie per il supporto! Veramente utile.