Hi everyone,
as I am really new to the whole Arduino topic, please forgive the (most likely) iinefficient code of mine. @MicroBahner, thank you so much for the most amazing library! I am digging into it right now, and I have used it successfully to drive standard dc and stepper motors, as well as fade LEDs (the "BULB" attribude is indeed beautyful to watch ).
But now I am stuck with the following problem:
I would like to sweep a servo fully (0 deg. to 180 deg., and back) every "n"-seconds.
What I've managed to do is to get the movement in one direction, but unfortunately it's always only half the movement I need. I have used the stepper example provided in MobaTools as the base, and when the sweep is run without the "myTimer" being triggered, it does actually work.
I am using a Nano.
Do you have a suggestion how to solve this? Thanks a lot in advance
PS: ich schreibe auf Englisch, da das Thema ggf. für ein größeres Publikum von Interesse sein könnte. Grösste Lob Franz-Peter, wirklich eine unglaubliche herausragende Leistung Deine Lib !
#include <MobaTools.h>
#include <EEPROM.h>
int address = 0; // save last servo position on shut down
const int servoPin = 6; // The servo is connected to this pin
// Sweeping targets
const byte target1 = 0;
const byte target2 = 180;
byte nextPosServo;
/* Servo */
MoToServo myServo;
MoToTimer myTimer;
MoToTimer servoPause; // Pause between servo moves
bool servoRunning;
byte angle;
MoToTimer ServoHomingTimer;
byte servoCount = 0;
byte lastServoCount = 0;
byte servoModulo;
void setup() {
Serial.begin(115200);
myServo.attach(servoPin);
angle = EEPROM.read(address); // read the last save angle
// home the servo
while (myServo.read() <= target2) {
if (ServoHomingTimer.running() == false) {
angle++;
myServo.write(angle);
if ((myServo.read() >= 178) && (myServo.read() <= 180)) break; // close enough to "0" degree setting, due to servo twitching
ServoHomingTimer.setTime(15);
}
}
servoRunning = true;
}
void loop() {
EEPROM.update(address, myServo.read()); // save current servo angle
myServo.setSpeedTime(3000); // one full servo sweep (0 > 180 > 0) should take place aaprox. every 3 seconds
if (myTimer.running() == false) {
myTimer.setTime(2000);
if (servoRunning) {
// Wait till servo has reached target, then set pause time
if (!myServo.moving()) {
// servo has reached target, start pause
servoPause.setTime(20);
servoRunning = false;
}
} else {
// servo doesn't move, wait till stepperPause time expires
if (servoPause.expired()) {
// servoPause time expired. Start servo in opposite direction
if (nextPosServo == target1) {
nextPosServo = target2;
} else {
nextPosServo = target1;
}
myServo.write(nextPosServo);
servoRunning = true;
}
}
}
}
Hi Gabriel,
thanks for your compliments about MobaTools
If you want one back and forth movement to start at every myTimer interval, this intervall must be longer than the complete movement. With your speed settings a complete back and forth movement needs about 6 seconds. The back and forth movement should be started when the timer expired, but it must stop independently from myTimer running.
This is fairly useless. The servo will only get an impulse every 20ms. So a delay of 20ms in the end will not do anything.
Hi Franz,
thanks a lot for the quick reply!
The idea with the timer to be twice as long as my single servo (0 to 180) movement totally makes sense, thanks a lot. As soon as I am home I shall try to implement it and report back to you.
And thanks for pointing out the 20ms issue, will remove that from code (I actually saw it in your manual of MobaTools but somehow ignored it )
Regarding the finite state machine: the whole project encompasses a push button, a servo, a stepper motor with a linear rail and a small DC motor ( I am building a toy). When the user pushes the button, the Stepper motor and the DC motor run all the time in parallel with the servo. The Stepper continuously moves the linear slider back and forth, the DC motor is simply on. Meanwhile, the servo should be doing a full sweep cycle every "n" seconds (e.g. every 6 seconds). When the button is pressed the second time the movement of all the motors is zeroed out. I have therefore already implemented a state machine by the means of the button class from your library. Or did you mean using the state machine in some different way in this case?
I will report back asap I regarding your timer suggestion, thanks a lot!
Regards, Gabriel
Of course you can have multiple FSM's in your sketch ( as long as they are not blocking ). And by setting a flag in one FSM you can start/stop another one. So the servo movement can be realised by this FSM, and you could start/stop it by one of your other FSM's.
Regards, Franz-Peter
Dear Franz! Today I've learned a great deal about state machines, thank you so much !
The code is working like a charm, and it's an amazingly elegant solution for repetitive task, I will definetely keep this in mind for all of my projects.
As an excercise for a newcomer: thanks for the hint about the EEPROM. Do you have any other thoughts on "homing" the servo in a rather calm way? The idea behind: if the power is abruptly cut off, I would like to let the servo get to a predefined "0"-position (in this case it will be either 0 or 180 degree). Every time I tried doing it without the implemented procedure, the servo jumps rather quickly back. I would like to let it zero itself out slowly.
I will also try to implement your state machine solution into the rest of the code with everything running synchronously
Thank you so much again!
Best regards,
Gabriel
@MicroBahner Dear Franz I would like to thank you again for your help, I've successfully managed to integrate the state machine into the rest of the code. Your amazing library is now driving in parallel: 1 DC motor, 1 linear rail stepper, a servo and last but not least a MOSFET pwm controlled Led module. Everything is running smoothly and in parallel on an Arduino Nano clone.
Regarding the limited number of write cycles for the EEPROM: thanks again for pointing that out. I've simply solved it with an external AT24C256 module. Around 2 million write cycles should suffice for my application.
Thanks again! Regards, Gabriel