Hi,
Novice here.
But thought I could do something simple like controlling 4 servos.
Started out with the code more compacted but ended up simply defining and executing 4 identical codes and even those loops are probably unnecessarily cumbersome.
However, everything works fine on pin A1.
The exact same code does NOT work on A2,A3,A4.
Meter shows the pins going LOW when the switch is closed! High when open.
The SAME on ALL pins.
Driving me nuts.
So, 4 servos on D3,D5,D6 and D9.
4 switches on A1,A2,A3,A4
Everything common grounded.Here is the code:
//control 4 servos
//????have 4 switches high/low to change point position
//4 PWM pins for servos
//Using 4 switches on A1-A4 (SPDT) as control.
//Hopefully that means only 4 inputs (either high OR low) AND 4 PWM outputs are used
#include <Servo.h>
#include <EEPROM.h>
Servo myservoa, myservob, myservoc, myservod; // create servo object to control a servo
byte store1 = 10; //cell address to store points position into EEPROM
byte store2 = 20; //give each one some space
byte store3 = 30;
byte store4 = 40;
byte switch1 = A1; //start using some analog pins here for input
byte switch2 = A2;
byte switch3 = A3;
byte switch4 = A4;
byte t1; //just for general use as a temp variable
byte t2;
byte t3;
byte t4;
int val1; //these represent actual servo position
int val2;
int val3;
int val4;
int straight = 80; //duration of the pulse to be sent if points are straight ahead
int turn = 100; //and if turning off
void setup()
{
pinMode(switch1, INPUT_PULLUP); //set input pins to PULL UP so the switch can pull them down.
pinMode(switch2, INPUT_PULLUP); //simply earth it for LOW
pinMode(switch3, INPUT_PULLUP);
pinMode(switch4, INPUT_PULLUP);
myservoa.attach(3);
myservob.attach(5);
myservoc.attach(6);
myservod.attach(9);
//Here get the stored values (to put everything the way it was before power-off).
//After all, if you've got an EEPROM, why not use it?
val1 = EEPROM.read (store1); //get the stored values from the eeprom
myservoa.write(val1); //set the servo
val2 = EEPROM.read (store2);
myservob.write(val2);
val3 = EEPROM.read (store3);
myservoc.write(val3);
val4 = EEPROM.read (store4);
myservod.write(val4);
}
void loop()
{
t1 = digitalRead (switch1);
if ((t1 == LOW) && (val1 == straight))
{
myservoa.write(turn);
val1 = turn; // if switch doesn't agree with current setting tell servo to go to new position
}
if ((t1 == HIGH) && (val1 == turn))
{
myservoa.write (straight);
val1 = straight; //and update val AND EEPROM
}
t2 = digitalRead (switch1);
if ((t2 == LOW) && (val2 == straight))
{
myservob.write(turn);
val2 = turn; // if switch doesn't agree with current setting tell servo to go to new position
}
if ((t2 == HIGH) && (val2 == turn))
{
myservob.write (straight);
val2 = straight;
}
t3 = digitalRead (switch3);
if ((t3 == LOW) && (val3 == straight))
{
myservoc.write(turn);
val3 = turn; // if switch doesn't agree with current setting tell servo to go to new position
}
if ((t3 == HIGH) && (val3 == turn))
{
myservoc.write (straight);
val3 = straight;
}
t4 = digitalRead (switch4);
if ((t4 == LOW) && (val4 == straight))
{
myservod.write(turn);
val4 = turn; // if switch doesn't agree with current setting tell servo to go to new position
}
if ((t4 == HIGH) && (val4 == turn))
{
myservod.write (straight);
val4 = straight;
}
EEPROM.update (store1, val1); //store everything for power down
EEPROM.update (store2, val2); //update ONLY writes to EEPROM if the setting has changed.
EEPROM.update (store3, 120); //this prolongs EEPROM life
EEPROM.update (store4, 120);
}
You can very quickly blow your Arduino up (not literally) with that code. True that update will only write if the contents have changed but if the values do happen to change for whatever reason, in a couple of seconds your unit could be toast. It is extremely unwise to place an EEPROM write/update in an uncontrolled loop. This statement brokers no argument.
Having said that, there doesn't appear to be anything egregiously wrong with your code so it must be with the values being tested. After each digitalRead and before your if statement, print out the two values being tested (i.e. t1 and val1). Have a look at them and see what's happening. You can share that with us if you'd like.
As for blowing the EEPROM, yes, I think I'll just set a safe value in setup and rely on that for keeping the servos under control till I execute the loop.
Not the cause of your problem, but avoid any misunderstanding by anyone reading this thread. the servo outputs do not need to be on PWM enabled pins. Any digital pin will work.
As to your problem, write a small program that simply outputs a message when pins A0 to A4 are taken LOW. This will help to isolate the problem which is likely caused by a wiring fault. Are you using a breadboard and, if so, are the power strips along the edge continuous or do they have breaks in them ?
Thanks for the input UKHeliBob,
But I reckon I've got PWM pins available, why not take the hard work out.
Here is something even weirder than the original problem.
I took the advice re EEPROM use, worked out it's nice but not really necessary and made THE FOLLOWING changes ONLY:
Removed all mention of the EEPROM and modified the setup up code from reading the eeprom stored value to a simple constant.
myservoa.write(val1); //set the servo
myservob.write(val2);
myservoc.write(val3);
myservod.write(val4);
THAT's IT.
Everything now works like a dream on ALL switches!!!!!!!!
Now THAT I would like an explanation for, I thought Arduinos were LOGIC devices???
Originally my 2 settings were "main"and "turn", but I had to change "main" to "straight as the assembler didn't like it.
Came up with some obscure error (on a different line, of course) but that ended up to be the problem.
Just wondering if that term is reserved somewhere???????? Couldn't find any references.
And if it is, is there a list of all/any such words somewhere??
main() is the standard main function that any C/C++ program uses; the Arduino approach hides it for you. That's where your compiler problem probably came from.
With regards to your original problem.
Your valX variables are ints, not bytes. EEPROM.read and EEPROM.update work on bytes so you will only get half of the data. Use EEPROM.get and EEPROM.put instead. EEPROM.put uses EEPROM.update under the hood.
If your valX variables only have to hold values between 0 and 255 (both included), changing them to byte will also work (with your origibal code).
Yes, I should have thought of the fact that the overall program would have that name. Just never occurred to me because as you say, Arduino hides it. Brilliant!
As far as the EEPROM values are concerned, my fault. I forgot that in desperation I had changed them to integers. Originally they were simple bytes (values are only 80 or 100). I tampered with them in desperation.
aussiewill:
As far as the EEPROM values are concerned, my fault. I forgot that in desperation I had changed them to integers. Originally they were simple bytes (values are only 80 or 100). I tampered with them in desperation.
As far as I can see, your code should have worked in that case; you say it didn't?
Meter shows the pins going LOW when the switch is closed! High when open.
The SAME on ALL pins.
.
That's the way you have them programmed.
pinMode(switch1, INPUT_PULLUP); //set input pins to PULL UP so the switch can pull them down.
pinMode(switch2, INPUT_PULLUP); //simply earth it for LOW
pinMode(switch3, INPUT_PULLUP);
pinMode(switch4, INPUT_PULLUP);
Hi again,
Yes Fred, I know. I programmed them that way. Simply pointing out that HARDWARE wise everything worked identically. Link that with the fact that ALL 4 statements are absolutely identical and you might understand why I was (am) mystified that ONE always worked and the others NOT.
Posting from my phone, so keeping it short and simple:
In your original code you have the four varX variables. As globals, they are initialised to zero when declared. The first time you ran the sketch you then assigned values to them from EEPROM. The values you pulled from there are for the purposes of this sketch unknown and unspecified.
Next you have a bunch of if's that compare the unspecified values to either 80 or 100. If they happen to match then you get to update varX, otherwise not.
Finally you write var1 and var2 back to EEPROM, still unspecified, and 120 to var3 and var4, which doesn't equal either 80 or 100.
Ill specified values give ill specified results.
Your second digitalRead also has the wrong pin name.
Hi
Thanks to arduarn for pointing that out. I had actually prewritten 120 into all 4 eeprom positions, by having a small loop in setup the very first time I uploaded the sketch. But valid point. As it is, I now simply center all servos on power on and don't bother with the eeprom.
Now that everything works fine, creating servo objects with comma separation works fine, I don't think the assembler cares either way.
And STILL I haven't found a really valid reason why no matter what I did, everything always worked for the first iteration of the loop bt NOT for the others. But all's well etc. I have now converted to an 8 switch point controller and have no more problems.
Think I'll just keep believing in Gremlins!