/*
Projeto 34 - Corrida de LEDs (fita WS2812B de 5 metros com 300 LEDs)
Física na Lixa
https://fisicanalixa.blogspot.com/
https://sites.google.com/aelixa.pt/fisicaearduino
*/
#include <Adafruit_NeoPixel.h>
#define MAXLED 300 // Número de LEDs da fita
#define fitaLED A0
#define btn1 7 // Botão do jogador 1
#define btn2 6 // Botão do jogador 2
#define som 3
#define COLOR1 track.Color(255,0,0) // Cor do jogador 1 - VERMELHO
#define COLOR2 track.Color(0,255,0) // Cor do jogador 2 - VERDE
int NPIXELS = MAXLED;
int musica[] = {2093, 2637, 3136, 2093, 2637, 3136, 2093, 2637, 3136};
byte gravidade[MAXLED];
int TBEEP = 3;
float velocidade1 = 0;
float velocidade2 = 0;
float dist1 = 0;
float dist2 = 0;
byte loop1 = 0;
byte loop2 = 0;
byte leader = 0;
byte loop_max = 5; // Total de voltas da corrida
float ACEL = 0.2;
float kf = 0.015; // Constante de atrito
float kg = 0.003; // Constante de gravidade
byte flag_sw1 = 0;
byte flag_sw2 = 0;
byte draworder = 0;
unsigned long timestamp = 0;
int tdelay = 5;
Adafruit_NeoPixel track = Adafruit_NeoPixel(MAXLED, fitaLED, NEO_GRB + NEO_KHZ800);
void setup()
{
for(int i=0; i<NPIXELS; i++)
{
gravidade[i] = 127;
}
track.begin();
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
set_ramp(12,90,100,110); // Neste exemplo o início da rampa está no LED 90, o topo no 100 e o final no 110
for(int i=0; i<NPIXELS; i++)
{
track.setPixelColor(i, track.Color(0,0,(127-gravidade[i])/8));
}
track.show();
start_race();
}
void loop()
{
for(int i=0; i<NPIXELS; i++)
{
track.setPixelColor(i, track.Color(0,0,(127-gravidade[i])/8));
}
if((flag_sw1==1) && (digitalRead(btn1)==0))
{
flag_sw1 = 0;
velocidade1 += ACEL;
}
if((flag_sw1==0) && (digitalRead(btn1)==1))
{
flag_sw1 = 1;
}
if((gravidade[(word)dist1 % NPIXELS])<127)
{
velocidade1 -= kg*(127-(gravidade[(word)dist1 % NPIXELS]));
}
if((gravidade[(word)dist1 % NPIXELS])>127)
{
velocidade1 += kg*((gravidade[(word)dist1 % NPIXELS])-127);
}
velocidade1 -= velocidade1*kf;
if((flag_sw2==1) && (digitalRead(btn2)==0))
{
flag_sw2 = 0;
velocidade2 += ACEL;
}
if((flag_sw2==0) && (digitalRead(btn2)==1))
{
flag_sw2 = 1;
}
if((gravidade[(word)dist2 % NPIXELS])<127)
{
velocidade2 -= kg*(127-(gravidade[(word)dist2 % NPIXELS]));
}
if((gravidade[(word)dist2 % NPIXELS])>127)
{
velocidade2 += kg*((gravidade[(word)dist2 % NPIXELS])-127);
}
velocidade2 -= velocidade2*kf;
dist1 += velocidade1;
dist2 += velocidade2;
if(dist1>dist2)
{
leader = 1;
}
if(dist2>dist1)
{
leader = 2;
}
if(dist1>NPIXELS*loop1)
{
loop1++;
tone(som,600);
TBEEP = 2;
}
if(dist2>NPIXELS*loop2)
{
loop2++;
tone(som,700);
TBEEP = 2;
}
if(loop1>loop_max)
{
for(int i=0; i<NPIXELS; i++)
{
track.setPixelColor(i, track.Color(0,255,0));
}
track.show();
winner_fx();
loop1 = 0;
loop2 = 0;
dist1 = 0;
dist2 = 0;
velocidade1 = 0;
velocidade2 = 0;
timestamp = 0;
start_race();
}
if(loop2>loop_max)
{
for(int i=0; i<NPIXELS; i++)
{
track.setPixelColor(i, track.Color(255,0,0));
}
track.show();
winner_fx();
loop1 = 0;
loop2 = 0;
dist1 = 0;
dist2 = 0;
velocidade1 = 0;
velocidade2 = 0;
timestamp = 0;
start_race();
}
if((millis() & 512)==(512*draworder))
{
if(draworder==0)
{
draworder = 1;
}
else
{
draworder = 0;
}
}
if(draworder==0)
{
draw_car1();
draw_car2();
}
else
{
draw_car2();
draw_car1();
}
track.show();
delay(tdelay);
if(TBEEP>0)
{
TBEEP -= 1;
if(TBEEP==0)
{
noTone(som);
}
}
}
void set_ramp(byte H,byte a,byte b,byte c)
{
for(int i=0; i<(b-a); i++)
{
gravidade[a+i] = 127-i*((float)H/(b-a));
}
gravidade[b] = 127;
for(int i=0; i<(c-b); i++)
{
gravidade[b+i+1] = 127+H-i*((float)H/(c-b));
}
}
void set_loop(byte H,byte a,byte b,byte c)
{
for(int i=0; i<(b-a); i++)
{
gravidade[a+i] = 127-i*((float)H/(b-a));
}
gravidade[b] = 255;
for(int i=0; i<(c-b); i++)
{
gravidade[b+i+1] = 127+H-i*((float)H/(c-b));
}
}
void start_race()
{
for(int i=0; i<NPIXELS; i++)
{
track.setPixelColor(i, track.Color(0,0,0));
}
track.show();
delay(2000);
track.setPixelColor(12, track.Color(0,255,0));
track.setPixelColor(11, track.Color(0,255,0));
track.show();
tone(som,400);
delay(2000);
noTone(som);
track.setPixelColor(12, track.Color(0,0,0));
track.setPixelColor(11, track.Color(0,0,0));
track.setPixelColor(10, track.Color(255,255,0));
track.setPixelColor(9, track.Color(255,255,0));
track.show();
tone(som,600);
delay(2000);
noTone(som);
track.setPixelColor(9, track.Color(0,0,0));
track.setPixelColor(10, track.Color(0,0,0));
track.setPixelColor(8, track.Color(255,0,0));
track.setPixelColor(7, track.Color(255,0,0));
track.show();
tone(som,1200);
delay(2000);
noTone(som);
timestamp = 0;
}
void winner_fx()
{
int msize = sizeof(musica) / sizeof(int);
for(int note = 0; note < msize; note++)
{
tone(som, musica[note],200);
delay(230);
noTone(som);
}
}
void draw_car1(void)
{
for(int i=0; i<=loop1; i++)
{
track.setPixelColor(((word)dist1 % NPIXELS)+i, track.Color(0,255-i*20,0));
}
}
void draw_car2(void)
{
for(int i=0; i<=loop2; i++)
{
track.setPixelColor(((word)dist2 % NPIXELS)+i, track.Color(255-i*20,0,0));
}
}