Sorry if this topic has been answered somewhere else but I just cant find exactly what I'm looking for. I have perfected my Model Train Level Crossing program but I want to add a couple of basic turn on/turn off subroutines to my program so I can independently control street lights, building lights, track lights, etc. with my Mega2560. I've looked at quite a few sketches from other people but I still don't understand how to add subs after the void loop() routine.
I've looked at quite a few sketches from other people but I still don't understand how to add subs after the void loop() routine.
Just like everybody else does it. A function is, effectively, a named block of code with a return type and zero or more arguments.
returnType functionName(argType1 argName1, ..., argTypeN argNameN)
{
// The code goes here
return aValueOfTheCorrectType; // Not needed if the type is void
}
Then, in place of the block of code that you have now, you call the function:
#include <Servo.h>
Servo myservo;
const int R1 = 9; // 1st Red LED
const int R2 = 10; // 2nd Red LED
const int G = 11; // Green Active LED
const int R = 12; // Red inactive LED
const int SW1 = 2; // switch number and input pin
int SW1State = 0; // variable for reading switch #1
int running = 0;
int long interval = 500;
long previousMillis = 0;
int R1State = HIGH;
int pos = 0;
void setup() {
pinMode(R1, OUTPUT);
pinMode(R2, OUTPUT);
pinMode(G, OUTPUT);
pinMode(R, OUTPUT);
pinMode(SW1, INPUT);
myservo.attach(7);
digitalWrite(SW1, HIGH);
}
// the loop routine runs and stops after last command
void loop() {
int SW1 = digitalRead(SW1);
// the switch has been activated and the program can run
if (SW1 == HIGH && running == 0) {
int running = 1;
tone(8, 900, 500); // play SOUND
digitalWrite(G, HIGH); // turn on GREEN LED
myservo.write(45);
delay(1500);
digitalWrite(G, LOW); // turn off GREEN LED
digitalWrite(R2, LOW); // turn the LED off
digitalWrite(R1, LOW); // turn the LED off
delay(250);
digitalWrite(R1, HIGH); // turn the LED on
digitalWrite(R2, HIGH); // turn the LED on
delay(2500);
SW1 = digitalRead(SW1);
while(SW1 == LOW && running == 1) {
// Timer used instead of delay to allow input to be read at the same time
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (R1State == HIGH){ // Switches lights over
digitalWrite(R1, LOW);
digitalWrite(R2, HIGH);
R1State = LOW;
}
else {
digitalWrite(R1, HIGH); // Switches lights over
digitalWrite(R2, LOW);
R1State = HIGH;
}
}
// Terminates program and switches off lights if the trigger input is detected
SW1 = digitalRead(SW1);
if (SW1 == HIGH){
digitalWrite(10, LOW); // turn the LED off
digitalWrite(9, LOW); // turn the LED off
tone(8, 900, 500); // play SOUND
digitalWrite(12, HIGH); // turn on RED LED
delay(1500);
myservo.write(0);
digitalWrite(12, LOW); // turn off RED LED
int R1State = LOW;
delay(5000);
int running = 0;
break;
}
}
}
}
I suspect that you meant to set the first running to 0, not create a new one. Remove the int declaration on the second statement. The compiler can remember that running is an int.
My question is can I just simply add...as a subroutine and put in some code to be able to turn the lights on and off
Yes.
without interfering with the main void loop() ??
I'm not sure what you mean by "interfering with". You have to call the function. It will take as much time as it needs to execute, and then return and execute the next instruction in loop().
Creating a function is not a way to spawn another thread. The Arduino doesn't do threads.
OK, so how would I go about integrating this code into my program?
Using a text editor?
Your existing code does something. That code does something. The combined code should do something. Those three somethings are not defined, though, so we can't help you.
What you said in your last post was that you wanted to incorporate this code into that code.
This code looks pretty simple. Turn an LED on if a switch is pressed. Turn it off if a different switch is pressed.
That code was posted in reply #2, but there was no explanation of what it does.
When you merge this code and that code to produce a new program, the new program should do so stuff.
What you need to do is explain what that stuff should be, so that we can help you merge the two programs.
It really looks like you just need to copy the two pinMode() calls from this setup() to that setup() and copy all the code from this loop() to that loop().
The potentially blocking nature of that code, though, could be a problem.
This my program with the new part added but I've done something wrong cause the new part doesn't work? Any ideas?
#include <Servo.h>
Servo myservo;
const int R1 = 9; // 1st Red LED
const int R2 = 10; // 2nd Red LED
const int G = 11; // Green Active LED
const int R = 12; // Red inactive LED
const int SW1 = 2; // switch number and input pin
const int SW2 = 3;
const int SW3 = 4;
const int Building = 53; // Building lights pin
int SW1State = 0; // variable for reading switch #1
int running = 0;
int long interval = 500;
long previousMillis = 0;
int R1State = HIGH;
int pos = 0;
void setup() {
pinMode(R1, OUTPUT); // RHS Flasher
pinMode(R2, OUTPUT); // LHS Flasher
pinMode(G, OUTPUT); // Active Program
pinMode(R, OUTPUT); // Inactive Program
pinMode(Building, OUTPUT); // Building Lights
pinMode(SW1, INPUT); // Crossing switch
pinMode(SW2, INPUT); // Building lights on
pinMode(SW3, INPUT); // Building lights off
myservo.attach(7); // Boom gate servo
digitalWrite(SW1, HIGH);
}
// the loop routine runs and stops after last command
void loop() {
[font=Verdana]if (digitalRead(SW2) == HIGH) // these 4 lines are to turn the building
{
digitalWrite(Building, HIGH); // lights on and off
}
if (digitalRead(SW3) == HIGH) // but I think somewhere I have either
{
digitalWrite(Building, LOW); // missed or forgotten something
}[/font]
int SW1 = digitalRead(SW1);
// the switch has been activated and the program can run
if (SW1 == HIGH && running == 0) {
int running = 1;
tone(8, 900, 500); // play SOUND
digitalWrite(G, HIGH); // turn on GREEN LED
myservo.write(45);
delay(1500);
digitalWrite(G, LOW); // turn the LEDs off
digitalWrite(R2, LOW);
digitalWrite(R1, LOW);
delay(250);
digitalWrite(R1, HIGH); // turn the LEDs on
digitalWrite(R2, HIGH);
delay(2500);
SW1 = digitalRead(SW1);
while(SW1 == LOW && running == 1) {
// Timer used instead of delay to allow input to be read at the same time
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (R1State == HIGH){ // Switches lights over
digitalWrite(R1, LOW);
digitalWrite(R2, HIGH);
R1State = LOW;
}
else {
digitalWrite(R1, HIGH); // Switches lights over
digitalWrite(R2, LOW);
R1State = HIGH;
}
}
// Terminates program and switches off lights if the trigger input is detected
SW1 = digitalRead(SW1);
if (SW1 == HIGH){
digitalWrite(10, LOW); // turn LEDs off
digitalWrite(9, LOW);
tone(8, 900, 500); // play SOUND
digitalWrite(12, HIGH); // turn on RED LED
delay(1500);
myservo.write(0);
digitalWrite(12, LOW); // turn off RED LED
int R1State = LOW;
delay(5000);
int running = 0;
break;
}
}
}
}
Well, yes. Please refrain from ever again saying "it doesn't work".
The 2nd code you posted set the mode of the pin to INPUT_PULLUP. The integrated code sets the mode to INPUT. Why the change? Did you decide to add external pullup resistors for the hell of it?
the loop routine runs and stops after last command
Not true
The loop() function runs and unless something happens to stop it then it runs again, and again, and again........
You were asking about adding a subroutine (aka a function) after the loop() function but what you have done is to add more code inside the loop() function. A function would look more like this
void printMessage()
{
Serial.println("This is a message");
}
and you would call it like thisprintMessage();
As to why your added code doesn't work, that will be at least partly due to your use of the delay() function in the body of the loop() function. The total delay is over 6 seconds. During that time the loop() function will not run again so cannot read your building light switches. Using a function would not solve that but use of millis instead of delay() would.
PaulS - I changed the pin to INPUT as I want the switches to be HIGH when pressed not grounded.
UKHeliBob - I've removed the code from main loop and put it at the end
void BuildingLights()
if (digitalRead(SW2) == HIGH) // these 4 lines are to turn the building - [u]This Line Was Highlighted After Compiling[/u]
{
digitalWrite(Building, HIGH); // lights on and off
}
if (digitalRead(SW3) == HIGH) // but I think somewhere I have either
{
digitalWrite(Building, LOW); // missed or forgotten something
}
I get this error when compiling :
train_crossing__3_.ino: In function 'void loop()':
train_crossing__3_:122: error: expected initializer before 'if'
What exactly am I initializing and how do I write it?
You're using the same name for the pin number as its result. Worse, you've masked the pin number by declaring this local version, so you're not reading the pin you expect.
Change the declaration to have a different name and don't forget to change it where you use it a few lines later.
I've removed the code from main loop and put it at the end
If you have left the delays in then expect to wait several seconds for the building light switches to be acted upon. Incidentally, the names seem to imply that they are switches rather than buttons. There is nothing wrong with that per se, but if they are switches, might they both be on at the same time ?