0

Im trying to test out these two motors I have where I need to call a function from the loop. I only want to call this function once so I made a quick little if statement to have the program only run once. However, it seems that when I run this file, the Variable I have set doesn't continue getting incremented. The code will tell more.

int i = 0;

void loop()
{
    // Serial.print("=====");Serial.print(i);Serial.println("=====");
    if(i == 1)
    {
        Serial.print("+++");Serial.print(i);Serial.print("+++");
        DeclinationMotor(DEC_freq, NULL, HIGH);
    }
    i++;
}

The behavior is really odd in that if i just run that code above, the variable i will not get incremented and become stuck at 1. However if I were to un-comment the other serial print line above the if statement, i would be incremented properly and that function will be executed only once.

For reference, the function DeclinationMotor is

float DeclinationMotor(float freqspeed, float angularDistance, byte direction)
{
    Serial.print(freqspeed); Serial.print("DEfS "); Serial.print(angularDistance); Serial.print("DEaD "); Serial.println(direction);

    int finalLocation = 0;
    if(freqspeed == NULL && angularDistance != NULL)
        freqspeed = DEC_freq;
    if(angularDistance != NULL)
    {
        if(direction == HIGH)
            finalLocation = DEC_degrees_from_home + angularDistance;
        else
            finalLocation = DEC_degrees_from_home - angularDistance;    
    }

    SetPinFrequency(DEC_STEP, freqspeed);
    pwmWrite(DEC_STEP, 128);
    digitalWrite(DEC_DIR, direction);
    digitalWrite(DEC_running, HIGH);

    return finalLocation;
}

Full Code Here

//-----------------------------------------------------------------------------
#include <PWM.h>
void analogJoyStick();
void serialEvent();
void meridianFlipT();
float RightAscensionMotor(float freqspeed, float angularDistance, byte direction);
float DeclinationMotor(float freqspeed, float angularDistance, byte direction);
void StopRAMotor();
void StopDECMotor();




// --------------Todo--------------
// Turn the Variables into motor actions for serial event
// Write program that helps figure out the encoders degrees for its 
// angle crap. You might just need to count exactly how many 
// times the revolution goes around manually
// set up isrs for optical sensors and joystick
// create stop motors function
// 



#define RA_sensor 2
#define DEC_sensor 3

// Sensor limit LEDs
#define RA_limit 27
#define DEC_limit 29

// Telescope Position Status LEDs
#define home_pos 35
#define tracking 37

// Joystick
#define xPin A0      // X axis
#define yPin A1      // Y axis
#define JS_button 26 // Button

// Motor 1
#define RA_STEP 10                // Step for Right Ascension
#define RA_DIR 12                 // Direction for Right Ascension
#define RA_EN 32                  // Enable motor disconnection
#define RA_OUT 36                 // Motor fault output
int RA_freq = 800;                // Frequency for normal movement
int RA_freq_tracking = 400;       // Frequency for tracking objects
int RA_freq_slow = 600;           // Frequency for when close to desired position
volatile byte RA_track_DIR = LOW; // Used to store last direction of RA motor

// Encoder 1
#define RA_A 18
#define RA_B 19
#define RA_I 22 
long int RA_Encoder_Count = 0;      // Positive value means net position is in B direction
int RA_Complete_Rotations = 0; // Positive value means net complete rotation is in B direction 
int RA_degrees_from_home = 0;  // Used to keep track of how far from home position

// Motor 2
#define DEC_STEP 11                 // Step for Declination
#define DEC_DIR 13                  // Direction for Declination
#define DEC_EN 34                   // Enable motor disconnection
#define DEC_OUT 38                  // Motor fault output
int DEC_freq = 800;                 // Frequency for normal movement
int DEC_freq_slow = 600;            // Frequency when close to desired position
volatile byte DEC_track_DIR = LOW;  // Used to store last direction of DEC motor

// Encoder 2
#define DEC_A 20
#define DEC_B 21
#define DEC_I 24
long int DEC_Encoder_Count = 0;      // Positive value means net position is in B direction
int DEC_Complete_Rotations = 0; // Positive value means net complete rotation is in B direction
int DEC_degrees_from_home = 0;  // Used to keep track of how far from home position


// Communication with ATmega328
#define COMM 39
#define RA_running 23
#define DEC_running 25

int i = 0;

void setup()
{
    // Sensor Inputs
    pinMode(RA_sensor, INPUT);
    pinMode(DEC_sensor, INPUT);

    // Sensor Fault LEDs
    pinMode(RA_limit, OUTPUT);
    pinMode(DEC_limit, OUTPUT);

    // Telescope Position Status LEDs
    pinMode(home_pos, OUTPUT);
    pinMode(tracking, OUTPUT);

    // Interrupts for Sensors
    // attachInterrupt(digitalPinToInterrupt(RA_sensor), RA_sensor_trip, CHANGE);
    // attachInterrupt(digitalPinToInterrupt(DEC_sensor), DEC_sensor_trip, CHANGE);

    // Right Ascension Motor Inputs and Outputs
    pinMode(RA_STEP, OUTPUT);
    pinMode(RA_DIR, OUTPUT);
    pinMode(RA_OUT, INPUT);
    // attachInterrupt(digitalPinToInterrupt(RA_OUT), RA_motor_fault, CHANGE);

    // Right Ascension Encoder Inputs
    pinMode(RA_A, INPUT);
    // attachInterrupt(digitalPinToInterrupt(RA_A), RA_Enc, RISING);
    pinMode(RA_B, INPUT);
    pinMode(RA_I, INPUT);

    // Declination Motor Inputs and Outputs
    pinMode(DEC_STEP, OUTPUT);
    pinMode(DEC_DIR, OUTPUT);
    pinMode(DEC_OUT, INPUT);
    // attachInterrupt(digitalPinToInterrupt(DEC_OUT), DEC_motor_fault, CHANGE);

    // Declination Encoder Inputs
    pinMode(DEC_A, INPUT);
    // attachInterrupt(digitalPinToInterrupt(DEC_A), DEC_Enc, RISING);
    pinMode(DEC_B, INPUT);
    pinMode(DEC_I, INPUT);   

    // Joystick inputs
    pinMode(xPin, INPUT); 
    pinMode(yPin, INPUT); 
    pinMode(JS_button, INPUT);

    // Communication with ATmega328
    pinMode(COMM, OUTPUT); 
    pinMode(RA_running, OUTPUT);
    pinMode(DEC_running, OUTPUT);

    // Constant signal to ATmega328 to confirm ATmega2560 is operational
    digitalWrite(COMM, HIGH);

    Serial.begin(9600);
    InitTimersSafe();

}

void loop()
{
    // Serial.print("=====");Serial.print(i);Serial.println("=====");
    if(i == 1)
    {
        Serial.print("+++");Serial.print(i);Serial.print("+++");
        DeclinationMotor(RA_freq, NULL, HIGH);
    }
    i++;
}



void analogJoyStick()
{
    int NumbX, NumbY;


    while(digitalRead(JS_button) == LOW)
    {
        NumbX = analogRead(xPin);
        NumbY = analogRead(yPin);

        // Here we go to to move the motor and the numbers have been created with
        // small numerical buffers to allow deadzones. It was made to be linear response
        // to the users input.

        if(NumbX > 530)
            RightAscensionMotor((RA_freq * (NumbX - 512)/512), NULL, HIGH);
        else if(NumbX < 500)
            RightAscensionMotor((RA_freq * (NumbX - 512)/512), NULL, LOW);
        else
            StopRAMotor();

        if(NumbY > 530)
            DeclinationMotor(800, NULL, HIGH);
        else if(NumbY < 500)
            DeclinationMotor(800, NULL, LOW);
        else
            StopDECMotor();
        delay(50);
    }
    // Track();
}


// this thing seems to be appended onto the end of the loop() so the immediate intersection must be
void serialEvent()
{
    char ident = Serial.read();     // first character will be the identifying character

    if(ident == 'R')
    {
        int number1 = Serial.parseInt();        // these variables should become global afterwards
        Serial.read();
        int number2 = Serial.parseInt();

        // you don't know what origin is yet so..
    }
    else if(ident == 'M')
    {
        int raAngle = Serial.parseInt();
        Serial.read();                              // These serial reads are for the separaters in the transmitted string
        int raDirection = Serial.parseInt();
        Serial.read();
        int dAngle = Serial.parseInt();
        Serial.read();
        int dDirection = Serial.parseInt();

        RightAscensionMotor(RA_freq, raAngle, raDirection);
        DeclinationMotor(DEC_freq, dAngle, dDirection);
    }

    // Serial.readbytes()
    Serial.read();      // this is to read the newline character out of the buffer.
}


// This needs to be called if 
// if(Osensor1 || Osensor2)
    // meridianFlip();
void meridianFlipT()
{
    float finalLocationRA, finalLocationD;
    byte RACheck = LOW; byte DCheck = LOW;
    Serial.println("F1");    // newline is already incorporated


    // Right so, RA is normal yea whatever, but Declination is made this way to allow the counter weight
    // to always be pointed away from the tripod. For the latitude is 0 at the pole.
    finalLocationRA = RightAscensionMotor(RA_freq, 180, !RA_track_DIR);
    finalLocationD = DeclinationMotor(DEC_freq, ((180 - DEC_degrees_from_home) * 2), !DEC_track_DIR);

    // This is going to check to see if both the motors have turned to their respective locations theres
    // a little buffer period that is inputted to just to see if the motor gets there. We can replaced this later on
    while(RACheck == LOW || DCheck == LOW)
    {
        if(RACheck == LOW && (finalLocationRA + 2 > RA_degrees_from_home && finalLocationRA - 2 < RA_degrees_from_home))
        {
            digitalWrite(RA_running, LOW); 
            RACheck = HIGH;
        }
        if(DCheck == LOW && (finalLocationD + 2 > DEC_degrees_from_home && finalLocationD - 2 < DEC_degrees_from_home))
        {
            digitalWrite(DEC_running, LOW); 
            DCheck = HIGH;
        }
        delay(10);
    }

    //Track();            // Resume Tracking
    Serial.println("F0");
}


// These two are just functions to move the motors with. Might have a 
// return to tell that its finished or something
float RightAscensionMotor(float freqspeed, float angularDistance, byte direction)
{
    Serial.print(freqspeed); Serial.print("RAfS "); Serial.print(angularDistance); Serial.print("RAaD "); Serial.println(direction);

    int finalLocation = 0;
    if(freqspeed == NULL && angularDistance != NULL)
        freqspeed = RA_freq;
    if(angularDistance != NULL)
    {
        if(direction == HIGH)
            finalLocation = RA_degrees_from_home + angularDistance;
        else
            finalLocation = RA_degrees_from_home - angularDistance;    
    }

    SetPinFrequency(RA_STEP, freqspeed);                 // Look at SetPinFrequencySafe()
    pwmWrite(RA_STEP, 128);
    digitalWrite(RA_DIR, direction);
    digitalWrite(RA_running, HIGH);                 // I think this just turns it on?

    return finalLocation;
}

float DeclinationMotor(float freqspeed, float angularDistance, byte direction)
{
    Serial.print(freqspeed); Serial.print("DEfS "); Serial.print(angularDistance); Serial.print("DEaD "); Serial.println(direction);

    int finalLocation = 0;
    if(freqspeed == NULL && angularDistance != NULL)
        freqspeed = DEC_freq;
    if(angularDistance != NULL)
    {
        if(direction == HIGH)
            finalLocation = DEC_degrees_from_home + angularDistance;
        else
            finalLocation = DEC_degrees_from_home - angularDistance;    
    }

    SetPinFrequency(DEC_STEP, freqspeed);
    pwmWrite(DEC_STEP, 128);
    digitalWrite(DEC_DIR, direction);
    digitalWrite(DEC_running, HIGH);

    return finalLocation;
}

void StopRAMotor()
{
    Serial.println("-RAMotor Stopped-");
    digitalWrite(RA_STEP, LOW);
    digitalWrite(RA_running, LOW);
}
void StopDECMotor()
{
    Serial.println("-DECMotor Stopped-");
    digitalWrite(DEC_STEP, LOW);
    digitalWrite(DEC_running, LOW);
}

Output from the Serial monitor after about 10 seconds

4
  • have you tried putting the code into setup() instead. It is made for things, that only should run once – chrisl Aug 28 '19 at 19:36
  • I totally could but that doesn't help me understand why this wouldn't work. (Btw i just did and it worked completely fine) @chrisl – Liro Aug 28 '19 at 19:39
  • Ahh sorry the F(freqspeed) was me just messing around with storing the data in the flash memory instead of the SRAM as i saw on some other threads.. I didn't have that during actual testing so i should've deleted it from this post. Thanks for the catch @juraj Edit: Its deleted now. – Liro Aug 28 '19 at 19:41
  • Yes that, AND the serial line inside of the if() inside of the loop function has a print out of the variable i, which constantly repeats it being 1. @Juraj – Liro Aug 28 '19 at 19:50
3

Here is my guess what happens:

Once the code in the if statement have run, the loop() only contains the incrementation of i. This will run very fast. After a rather short time (maybe someone here can make the calculation to get the time, that is needed) i will overflow, going from it's most positive value to it's most negative value, then incrementing further and finally reaching again 1. As this happens rather fast, you think, that i does not increment, but it is just flowing over again and again. i is of type int, which means, that it needs 65535 loop() iterations, to get to 1 again.

About the version with the extra Serial.print() calls: You didn't show us your setup(), but you probably have chosen a rather slow baudrate (maybe 9600, as it is used by many examples). At the first iterations the calls are just placing the data in the buffer and returning fast. But after a few iterations the Serial buffer is full. In this case the Serial.print()/Serial.write() functions (and their siblings) are blocking the code execution, until enough space in the buffer is free. So this would considerably slow down the executing of the loop(), thus considerably increasing the time between i overflows - to a point, where you don't wait long enough to actually see it overflow (but it will happen at some point).


To execute a code part only once you can either use the setup() function (if the call should happen at the start of the program), or you can use a simple flag. Imagine, that you don't increment i in the loop(), but that you are setting it's value to zero inside of the if statement. That would prevent the code in the if statement to execute again, until you yourself set i to 1 again.

byte flag = 0;

void setup(){
    flag = 1; // Set flag to 1 somewhere in your sketch as you like, to execute the if statement
}

void loop(){
    if(flag){
        //execute the wanted code here
        flag = 0; // deactivate this code by setting the flag to 0
    }
}

Notice, that I changed some things here:

  1. I changed the name of the variable to flag, because that's what it is: A simple flag with only 2 states - zero and non-zero

  2. I changed the type of the variable to byte, as you don't need a whole int (16 bits) for a simple flag. So I used the smallest variable type, a byte. (you could also use boolean here, but basically that's the same)

  3. The if statement now only checks for the value of flag directly. It will evaluate as true, if flag is not zero, as false, if it is zero. (So you could set flag to any other value than zero to activate the code, but true is also defined as 1, so I stayed in line with this).

  4. I set the flag back to zero inside the if statement, so that it will not be executed another time. It will only execute again, if you yourself set flag again to a non-zero value somewhere in your code.

11
  • Hmm thats interesing, but i don't get why then it wouldn't just skip some numbers at some point and be iterating slowly. However you gave me an idea for something that might be happening. So in other words, the buffer fills up with 8 prints and continues the loop. Once the loop reaches 1 again then it prints out the same 8 prints again which happen to be at i equals 1. This explains it printing out again every half a second. If this is the case, then making the variable i a double or something large should slow down the repeated print outs. – Liro Aug 28 '19 at 20:39
  • Im going to be putting a screenshot of the print out in the post – Liro Aug 28 '19 at 20:40
  • Also i just realized, then why is it that when I un-comment the Serial print line above the if() statement then the variable i gets properly incremented and outputed. – Liro Aug 28 '19 at 20:55
  • Can confirm, I did the opposite of that and made the variable i a byte, and now it prints out everything again a lot faster then before. Increasing it to a float makes it print out only one, but i did not wait nearly long enough to make up the for the numerical difference between an int and a float – Liro Aug 28 '19 at 21:00
  • The print in the if statement can only output i as 1, since it only executes, if i is one. So here you don't see if i increments. The increments happens outside of the if statement, so you can only see the incrementation, if you output i outside of the if statement. But just because you don't see it increment doesn't mean that it does not increment. – chrisl Aug 28 '19 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.