Problem with calling a fonction

Good evening everyone!
English isnt my native language so this is probably gonna be full of mistakes, SORRY! :smiley:

I am a student in Master Mechatronics.

I have a mini project to do with Arduino: a turret controlled with a joystick (2 servos). With 2 operating modes:

  • Holding position even when releasing the joystick (with dead zone or dead band).
  • Continuous monitoring of the position of the joystick.

For this I used a push button, turned into switch (a simple algorithm to toggle his state) , to select between the two.

I also added a LCD to show which of the modes is active. So far, everything is good

The problem is when I call the functions, depending on the state of the button, the functions of both modes do not work, even if the LCD displays correctly which mode is active, without any problem.

I have tested every part of the code. The LCD works perfectly, th two modes too, the bouton does his mission pretty fine. So dont know what it could be.

I leave you here a sample of the code, just with the call of one of two modes. Without lcd and without buttons:

#include <Servo.h>;

const int servoHPin = 9;
const int servoVPin = 10;

int horzPin = A0;
int vertPin = A1;

Servo horzServo;
Servo vertServo;

int horzInitPos;
int vertInitPos;

int horzPotMAX = 2350;
int horzPotMIN = 594;
int vertPotMAX = 2350;
int vertPotMIN = 594;

int horzDeadBandLOW = 400;
int horzDeadBandHIGH = 600;
int vertDeadBandLOW = 400;
int vertDeadBandHIGH = 600;

int horzSpeed = 4 ;
int vertSpeed = 4 ;

int jyHorzVal;
int jyVertVal;
int jyHorzMapped;
int jyVertMapped;




void setup() {
  // put your setup code here, to run once:

  horzServo.attach(servoHPin);
  vertServo.attach(servoVPin);
  horzInitPos = 1472;
  vertInitPos = 1472;
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);


}


void loop() {
  // put your main code here, to run repeatedly:

holdPositionMODE();

}



void holdPositionMODE() {
  
  int horzInitPos;
  int vertInitPos;

  jyHorzVal=analogRead(horzPin);
  jyVertVal=analogRead(vertPin);
  
  horzInitPos = constrain(horzInitPos, horzPotMIN, horzPotMAX) ;
  vertInitPos = constrain(vertInitPos, vertPotMIN, vertPotMAX) ;
  
  if(jyHorzVal<horzDeadBandLOW || jyHorzVal>horzDeadBandHIGH)
    {
      jyHorzMapped=map(jyHorzVal,0,1023,horzSpeed,-horzSpeed);
      horzInitPos=horzInitPos+jyHorzMapped;
    }
  
  if(jyVertVal<vertDeadBandLOW || jyVertVal>vertDeadBandHIGH)
    {
      jyVertMapped=map(jyVertVal,0,1023,vertSpeed,-vertSpeed);
      vertInitPos=vertInitPos+jyVertMapped;
    }
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);

  delay(20);
}

And here is my entire code

I hope u can help me with this because im really blocked.

Thanks a lot!!

two_modes_servos.ino (5.02 KB)

By holding the position do you mean the Turret stays still and has no motion at all?

Why have you got 2 different variables named horzInitPos ? One has global scope, the other local to the holdPositionMODE() function.

BruceBerrios:
By holding the position do you mean the Turret stays still and has no motion at all?

Yes exactly, when the joystick return to central position the turret doesnt follow it, but stays in the last position.

UKHeliBob:
Why have you got 2 different variables named horzInitPos ?
One has global scope, the other local to the holdPositionMODE() function.

my mistake when i was copying the code, it shouldnt be in the function. here is the my code:

#include <Servo.h>;

const int servoHPin = 9;
const int servoVPin = 10;

int horzPin = A0;
int vertPin = A1;

Servo horzServo;
Servo vertServo;

int horzInitPos;
int vertInitPos;

int horzPotMAX = 2350;
int horzPotMIN = 594;
int vertPotMAX = 2350;
int vertPotMIN = 594;

int horzDeadBandLOW = 400;
int horzDeadBandHIGH = 600;
int vertDeadBandLOW = 400;
int vertDeadBandHIGH = 600;

int horzSpeed = 4 ;
int vertSpeed = 4 ;

int jyHorzVal;
int jyVertVal;
int jyHorzMapped;
int jyVertMapped;




void setup() {
  // put your setup code here, to run once:

  horzServo.attach(servoHPin);
  vertServo.attach(servoVPin);
  horzInitPos = 1472;
  vertInitPos = 1472;
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);


}


void loop() {
  // put your main code here, to run repeatedly:

holdPositionMODE();

}



void holdPositionMODE() {
  

  jyHorzVal=analogRead(horzPin);
  jyVertVal=analogRead(vertPin);
  
  horzInitPos = constrain(horzInitPos, horzPotMIN, horzPotMAX) ;
  vertInitPos = constrain(vertInitPos, vertPotMIN, vertPotMAX) ;
  
  if(jyHorzVal<horzDeadBandLOW || jyHorzVal>horzDeadBandHIGH)
    {
      jyHorzMapped=map(jyHorzVal,0,1023,horzSpeed,-horzSpeed);
      horzInitPos=horzInitPos+jyHorzMapped;
    }
  
  if(jyVertVal<vertDeadBandLOW || jyVertVal>vertDeadBandHIGH)
    {
      jyVertMapped=map(jyVertVal,0,1023,vertSpeed,-vertSpeed);
      vertInitPos=vertInitPos+jyVertMapped;
    }
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);

  delay(20);
}

Ooh crap!!! what a stupid mistake have I done! I had connected the servos to pins 5 and 6. Because i used a shift register with the LCD so i dont have to use 9 pins just for it, now the LCD uses 3 pins: 13, 12 and 9.

Okey so the function call is solved, buut now i have new problems.

PROBLEMS:

  • at first the LCD doesnt show any mode (just the “ARDUINO TURRET” fix msg)

  • when i click the button one time it show “Hold position ON”

  • if i click again nothing changes

  • i gotta do an extended click so it changes and shows “Sweep mode ON”

  • Even if i press the button the mode doesnt change, the LCD changes the message (it means it calls the other lcd function) but not the mode’s function. its always the hold position mode

  • anytime i click the button the turret tries to go to 90º (in microseconds for my servos is 1472)

here is the full code

#include <Servo.h>;
#include <ShiftedLCD.h>

const int servoHPin = 5;      //  arduino pin affected to SERVO 1 (horizontal motion)
const int servoVPin = 6;     //  arduino pin affected to SERVO 2 (vertical motion)

const int laserPin = 4;       //  arduino pin affected to the laser
const int lsrButtonPin = 2;   //  arduino pin affected to the laser button

const int modeButtonPin = 8;  //  arduino pin affected to the "Mode" activated

int lsrButtonState = LOW;    //  tracks the state of the button, low if not pressed, high if pressed
int laserState = -1;         //  tracks the state of the LED, negative if off, positive if on
long lastDebounceTime1 = 0;  // the last time the output pin was toggled
long debounceDelay1 = 200;   // the debounce time; increase if the output flickers


int lastModeButtonState = LOW;    //  tracks the last state of the button
int currentModeButtonState = HIGH;  //  tracks the current state of the button
long lastDebounceTime2 = 0;       // the last time the output pin was toggled
long debounceDelay2 = 200;        // the debounce time; increase if the output flickers


int horzPin = A0;
int vertPin = A1;

Servo horzServo;
Servo vertServo;

LiquidCrystal lcd(9);

int horzInitPos;
int vertInitPos;

int horzPotMAX = 2350;
int horzPotMIN = 594;
int vertPotMAX = 2350;
int vertPotMIN = 594;

int horzDeadBandLOW = 400;
int horzDeadBandHIGH = 600;
int vertDeadBandLOW = 400;
int vertDeadBandHIGH = 600;

int horzSpeed = 2 ;
int vertSpeed = 2 ;

int jyHorzVal;
int jyVertVal;
int jyHorzMapped;
int jyVertMapped;

void setup() {
  // put your setup code here, to run once:

  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("ARDUINO TURRET");
    
  horzServo.attach(servoHPin);
  vertServo.attach(servoVPin);
  
  pinMode (laserPin, OUTPUT);
  pinMode (lsrButtonPin, INPUT);
  pinMode (modeButtonPin, INPUT);
  
  horzInitPos = 1472;
  vertInitPos = 1472;
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);

}


void loop() {
  // put your main code here, to run repeatedly:
  lsrButtonState = digitalRead(lsrButtonPin);
 
  //filter out any noise by setting a time buffer
  if ((millis() - lastDebounceTime1) > debounceDelay1) {
 
    //if the button has been pressed, toggle the Laser from "off to on" or "on to off"
    if ((lsrButtonState == HIGH) && (laserState < 0)) {
 
      digitalWrite(laserPin, HIGH); //turn Laser on
      laserState = -laserState; //now the Laser is on, we need to change the state
      lastDebounceTime1 = millis(); //set the current time
    }
    else if ((lsrButtonState == HIGH) && (laserState > 0)) {
 
      digitalWrite(laserPin, LOW); //turn Laser off
      laserState = -laserState; //now the Laser is off, we need to change the state
      lastDebounceTime1 = millis(); //set the current time
    }
 
  }

  
  currentModeButtonState=digitalRead(modeButtonPin);

    //filter out any noise by setting a time buffer
  if ((millis() - lastDebounceTime2) > debounceDelay2) {

    //if the button has been pressed, change the motion mode of the turret, call the  functions
    if ((currentModeButtonState == HIGH) && (lastModeButtonState == LOW)){
      sweepMODE();
      lcdMODE1();
      lastDebounceTime2 = millis();
    }
    else if ((currentModeButtonState == LOW) && (lastModeButtonState == HIGH)){
      holdPositionMODE();
      lcdMODE2();
      lastDebounceTime2 = millis();

    }
    
 }
  lastModeButtonState = currentModeButtonState;
}




void holdPositionMODE() {

  jyHorzVal=analogRead(horzPin);
  jyVertVal=analogRead(vertPin);
  
  horzInitPos = constrain(horzInitPos, horzPotMIN, horzPotMAX) ;
  vertInitPos = constrain(vertInitPos, vertPotMIN, vertPotMAX) ;
  
  if(jyHorzVal<horzDeadBandLOW || jyHorzVal>horzDeadBandHIGH)
    {
      jyHorzMapped=map(jyHorzVal,0,1023,horzSpeed,-horzSpeed);
      horzInitPos=horzInitPos+jyHorzMapped;
    }
  
  if(jyVertVal<vertDeadBandLOW || jyVertVal>vertDeadBandHIGH)
    {
      jyVertMapped=map(jyVertVal,0,1023,vertSpeed,-vertSpeed);
      vertInitPos=vertInitPos+jyVertMapped;
    }
  
  horzServo.writeMicroseconds(horzInitPos);
  vertServo.writeMicroseconds(vertInitPos);

  delay(2);
 
}


void lcdMODE1() {

  lcd.setCursor(0,1);
  lcd.print("Hold position ON");
  
}


void sweepMODE () {
  
  jyHorzVal=analogRead(horzPin);
  jyVertVal=analogRead(vertPin);
  
  
  horzInitPos = constrain(horzInitPos, horzPotMIN, horzPotMAX) ;
  vertInitPos = constrain(vertInitPos, vertPotMIN, vertPotMAX) ;
  
  jyHorzMapped=map(jyHorzVal,0,1023,horzPotMIN,horzPotMAX);
  //horzInitPos=horzInitPos+jyHorzMapped;
  
  jyVertMapped=map(jyVertVal,0,1023,vertPotMIN,vertPotMAX);
  //vertInitPos=vertInitPos+jyVertMapped;
  
  if(jyHorzMapped<horzInitPos){
    horzInitPos=horzInitPos+horzSpeed;
  }
  
  if(jyVertMapped<vertInitPos){ 
    vertInitPos=vertInitPos+vertSpeed;
  }
  
  horzServo.writeMicroseconds(jyHorzMapped);
  vertServo.writeMicroseconds(jyVertMapped);
  delay(100);

}


void lcdMODE2() {
  
  lcd.setCursor(0,1);
  lcd.print("Sweep mode ON   ");
  
}
  delay(100);

This means that some button pushes less than 1/10th of a second can be completely missed by the code.

With the additional debouncing code, it will see some pushes of up to 2/10th as glitches that are not actual button pushes.

Your inner functions should not have delays. If there’s some reason why you don’t want to call them a few thousand times per second, use the blink-without-delay technique to only call them when required on schedule. The outer loop which is looking at the buttons (and limit switches and whatever else) should run as fast as possible. Several thousand times per second is probably about right.