[Risolto] Problema monitor seriale con shiftIn

Buonasera a tutti,
ho un problema, ho costruito un circuto come quello descritto sell'esempio shiftIn, ho preso il codice dello sketck 1.2 http://arduino.cc/en/Tutorial/ShftIn12 e ho caricato il tutto senza problemi.

Quando vado ad aprire il monitor seriale però mi compare sempre la stessa stringa indipendentemente dal tasto che premo sulla board...

0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------

Cosa sbaglio?

Forse hai sbagliato un collegamento. manda una foto
Ciao Uwe

https://docs.google.com/file/d/0B_P7vD_dWeryMWwxSms4cXpCVWc/edit?usp=sharing

C'è anche un integrato nella foto, che nella fattispecie ho scollegato per provare solo la parte di shiftIn, per cui non era collegato al momento delle prove.

Nella seconda foto si vede invece il collegamento dell'IC per lo shiftIn , ovviamente v+ e GND sono collegati giusti anche se non si vedono.
Banalmente ho corretto nel programma anche la il nuero dei pin coinvolti, in quanto li ho cambiati. 10 - Data --- 11 - Clock --- 12 - Latch.

Questo il codice modificato:

//define where your pins are
int latchPin = 12;
int dataPin = 10;
int clockPin = 11;

//Define variables to hold the data 
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000

//define an array that corresponds to values for each 
//of the shift register's pins
char note2sing[] = {
  'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'}; 


void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, INPUT);

}

void loop() {

  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first 
  switchVar1 = shiftIn(dataPin, clockPin);

  //Print out the results.
  //leading 0's at the top of the byte 
  //(7, 6, 5, etc) will be dropped before 
  //the first pin that has a high input
  //reading  
  Serial.println(switchVar1, BIN);


  //This for-loop steps through the byte
  //bit by bit which holds the shift register data 
  //and if it was high (1) then it prints
  //the corresponding location in the array
  for (int n=0; n<=7; n++)
  {
    //so, when n is 3, it compares the bits
    //in switchVar1 and the binary number 00001000
    //which will only return true if there is a 
    //1 in that bit (ie that pin) from the shift
    //register.
    if (switchVar1 & (1 << n) ){
      //print the value of the array location
      Serial.println(note2sing[n]);
    }
  }

//white space
Serial.println("-------------------");
//delay so all these print satements can keep up. 
delay(500);

}

//------------------------------------------------end main loop

////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0

byte shiftIn(int myDataPin, int myClockPin) { 
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop

//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
  for (i=7; i>=0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(0.2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      //set the bit to 0 no matter what
      myDataIn = myDataIn | (1 << i);
    }
    else {
      //turn it off -- only necessary for debuging
     //print statement since myDataIn starts as 0
      pinState = 0;
    }

    //Debuging print statements
    //Serial.print(pinState);
    //Serial.print("     ");
    //Serial.println (dataIn, BIN);

    digitalWrite(myClockPin, 1);

  }
  //debuging print statements whitespace
  //Serial.println();
  //Serial.println(myDataIn, BIN);
  return myDataIn;
}

Non credo funzioni

delayMicroseconds(0.2);

Assolutamente no. delayMicroseconds vuole un unsigned int.

boh, non mi da problemi quella parte in particolare..poi ho fatto copia/incolla dall'esempio, per cui potrebbe essere un errore nell'esempio stesso e varrebbe la pena segnalarlo?

cmq ho semplificato il tutto per vedere se riuscivo a risolvere il problema, per cui stesso circuito di prima ma seguente codice;

int latchPin = 12;
int dataPin = 10;
int clockPin = 11;

byte incoming = 72;

void setup() {
  Serial.begin(9600);
  
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);
  
}

void loop() {
  
  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);
  
  byte incoming = shiftIn(dataPin, clockPin, MSBFIRST);
  
  Serial.println(incoming, BIN);
  Serial.println("             ");
  delay(500);
  
}

Carico senza problemi, ma...

0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0
             
0

e via dicendo..in quanto ogni 500ms genera un nuovo "0"

Ora..nella mia ignoranza, questo programmino dovrebbe restituire il codice binario corrispondente al pulsante premuto giusto??

Lo shift register che uso è un CD4021BEE4 (cod 662-9565 su RS), giusto per essere certo di non sbagliare a monte (ma non credo!!)

Hai un delay di 500 ms, significa che la lettura verrà fatta solo ogni 500 ms, quindi devi essere bravo a cogliere quei 20 us durante i quali lo sketch manda il segnale allo shift register di leggere gli ingressi: collegando direttamente un ingresso dello shift register a +5V, il risultato cambia?

leo72:
Hai un delay di 500 ms, significa che la lettura verrà fatta solo ogni 500 ms, quindi devi essere bravo a cogliere quei 20 us durante i quali lo sketch manda il segnale allo shift register di leggere gli ingressi: collegando direttamente un ingresso dello shift register a +5V, il risultato cambia?

Appena posso provo a collegare direttamente a +5V, ma anche tenendo premuto a lungo il tasto non ottengo cambiamenti!

Intanto che ci sono ho un'altra domanda: come posso utilizzare gli switch collegati al CD4021 come interruttori? Se con uno switch collegato ad un pin mi basta una condizione IF if switch1 = HIGH --> fai quello che devi come devo definire la variabile switch1 perchè funzioni allo stesso modo quando premo lo switch numero 1 collegato allo switch register?

Non ho capito la domanda. Il chip si chiama "shift register", che in italiano significa "registro a scorrimento" perché il registro interno su cui memorizza lo stato dei pin è letto/scritto pigiando in ingresso o in uscita (a seconda del tipo di chip) i bit uno alla volta e facendo scorrere gli altri già presenti.
Per capirsi, se devi mandar fuori il byte 10010001 da destra, sarà quindi:
10010001
[0]1001000->1
[00]100100->01
[000]10010->001
ecc...

leo72:
Non ho capito la domanda. Il chip si chiama "shift register", che in italiano significa "registro a scorrimento" perché il registro interno su cui memorizza lo stato dei pin è letto/scritto pigiando in ingresso o in uscita (a seconda del tipo di chip) i bit uno alla volta e facendo scorrere gli altri già presenti.
Per capirsi, se devi mandar fuori il byte 10010001 da destra, sarà quindi:
10010001
[0]1001000->1
[00]100100->01
[000]10010->001
ecc...

Devo dirti la verità, non ho capito molto bene. Ho un'idea un po' vaga di come funzioni lo shift register come input, un po' più chiara come funzioni quello in output e ho comunque parecchio materiale (libri) da sfogliare perchè l'argomento mi interessa molto.

Ti spiego brevemente quello che vorrei fare e come avevo pensato di farlo:

Input: 8 pulsanti (momentanei) che entrano in arduino tramite CD4021
Output: 8 relé che vanno ad aprire/chiudere altrettanti circuiti, collegati ad arduino tramite 74HC595 e batteria di darlington

  • una serie di altre applicazioni che nella fattispecie sono uno step successivo e su cui mi concentrerò in seguito.

Funzionamento: io premo uno di questi switch e attivo una serie di relè preimpostati (che in un secondo momento andrò a leggere da EEPROM, ma per ora non voglio complicarmi troppo la vita)

Collegando direttamente gli switch ad Arduino senza shift register, ne in input ne in output mi trovo una programmazione di questo tipo (la sintassi è probabilmente errata..ma è un esempio):

Int switch0 = x;
.
.
.
Int switch7 = y;

Int out0 = a;
.
.
.
Int out7 = b;

//x, y, a, b sono variabili numeriche corrispondenti ai pin di arduino a cui sono collegati gli switch di in/out, ovviamente definisco tutte le variabili da 0 a 7 sia per in che per out...

void setup() {

pinMode(switch0, INPUT);
.
.
.
pinMode(out7, OUTPUT);

//con tutto quello che ci sta in mezzo..
}

void loop(){

if (switch0 = HIGH) {

out1 = HIGH
out4 = HIGH
out7 = HIGH

}

else

{

out1 = LOW
out4 = LOW
out7 = LOW

}

//ovviamente questa è una sequenza arbitraria e bisogna ripetere la condizione if per ogni switch..

Ora pensando il programma utilizzando la condizione "switch case", leggendo l'input dello shift register vorrei fare la stessa cosa

Pensa allo shift register di tipo PISO, ossia Parallel In - Serial Out, quello che stai usando tu, come se fosse una macchina fotografica.

Nel momento in cui attivi il pin di latch lui "scatta" un'istantanea dello stato logico dei pin e la salva nel registro interno.
A questo punto con shiftIn tu non fai altro che spingere fuori da quel registro il valore memorizzato un pin alla volta. Immagina di avere una bottiglia verticale tipo quella dei whisky nei pub con dentro 8 dosi: ad ogni pressione del dosatore sottostante estrai una dose. Dopo 8 dosi hai svuotato la bottiglia. Nel caso della bottiglia, la dose di liquore è sempre presente, mentre nel caso dello shift register può esserci, in questo caso si legge "1", come non esserci, in questo caso il "vuoto" equivale allo "0".

Detto questo, shiftIn ti restituisce lo stato degli 8 ingressi del 4021. Per leggere lo stato dei singoli bit, fai una semplice operazione di lettura con bitRead che restituisce lo stato di un particolare bit.
Per sapere se il 1° bit è acceso o spento, basta fare

if (bitRead(valore, 0)) { //bit acceso
 ...
} else { //bit spento
 ...
}

ah, ok molto più chiaro ora 8)

allora, ho provato a fare come avevi detto, con lo sketch precedente caricato ho provato a dare 5v direttamente ad un pin del cd4021 e...niente sempre questa demoralizzantissima sfilza di zeri!!!

Per sicurezza ho cambiato anche il componente con un altro uguale..ma niente

Che cosa posso fare?

EDIT: come al solito il problema è una ca***ta...la mia breadboard ha probabilmente un qualche morsetto ossidato e non arrivava l'alimentazione al cd4021...ora sembra che vada..e almeno il primo dei miei problemi è risolto!!!!

Grazie a tutti, per ora

Ok. Metti [Risolto] nel titolo del 1° post di questa discussione :wink: