// https://www.plcforum.it/f/topic/317579-programma-per-realizzare-4-uscite-random-con-arduino
// Definizioni ingressi/uscite/livelli
#define PIN_PULS A0
#define PRESS_LEVEL HIGH // livello letto a pulsante premuto
#define PIN_R1 5
#define PIN_R2 4
#define PIN_R3 3
#define PIN_R4 2
#define ON_LEVEL HIGH // livello accensione elemento esterno
#define PIN_ANALOG A1 // In analogico da lasciare scollegato
// Variabili usate nel programma
int8_t xin = 0; // shift register per debounce
bool xq = 0; // ingresso pulsante filtrato
bool xqp = 0; // flag per P-edge detect
uint8_t n; // numero random estratto
uint8_t np = ~n; // numero random precedente
//----------------------------------------
void randomize(uint8_t pin) {
uint32_t seed;
// Crea un seed non deterministico
// da rumore su ingresso analogico
for (uint8_t n=0; n<7; n++) {
for (uint8_t m=0; m<50; m++)
seed += analogRead(pin);
seed <<= 4;
}
// Imposta punto di partenza casuale nella
// sequenza di valori pseudo casuali
randomSeed(seed);
}
//----------------------------------------
void setup() {
pinMode(PIN_PULS, INPUT);
pinMode(PIN_R1, OUTPUT);
digitalWrite(PIN_R1, !ON_LEVEL);
pinMode(PIN_R2, OUTPUT);
digitalWrite(PIN_R2, !ON_LEVEL);
pinMode(PIN_R3, OUTPUT);
digitalWrite(PIN_R3, !ON_LEVEL);
pinMode(PIN_R4, OUTPUT);
digitalWrite(PIN_R4, !ON_LEVEL);
randomize(PIN_ANALOG);
}
//----------------------------------------
void loop() {
// debounce 50 ms
xin = ((xin << 1) & B111111) | (digitalRead(PIN_PULS) == PRESS_LEVEL);
xq = (B111111 == xin) ? 1 : (0 == xin) ? 0 : xq;
// P-edge detect
if (xq && !xqp) {
// Estrae nuova combinaz. diversa da precedente
for (n = random(4); n == np; n = random(4));
np = n;
// Aggiorna uscite
digitalWrite(PIN_R1, 0==n ? ON_LEVEL : !ON_LEVEL);
digitalWrite(PIN_R2, 1==n ? ON_LEVEL : !ON_LEVEL);
digitalWrite(PIN_R3, 2==n ? ON_LEVEL : !ON_LEVEL);
digitalWrite(PIN_R4, 3==n ? ON_LEVEL : !ON_LEVEL);
}
xqp = xq;
// rallenta elaborazione a 100 cicli al secondo
delay(10);
}
//----------------------------------------