Fast Led
Fast Led
h>
#define LED_PIN 3
#define NUM_LEDS 265
#define CAR_LENGTH 3
#define MAX_CARS 10
CRGB leds[NUM_LEDS];
int carPositions[MAX_CARS];
CRGB carColors[MAX_CARS];
int carLanes[MAX_CARS]; // To track which lane each car is in
int numCars = 0;
// Buttons
#define BTN_SLOW 4
#define BTN_FAST 5
#define BTN_MAIN_UP 10
#define BTN_MAIN_DOWN 11
#define BTN_SIDE_UP 12
#define BTN_SIDE_DOWN 13
#define BTN_SPAWN_FASTER A0
#define BTN_SPAWN_SLOWER A1
#define BTN_AUTO_TOGGLE A3
if (!collision) {
// Clear LEDs at the previous position (for straight movement)
if (turnStart == -1) { // If it's a straight segment
for (int i = 0; i < CAR_LENGTH; i++) {
if (previousPosition + i < NUM_LEDS && previousPosition + i >= 0) {
leds[previousPosition + i] = CRGB::Black;
}
}
}
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.clear();
FastLED.setBrightness(255); // Set brightness here (adjust as needed)
FastLED.show();
pinMode(BTN_SLOW, INPUT_PULLUP);
pinMode(BTN_FAST, INPUT_PULLUP);
pinMode(BTN_MAIN_UP, INPUT_PULLUP);
pinMode(BTN_MAIN_DOWN, INPUT_PULLUP);
pinMode(BTN_SIDE_UP, INPUT_PULLUP);
pinMode(BTN_SIDE_DOWN, INPUT_PULLUP);
pinMode(BTN_SPAWN_FASTER, INPUT_PULLUP);
pinMode(BTN_SPAWN_SLOWER, INPUT_PULLUP);
pinMode(BTN_AUTO_TOGGLE, INPUT_PULLUP);
pinMode(RED_LIGHT_PIN, OUTPUT);
pinMode(GREEN_LIGHT_PIN, OUTPUT);
pinMode(RED_LIGHT_PIN2, OUTPUT);
pinMode(GREEN_LIGHT_PIN2, OUTPUT);
trafficLightTimer = millis();
// Initialize previous car positions
for (int i = 0; i < MAX_CARS; i++) {
previousCarPositions[i] = -1; // -1 indicates no previous position
turnState[i] = 0; // No turn initially
turnClear[i] = 0; // No clear initially
carLanes[i] = 0; // Initialize car lanes
}
}
void loop() {
if (autoTimingEnabled) {
int mainQueue = 0;
int sideQueue = 0;
// LANE 1
for (int i = 0; i < numCars; i++) {
if (carLanes[i] == 1 && carPositions[i] >= lane1StopZoneStart &&
carPositions[i] <= lane1StopZoneEnd) {
mainQueue += 1 + countCarsBehind(1, carPositions[i]);
break;
}
}
// LANE 2
for (int i = 0; i < numCars; i++) {
if (carLanes[i] == 2 && carPositions[i] >= lane2StopZoneStart &&
carPositions[i] <= lane2StopZoneEnd) {
mainQueue += 1 + countCarsBehind(2, carPositions[i]);
break;
}
}
// LANE 3
for (int i = 0; i < numCars; i++) {
if (carLanes[i] == 3 && carPositions[i] >= lane3StopZoneStart &&
carPositions[i] <= lane3StopZoneEnd) {
sideQueue += 1 + countCarsBehind(3, carPositions[i]);
break;
}
}
// LANE 4
for (int i = 0; i < numCars; i++) {
if (carLanes[i] == 4 && carPositions[i] >= lane4StopZoneStart &&
carPositions[i] <= lane4StopZoneEnd) {
sideQueue += 1 + countCarsBehind(4, carPositions[i]);
break;
}
}
dynamicMainDuration = baseGreen + greenPerCar * mainQueue;
dynamicSideDuration = baseGreen + greenPerCar * sideQueue;
spawnTimer = millis();
} else if (millis() - spawnTimer > spawnInterval && numCars < MAX_CARS) {
// If fewer than 4 slots available, try to spawn in a random lane
int randomLane = random(4); // 0, 1, 2, 3 -> Map to 1, 2, 3, 4
int spawnPos = 0;
if (randomLane == 0) spawnPos = 2; // Lane 1
else if (randomLane == 1) spawnPos = 69; // Lane 2
else if (randomLane == 2) spawnPos = 199; // Lane 3 (Updated spawn
position)
else if (randomLane == 3) spawnPos = 134; // Lane 4
carPositions[numCars] = spawnPos;
carLanes[numCars] = randomLane + 1;
carColors[numCars] = CHSV(random(255), 255, 255);
numCars++;
spawnTimer = millis();
}
// Process Cars
for (int i = 0; i < numCars; i++) {
int currentLane = carLanes[i];
int currentPosition = carPositions[i];
bool canMove = true; // Assume car can move unless a condition says
otherwise
if (canMove) {
// Turning Logic and Movement
if (currentLane == 1) {
if (currentPosition == lane1RightTurnDecision) {
if (random(2) == 0) { // 50% chance to turn right
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane1RightTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane1RightTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else if (currentPosition == lane1LeftTurnDecision) {
if (random(2) == 0) { // 50% chance to turn left
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane1LeftTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane1LeftTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else { // Moving straight in lane 1, no turn decision yet
if (moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0) && currentPosition < NUM_LEDS -
CAR_LENGTH) {
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
if (turnState[i] == 1 && (currentPosition == lane1RightTurnStart
|| currentPosition == lane1LeftTurnStart)) {
turnState[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane1LeftTurnStart +
1) {
leds[lane1LeftTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane1RightTurnStart +
1) {
leds[lane1RightTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
}
} else if (currentLane == 2) { // Logic for Lane 2
if (currentPosition == lane2RightTurnDecision) {
if (random(2) == 0) { // 50% chance to turn right
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane2RightTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane2RightTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else if (currentPosition == lane2LeftTurnDecision) {
if (random(2) == 0) { // 50% chance to turn left
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane2LeftTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane2LeftTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else { // Moving straight in lane 2, no turn decision yet
if (moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0) && currentPosition < NUM_LEDS -
CAR_LENGTH) {
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
if (turnState[i] == 1 && (currentPosition == lane2RightTurnStart
|| currentPosition == lane2LeftTurnStart)) {
turnState[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane2LeftTurnStart +
1) {
leds[lane2LeftTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane2RightTurnStart +
1) {
leds[lane2RightTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
}
} else if (currentLane == 3) { // Logic for Lane 3 (Movement now
always positive)
if (currentPosition == lane3RightTurnDecision) {
if (random(2) == 0) { // 50% chance to turn right
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane3RightTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane3RightTurnStart;
} else { // Go straight (Now increments for Lane 3)
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++; // CHANGED to increment
}
} else if (currentPosition == lane3LeftTurnDecision) {
if (random(2) == 0) { // 50% chance to turn left
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane3LeftTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane3LeftTurnStart;
} else { // Go straight (Now increments for Lane 3)
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++; // CHANGED to increment
}
} else { // Moving straight in lane 3, no turn decision yet
// Check bounds for incrementing
if (moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0) && currentPosition < NUM_LEDS -
CAR_LENGTH) { // CHANGED bound check
previousCarPositions[i] = currentPosition;
carPositions[i]++; // CHANGED to increment
}
if (turnState[i] == 1 && (currentPosition == lane3RightTurnStart
|| currentPosition == lane3LeftTurnStart)) {
turnState[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane3LeftTurnStart +
1) {
leds[lane3LeftTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane3RightTurnStart +
1) {
leds[lane3RightTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
}
} else if (currentLane == 4) { // Logic for Lane 4
if (currentPosition == lane4RightTurnDecision) {
if (random(2) == 0) { // 50% chance to turn right
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane4RightTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane4RightTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else if (currentPosition == lane4LeftTurnDecision) {
if (random(2) == 0) { // 50% chance to turn left
for (int j = 0; j < CAR_LENGTH; j++) {
leds[lane4LeftTurnDecision - j] = CRGB::Black;
}
turnState[i] = 1;
turnClear[i] = 1;
carPositions[i] = lane4LeftTurnStart;
} else { // Go straight
moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0);
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
} else { // Moving straight in lane 4, no turn decision yet
if (moveCar(currentPosition, carColors[i], false, -1,
previousCarPositions[i], false, 0) && currentPosition < NUM_LEDS -
CAR_LENGTH) {
previousCarPositions[i] = currentPosition;
carPositions[i]++;
}
if (turnState[i] == 1 && (currentPosition == lane4RightTurnStart
|| currentPosition == lane4LeftTurnStart)) {
turnState[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane4LeftTurnStart +
1) {
leds[lane4LeftTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
if (turnClear[i] == 1 && currentPosition == lane4RightTurnStart +
1) {
leds[lane4RightTurnDecision + 1] = CRGB::Black;
turnClear[i] = 0;
}
}
}
} else {
// Car is stopped at red light OR waiting to turn left due to
conflicting traffic
moveCar(currentPosition, carColors[i], true, -1,
previousCarPositions[i], false, 0); // stopAtRed is true
}