Shift register

Salve a tutti,
vorrei avere un chiarimento sulla programmazione degli shift register.
La board in uso è una Arduino Uno R3.

Ciò che questo sketch dovrebbe fare è:
-Leggere quanti impulsi arrivano al pin 11
-Printare il valore della variabile rpm
-Far accendere una serie di 24 led, collegati a 3 shift register 74HC595 in daisy chain, in base al valore di rpm (che si sposta da 0 a 8200, quindi un led si somma al precedente ogni 340rpm).

Questo è il codice (schifezza) prodotto fin'ora, siate buoni... :grinning:
Il problema è che non so proprio come commutare lo stato delle porte degli shift register, ho visto vari tutorial, ma continuo a non venirne a capo... :slightly_frowning_face:
Al posto di tutti quegli "if" poi, sarebbe carino poter usare una funzione lineare tipo "map", ma non saprei come infilarcela...

Idee e consigli? :grinning:

int P_latch = 8;
int P_clock = 12;
int P_data = 11;
int sensorerpm = 11;
unsigned long rpm;

void setup() {
  // put your setup code here, to run once:
  pinMode(sensorerpm, INPUT);
  pinMode(P_latch, OUTPUT);
  pinMode(P_clock, OUTPUT);
  pinMode(P_data, OUTPUT);
}

void loop() {
  rpm = pulseIn(sensorerpm, HIGH);
  if (rpm <= 340) {
    }
  if (340 < rpm <= 680) {
    }
  if (680 < rpm <= 1020) {
    }
  if (1020 < rpm <= 1360) {
    }
  if (1360 < rpm <= 1700) {
    }
  if (1700 < rpm <= 2040) {
    }
  if (2040 < rpm <= 2380) {
    }
  if (2380 < rpm <= 2720) {
    }
  if (2720 < rpm <= 3060) {
    }
  if (3060 < rpm <= 3400) {
    }
  if (3400 < rpm <= 3740) {
    }
  if (3740 < rpm <= 4080) {
    }
  if (4080 < rpm <= 4420) {
    }
  if (4420 < rpm <= 4760) {
    }
  if (4760 < rpm <= 5100) {
    }
  if (5100 < rpm <= 5440) {
    }
  if (5440 < rpm <= 5780) {
    }
  if (5780 < rpm <= 6120) {
    }
  if (6120 < rpm <= 6460) {
    }
  if (6460 < rpm <= 6800) {
    }
  if (6800 < rpm <= 7140) {
    }
  if (7140 < rpm <= 7480) {
    }
  if (7480 < rpm <= 7820) {
    }
  if (7820 < rpm) {
    }
  Serial.print("rpm ");
  Serial.print(rpm);
}

Seguendo questo tutorial, credo di aver capito che le porte si abilitano in base al "numero" inviato allo shift register.
Ho quindi modificato lo sketch di conseguenza, è corretto?

int P_latch = 8;
int P_clock = 12;
int P_data = 11;
int sensorerpm = 11;
unsigned long rpm;

void setup() {
  pinMode(sensorerpm, INPUT);
  pinMode(P_latch, OUTPUT);
  pinMode(P_clock, OUTPUT);
  pinMode(P_data, OUTPUT);
}

void loop() {
  rpm = pulseIn(sensorerpm, HIGH);
  if (rpm <= 340) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 1);  
    digitalWrite(P_latch, HIGH);}
  if (340 < rpm <= 680) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 2);  
    digitalWrite(P_latch, HIGH);}
  if (680 < rpm <= 1020) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 4);  
    digitalWrite(P_latch, HIGH);}
  if (1020 < rpm <= 1360) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 8);  
    digitalWrite(P_latch, HIGH);}
  if (1360 < rpm <= 1700) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 16);  
    digitalWrite(P_latch, HIGH);}
  if (1700 < rpm <= 2040) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 32);  
    digitalWrite(P_latch, HIGH);}
  if (2040 < rpm <= 2380) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 64);  
    digitalWrite(P_latch, HIGH);}
  if (2380 < rpm <= 2720) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 128);  
    digitalWrite(P_latch, HIGH);}
  if (2720 < rpm <= 3060) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 256);  
    digitalWrite(P_latch, HIGH);}
  if (3060 < rpm <= 3400) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 512);  
    digitalWrite(P_latch, HIGH);}
  if (3400 < rpm <= 3740) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 1024);  
    digitalWrite(P_latch, HIGH);}
  if (3740 < rpm <= 4080) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 2048);  
    digitalWrite(P_latch, HIGH);}
  if (4080 < rpm <= 4420) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 4096);  
    digitalWrite(P_latch, HIGH);}
  if (4420 < rpm <= 4760) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 8192);  
    digitalWrite(P_latch, HIGH);}
  if (4760 < rpm <= 5100) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 16384);  
    digitalWrite(P_latch, HIGH);}
  if (5100 < rpm <= 5440) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 32768);  
    digitalWrite(P_latch, HIGH);}
  if (5440 < rpm <= 5780) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 65536);  
    digitalWrite(P_latch, HIGH);}
  if (5780 < rpm <= 6120) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 131072);  
    digitalWrite(P_latch, HIGH);}
  if (6120 < rpm <= 6460) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 262144);  
    digitalWrite(P_latch, HIGH);}
  if (6460 < rpm <= 6800) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 524288);  
    digitalWrite(P_latch, HIGH);}
  if (6800 < rpm <= 7140) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 1048576);  
    digitalWrite(P_latch, HIGH);}
  if (7140 < rpm <= 7480) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 2097152);  
    digitalWrite(P_latch, HIGH);}
  if (7480 < rpm <= 7820) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 4194304);  
    digitalWrite(P_latch, HIGH);}
  if (7820 < rpm) {
    digitalWrite(P_latch, LOW);
    shiftOut(P_data, P_clock, MSBFIRST, 8388608);  
    digitalWrite(P_latch, HIGH);}
  Serial.print("rpm ");
  Serial.print(rpm);
}

Potresti fare, ma non sono sicuro

int numLed = rpm / 340;
int data = 2^numLed;
digitalWrite(P_latch, LOW);
shiftOut(P_data, P_clock, MSBFIRST, data >> 16);  
digitalWrite(P_latch, HIGH);
digitalWrite(P_latch, LOW);
shiftOut(P_data, P_clock, MSBFIRST, data >> 8);  
digitalWrite(P_latch, HIGH);
digitalWrite(P_latch, LOW);
shiftOut(P_data, P_clock, MSBFIRST, data);  
digitalWrite(P_latch, HIGH);

Controlla l'elevazione a potenza.

Grazie mille del suggerimento oggi farò delle prove, molto interessante sfruttare direttamente l'elevazione a potenza, non ci avevo pensato! :smiley:

penso che @paolo avrebbe dovuto dichiarare data come long e non int, essendo un int a 16 bit la prima serie di 8 bit sarà sempre 0
se si vuole accendere solo il led corrispondente allora data risulterà:

long data = 1 << ( rpm / 340);

se invece si vogliono accendere tutti i led fino al valore voluto data sarà:

long data = ~((~(long)0) << ( rpm / 340));

Vero. Non ho considerato la dimensione della variabile. Meglio usare unsigned long. :slight_smile: