I'm getting close to finishing my air raid siren ( see attached photo's ) I've written some code to alter the siren speed depending the position of a rotary switch, this took me a while using the arduino cook book, Jeremy Blum vids on youtube and here searching the forums.
My setup is RC motor and controller with BEC, 7.2v 3700mah battery, arduino uno, 6 position rotary switch with voltage divider circuit to sense position, main power on / off switch, on order two led push buttons.
I've got the siren running on this set up but would like to add 2 NO push buttons in series to start the siren. this is a safety feature to ensure both hands are on the buttons when running. ( and not in the chopper )
The first three positions on the rotary switch will be low speed cycles for indoor use for me and my kid to use. the remaining three postion will be full speed simulating WWII air raid, and fire trucks but I don't want the little guy hurting his ears so I was thinking of creating a pushing pattern to enable the high speed cycles. something like 5 short presses on the push buttons.
This is where i need some help in formating the right code into my program. my thoughts are sense the button being pressed add 1 to variable each time it's pressed then i need to add this to my else if statements but I not sure of the correct formatting.
Any help would gratefully recieved, please go gently on my code as this is the 1st arduino program I've written, I'm sure it could be more efficient, but the only other thing I've programmed is a 1970's Casio calculator for trigonometry.
Regards
Dale
#include <Servo.h>
Servo myservo1; // create servo object to control a servo
// a maximum of eight servo objects can be created
float pos = 0; // variable to store the rotary switch input
void setup() {
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo1.write(pos);// arm speed controller
delay(3000);
}
// the loop routine runs over and over again forever:
void loop() {
start:
int sensorValue = analogRead(A0); // read the input on analog pin 0:
if (sensorValue > 100 && sensorValue < 200) { goto servo1;} // create jump to values
else if (sensorValue > 300 && sensorValue < 400) { goto servo2;}
else if (sensorValue > 500 && sensorValue < 599) { goto servo3;}
else if (sensorValue > 600 && sensorValue < 699) { goto servo4;}
else if (sensorValue > 800 && sensorValue < 899) { goto servo5;}
else if (sensorValue > 900) { goto servo6;}
servo1:
{ // MAX SPEED 120
myservo1.write(pos = 10); // tell servo to go to position in variable 'pos'
}
{ goto start;}
servo2:
{
myservo1.write(pos = 13);
}
{ goto start;}
servo3:
{
myservo1.write(pos = 20); // tell servo to go to position in variable 'pos'
}
{ goto start;}
servo4:
{
myservo1.write(pos = 25); // tell servo to go to position in variable 'pos'
}
{ goto start;}
servo5:
{
myservo1.write(pos = 30); // tell servo to go to position in variable 'pos'
}
{ goto start;}
servo6:
{
myservo1.write(pos = 120); // tell servo to go to position in variable 'pos'
//delay(700);
}
{ goto start;}
}
The value used by servo.write() is an integer which moves normal servos to the angle defined by the number or it sets the speed for continuous rotation servos. I cannot begin to imagine what it does with (pos = 13) etc.
As an aside, a continuous rotation servo is not a servo at all as far as I am concerned, but that battle was lost some time ago.
I am happy with my motor control, it runs, I can controller it's rise and fall with great precision. John thanks you have been most helpfull and have explained the best way to write my else if statements I did pre check the analog values before doing my else if statements 168/339/509/680/852/1023.
Thank you and I am glad it is running for you "so far". When it comes time to add buttons you are really going to have to take your understanding "to the next level" though!
And the first step of that will be to heed the advice above about getting rid of the gotos. If you need a better hint it would be:
void loop() {
// NO start: LABEL
int s=sensorValue;
if (sensorValue > 100 && sensorValue < 200) {
pos=10;
}
else if (sensorValue > 300 && sensorValue < 400) {
pos=13;
}
...
myservo1.write(pos);
// NO goto: start
} // Arduino does it for you, back to loop
lloyddean:
A somewhat different multi-press button example -
led_t led(pinLED);
push_button_t button(pinBUTTON, LOW, 4);
void loop()
{
switch ( button )
{
case 0: led = 0; break;
case 1: led = !led; delay(125UL); break;
case 2: led = !led; delay(250UL); break;
case 3: led = !led; delay(500UL); break;
}
}
Thats a lot above my ability right now, I think i can make out it's altering the delay of the led based on the the button couter. hard for me to understand without the comment lines.
The key here is in asking questions of things you don't understand now, and will never understand, until enough questions are asked, and not simply ignoring what is not currently understood.
Object oriented code, even on embedded systems, can simplify code considerably.
Thing to know learn here is classes and what conversion operators do.
Given that your project appears to be at its start I'll throw this one out there.
It does make use of a non-standard feature of the GCC/CPP compiler included with the Arduino IDE and thus I feel fair game but it may be non portable to other compilers - the range based 'case' statements associated with the standard 'switch'/'case' pair.
#include <Servo.h>
const uint8_t pinSERVO = 9;
float pos = 0; // variable to store the rotary switch input
Servo servo;
void loop()
{
// ... 'analogRead' will return a value in the range 0 - 1023
switch ( analogRead(A0) )
{
case 0 ... 99: return;
case 200 ... 299: return;
case 400 ... 499: return;
case 700 ... 799: return;
case 100 ... 199: pos = 10; break;
case 300 ... 399: pos = 13; break;
case 500 ... 599: pos = 20; break;
case 600 ... 699: pos = 25; break;
case 800 ... 899: pos = 30; break;
case 900 ... 1023: pos = 120; break;
}
servo.write(pos);
}
void setup()
{
servo.attach(pinSERVO);
servo.write(pos); // arm speed controller
delay(3000);
}
I've modified my code without the goto's and the program is working ok
#include <Servo.h>
Servo myservo1; // create servo object to control a servo
// a maximum of eight servo objects can be created
float pos = 0; // variable to store the rotary switch input
void setup() {
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo1.write(pos);
delay(3000);
}
// the loop routine runs over and over again forever:
void loop() {
int sensorValue = analogRead(A0);
if (sensorValue > 100 && sensorValue < 200) {
pos=10;
}
else if (sensorValue > 200 && sensorValue < 400) {
pos=13;
}
else if (sensorValue > 400 && sensorValue < 600) {
pos=14;
}
else if (sensorValue > 600 && sensorValue < 700) {
pos=15;
}
else if (sensorValue > 700 && sensorValue < 900) {
pos=16;
}
else if (sensorValue > 900) {
pos=17;
}
myservo1.write(pos);
}
But then I added a basic rise and fall code for the first rotary switch position but get the error:
_13_prog.cpp: In function 'void loop()':
_13_prog:44: error: 'else' without a previous 'if'
I removed the else and the code compiled, but when I tested the air raid it only ran the rise and fall code and not the other switch positions
#include <Servo.h>
Servo myservo1; // create servo object to control a servo
// a maximum of eight servo objects can be created
float pos = 0; // variable to store the rotary switch input
void setup() {
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo1.write(pos);
delay(3000);
}
// the loop routine runs over and over again forever:
void loop() {
int sensorValue = analogRead(A0);
if (sensorValue > 100 && sensorValue < 200)
{
pos=12.5;
}
// rise and fall code
for(pos = 12.5; pos < 15; pos += .1) // goes from 12.5 to 15
{ // in steps of .1
myservo1.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
delay(5000);
for(pos = 15; pos>=12.5; pos-=.1) // goes from 15 to 12.5
{
myservo1.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
else if (sensorValue > 200 && sensorValue < 400) // error on this line
{
pos=13;
}
else if (sensorValue > 400 && sensorValue < 600) {
pos=14;
}
else if (sensorValue > 600 && sensorValue < 700) {
pos=15;
}
else if (sensorValue > 700 && sensorValue < 900) {
pos=16;
}
else if (sensorValue > 900) {
pos=17;
}
myservo1.write(pos);
}
Where am I going wrong with this piece of code? Any infomation would be gratefully recieved
Hazzard thanks for the upload, I was thinking more of a count then time based, but thinking more about it, if i did go down the count method I would need to have a way to re-set the counter and time based is maybe the way to go. Hmm my hurts. I need to wire these switches to my breadboard and start experimenting.