Se volessi leggere l'ingresso analogico su 8 bit(led)?

Sono alle prime armi con Arduino e il C++, anche se avevo fatto un corso qualche anno fa ormai.
Ho un po' di esperienza con micro-controllori programmati in assembler dedicato, ma ormai ho abbandonato da un po' di tempo.
Consulto questo forum per la prima volta, non so come fare una ricerca sull'argomento fra i vari messaggi fin quì postati e ho deciso di scrivere il presente messaggio.

Per sperimentare mi piacerebbe leggere il valore in binario su 8 bit, corrispondenti a 8 led montati sulle uscite digitali, del valore del convertitore ADC.
La mia idea era leggere in diretta ciò che fornisce il convertitore A/D su 8 bit, anche se esso è a 10 bit, e fornisce valori che vanno da 0 a 1024.
Come posso pilotare le uscite digitali in base al valore dell'ADC?

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

I valori letti vanno da 0 a 1023. Per avere dei valori da 0 a 255 ( 8bit) basta dividere il valore con 4.
Ciao Uwe

Non hai risposto alla sua domanda però.

mi piacerebbe leggere il valore in binario su 8 bit, corrispondenti a 8 led montati sulle uscite digitali, del valore del convertitore ADC.

Ti potrei suggerire di passare il valore (intero) ricavato dopo la divisione per 4 al registro direttamente, non avendo detto quale arduino hai e supponendo che hai un 328 usare il registro PORTB, sempre supponendo che non usi uno shield, altrimenti ti crei un array con 8 pin dedicati alla conversione
http://www.arduino.cc/en/Reference/PortManipulation

nid69ita:
Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Buongiorno,

scusate!!
Sono perito elettronico, attualmente lavoro nella scuola come assistente tecnico di laboratorio, per quanto riguarda il settore elettrico ed automazione industriale.
In passato ho avuto esperienza con i microcontrollori PIC della Microchip e ho lavorato nel privato, per circa 10 anni, nel settore dell'automazione industriale.
Mi sto avvicinando ad ARDUINO a piccoli passi. Ho acquistato la scheda ARDUINO 1 ed il libro "Primi passi con Arduino", già finito di leggere e sperimentare.

Saluti.

A livello binario il valore dell'ADC a 10 bit di Arduino (0-1023) corrisponde a B0000000000-B1111111111.

Perciò potresti usare la funzione bitRead(x, n) ove x è il bit da esaminare ed n è il numero.

Con una semplice sequenza di digitalWrite(pin, value), accendi o spegni il LED corrispondente (ricordati di inserire il resistore di limitazione corrente):

unsigned int N = analogRead(A0);

digitalWrite(LED1, bitRead(0, N)); 
digitalWrite(LED2, bitRead(1, N)); 
digitalWrite(LED3, bitRead(2, N)); 
...

pablos:
Ti potrei suggerire di passare il valore (intero) ricavato dopo la divisione per 4 al registro direttamente, non avendo detto quale arduino hai e supponendo che hai un 328 usare il registro PORTB, sempre supponendo che non usi uno shield, altrimenti ti crei un array con 8 pin dedicati alla conversione
http://www.arduino.cc/en/Reference/PortManipulation

Leggendo il libro e consultando il sito, non avevo trovato niente riguardo ai registri dedicate alle porte di I/O, per cui non sapevo come orientarmi. Ho letto il link che hai postato e noto che la situazione è simile ai registri che si utilizzano per pilotare i micro-controllori della Microchip, per cui la cosa mi è più familiare.
L'unico dubbio riguarda la sintassi da usare nel linguaggio C++. Domanda: l'esempio che trovo nel link che hai postato è quello da utilizzare anche sulla IDE di Arduino 1?

Se hai una porta da 8 bit (sono tutte da 8 bit su ATmega) dedicata ai led (es. da PB0-PB7), conviene usare:

PORTB = (uint8_t)adcValue;

Il quale assegna il valore di adcValue a PORTB forzando la perdita di risoluzione a 8bit tramite il cast esplicito (uint8_t), che se viene rimosso dovrebbe portare il compilatore ad emettere un warning senza per questo impedire la corretta compilazione e funzionamento del codice.

Ovviamente tutti i led rimarranno accesi per valori di adcValue superiori a 255.

Nel caso in cui si voglia usare digitalWrite() serve compilare un array = {2,8,6, ...
dove 2,8,6 ecc sono i pin di arduino, poi bisogna un ciclo for lungo 8 iterazioni al cui all'interno
si legge un bit dal valore adcValue che viene passato a digitalWrite insieme a array*, dove i è l'indice che conta da 0 a 7.*
PS: non uso più digitalWrite da un secolo
Hai postato poco prima di me.
* *Leggendo il libro e consultando il sito, non avevo trovato niente riguardo ai registri dedicate alle porte di I/O, per cui non sapevo come orientarmi.* *
C'è tutto quello che conosci dei PIC anche con arduino. Immagina dei livelli, i registri sono a livello 0, mentre arduino sta sopra di molti livelli e usa anche esso il livello 0. Il livello 0 lo trovi descritto nel datasheet del microcontroller che hai montato su arduino, il livello appena superiore a 0 lo trovi descritto in avrlibc avr-libc: AVR Libc
La mia opinione in merito a Why use port manipulation? presente nel link Arduino Reference - Arduino Reference
Purtroppo devo dissentire, digitalWrite e digitalRead sono funzioni parecchio lente per i seguenti motivi:
- C'è la chiamata a funzione e il passaggio di parametri che impegna cicli CPU
- si accede in lettura alla memoria Flash che è molto più lenta della ram
Tutto questo per semplificare l'uso ai novizi, che si perderebbero con il concetto di registri,
manipolazione bitwise ecc. Arduino è pensato per l'uso immediato da parte di persone che
non vogliono, non hanno il tempo, non hanno interesse verso i problemi informatici. Poi il
novizio smetterà di esserlo con i suoi tempi magari scontrandosi con la lentezza di digitalWrite
e cercherà una soluzione, la trova e non si scoraggia di fronte a bitwise perché forte dei successi precedenti.
Quindi io consiglio queste funzioni per la stesura iniziale del software, sempre se ciò semplifica e non complica, in tal caso si passa ad usare l'accesso diretto alle porte.
Ciao.

Avevo pensato anch'io ad un array con cui gestire le porte connesse ai led, ma poi mi sono incartato e non sapevo come andare avanti. Inizio seguendo questa strada poi proseguo cercando altre soluzioni percorrendo le indicazioni che avete suggerito.
Vediamo cosa riesco a fare, vi faccio sapere... :wink:

Ciao a tutti.

Allora... ho provato a seguire la strada degli array, ma purtroppo non riesco a far accendere i led in base al valore dei bit del convertitore analogico-digitale. Non ho ancora provato ad utilizzare le funzioni per la manipolazione delle porte del micro-controllore. Per il momento volevo provare a utilizzare la funzione digitalWrite mediante un ciclo for e un array dedicato, ma appunto, come detto, non so come fare. La difficoltà è trasferire il valore di analogRead in un array, sul quale poi leggere il valore dei bit e far accendere i led corrispondenti!! :confused:

Fabrizio

MauroTec:
Purtroppo devo dissentire, digitalWrite e digitalRead sono funzioni parecchio lente per i seguenti motivi:

  • C'è la chiamata a funzione e il passaggio di parametri che impegna cicli CPU
  • si accede in lettura alla memoria Flash che è molto più lenta della ram
  • c'è il controllo in caso il pin avesse anche la funzione PWM che viene disattivata.

gieffe:
La difficoltà è trasferire il valore di analogRead in un array, sul quale poi leggere il valore dei bit e far accendere i led corrispondenti!!

--> c - Represent Unsigned Integer in Binary - Stack Overflow
Da adattare...

#include <stdlib.h>

int main(int argc, char *argv[]) {
  int j;
  unsigned int value = 1024+2048+4096; // some value
  char mask[8*sizeof(unsigned int) + 1] = {0};
  for (j = 0; j < (8*sizeof(unsigned int) + 1); j++) {
    mask[j] = (value << j) & (1 << (8*sizeof(unsigned int)-1)) ? '1' : '0';
  }
  printf("value is b%s\n", mask);
  return 0;
}

Oppure più velocemente con una struct.
--> Bitwise Operators in C
Esempio

struct packed_struct {
  unsigned int f1:1;
  unsigned int f2:1;
  unsigned int f3:1;
  unsigned int f4:1;
  unsigned int type:4;
  unsigned int my_int:9;
} pack;

Vorrei capire se vuoi fare la manipolazione diretta delle porte (PORTB ecc) oppure se vuoi semplicemente - con qualsiasi metodo - visualizzare lo stato 1/0 dei bit dell'ADC.
Nella seconda ipotesi, potresti anche visualizzare tutti e 10 i bit, basta usare 10 uscite e 10 LED.
Se vuoi 8 bit, bisogna vedere cosa vuoi ottenere. Tronchi di netto, per cui hai 255 per OGNI VALORE superiore a 255, oppure riscali tutto perdendo in risoluzione ma avendo comunque la scala piena, quindi 255 corrisponde al 1024 dell'ADC.

paulus1969:
Vorrei capire se vuoi fare la manipolazione diretta delle porte (PORTB ecc) oppure se vuoi semplicemente - con qualsiasi metodo - visualizzare lo stato 1/0 dei bit dell'ADC.
Nella seconda ipotesi, potresti anche visualizzare tutti e 10 i bit, basta usare 10 uscite e 10 LED.
Se vuoi 8 bit, bisogna vedere cosa vuoi ottenere. Tronchi di netto, per cui hai 255 per OGNI VALORE superiore a 255, oppure riscali tutto perdendo in risoluzione ma avendo comunque la scala piena, quindi 255 corrisponde al 1024 dell'ADC.

Per il momento vorrei seguire la seconda ipotesi, mediante altro metodo, diverso dalla manipolazione diretta delle porte. Lo faccio per avere un pochino più confidenza con il C++.
Per quanto riguarda i led di visualizzazione dei bit, in effetti, ho cambiato e ho messo 10 led usando 10 uscite.

PaoloP:
--> c - Represent Unsigned Integer in Binary - Stack Overflow
Da adattare...

#include <stdlib.h>

int main(int argc, char argv[]) {
 int j;
 unsigned int value = 1024+2048+4096; // some value
 char mask[8
sizeof(unsigned int) + 1] = {0};
 for (j = 0; j < (8sizeof(unsigned int) + 1); j++) {
   mask[j] = (value << j) & (1 << (8
sizeof(unsigned int)-1)) ? '1' : '0';
 }
 printf("value is b%s\n", mask);
 return 0;
}




Oppure più velocemente con una struct.
--> http://www.tutorialspoint.com/ansi_c/c_bits_manipulation.htm
Esempio


struct packed_struct {
 unsigned int f1:1;
 unsigned int f2:1;
 unsigned int f3:1;
 unsigned int f4:1;
 unsigned int type:4;
 unsigned int my_int:9;
} pack;

Grazie del suggerimento... :wink:
Oddio... :o Ci devo studiare un po'!! Mi applico poi vediamo cosa accade!! ::slight_smile: