c++carduino

Unexpected behavior of LEDs in a four way traffic system with Arduino


I'm fairly new to Arduino. I wanted to create a 4 way traffic lights system using Arduino and two eight bit shift registers. I've noticed weird behavior with two of my "roads" that are connected to the second shift register. This circuit will eventually incorporate the IR sensors but for now I am using a default sequence to test out my code.

// Pin Definitions
const int dataPin = 10;  // DS
const int clockPin = 8; // SH_CP
const int latchPin = 9; // ST_CP

// Sensors
const int sensor1 = A0, sensor2 = A1, sensor3 = A2, sensor4 = A3;

// LED States (12 LEDs controlled via 2 shift registers)
byte road1 = 0b001; // Red: 1, Yellow: 0, Green: 0
byte road2 = 0b001;
byte road3 = 0b001;
byte road4 = 0b001;

void setup() {
  // Setup Serial monitor
  Serial.begin(9600);
  // Shift register pins
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  
  // Sensor pins
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(sensor3, INPUT);
  pinMode(sensor4, INPUT);
}

void loop() {
  defaultSequence();
}

void updateTraffic(int road) {
  // Set all roads to red
  road1 = 0b001; road2 = 0b001; road3 = 0b001; road4 = 0b001;
  // Update the road based on priority
  switch (road) {
    case 1: road1 = 0b100; break; // Green for Road 1
    case 2: road2 = 0b100; break; // Green for Road 2
    case 3: road3 = 0b100; break; // Green for Road 3
    case 4: road4 = 0b100; break; // Green for Road 4
  }

  writeShiftRegisters();
  delay(10000); // Green light duration
  setYellow(road);
  //delay(1000);
  //setRed(road);
}

void setYellow(int road) {
  // Set the selected road to yellow
  switch (road) {
    case 1: road1 = 0b010; break;
    case 2: road2 = 0b010; break;
    case 3: road3 = 0b010; break;
    case 4: road4 = 0b010; break;
  }

  writeShiftRegisters();
  delay(2000); // Yellow light duration
}

void setRed(int road) {
    // Set the selected road to red
  switch (road) {
    case 1: road1 = 0b001; break;
    case 2: road2 = 0b001; break;
    case 3: road3 = 0b001; break;
    case 4: road4 = 0b001; break;
  }

  writeShiftRegisters();
}

void defaultSequence() {
  for (int i = 1; i <= 4; i++) {
    Serial.print("Road: ");
    Serial.println(i);
    updateTraffic(i);
    delay(10000); // Delay for default traffic
  }
}

void writeShiftRegisters() {
  // Combine all roads into a 16-bit data word
  unsigned int allRoads = (road4 << 9) | (road3 << 6) | (road2 << 3) | road1;
  Serial.print("allRoads (binary): ");
  for (int i = 15; i >= 0; i--) {
    Serial.print((allRoads >> i) & 1);
  }
  Serial.println();
  // Send data to shift registers
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, highByte(allRoads)); // First register
  delay(10);
  shiftOut(dataPin, clockPin, MSBFIRST, lowByte(allRoads));  // Second register
  digitalWrite(latchPin, HIGH);
}

Now coming to the weird behavior, by default the yellow light for road 3 is turned on as opposed to red light. Upon reaching road 3, it turns on both yellow and red. It never turns on green in its own turn. Only when I reach road 4 and after 1 tick (?)(I'm not sure what to call but one Serial.print), green light of road 3 turns on.

Again, I'm a beginner with Arduino so not sure what's going on here. I am also attaching a screenshot of my circuit.

Components: Arduino Uno R3, 74HC595 8-bit Shift Registers, LEDs, Resistors

4 way traffic control circuit


Solution

  • Looks like you are using the first 6 bits of each shift register to control the traffic lights. When packing the data into 16 bits in writeShiftRegisters(), you should use the lower 6 bits of each byte as so, instead of the lower 12 bits of the 16-bit word:

    unsigned int allRoads = (road4 << 11) | 
                            (road3 << 8)  |
                            (road2 << 3)  |
                             road1;