Last Updated: 26/01/2024

#63 Arduino Uno, PCA685, LED's Gas Lights Effects

Components >> #63 Arduino Uno, PCA685, LED's Gas Lights Effects

#63 Arduino Uno, PCA685, LED's Gas Lights Effects

After creating a number of LED lighting efects using the PCA9685 board I was asked if I could come up with some code for a gas lamp.

I thought this ould be easy, and to a degrree the effect was easy to create. The issue is that unlike a fire flicker in a building, there could be multiple lights and I wanted to avoid the effect of all of them doing the same effects at the same time, in other words they would all flicker at exactly the same time. This with a large number of LED's would be very obvious and look wrong so each LED in the system needed to have it's own random effect.

There are some gas lamps that are alive and still running on gas in the UK. London has about 1500 including one powered off the sewers in Carting Lane, the pictures below are of a couple of gas lamps in Malvern, again still gas powered, you can see the mantles lit by the pilot lights. These are the ones that are thought to have inspired C.S Lewis for the lamp post in his book "The Lion, the Witch, and the wardrobe".

Gas Lamp Malvern

Malvern gas lamp post

This code uses the PCA9685 servo board that can control 16 LED's, however as multiple boards can be used together (62 Maximum) it would be possible to have 992 LED's all on their unique flicker code. At 200mm spacings (50ft in 4mm scale) that would give enough to light 193 metres of road.... enough for most layouts.

The code is Non Blocking so could be run no the same Arduino as other lighting effects.

Pinout and wiring diagrams

The PCA9685 circuit is shown below.

Please note that the 5v IS NOT supplied by the Arduino. You will need a seperate supply due to the power draw being more than an Arduino can handle.
Also note the PCA9685 have both the VCC and V+ conected to 5V.

Only 3 wires should go to the Arduino, Gnd, A5 and A4 from the SDA/SCl of all boards connected.

Leds locations are set in the code and are for illustration purposes only.

PCA9685 Arduino UNO LED circuit

If you are using multiple PCA9685 boards don't forget to solder accross the tabs top right in different positions on each board to change the I2C address.

Pins

A5 to PCA9685 SCL
A4 to PCA9685 SDA

Make sure you have 5v going to the PCA9685 board as well as the VCC and GND. One powers the circuitry, the other supply powers the servo.


Wiring:for a few common boards

SDA/SCL connections

Arduino UNO: A4 (SDA), A5 (SCL) :

Arduino Mega 2560: 20 (SDA), 21 (SCL) :

ESP32: 21(SDA), 22 (SCL)

For other Arduino boards see:https://www.arduino.cc/en/reference/wire

 

Set ups for different boards

The DCC decoder circuit

Connection Test 1 ...IMPORTANT

Bad wiring is one of the biggest problems with Arduino projects so run this test to make sure your board is being found before doing anythine else.

Once you have connected your board up as shown above check that it can be found.

If you are using an Arduino board go to File>Examples> Wire>I2c_scanner and upload the skecth to your board.

if all goes well your serial Monitor will display something like

Scanning...
I2C device found at address 0x40 !
done

NOTE: if you have multipl boards you will see other addresses depending on the tabs soldered across that set the boards I2C address.

Once your device has been found it's time to add the LED's

Connection Test 2 ...Board and Servo Test

First make sure you have the Adafruit PWM Servo Library installed.

Tools>Manage Libraries> Type Adafruit PWM Servo Library in the serach bar.

If it is not installed install it.

Adafruit PM Servo Library


 

Example 1: PCA9685GasLightsV1.ino


Click to Download code: PCA9685GasLightsV1.ino

This sketch controls 16 leds, ports 0-7 are running as street lights, ports 8-15 are running as house lights (dimmer)

 

 
/* 25/01/2024
 *  
 *  PCA9685GasLightsV1
 *  
 Single PCA9685 board
 * 
 */




#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"
//pca9685 settings

Adafruit_PWMServoDriver ledBoard1 = Adafruit_PWMServoDriver(0x40);


unsigned long currentMillis;

const int streetnormalBrightness = 4000;// Maximum brightness is 4095
const int streetminBrightness = 1500;// minimum is 0 OFF Gas lights Reduce value to make more aggressive flicker
unsigned long streetgasTimerArray[16];
int streetgasChangeLength[16][2];//length  //flickerState 0 = normalBrightness 1 = flicker

//street gas lamps flicker function
void streetGasLights() {
  int q;
    for(q=0;q < 8;q++){
      if(currentMillis - streetgasTimerArray[q] >= streetgasChangeLength[q][0]){
        streetgasTimerArray[q] = currentMillis;
        if(streetgasChangeLength[q][1] < 1){//currently at max brightness
          ledBoard1.setPWM(q, 0, random(streetminBrightness,streetnormalBrightness));
          streetgasChangeLength[q][0] = random(100,500);//flicker will last 0.1 - 0.5 secs
          streetgasChangeLength[q][1] = 1;
        }else{
          ledBoard1.setPWM(q, 0,random(streetnormalBrightness - 300,streetnormalBrightness));
          streetgasChangeLength[q][0] = random(1000,5000);//1-5 secs before next flicker
          streetgasChangeLength[q][1] = 0;  
        }
      }
  }
}



const int housenormalBrightness = 1000;// Maximum brightness is 4095
const int houseminBrightness = 300;// minimum is 0 OFF Gas lights Reduce value to make more aggressive flicker
unsigned long housegasTimerArray[16];
int housegasChangeLength[16][2];//length  //flickerState 0 = normalBrightness 1 = flicker
//house gas lamps flicker function...dimmer than street version
void houseGasLights() {
  int q;
    for(q=8;q < 16;q++){
      if(currentMillis - housegasTimerArray[q] >= housegasChangeLength[q][0]){
        housegasTimerArray[q] = currentMillis;
        if(housegasChangeLength[q][1] < 1){//currently at max brightness
          ledBoard1.setPWM(q, 0, random(houseminBrightness,housenormalBrightness));
          housegasChangeLength[q][0] = random(100,500);//flicker will last 0.1 - 0.5 secs
          housegasChangeLength[q][1] = 1;
        }else{
          ledBoard1.setPWM(q, 0,random(housenormalBrightness - 300,housenormalBrightness));
          housegasChangeLength[q][0] = random(1000,5000);//1-5 secs before next flicker
          housegasChangeLength[q][1] = 0;  
        }
      }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("PCA9685GasLightsV1");

  
                                       //start led board
  ledBoard1.begin();                   
  ledBoard1.setPWMFreq(1600);         

  
}

void loop() {
  currentMillis = millis();  //get current time since board started in milliseconds
  
  streetGasLights();  //calls the gas function

  houseGasLights();  //calls the gas function
  
}

 

Example 2: PCA9685GasLightsV2.ino


Click to Download code: PCA9685GasLightsV2.ino

This sketch is controlling 8 PCA9685 boards controlling 128 leds to demonstrate how more boards would be used.

 

 
/* 25/01/2024
 *  
 *  PCA9685GasLightsV2
 *  
 Multiple PCA9685 board...4 houselights, 4 street lights (128 leds)
 * 
 */




#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"
//pca9685 settings


Adafruit_PWMServoDriver streetLights1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver streetLights2 = Adafruit_PWMServoDriver(0x42);
Adafruit_PWMServoDriver streetLights3 = Adafruit_PWMServoDriver(0x41);
Adafruit_PWMServoDriver streetLights4 = Adafruit_PWMServoDriver(0x43);
Adafruit_PWMServoDriver houselights1 = Adafruit_PWMServoDriver(0x48);
Adafruit_PWMServoDriver houselights2 = Adafruit_PWMServoDriver(0x50);
Adafruit_PWMServoDriver houselights3 = Adafruit_PWMServoDriver(0x45);
Adafruit_PWMServoDriver houselights4 = Adafruit_PWMServoDriver(0x56);


unsigned long currentMillis;

const int streetnormalBrightness = 4000;// Maximum brightness is 4095
const int streetminBrightness = 1500;// minimum is 0 OFF Gas lights Reduce value to make more aggressive flicker
unsigned long streetgasTimerArray[16];
int streetgasChangeLength[16][2];//length  //flickerState 0 = normalBrightness 1 = flicker

//street gas lamps flicker function
void streetGasLights() {
  int q;
    for(q=0;q < 16;q++){
      if(currentMillis - streetgasTimerArray[q] >= streetgasChangeLength[q][0]){
        streetgasTimerArray[q] = currentMillis;
        if(streetgasChangeLength[q][1] < 1){//currently at max brightness
          streetLights1.setPWM(q, 0, random(streetminBrightness,streetnormalBrightness));
          streetLights2.setPWM(q, 0, random(streetminBrightness,streetnormalBrightness));
          streetLights3.setPWM(q, 0, random(streetminBrightness,streetnormalBrightness));
          streetLights4.setPWM(q, 0, random(streetminBrightness,streetnormalBrightness));

          streetgasChangeLength[q][0] = random(100,500);//flicker will last 0.1 - 0.5 secs
          streetgasChangeLength[q][1] = 1;
        }else{
          streetLights1.setPWM(q, 0,random(streetnormalBrightness - 300,streetnormalBrightness));
          streetLights2.setPWM(q, 0,random(streetnormalBrightness - 300,streetnormalBrightness));
          streetLights3.setPWM(q, 0,random(streetnormalBrightness - 300,streetnormalBrightness));
          streetLights4.setPWM(q, 0,random(streetnormalBrightness - 300,streetnormalBrightness));
          
          streetgasChangeLength[q][0] = random(1000,5000);//1-5 secs before next flicker
          streetgasChangeLength[q][1] = 0;  
        }
      }
  }
}



const int housenormalBrightness = 1000;// Maximum brightness is 4095
const int houseminBrightness = 300;// minimum is 0 OFF Gas lights Reduce value to make more aggressive flicker
unsigned long housegasTimerArray[16];
int housegasChangeLength[16][2];//length  //flickerState 0 = normalBrightness 1 = flicker
//house gas lamps flicker function...dimmer than street version
void houseGasLights() {
  int q;
    for(q=0;q < 16;q++){
      if(currentMillis - housegasTimerArray[q] >= housegasChangeLength[q][0]){
        housegasTimerArray[q] = currentMillis;
        if(housegasChangeLength[q][1] < 1){//currently at max brightness
          houselights1.setPWM(q, 0, random(houseminBrightness,housenormalBrightness));
          houselights2.setPWM(q, 0, random(houseminBrightness,housenormalBrightness));
          houselights3.setPWM(q, 0, random(houseminBrightness,housenormalBrightness));
          houselights4.setPWM(q, 0, random(houseminBrightness,housenormalBrightness));
          housegasChangeLength[q][0] = random(100,500);//flicker will last 0.1 - 0.5 secs
          housegasChangeLength[q][1] = 1;
        }else{
          houselights1.setPWM(q, 0,random(housenormalBrightness - 300,housenormalBrightness));
          houselights2.setPWM(q, 0,random(housenormalBrightness - 300,housenormalBrightness));
          houselights3.setPWM(q, 0,random(housenormalBrightness - 300,housenormalBrightness));
          houselights4.setPWM(q, 0,random(housenormalBrightness - 300,housenormalBrightness));
          housegasChangeLength[q][0] = random(1000,5000);//1-5 secs before next flicker
          housegasChangeLength[q][1] = 0;  
        }
      }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("PCA9685GasLightsV2");
                                       //start led boards
  streetLights1.begin();                   
  streetLights1.setPWMFreq(1600); 
  streetLights2.begin();                   
  streetLights2.setPWMFreq(1600); 
  streetLights3.begin();                   
  streetLights3.setPWMFreq(1600); 
  streetLights4.begin();                   
  streetLights4.setPWMFreq(1600); 

  houselights1.begin();                   
  houselights1.setPWMFreq(1600);          
  houselights2.begin();                   
  houselights2.setPWMFreq(1600);         
  houselights3.begin();                   
  houselights3.setPWMFreq(1600);          
  houselights4.begin();                  
  houselights4.setPWMFreq(1600);          

  
}

void loop() {
  currentMillis = millis();  //get current time since board started in milliseconds
  
  streetGasLights();  //calls the street lights function

  houseGasLights();  //calls the house lights function
  
}

Additional Resource Links

Model Railway Light Effects using PCA685 and LED's with Arduino or ESP32

Multiple PCA9685 PWM Servo Boards with servos and LED's

Lesson 4: Using "for loop" to control code 21/07/2021

Adafruit PWM servo library

Comments


To ask a question please comment on YouTube or email the address in this image: and use #63 Arduino Uno, PCA685, LED's Gas Lights Effects as a reference.