Hi all! I am a novice programmer trying to run tests cases in tandem with each other. The objective is to create one file with all tests cases on it so they can be tested one right after the other. I am currently testing the use of a pushbutton to turn an led on and off (test case 1) and a test to rotate a servo (test case 2).
Both test cases work separately when I run them, however, having the servo test case active prevents the pushbutton test case from working. I found this to be because of a delay function used in the servo test which for some reason stops my pushbutton test case from working.
When I remove the delay they both work fine but the servo spins like crazy which is not my desired output (I just want it to rotate fully back in forth in a smooth motion).
Here is the code
Servo servo1;
const int BUTTON_PIN = 2;
const int LED_PIN = 3;
byte lastButtonState = LOW;
byte ledState = LOW;
void setup() {
servo1.attach(5);
pinMode(BUTTON_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
//TEST CASE 1
//PUSHBUTTON
byte buttonState = digitalRead(BUTTON_PIN);
if (buttonState != lastButtonState) {
lastButtonState = buttonState;
if (buttonState == LOW) {
ledState = (ledState == HIGH) ? LOW: HIGH;
digitalWrite(LED_PIN, ledState);
}
}
// TEST CASE 2
// SERVO
for(int position = 0; position <= 180; position += 1){
servo1.write(position+5);
delay(55); //THIS IS CREATING PROBLEMS
}
for(int position = 180; position >= 0; position -= 1){
servo1.write(position-5);
delay(55); //THIS IS CREATING PROBLEMS
}
}
Is there some way I can get both test cases to run together? Any help would be greatly appreciated.
need to recognize a button press while the servo loop is running.
the better approach is to use millis() instead of a delay. the following in/decrements the position each iteration using "dir" avoiding separate loops.
add your servo, button and LED functions
unsigned long msecLst;
const int Pos0 = 0;
const int PosN = 180;
int pos = Pos0;
int dir = 1;
void loop() {
unsigned long msec = millis ();
if (msec - msecLst >= 55) {
pos += dir;
Serial.println (pos);
if (Pos0 == pos || PosN == pos)
dir = -dir;
}
}
void setup ()
{
Serial.begin (9600);
}
Are you saying that I can just directly implement this into my code without changing any of it? Or should I still remove the delays I have in my servo test case?
This is code that is blocking.
// stay INSIDE this for-loop until the counting up from 0 to 180 has finished
// which needs 181 * 55 milliseconds = 9900 milliseconds = 9,9 seconds
To make the code responsive again that at the code is reacting on button-presses
at any time requires non-blocking coding.
The basic principle of non-blocking coding is
avoid all and any for-loops
avoid all and any while-loops
avoid all and any delay()
the only thing that is looping is
void loop() itself
if code shall not be executed all the time the execution has to be made conditional with if-conditions or switch-case-break-statements.
to achieve the goal that parts of the code shall be only executed after some time non-blocking timing must be used.
From this description you can see going beyond some small demo-programs requires quite some knowledge of more advanced programming-techniques
Of course there are a lot of tutorials online for that. Most of them really bad in explaining.
Some of them of medium quality but don't use everyday examples which would make it easier to understand.
And in very rare cases easy to understand tutorials that use everyday examples (as analogons) to explain what the code does.
Still the main thing is: understanding the concepts of
non-blocking timing
state-machines
looping through using of void loop() combined with using quickly___ jump-in / jump-out functions
This is not a trivial matter of 15 minutes. It is more of some hours with very good tutorials and it is a matter of days with medium quality tutorials.
As a starting point give this tutorial about non-blocking timing a try