sono 2 giorni che tento inutilmente senza successo, di utilizzare gli shift in ed out...
incomincio:
ho 2 cd4021 messi in cascata, con data > D2, latch > D3, clock > D4.
a questi ci sono collegati: al primo cd4021 8 pulsanti, più le resistenze di pull down (10k) su ogni ingresso, e sul secondo 6 interruttori, più resistenze di pull down...
in una subroutine che ho chiamato readshiftin(), dovrei vedere lo stato di ogni pulsante e interruttore, che se premuto (o chiuso), deve fare una determinata azione, modificare una variabile booleana, oppure incrementare una variabile intera, ecc...
ma dopo una marea di codici che ho testato, non ho avuto successo...
stessa cosa per i 74hc595 (sempre 2 in cascata) con data > D10, latch > D11, clock > D12.
a questi ci sono collegati 16 leds ed un transistor npn bc337 con resistenza di base da 150ohm.
vorrei gestire i leds ed il transistor, in modo indipendente, ovvero cambiare una sola uscita, senza intaccare le altre... (con un array (byte), sarebbe semplice, ma non ci sono riuscito -.- in quanto nell'istruzione shiftout devi mettere una variabile byte, o una sola variabile dell'array)
ho trovato qualche codice, ma anche qui non ho avuto fortuna...
chiedo cortesemente il vostro aiuto per risolvere questi problemi.
vorrei gestire i leds ed il transistor, in modo indipendente, ovvero cambiare una sola uscita, senza intaccare le altre... (con un array (byte), sarebbe semplice, ma non ci sono riuscito -.- in quanto nell'istruzione shiftout devi mettere una variabile byte, o una sola variabile dell'array)
Usa un unica variabile a 16 bit che rappresenta le singole uscite degli shift register, ad esempio:
uint16_t PORTS = 0x0000;
Quando vuoi cambiare una uscita (senza intaccare le altre) usi la tecnica del bitwise.
Ad esempio:
PORTS |= (1 << 2); // ON - mette a "1" il bit n.2, che corrisponde alla terza uscita degli SR (uscite numerate da 1 a 16)
PORTS &= ~(1 << 2); // OFF - mette a "0" il bit n.2, che corrisponde alla terza uscita degli SR (uscite numerate da 1 a 16)
Puoi più opportunamente definire delle costanti che rappresentino le uscite per una maggiore chiarezza di codice:
#define LED0 0
#define LED1 1
....
#define BJT 15
Ad ogni modifica di PORTS invii la variabile agli SR con una routine tipo:
@uwe, leo e pelletta, ho usato le guide descritte sia per i collegamenti (uwe certamente ho collegato il din col dout, non hanno il data in comune, e certamente i diodi leds hanno ognuno una resistenza da 330ohm in serie), sia per i primi tests, ma poi ho creato codici di testa mia, basandomi su quel pò di teoria di elettronica digitale fatta quest'anno a scuola, anche se senza risultati... (ed ho anche scoperto, che le funzioni shiftin e shiftout, utilizzavano un codice con un ciclo molto simile a quello che avevo pensato io...)
@dalubar: non ci ho capito molto su quello che hai scritto, e non ho capito soprattutto, come associare i define dei leds al codice riportato... ti chiederei, di essere un po più clemente, e spiegarmi meglio come fare, grazie
ringrazio tutti per le risposte!
P.S. il code lo posto domani, perchè c'è l'ho nell'altro pc...
nella prima riga dello shiftOut,con highByte(PORTS) si inviano gli otto bit più significativi che compongono la variabile unit_16 PORTS,di conseguenza con lowByte(PORTS) si inviano gli otto bit meno significativi,ho capito bene o dico una fesseria? Grazie
@ultra:
si tratta di manipolazione diretta dei bit di una variabile.
Se le cose ti sembrano difficili, lascia perdere per ora e cerca di far funzionare il circuito nel modo a te più congeniale e comprensibile. In un secondo tempo ti studierai i bit e la manipolazione degli stessi. http://arduino.cc/en/Reference/Bit
XD
Allora, cerco di spiegarmi meglio. Il concetto è quello di associare ognuna delle 16 uscite degli Shift Register (SR) ad uno specifico bit di una variabile denominata PORTS. Supponendo che stai collegando 16 LED numerati da 1 a 16, allora potresti definire qualcosa di simile:
In questo modo, quando vuoi accendere (o spegnere) un particolare LED puoi usare direttamente il suo nome. Se il codice che ho postato ti sembra troppo complicato allora puoi usare le comode e semplici istruzioni bitSet() e bitClear().
Quindi, ad esempio, se vuoi accendere il led 5 puoi scrivere semplicemente:
bitSet(PORTS, LED5);
mentre se vuoi spegnere il led 1:
bitClear(PORTS, LED1);
Quando hai finito le modifiche invii PORTS agli SR con la funzione che ti ho scritto.
Nota che nella natura intrinseca degli shift register, il bit inviato per PRIMO si trovera nell'ULTIMA uscita, ecco perchè si inviano prima i bit più significativi e poi quelli meno significativi.
digitalWrite(latchin,1);
delayMicroseconds(20);
digitalWrite(latchin,0);
shiftin1 = shiftIn(datain, clockin);
shiftin2 = shiftIn(datain, clockin);
for (int n=0; n<=7; n++)
{
if (shiftin1 & (1 << n) ){
switch(n){
case 0:
block3=false;
break;
case 1:
block2=false;
break;
case 2:
block1=false;
break;
case 3:
if (block3==false && manual==true){
if (start3 == true){
start3=false;
}else{
start3=true;
}
}else {
start3=false;
}
break;
case 4:
if (block2==false && manual==true){
if (start2 == true){
start2=false;
}else{
start2=true;
}
}else {
start2=false;
}
break;
case 5:
if (block1==false && manual==true){
if (start1 == true){
start1=false;
}else{
start1=true;
}
}else {
start1=false;
}
break;
case 6:
if (manual == true){
manual=false;
}else{
manual=true;
}
break;
}
}
}
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 (shiftin2 & (1 << n) ){
//print the value of the array location
//Serial.println(note2sing[n]);
}
}
delay(500);
poi ho provato con questo:
for (int x=15; x >=0; x--){
digitalWrite(clockin,LOW);
if (digitalRead(datain)==HIGH) {
switch(x){
case 0:
block3=false;
break;
case 1:
block2=false;
break;
case 2:
block1=false;
break;
case 3:
if (block3==false && manual==true){
if (start3 == true){
start3=false;
}else{
start3=true;
}
}else {
start3=false;
}
break;
case 4:
if (block2==false && manual==true){
if (start2 == true){
start2=false;
}else{
start2=true;
}
}else {
start2=false;
}
break;
case 5:
if (block1==false && manual==true){
if (start1 == true){
start1=false;
}else{
start1=true;
}
}else {
start1=false;
}
break;
case 6:
if (manual == true){
manual=false;
}else{
manual=true;
}
break;
}
}
}
digitalWrite(clockin,HIGH);
delay(200);
Una domanda: ma ciò che leggi è ciò che devi fare? Ossia, c'è una corrispondenza fra gli ingressi e le uscite?
Se è così potresti semplicemente spedire in uscita i 2 byte letti in ingresso per cui se ad esempio 1 bit in ingresso va alto, lo mandi in uscita per attivare il corrispondente dispositivo (led, relè ecc..).
Il piedino 15 è denominato P7, non è il 6° ingresso, è l'7°, dato che la numerazione va da P1 a P8. Se parliamo di "posizione" del bit che lo indica, allora è il 6° bit.
perchè cliccando i pulsanti, a volte è come se non li clicchi, ovvero non viene registrato il passaggio di stato?
Probabilmente è un problema di bounce, cioè di "rimbalzo" elettrico del pulsantino. Prova effettuando 2 letture distanziate di 30 ms e poi prendi per buone solo quelle che in entrambi i casi sono risultate HIGH.
@leo, anch'io credo sia un problema di bounce, grazie della risposta, proverò...
per quanto riguarda il cd4021 il p7 nella funzione getbit, ha come indice 0, il p6 ha indice 1, il p1 ha indice 6, il p8 che indice avrà? 7? non ho provato perchè in entrambi gli shift l'ho cortocircuitato col gnd, in quanto non lo uso, ma era per un chiarimento...