Why can't i divide?

I trying to get an percentage out, but can’t seem to get it out.

I seem to be printing the original integer value for some reason…

Could anyone explain why?

When i do

     status_step_count.data = (float)(profile.current_step_position/23400.0)*100;//(profile.current_step_position/23400)*100;

I get

status_step_count.data = int8
profile.current_step_position = volatile unsigned int

I would have like this to become 4 => but gets instead 1000… How come?

Look for post #10 for more information!!!

change your 100 to 100.0?

status_step_count.data = (float)(profile.current_step_position/23400.0)*100.0;

it doesn’t work… it still gives me 1000…

I even tried constrain which doesn’t work either…

I guess something is wrong with the code.

void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
  while(global_state == false)
  {
    //do nothing
    status_step_count.data = profile.current_step_position;
    chatter.publish( &status_step_count);
    nh.spinOnce();    
    moved_to_position = true;
    delay(1);

  }
  
    digitalWrite(en_pin,HIGH);
    delay(1);

    if (motor_steps < 0)
    {
      profile.dir = CCW;
      motor_steps = -motor_steps;
      digitalWrite(dir_pin,LOW);
    }
    else
    {
      profile.dir = CW;
      digitalWrite(dir_pin,HIGH);
    }
  
    delay(1);

    computation_of_speed_profile(motor_steps,motor_accel,motor_decel,motor_speed);
    
    OCR1A = 10;
    // Set Timer/Counter to divide clock by 8
    TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
      
      
    while(global_state == true)
    { int temp = 0; 
      cli();
      temp = profile.moved_steps;  // Keeping ISR disable shortest time possible
      sei();
      
      if(profile.dir == CCW)
      {
        profile.current_step_position -=  temp;
      }
      else
      {
        profile.current_step_position += temp;
      }
            
      //status_step_count.data = (float)(profile.current_step_position/23400.0)*100.0;//(profile.current_step_position/23400)*100; 
      status_step_count.data = (float)(profile.current_step_position/23400.0)*100.0;//map(profile.current_step_position,0,23400,0,100);
      chatter.publish( &status_step_count);
      
      if(moved_to_position == false) // Ensures that I am reading the newest variable
      {
        global_state = false;
      }
      
      nh.spinOnce();    
      delay(1);
    }     
}
  



  
ISR(TIMER1_COMPA_vect)
{
  // Holds next delay period.
  unsigned int new_first_step_delay;

  // Remember the last step delay used when accelrating.
  static int last_accel_delay;

  // Counting steps when moving.
  static unsigned int step_count = 0;

  // Keep track of remainder from new_step-delay calculation to incrase accurancy
  static unsigned int rest = 0;
  
  OCR1A = profile.first_step_delay;
  switch (profile.run_state)
  {
    
    case STOP:
      profile.moved_steps = step_count;
      step_count = 0;
      rest = 0;
      TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
      break;

    case ACCEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay) + rest) % (4 * profile.accel_count + 1);

      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_length;
        profile.run_state = DECEL;
      }

      // Chech if we hitted max speed.
      else if (new_first_step_delay <= profile.min_time_delay)
      {
        last_accel_delay = new_first_step_delay;
        new_first_step_delay = profile.min_time_delay;
        rest = 0;
        profile.run_state = RUN;
      }
      break;
    case RUN:
      digitalWrite(step_pin,!digitalRead(step_pin));
      
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      new_first_step_delay = profile.min_time_delay;
      // Chech if we should start decelration.
      if (step_count >= profile.decel_start) 
      {
        profile.accel_count = profile.decel_length;
        // Start decelration with same delay as accel ended with.
        new_first_step_delay = last_accel_delay;
        profile.run_state = DECEL;
      }
      break;
    case DECEL:
      digitalWrite(step_pin,!digitalRead(step_pin));      
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest)/(4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay)+rest)%(4 * profile.accel_count + 1);
      // Check if we at last step
      //digitalWrite(step_pin,!digitalRead(step_pin));
      if(profile.accel_count >= 0)
      {
        digitalWrite(en_pin,!digitalRead(en_pin));
        profile.moved_steps = step_count;  
        moved_to_position=true;
        profile.run_state = STOP;
      }
      
      break;
    
  }
    profile.first_step_delay = new_first_step_delay;  
      
    if(moved_to_position==true)
    {
        moved_to_position = false;
    }
}

What is the value of current_step_position just before that line?

I trying to get an percentage out, but can't seem to get it out.

I don't understand "out". Are you saying that after executing this line,

status_step_count.data = (float)(profile.current_step_position/23400.0)*100;

status_step_count.data is 1000 instead of what it should be?

What should it be? What actually is it? What is profile.current_step_position prior to executing this line? How do you know that?

Because my guesses are that
a) you are printing or using some other value that has nothing whatever to do with status_step_count.data; or
b) you are resetting status_step_count.data to 1000 after this calculation

Oh, PS:

status_step_count.data = profile.current_step_position/234.0f;

Actually, there's another possibility:

c) your math to calculate a percentage is wrong - you have too many zeros or not enough. Possibly, you are converting into a percentage twice and only displaying the trailing digits which are always zero.

With as many questions as you have asked in the last couple of days and as many times as you've been told this I can't believe I'm having to tell you again.

IF YOU WANT HELP POST ALL THE DAMNED CODE. The one or two lines don't tell enough to answer.

If you can't follow that simple instruction then you are far too stupid to write code. But I'm thinking it isn't like that. I bet you can manage to post your whole code. Or at least a program that can be compiled and exhibits the problem.

Maybe ask this guy - s/he seems to be having a similar problem.

Related: How do I ensure i am getting the newest input?

Hi,

 status_step_count.data = (float)(profile.current_step_position/23400.0)*100.0;

should be.

 status_step_count.data = ((float)profile.current_step_position/23400.0)*100.0;

Tom... :slight_smile:

Did you say:

status_step_count.data = int8

I don't see how that can be a float. or how it could be 1000, for that matter...

Sorry for not being clear about what my issues where related to the task i am trying to fulfill. I might have been a bit frustrated with some of the things, and ended up spamming different forums without thinking clearly.

The program Is controlling a stepper motor, which moves a ladder. The variable which i want to compute tells me how far the ladder is in percentage. The ladder is at 100% when the stepper motor has stepped 23400 steps.

The step variable is being increment in the ISR routine, in which the step signal for the motor is being sent.

The ISR Routine can be seen here. 

ISR(TIMER1_COMPA_vect)
{
  // Holds next delay period.
  unsigned int new_first_step_delay;

  // Remember the last step delay used when accelrating.
  static int last_accel_delay;

  // Counting steps when moving.
  static unsigned int step_count = 0;

  // Keep track of remainder from new_step-delay calculation to incrase accurancy
  static unsigned int rest = 0;
  
  OCR1A = profile.first_step_delay;
  switch (profile.run_state)
  {
    
    case STOP:
      profile.moved_steps = step_count;
      step_count = 0;
      rest = 0;
      TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
      break;

    case ACCEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay) + rest) % (4 * profile.accel_count + 1);

      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_length;
        profile.run_state = DECEL;
      }

      // Chech if we hitted max speed.
      else if (new_first_step_delay <= profile.min_time_delay)
      {
        last_accel_delay = new_first_step_delay;
        new_first_step_delay = profile.min_time_delay;
        rest = 0;
        profile.run_state = RUN;
      }
      break;
    case RUN:
      digitalWrite(step_pin,!digitalRead(step_pin));
      
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      new_first_step_delay = profile.min_time_delay;
      // Chech if we should start decelration.
      if (step_count >= profile.decel_start) 
      {
        profile.accel_count = profile.decel_length;
        // Start decelration with same delay as accel ended with.
        new_first_step_delay = last_accel_delay;
        profile.run_state = DECEL;
      }
      break;
    case DECEL:
      digitalWrite(step_pin,!digitalRead(step_pin));      
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest)/(4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay)+rest)%(4 * profile.accel_count + 1);
      // Check if we at last step
      //digitalWrite(step_pin,!digitalRead(step_pin));
      if(profile.accel_count >= 0)
      {
        digitalWrite(en_pin,!digitalRead(en_pin));
        profile.moved_steps = step_count;  
        moved_to_position=true;
        profile.run_state = STOP;
      }
      
      break;
    
  }
    profile.first_step_delay = new_first_step_delay;  
      
    if(moved_to_position==true)
    {
        moved_to_position = false;
    }
}

As the variable step_count is a static variable, it therefore only viewable inside the scope of the ISR, which is why i store the value in profile.moved_steps = step_count, such I can use it outside the scope;

Profile is an instantiation of the struct speed_profile, which is instantiated as a global variable and can be read anywhere.

The struct is defined as such:

typedef struct 
{
 volatile unsigned char run_state : 3; // Determining the state of the speed profile
 volatile unsigned char dir: 1; // Determining the direction the motor has to move - Start being CCW 
 volatile unsigned int first_step_delay; // Period time for the next timer_delay, determines the acceleration rate. 
 volatile unsigned int decel_start; //  Determines at which step the deceleration should begin. 
 volatile signed int decel_length; // Set the deceleration length
 volatile signed int min_time_delay; //minium time required time_delay for achieving the wanted speed.
 volatile signed int accel_count; // counter used when computing step_delay for acceleration/decelleration. 
 volatile unsigned int moved_steps; // Used by ros to publish current tipper position
 volatile unsigned int current_step_position; // contains the current step_position
 volatile unsigned int step_counter; //used for debug purpose

}speed_profile;

profile.moved_steps is being used to compute the percentage, it is constantly being published on a ros topic within this function.

void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
  while(global_state == false)
  {
    //do nothing
    status_step_count.data = profile.current_step_position;
    chatter.publish( &status_step_count);
    nh.spinOnce();    
    moved_to_position = true;
    //motor_steps = received_data  // not currently added for testing purposes
    delay(1);

  }
  
    digitalWrite(en_pin,HIGH);
    delay(1);

    if (motor_steps < 0)
    {
      profile.dir = CCW;
      motor_steps = -motor_steps;
      digitalWrite(dir_pin,LOW);
    }
    else
    {
      profile.dir = CW;
      digitalWrite(dir_pin,HIGH);
    }
  
    delay(1);

    computation_of_speed_profile(motor_steps,motor_accel,motor_decel,motor_speed); // function should be called with the correct motor_steps value
    
    OCR1A = 10;
    // Set Timer/Counter to divide clock by 8
    TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
      
      
    while(global_state == true)
    { int temp = 0; 
      cli();
      temp = profile.moved_steps;  // Keeping ISR disable shortest time possible
      sei();
      
      if(profile.dir == CCW)
      {
        profile.current_step_position -=  temp;
      }
      else
      {
        profile.current_step_position += temp;
      }
            
      status_step_count.data = ((float)(profile.current_step_position/23400.0))*100.0;
      chatter.publish( &status_step_count);
      
      if(moved_to_position == false) // Ensures that I am reading the newest variable
      {
        global_state = false;
      }
      
      nh.spinOnce();    
      delay(1);
    }     
}

Which switch between two thread (One where global_state = state or false).
The status of the global_state becomes true, when a ros node send a message to it to the topic it subscribes from, and after the motor has moved will the global_state return to the false state and wait for outside message.

void call_back( const std_msgs::Empty & msg)
{
  global_state = true;

}

ros::Subscriber<std_msgs::Empty> sub("tipper_control", &call_back );

So the problem is when i want to compute the percentage

status_step_count.data = ((float)(profile.current_step_position/23400.0))*100.0;

It seems like the the calculations does not have any effect. It keeps returning the number of steps the motor has moved in steps rather in the percentage? - which i quite unsure why is the case.

The full code is attached here…

speed_profile.h (2.37 KB)

speed_profile.cpp (8.95 KB)

main.ino (520 Bytes)

I seem to have resolved the issue.
Aparrently is the placement of the where i read the variable in the ISR very important.
Placing it where i had it before blocks it for being processed, or somehow blocked such that no math could be used.

So i placed it somewhere else, and now have the problem that i am not having the most current value, but the an older value.

You probably forgot a volatile declaration, forgot to read the volatile with interrupts disabled in the
main code, or tried to use Serial.print in the ISR which can lock up - never use Serial or delay() in
an ISR, they cannot proceed. I'm not sure declaring fields volatile in a typedef is meaningful, its
the actual variable that should be annotated that way, since volatility is a property of the storage
location, not the type.

It is not the volatile, i just changed step_count to be a volatile static unsigned int and it still performs that way.

Adding that makes both the variable volatile.

I mean the variable 'profile' which is not volatile but which you access in the ISR.

i changed profile to be volatile, and it still does the same thing…

Best to post your full code as it is now and people can then check it out properly.

The code as it now looks like this…

speed_profile.h (2.37 KB)

speed_profile.cpp (8.86 KB)

main.ino (521 Bytes)

215_215:
I seem to have resolved the issue.
Aparrently is the placement of the where i read the variable in the ISR very important.
Placing it where i had it before blocks it for being processed, or somehow blocked such that no math could be used.

So i placed it somewhere else, and now have the problem that i am not having the most current value, but the an older value.

Also asked here