#include <SPI.h>
// https://programmersqtcpp.blogspot.com/
const byte PIN_DATA = 11;
const byte PIN_LATCH = 4;
const byte PIN_CLOCK = 13;
const byte PIN_START = 7;
byte g_state;
uint16_t g_rndNumber; // range 1000÷3000 ms
bool g_btn0State;
struct timer_t {
uint32_t oneSec;
uint16_t oneSecInt;
uint32_t t0;
uint32_t t1;
} timer;
struct Semaforo_t {
byte cnt = 8;
byte data;
} semaforo; // istanza di tipo Semaforo_t
enum State {
RE_START, SEMAFORO, MONITORING, END_RESET
};
byte g_testResult;
void setup() {
Serial.begin(115200);
pinMode(PIN_START, INPUT_PULLUP);
SPI.begin();
pinMode(PIN_LATCH, OUTPUT);
//pinMode(PIN_DATA, OUTPUT);
//pinMode(PIN_CLOCK, OUTPUT);
digitalWrite(PIN_LATCH, HIGH);
/*digitalWrite(PIN_LATCH, LOW);
SPI.transfer(85);
digitalWrite(PIN_LATCH, HIGH);
delay(100);
digitalWrite(PIN_LATCH, LOW);
SPI.transfer(0);
digitalWrite(PIN_LATCH, HIGH);*/
writeShiftReg(0);
}
// writeShiftReg usa la SPI hardware
// la chiamata writeShiftReg(byte data) consuma 148us
void writeShiftReg(byte data) {
digitalWrite(PIN_LATCH, LOW);
SPI.transfer(data); // spi hardware
//shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, data); //spi software
digitalWrite(PIN_LATCH, HIGH);
}
byte semaforoRun() {
if ((millis() - timer.oneSec) >= timer.oneSecInt) {
timer.oneSec = millis();
timer.oneSecInt = 1000;
semaforo.data |= (1 << (semaforo.cnt - 1))
| (1 << (semaforo.cnt - 2)); // end command
//uint32_t g_us = micros();
writeShiftReg(semaforo.data);
//Serial.println(micros() - g_us);
semaforo.cnt -= 2;
if (semaforo.cnt == 0) {
semaforo.cnt = 8;
// *** GHANGE STATE
g_state = MONITORING;
timer.t0 = millis();
return g_state;
}
}
return g_state;
}
void initRandom() {
static bool lstate;
if (!lstate) {
Serial.println("Premi per iniziare il test.");
lstate = true;
} else {
if (digitalRead(PIN_START) == LOW) {
// carica il timer oneSec
timer.oneSec = millis();
// azzera intervallo
timer.oneSecInt = 0;
// Inizializza il generatore rnd
randomSeed(micros());
// genera un numero nel range 1000÷3000
g_rndNumber = random(1000, 3001);
}
}
}
void loop() {
switch (g_state) {
case RE_START:
initRandom();
if (g_rndNumber) {
// *** CHAGE STATE ***
g_state = SEMAFORO;
Serial.println("Premi il pulsante allo \nspegnimento del semaforo.");
}
break;
case SEMAFORO:
// quando tutte le luci sono accese
// g_state assume il valore SEMAFORO + 1
// che è uguale a MONITORING
g_state = semaforoRun();
break;
case MONITORING:
g_btn0State = digitalRead(PIN_START);
if (((millis() - timer.t0) >= g_rndNumber
&& semaforo.data != 0)) {
// spegne tutt i led
semaforo.data = 0;
writeShiftReg(0);
// salva millis()
timer.t0 = millis();
}
// Se pulsante premuto e data == 0
if (g_btn0State == LOW && semaforo.data == 0) {
g_testResult = 1;
timer.t1 = millis();
/*Serial.print("Tempo di reazione: ");
Serial.print(millis() - timer.t0);
Serial.println("ms");*/
// ** CHAGE STATE **
g_state = END_RESET;
// Se premi il pulsante con i led ancora accesi
} else if (g_btn0State == LOW && semaforo.data != 0) {
//Serial.println("Falsa partenza");
g_testResult = 2;
// ** CHAGE STATE **
g_state = END_RESET;
}
break;
case END_RESET:
semaforo.data = 0;
writeShiftReg(0);
if (g_testResult == 1) {
Serial.print("Tempo di reazione: ");
Serial.print(timer.t1 - timer.t0);
Serial.println("ms");
} else if (g_testResult == 2) {
Serial.println("Falsa partenza");
}
g_testResult = 0;
delay(200);
while(!digitalRead(PIN_START));
//delay(200);
delay(g_rndNumber/8);
Serial.print("rnd number: ");
Serial.println(g_rndNumber);
Serial.println("Premi per ricominciare.");
g_rndNumber = 0;
// ** CHAGE STATE **
g_state = RE_START;
break;
}
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
sr1:Q1
sr1:Q2
sr1:Q3
sr1:Q4
sr1:Q5
sr1:Q6
sr1:Q7
sr1:GND
sr1:Q7S
sr1:MR
sr1:SHCP
sr1:STCP
sr1:OE
sr1:DS
sr1:Q0
sr1:VCC
led1:A
led1:C
led2:A
led2:C
led3:A
led3:C
led4:A
led4:C
led5:A
led5:C
led6:A
led6:C
led7:A
led7:C
led8:A
led8:C
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
gnd1:GND
r1:1
r1:2
r2:1
r2:2
r3:1
r3:2
r4:1
r4:2
r5:1
r5:2
r6:1
r6:2
r7:1
r7:2
r8:1
r8:2