Hi
I'm constructing a useless box with the arduino Uno rev3 as microcontroller.
Everything works besides a very strange servo issue.
The lid opens and the arm turns off the switch and then retracts and closes the lid.
If you stress it enough it will retract the button inside the box.
It works for 4-10 cycles then suddenly the arm stays in the up position and nothing seems to happen
I have narrowed it down to the write method the the servo object.
So what happens is the lid opens the arm goes up and turns the switch off, then the code goes in to
the deactivate method and calls the write_arm method. in the write_arm method everything gets stuck on
arm.write(i);
It does not seem as this is a code issue on my behalf, could anyone have n idea on how to solve this?
I have tried with different servos, and on different output pins.
Code goes here:
#include <Servo.h>
#include <MsTimer2.h>
/*
// speed 0=fast, speed 20=slow
//
// initial_delay
// lid_speed
// lid_delay
// arm_speed1
// arm_speed2
// arm_delay
//
*/
int levels[4][6] = {{1000,10,2000,20,20,200},{200,7,500,2,2,100},{1,1,50,1,1,1},{1,1,50,1,1,1}};
Servo arm;
Servo btn;
Servo lid;
int switchPin = 8;
int lid_up = 80;
int lid_down = 150;
int btn_up = 170;
int btn_down = 1;
int arm_up = 180;
int arm_down = 1;
int pmin = 1;
int pmax = 100;
int btn_state=LOW;
int counter = 0;
int level = 1;
unsigned long lastStateHigh = millis();
unsigned int currentLidValue = pmin;
unsigned int currentArmValue = pmin;
unsigned int currentBtnValue = pmax;
int ignoreInitialDelay = 0;
int stressLevel = 0;
void setup()
{
arm.attach(9, 1000, 2300);
btn.attach(10, 1000, 2500);
lid.attach(11, 1000, 2500);
Serial.begin(38400);
//set default position
arm.write(arm_down);
lid.write(lid_down);
btn.write(btn_up);
pinMode(switchPin,INPUT);
//start timer
MsTimer2::set(50, checkBtn);
MsTimer2::start();
}
//Check for button state changes, and calculate current level
void checkBtn() {
int val1;
int val2;
do {
val1 = digitalRead(switchPin);
val2 = digitalRead(switchPin);
} while(val2!=val1);
unsigned long ms = millis();
if(val1 == HIGH && btn_state == LOW) {
btn_state = HIGH;
//the more you stress the machine, increase level faster
if (ms-lastStateHigh<1000) {
counter+=4;
} else if(ms-lastStateHigh<2500) {
counter+=2;
} else if(ms-lastStateHigh<5000) {
counter+=1;
}
lastStateHigh = ms;
} else if(val1 == LOW && btn_state == HIGH) {
btn_state = LOW;
} else {
//no state change
}
//if no change for 30sek reset everything
if(ms-lastStateHigh>30000) {
level = 1;
counter = 0;
lastStateHigh = millis();
currentLidValue = pmin;
currentArmValue = pmin;
currentBtnValue = pmax;
stressLevel = 0;
}
if(counter>=16) {
level+=1;
if (level==5) {
level = 4;
}
counter = 0;
}
}
//main loop, calls activate and deactivate arm
//also check if stresslevel is to high and lower the button
void loop()
{
if (btn_state==HIGH) {
ignoreInitialDelay = activate_arm();
if(ignoreInitialDelay==1 && level==4) {
stressLevel +=1;
}
ignoreInitialDelay = deactivate_arm();
if(ignoreInitialDelay==1 && level==4) {
stressLevel +=1;
}
if(ignoreInitialDelay==0 && level==4) {
stressLevel =0;
}
}
if(stressLevel>=10) {
stress();
}
delay(20);
}
int activate_arm() {
int initial_delay = levels[level-1][0];
int lid_speed = levels[level-1][1];
int lid_delay = levels[level-1][2];
int arm_speed1 = levels[level-1][3];
int arm_speed2 = levels[level-1][4];
int arm_delay = levels[level-1][5];
Serial.println("activate: level: "+String(level) + " counter: " + String(counter));
//delay before open the lid
if(ignoreInitialDelay==0) {
for(int i = 1;i<=initial_delay;i++) {
delay(1);
if(checkBtn==LOW) {return(1);}
}
}
//open lid
if(currentLidValue<pmax) {
for(int i = currentLidValue;i<=pmax;i++) {
write_lid(i);
delay(lid_speed);
if(btn_state==LOW) {return(1);}
}
}
//delay before arm is activated
if(ignoreInitialDelay==0) {
for(int i = 1;i<=lid_delay;i++) {
delay(1);
if(btn_state==LOW) {return(1);}
}
}
//raise arm first 50%
if(currentArmValue<pmax-50) {
for(int i = currentArmValue;i<=pmax-50;i++) {
write_arm(i);
delay(arm_speed1);
if(btn_state==LOW) {return(1);}
}
}
//raise arm the last 50%
if(currentArmValue<pmax) {
for(int i = currentArmValue;i<=pmax;i++) {
write_arm(i);
delay(arm_speed2);
if(btn_state==LOW) {break;}
}
}
//delay before arm is lowered
if(ignoreInitialDelay==0) {
for(int i = 1;i<=arm_delay;i++) {
delay(1);
}
}
currentLidValue = pmax;
return 0;
}
int deactivate_arm() {
int initial_delay = levels[level-1][0];
int lid_speed = levels[level-1][1];
int lid_delay = levels[level-1][2];
int arm_speed1 = levels[level-1][3];
int arm_speed2 = levels[level-1][4];
int arm_delay = levels[level-1][5];
Serial.println("deactivate 1 level: "+String(level) + " counter: " + String(counter));
//lower the arm first 50%
if(currentArmValue>pmax-50) {
for(int i=currentArmValue;i>=pmax-50;i--) {
write_arm(i);
delay(arm_speed1);
if(btn_state==HIGH) {return(1);}
}
}
//lower the arm the rest 50%
if(currentArmValue>pmin) {
for(int i=currentArmValue;i>=pmin;i--) {
write_arm(i);
delay(arm_speed2);
if(btn_state==HIGH) {return(1);}
}
}
//wait before closing the lid
if(ignoreInitialDelay==0) {
for(int i = 1;i<=lid_delay;i++) {
delay(1);
if(btn_state==HIGH) {return(1);}
}
}
//close the lid
if(currentLidValue>pmin) {
for(int i=currentLidValue;i>=pmin;i--) {
write_lid(i);
delay(lid_speed);
if(btn_state==HIGH) {return(1);}
}
}
//if a fully undisturbed deactivate is performed, increase level
counter +=(8/level);
currentArmValue = pmin;
currentLidValue = pmin;
return 0;
}
//writes the new arm value
void write_arm(int value) {
int v = map(value,1,100,arm_down,arm_up);
arm.write(v);
currentArmValue = value;
}
//writes the new lid value
void write_lid(int value) {
int v = map(value,100,1,lid_up,lid_down);
lid.write(v);
currentLidValue = value;
}
//write the new button value
void write_btn(int value) {
int v = map(value,1,100,btn_down,btn_up);
btn.write(v);
currentBtnValue = value;
}
//to much stress, lower arm and close lid
//retract button and wait for 10sek, then raise the button
//and turn of the button if it is turned on
void stress() {
Serial.println("stress");
write_arm(pmin);
delay(300);
write_lid(pmin);
write_btn(pmin);
delay(10000);
stressLevel = 0;
for(int i = 1;i<pmax;i++) {
write_btn(i);
delay(20);
}
if(btn_state==HIGH) {
level=4;
activate_arm();
deactivate_arm();
}
delay(300);
}
Kind Regards
/Danjel