This module of the RaylFX system can be used to illuminate a settlement, a building or a city. Up to ten residential buildings can be illuminated. In addition, there is an LED that simulates a TV, street lighting with two channels that light up at night, one channel that flickers and two channels for one or two billboards that either alternate or flash differently from each other.
Wiring Diagram
This module also works with an Arduino Nano. LEDs are connected to the digital channels 2, 3, 4, 5 and 12, 13, 14 (A0), 15 (A1), 16 (A2), 17 (A3) as residential lighting. Each channel can supply up to 40mA. Additional LEDs can be connected here in parallel to the current LEDs. They then all share one resistor. However, the luminosity of the individual LEDs is reduced. In addition, the LEDs in the respective parallel circuit must be the same (same internal resistance), otherwise only the LED with the smallest internal resistance will light up. At pin 6 a LED is connected, which flickers and should simulate a TV. In my case it is green because football is on.
The street lamps are connected to pins 10 and 11. Additionally there is a connection for a flickering, defective street lamp at pin 9. With these pins you could also realize a motel lighting, in which a letter flashes (known from motel signs :-D)
Pins 7 and 8 can illuminate billboards. They can be set so that they do not flash, flash alternately or flash at different speeds. This can be used to illuminate advertising banners above stores, or to create animations with two phases and so on. Here I could imagine engraved acrylic glass panes, which are illuminated from the edge by LED.
Attention: The control signal of the RaylFX control module is applied to pin A4. It controls the time of day and is mandatory.
Code Settings
Like all RaylFX modules, this one is also controlled by the control module. It provides the time and thus synchronizes all RaylFX modules.
Several settings can be made in the code.
The variable streetlampTimeout controls the switch-on time of the street lamps in milliseconds. These then dim themselves in the specified time.
With the variable streetlampFlicker the flickering frequency can be set. The higher the value, the slower the LED flickers at pin 9.
The residential building lights should switch on and off differently, so that the settlement also looks nice and lively. This can be influenced with the variable switchonLikelihood. The higher the value, the more displaced the houses switch on. The same for switching off is done by the variable switchoffLikelihood.
Now some advertising: The variables adBlink1 and adBlink2 control the LEDs for the advertising panels. If the value of both variables is the same, they blink alternately. This could be used for an animation. If the value is different, they blink in independent frequencies. So here, for example, two independent advertising boards can be operated. If the value is set to 0, the LEDs light up permanently.
int streetlightTimeout = 100; // switch-on time of the street lights (ms)
int streetlightFlicker = 1000; // the higher the value, the slower the LED flickers at pin 9
int switchonLikelihood = 2000; // the higher the value, the more displaced the residential lighting will turn on
int switchoffLikelihood = 2000; // the higher the value, the more displaced the residential lighting will turn off
int adBlink1 = 1500; // flashing speed of the advertising LED, 0 = do not flash
int adBlink2 = 1500; // flashing speed of the advertising LED, 0 = do not flash
When uploading you have to make sure that the correct board is selected in the Arduino menu. To do this, “ATmega328P (Old Bootlaoder)” must also be selected in the Processor subitem of the Tools menu.
The following program code can be easily copied with the above mentioned changes and loaded onto the Arduino nano.
Code for the RaylFX Village Module
/*
Rayl-FX Village Module
StartHardware.org/en
*/
/* ***** ***** Settings ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
int streetlightTimeout = 100; // switch-on time of the street lights (ms)
int streetlightFlicker = 1000; // the higher the value, the slower the LED flickers at pin 9
int switchonLikelihood = 2000; // the higher the value, the more displaced the residential lighting will turn on
int switchoffLikelihood = 2000; // the higher the value, the more displaced the residential lighting will turn off
int adBlink1 = 1500; // flashing speed of the advertising LED, 0 = do not flash
int adBlink2 = 1500; // flashing speed of the advertising LED, 0 = do not flash
/* ***** ***** From here begins the program code, which does not need to be adjusted ***** ***** ***** ***** */
int streetlightPin1 = 11; // this pin connects to streetlights
int streetlightPin2 = 10; // this pin connects to more streetlights
int streetlightPin3 = 9; // this pin connects to a defective streetlight
int residentialPins[10] = {2, 3, 4, 5, 12, 13, 14, 15, 16, 17}; // digital output pins -> for pin assignment see below
int adPin1 = 7; // this pin connects to the advertising LED 1
int adPin2 = 8; // this pin connects to the advertising LED 2
int tvPin = 6; // this pin connects to the LED for the TV
/*
Pin Assignment
(Attention, LEDs switch on on LOW)
2, 3, 4, 5, 6 = residential house
13, 14, 15, 16 = residential house
12 = TV
7 = advertising 1
8 = advertising 2
9 = street lights 1
10 = street lights 2
11 = defective street light
*/
/* Memory Variables */
int streetlightsBrightness = 0; // stores how bright the street lights shine
int advertisingLED1 = 1; // stores the state of the advertising LED 1
int advertisingLED2 = 1; // stores the state of the advertising LED 2
/* Timer Variables */
long streetlightsTimer = 0; // timer for the street lights
/* Variables from the control module to determine the time of day */
boolean receive = false;
boolean receiveStarted = false;
int receiveTimeout = 10;
long receiveTimer = 0;
int receivedTime = 0;
int receivePulse = 0;
int lastReceivePulse = 0;
int receivePin = 18;
int myTime = 0;
#define PAYLOAD_SIZE 2 // mandatory for communication with master-module
int timeOfDay = 0; // stores timeOfDay of master-module (0 and 255)
byte nodePayload[PAYLOAD_SIZE]; // temporarily stores data of master-module
void setup() {
Serial.begin(115200); // starts the serial communication
/* for (int i = 0; i < 13; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], HIGH);
}*/
pinMode(adPin1, OUTPUT);
pinMode(adPin2, OUTPUT);
for (int i = 0; i < 10; i++) {
pinMode(residentialPins[i], OUTPUT);
digitalWrite(residentialPins[i], HIGH);
}
streetlightsOff();
}
void loop() {
receiveFunction(); // execute instructions for reception
if (receiveStarted == false) { // if no data is currently being received:
if (myTime > 22) { // ***** late evening *****
streetlightsOn(); // turn on street lights
tvOff(); // turn off tv
advertisinglightOn(); // show the lights of stores or billboards
residentiallightingOff(); // turn off residential lighting
} else if (myTime > 18) { // ***** evening *****
streetlightsOn(); // turn on street lights
tvOn(); // turn on tv
advertisinglightOn(); // show the lights of stores or billboards
residentiallightingOn(); // turn on residential lighting
} else if (myTime > 12) { // ***** noon *****
streetlightsOff(); // turn off street lights
tvOff(); // turn off tv
advertisinglightOff(); // hide the lights of stores or billboards
residentiallightingOff(); // turn off residential lighting
} else if (myTime > 9) { // ***** forenoon *****
streetlightsOff(); // turn off street lights
tvOff(); // turn off tv
advertisinglightOff(); // hide the lights of stores or billboards
residentiallightingOff(); // turn off residential lighting
} else if (myTime > 7) { // ***** morning *****
streetlightsOn(); // turn on street lights
tvOff(); // turn off tv
advertisinglightOff(); // hide the lights of stores or billboards
residentiallightingOff(); // turn off residential lighting
} else { // ***** night *****
streetlightsOn(); // turn on street lights
tvOff(); // turn off tv
advertisinglightOn(); // show the lights of stores or billboards
residentiallightingOff(); // turn on residential lighting
}
}
}
void tvOn() {
if (random(500) == 1) analogWrite(tvPin, random(150));
}
void tvOff() {
analogWrite(tvPin, 255);
}
void advertisinglightOn() {
if (adBlink1 == 0) {
digitalWrite(adPin1, LOW);
} else if (millis() % adBlink1 * 2 < adBlink1) {
digitalWrite(adPin1, LOW);
} else {
digitalWrite(adPin1, HIGH);
}
if (adBlink2 == 0) {
digitalWrite(adPin2, LOW);
} else if (millis() % adBlink2 * 2 > adBlink2) {
digitalWrite(adPin2, LOW);
} else {
digitalWrite(adPin2, HIGH);
}
}
void advertisinglightOff() {
digitalWrite(adPin1, HIGH);
digitalWrite(adPin2, HIGH);
}
void residentiallightingOn() {
if (random(switchonLikelihood) == 1) { // randomly switching on the residential lighting
digitalWrite(residentialPins[random(10)], LOW);
}
}
void residentiallightingOff() {
if (random(switchoffLikelihood) == 1) { // randomly switching off the residential lighting
digitalWrite(residentialPins[random(10)], HIGH);
}
}
void streetlightsOn() {
if (streetlightsTimer + streetlightTimeout < millis()) {
streetlightsBrightness++;
if (streetlightsBrightness > 255) streetlightsBrightness = 255;
streetlightsTimer = millis();
analogWrite(streetlightPin1, 255 - streetlightsBrightness);
analogWrite(streetlightPin2, 255 - streetlightsBrightness);
analogWrite(streetlightPin3, 255 - streetlightsBrightness);
}
if (streetlightFlicker != 0) {
if (random(streetlightFlicker) == 1) analogWrite(streetlightPin3, random(255) - streetlightsBrightness);
}
}
void streetlightsOff() {
streetlightsBrightness = 0;
analogWrite(streetlightPin1, 255);
analogWrite(streetlightPin2, 255);
analogWrite(streetlightPin3, 255);
streetlightsTimer = millis();
}
void receiveFunction() { // receives time of day from control-module
receivePulse = digitalRead(receivePin); // read out the receive pin
if ((receiveTimer + receiveTimeout < millis()) && (receiveStarted == true)) {
// on timeout and active reception
receiveStarted = false; // end active reception
myTime = receivedTime - 1; // store received time
receivedTime = 0; // reset the auxiliary variable for time reception
Serial.println(myTime); // serial output
}
// if a pulse is detected at the receive pin that was not there before
if ((receivePulse == 0) && (lastReceivePulse == 1)) {
receiveTimer = millis(); // restart timer
if (receiveStarted == false) receiveStarted = true; // start active reception, if not already done
receivedTime++; // there was a pulse, so increase the auxiliary variable to receive time
}
lastReceivePulse = receivePulse; // remember current state at pin for next pass
}