I'm new to arduino, I purchased an arduino uno after watching a you tube video where a guy connected an arduino to his dust collection blast gates and though I can do that. I have some programming experience but nothing complex.
What i'm trying to do is have a momentary switch at each of the blast gates and have the gate at the switch open and all the others close
the momentary switches are on pins 2,4,7,8,12 with one 10K pull down resistor for all the inputs and the servo pins are pwm 3,5,6,9,10.
The problem I'm having is that the program continually loops and I have to hold the button down until the loop sees that the pin is high. I added a dummy while loop to loop on nothing until one of the pins is high but I don't like it. Personally it seems sloppy and wasteful what can I do instead of the adding a empty while loop. I would like to add a sleep timeout in case I leave the shop with out turning it off if I can but I'm not sure how to do that. I'm open to suggestions on any other aspect of the code. A nice to have would be a status light showing which gates are open or closed but I don't think I have the outputs left for that.
#include <Servo.h>
const int pin[5]={3,5,6,9,10};
int i;
const int open_pos = 170;
const int closed_pos = 10;
int pos;
const int switch_pin[5] = {2,4,7,8,12};
boolean switch_state[5]={LOW, LOW, LOW,LOW,LOW};
long time = 0;
long debounce =50;
Servo my_servo[5];
void setup() {
Serial.begin(9600);
for(i=0;i<5;i++){ // set the momentary switch pins to inputs abd define servo pins
my_servo[i].attach(pin[i]);
pinMode(switch_pin[i], INPUT);
}
for(int k=0; k < 5; k++){ // Open all blast gates on start up
my_servo[k].write(open_pos);
delay(5);
}
}
void loop() {
while(digitalRead(switch_pin[0]) == LOW && digitalRead(switch_pin[1]) == LOW
&& digitalRead(switch_pin[2]) == LOW && digitalRead(switch_pin[3]) == LOW
&& digitalRead(switch_pin[4]) == LOW) {
} // Waiting loop for input from the switch while all switchs low
Serial.print('\n');
for(int k = 0;k<5;k++){ // read pin state if high then open that gate else close all others
switch_state[k] = digitalRead(switch_pin[k]);
if(switch_state[k] == HIGH && millis() - time > debounce){
Serial.print(switch_state[0]);
Serial.print(switch_state[1]);
Serial.print(switch_state[2]);
Serial.print(switch_state[3]);
Serial.print(switch_state[4]);
Serial.print('\n');
for(pos= closed_pos; pos <= open_pos; pos++){ // Open the blast gate
my_servo[k].write(pos);
delay(5);
}
// Serial.print(k);
}
else{
for(pos= open_pos; pos >= closed_pos; pos--){ // Close all other Gates
my_servo[k].write(open_pos);
delay(5);
}
// Serial.print(k);
}
} // End for loop checking the state of the switches
} // End Void
Hardware layout:
[/URL]
Mike
The first thing to do is to use INPUT_PULLUP in your pinMode() calls to activate the built in pullup resistors so that the inputs do not float at an uncertain voltage. Change the switch wiring to take the inputs LOW when the switch is closed.
Read each of the inputs and if you find one LOW exit the for loop. The for loop variable will contain the array index number of the switch found closed,
Move all of the servos to the closed position except the one whose array index corresponds to the switch found to be closed and open that one.
Note that there may be problems if the wiring to the switches is long or subject to electrical noise.

OK I made some modifications to the code and the wiring. I'm not sure what you mean here, there already is a loop to search for the changed state the only difference is that I am not exiting the loop when the low state is found. Could you elaborate or show an example of what you are referring to?
The runs will be between 6 feet and 30 feet with some high draw woodworking equipment, i'm not sure how much noise the wires will see. should I also ground the lead to household ground or do I need to play with the debounce?
UKHeliBob:
The first thing to do is to use INPUT_PULLUP in your pinMode() calls to activate the built in pullup resistors so that the inputs do not float at an uncertain voltage. Change the switch wiring to take the inputs LOW when the switch is closed.
Read each of the inputs and if you find one LOW exit the for loop. The for loop variable will contain the array index number of the switch found closed,
Move all of the servos to the closed position except the one whose array index corresponds to the switch found to be closed and open that one.
Note that there may be problems if the wiring to the switches is long or subject to electrical noise.
#include <Servo.h>
const int pin[5]={3,5,6,9,10};
int i;
const int open_pos = 170;
const int closed_pos = 10;
int pos;
const int switch_pin[5] = {2,4,7,8,12};
boolean switch_state[5]={HIGH, HIGH, HIGH,HIGH,HIGH};
long time = 0;
long debounce =50;
Servo my_servo[5];
void setup() {
Serial.begin(9600);
for(i=0;i<5;i++){ // set the momentary switch pins to inputs abd define servo pins
my_servo[i].attach(pin[i]);
pinMode(switch_pin[i], INPUT_PULLUP);
}
for(int k=0; k < 5; k++){ // Open all blast gates on start up
my_servo[k].write(open_pos);
delay(5);
}
}
void loop() {
while(digitalRead(switch_pin[0]) == HIGH && digitalRead(switch_pin[1]) == HIGH
&& digitalRead(switch_pin[2]) == HIGH && digitalRead(switch_pin[3]) == HIGH
&& digitalRead(switch_pin[4]) == HIGH) {
} // Waiting loop for input from the switch while all switchs high
Serial.print('\n');
for(int k = 0;k<5;k++){ // read pin state if low then open that gate else close all others
switch_state[k] = digitalRead(switch_pin[k]);
if(switch_state[k] == LOW && millis() - time > debounce){
// Serial.print(switch_state[0]);
// Serial.print(switch_state[1]);
// Serial.print(switch_state[2]);
// Serial.print(switch_state[3]);
// Serial.print(switch_state[4]);
// Serial.print('\n');
for(pos= closed_pos; pos <= open_pos; pos++){ // Open the blast gate
my_servo[k].write(pos);
delay(5);
}
// Serial.print(k);
}
else{
for(pos= open_pos; pos >= closed_pos; pos--){ // Close all other Gates
my_servo[k].write(open_pos);
delay(5);
}
// Serial.print(k);
}
} // End for loop checking the state of the switches
} // End Void
for(pos= closed_pos; pos <= open_pos; pos++){ // Open the blast gate
my_servo[k].write(pos); //comment 1
delay(5);
}
// Serial.print(k);
}
else{
for(pos= open_pos; pos >= closed_pos; pos--){ // Close all other Gates
my_servo[k].write(open_pos); //comment 2
delay(5);
comment 1 - here you move the servo in roughly 160 steps with 5 ms delay just to open it
comment 2 - here you do the 160 steps again, but you write the open_pos to servo 160 times.
In setup, you spent 25 ms opening all 5 blast gates, here you spend almost a second per gate blocking everything else.
Why?
Gabriel_swe:
for(pos= closed_pos; pos <= open_pos; pos++){ // Open the blast gate
my_servo[k].write(pos); //comment 1
delay(5);
}
// Serial.print(k);
}
else{
for(pos= open_pos; pos >= closed_pos; pos--){ // Close all other Gates
my_servo[k].write(open_pos); //comment 2
delay(5);
comment 1 - here you move the servo in roughly 160 steps with 5 ms delay just to open it
comment 2 - here you do the 160 steps again, but you write the open_pos to servo 160 times.
In setup, you spent 25 ms opening all 5 blast gates, here you spend almost a second per gate blocking everything else.
Why?
comment 1 I based this on the example sketch where they used a for loop to sweep a servo. if there is a better way I'm open to it. I thought about just setting the open or closed position value in a single write command.
comment 2 That was a typo when I was trying different inputs while debugging the section of the code has been updated.
// This section waits until on of the pins goes to LOW
while(digitalRead(switch_pin[0]) == HIGH && digitalRead(switch_pin[1]) == HIGH
&& digitalRead(switch_pin[2]) == HIGH && digitalRead(switch_pin[3]) == HIGH
&& digitalRead(switch_pin[4]) == HIGH) {
} // Waiting loop for input from the switch while all switchs high
// This section loops through all 5 gates
for(int k = 0;k<5;k++){ // read pin state if low then open that gate else close all others
switch_state[k] = digitalRead(switch_pin[k]); //stores the switch state in an array
if(switch_state[k] == LOW && millis() - time > debounce){
//if switch state is low then open the gate
for(pos= closed_pos; pos <= open_pos; pos++){ // Open the blast gate
my_servo[k].write(pos);
delay(5);
}
// Serial.print(k);
}
else{
for(pos= open_pos; pos >= closed_pos; pos--){ // Close all other Gates
my_servo[k].write(pos); // There was a typo here should have been written this way for the loop to work
delay(5);
}
// Serial.print(k);
}
} // End for loop checking the state of the switches
The set up section is just to set the initial state I have no idea if the controller has the ability to store the previous state after a power down, if it can I would rather have that than reopen all the gates. The way I have it the initial state is known.
Could you elaborate or show an example of what you are referring to?
This is the sort of thing that I had in mind
const byte inputs[] = {A1, A2, A3};
const byte outputs[] = {10, 11, 12};
boolean gateChanged = true;
byte changedGateSwitch = 0;
void setup()
{
Serial.begin(115200);
for (int pin = 0; pin < 3; pin++)
{
pinMode(inputs[pin], INPUT_PULLUP);
pinMode(outputs[pin], OUTPUT);
digitalWrite(outputs[pin], HIGH);
}
Serial.println();
}
void loop()
{
for (int gateSwitch = 0; gateSwitch < 3; gateSwitch ++)
{
if (digitalRead(inputs[gateSwitch ]) == LOW)
{
if (gateSwitch != changedGateSwitch)
{
changedGateSwitch = gateSwitch;
gateChanged = true;
break;
}
}
}
if (gateChanged)
{
changeGates();
gateChanged = false;
}
}
void changeGates()
{
for (int gate = 0; gate < 3; gate++)
{
digitalWrite(outputs[gate], HIGH);
}
digitalWrite(outputs[changedGateSwitch], LOW);
}
I used LEDs to test the program so it will need modifying to use servos but you already have an array of those in your program anyway. Debouncing the inputs would be a good idea too.
If your gates will take the punishment of moving quickly then you can just write the open and shut values to them with no need for a loop to do it
I finally finished the installation and I thought I should provide an update. The boost converter was useless it turns out that the start up current draw of the servos was too much for the power supply to handle. I isolated the Arduino from the servo with a 5V 10A power supply and it works flawlessly. I added a relay to switch the servo power supply when it is needed just in case I forget it on and to extend the life of the servos.
As a side note pin 13 and pin 2 doesn't work with the relay 13 I suspect is because of the built in resistor and led, pin 2 I'm not quite sure I thought I could assign the pin as an output but it appears not. Not sure so I moved it to pin 11 and all was well so I didn't pursue it further.
here is the code I finally ended up with
#include <Servo.h>
const int relay_pin = 11;
const int pin[5]={3,5,6,9,10};
const int open_pos = 48;
const int closed_pos = 119;
const int switch_pin[5] = {2,4,7,8,12};
boolean gateChanged = true;
byte changedGateSwitch = 0;
long time = 0;
long debounce =50;
Servo my_servo[5];
void setup() {
pinMode(relay_pin,INPUT_PULLUP);
pinMode(relay_pin,OUTPUT);
digitalWrite(relay_pin,LOW);
Serial.begin(9600);
//my_servo[0].write(open_pos);
for(int i=0; i<5; i++){ // set the momentary switch pins to inputs abd define servo pins
my_servo[i].attach(pin[i]);
pinMode(switch_pin[i], INPUT_PULLUP);
}
} // END Setup LOOP
void loop() {
for(int gate = 0; gate<5; gate++){ // read pin state if low then open that gate else close all others
if(digitalRead(switch_pin[gate]) == LOW && millis() - time > debounce){
if(gate != changedGateSwitch){
changedGateSwitch = gate;
gateChanged = true;
break;
}
}
}
if(gateChanged){
digitalWrite(relay_pin,LOW);
delay(500);
changeGates(changedGateSwitch);
gateChanged = false;
delay(1500);
digitalWrite(relay_pin,HIGH);
}
} // END of VOID LOOP
void changeGates(int loc){
Serial.println(loc);
for(int mv = 0; mv < 5; mv++){ // close all blast gate
if (mv == loc){
my_servo[mv].write(open_pos);
}
else{
my_servo[mv].write(closed_pos);
}
}
} // END function change gates
You attachments show to me as a message to update photobucket.
pin 2 doesn't work with the relay
You appear to be using pin 2 as as input. Could that be the reason ?
I don't know why the photobucket link stopped working but it was an obsolete wiring diagram.
As far as using pin 2, I wasn't paying attention when I wrote the post it was pin 1 since it was open.
The relay would click on and off rapidly when it was connected to pin 1.
It weird but when I was researching some fixes for the problem I came across settings the pin to INPUT_PULLUP then immediately setting the pin to output. That stops the boot up clicking that I was seeing.
Mike
As far as using pin 2, I wasn't paying attention when I wrote the post it was pin 1 since it was open.
Now I am confused as to which pin you had the problem with. Did you not copy the posted code from the IDE ?
As to using pin1, that is not usually a good idea because it is used by the hardware Serial interface.