Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Reading the latest value from incremented in ISR

Status
Not open for further replies.

kidi3

Full Member level 1
Joined
Mar 31, 2013
Messages
98
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
2,350
I at the moment trying to extract a value that gets incremented inside of a ISR, but can't seem to get the final value, or the correct value.
here is the code:

How do i extract the newest value from the ISR?

code example:

Code:
 volatile speed_prof profile;
    bool activate = false;
    void process(int a)
    { 
      // do something
    }
    void loop()
    { 
       while(activate == false)
       { 
         process(profile.moved_steps);
       } 
       
       OCR1A = 10;
       // Set Timer/Counter to divide clock by 8
       TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
       
       while(activate == true)
       {
          cli();
          int temp = profile.moved_steps;
          sei();
          process(profile.moved_steps);
       }
    }
    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;
    
      static unsigned int rest = 0;
      OCR1A = profile.first_step_delay;
      switch (profile.run_state)
      {
    
        case STOP:
          activation = false;
          rest = 0;
          TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
          break;
    
        case ACCEL:
          profile.moved_steps++;
          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);
    
          if(profile.moved_steps >= profile.decel_start)
          {
            profile.accel_count = profile.decel_length;
            profile.run_state = DECEL;
          }
          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:
          profile.moved_steps++;
          new_first_step_delay = profile.min_time_delay;
          if (profile.moved_steps >= profile.decel_start)
          {
            profile.accel_count = profile.decel_length;
            new_first_step_delay = last_accel_delay;
            profile.run_state = DECEL;
          }
          break;
        case DECEL:
          profile.moved_steps++;
          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);
          if (profile.accel_count >= 0)
          {
             profile.run_state = STOP;
          }
    
          break;
      }
      profile.first_step_delay = new_first_step_delay;  
    }


And outside component changes the state of the bool activate, and depending of the state of activate variable would the the function `process` provide a certain output. Problem is that when `Activate = true` , process isn't outputting the wanted value, I know the value it has to be, and have confirmed it using serial monitor which should be 1000, but the output i am receiving is 991. I tested the value with serial.print inside the ISR and have seen that the last value it becomes is 1000. So I am not able to get the last value.. what am I doing wrong?
 

I don't use C for microcontrollers, but I don't see where you've declared your variables. Make sure they're declared globally so that their values are accessible everywhere.
 

Makes no sense:
Code:
cli();
int temp = profile.moved_steps;
sei();
process(profile.moved_steps);

did you mean
Code:
process(temp);

I don't see a particular fault. I guess you are seeing the correct actual value, but probably from a time different than expected.
 

Variables used by interrupt must be volatile (avoiding optimizing them out by the compiler). You permanently (in the loop) initialize your timer. You always set OCR1A to 10. Your interrupt will never trigger (as you do not set timer to trigger any interrupts). Your process() call is not atomic - the value of the profile.moved_steps can change during the call etc etc. You should reconsider the program logic first.
 

I choose not to post the full code, as it would just cause confusing.. but can see that i might need to post it.

- - - Updated - - -

Here is the full code:

.cpp


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#include "speed_profile.h"
 
 
speed_profile profile;
 
ros::NodeHandle nh;
 
std_msgs::Int16 status_step_count;
ros::Publisher chatter("tipper_status", &status_step_count);
 
bool global_state = false;
bool moved_to_position = true;
int received_data = 0;
void call_back( const std_msgs::Empty & msg)
{
  global_state = true;
  // For HMI
  // received_data  = msg.data
 
}
 
ros::Subscriber<std_msgs::Empty> sub("tipper_control", &call_back );
 
void output_pin_setup()
{
  pinMode(en_pin,OUTPUT);
  pinMode(dir_pin,OUTPUT);
  pinMode(step_pin,OUTPUT); 
  nh.initNode();
  nh.advertise(chatter);
  nh.subscribe(sub);
  profile.moved_steps = 0;
  profile.current_step_position = 0;
  delay(1000);
  nh.getHardware()->setBaud(57600);
 
  
}
 
void timer1_setup()
{
  // Tells what part of speed ramp we are in.
  profile.run_state = STOP;
 
  // Timer/Counter 1 in mode 4 CTC (Not running).
  TCCR1B = (1 << WGM12);
 
  // Timer/Counter 1 Output Compare A Match Interrupt enable.
  TIMSK1 = (1 << OCIE1A);
}
 
void computation_of_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
    unsigned int steps_to_speed;  // Steps required to achieve the the speed desired
    unsigned int acceleration_step_limit; // If desired speed is not achieved, will this variable contain step_limit to when to stop accelerating.
  // If moving only 1 step.
    if (motor_steps == 1)
    {
    // Move one step
      profile.accel_count = -1;
    // in DECEL state.
      profile.run_state = DECEL;
    // Just a short delay so main() can act on 'running'.
      profile.first_step_delay = 1000;
      OCR1A = 10;
    // Run Timer/Counter 1 with prescaler = 8.
      TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
    }  
    else if (motor_steps != 0)
    {
    // Set max speed limit, by calc min_delay to use in timer.
    // min_delay = (alpha / tt)/ w
      profile.min_time_delay = A_T_x100 / motor_speed;
 
    // Set accelration by calc the first (c0) step delay .
    // first_step_delay = 1/tt * sqrt(2*alpha/accel)
    // first_step_delay = ( tfreq*0.676/100 )*100 * sqrt( (2*alpha*10000000000) / (accel*100) )/10000
      profile.first_step_delay = (T1_FREQ_148 * sqrt(A_SQ / motor_accel)) / 100;
 
    // Find out after how many steps does the speed hit the max speed limit.
    // steps_to_speed = speed^2 / (2*alpha*accel)
      steps_to_speed = (long)motor_speed * motor_speed / (long)(((long)A_x20000 * motor_accel) / 100);
    // If we hit max speed limit before 0,5 step it will round to 0.
    // But in practice we need to move atleast 1 step to get any speed at all.
      if (steps_to_speed == 0) 
      {
        steps_to_speed = 1;
      }
 
      // Find out after how many steps we must start deceleration.
      // n1 = (n1+n2)decel / (accel + decel)
      acceleration_step_limit = ((long)motor_steps * motor_decel) / (motor_accel + motor_decel);
      // We must accelrate at least 1 step before we can start deceleration.
      if (acceleration_step_limit == 0) 
      {
        acceleration_step_limit = 1;
      }
 
      // Use the limit we hit first to calc decel.
      if (acceleration_step_limit <= steps_to_speed) 
      {
        //profile.decel_length = steps_to_speed - motor_steps;
        profile.decel_length = -(motor_steps-acceleration_step_limit); //---
      }
      else 
      {
        //profile.decel_length = -((long)steps_to_speed * acceleration_step_limit) / motor_decel;acceleration_step_limit
        profile.decel_length = -((long)steps_to_speed * motor_accel) / motor_decel; //--
      }
      // We must decelrate at least 1 step to stop.
      if (profile.decel_length == 0) 
      {
        profile.decel_length = -1;
      }
 
      // Find step to start decleration.
      //int steps_in_run = motor_steps - steps_to_speed-profile.decel_length;
    
      profile.decel_start = motor_steps + profile.decel_length;
    //profile.decel_start = motor_steps - steps_to_speed-steps_in_run;
    
    // If the maximum speed is so low that we dont need to go via accelration state.
      if (profile.first_step_delay <= profile.min_time_delay)
      { 
        profile.first_step_delay = profile.min_time_delay;
        profile.run_state = RUN;
      }
      else
      {
        profile.run_state = ACCEL;
      }
  
    // Reset counter.
      profile.accel_count = 0;
      //profile.step_counter = steps_to_speed;
    }
}
 
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;//(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;
    }
}



.h


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
 * Contains the class concerning with calculating the proper speed profile 
 * for accelerating and decelerating the stepper motor.
 * 
 */
 
#ifndef speed_profile_h
#define speed_profile_h
 
 
#include <Arduino.h> 
#include <ros.h>
#include <std_msgs/Int16.h>
#include <std_msgs/Empty.h>
// Timer/Counter 1 running on 3,686MHz / 8 = 460,75kHz (2,17uS). (T1-FREQ 460750)
//#define T1_FREQ 460750
#define T1_FREQ 1382400
 
//! Number of (full)steps per round on stepper motor in use.
#define FSPR 1600
 
// Maths constants. To simplify maths when calculating in compute_speed_profile().
#define ALPHA (2*3.14159/FSPR)                    // 2*pi/spr
#define A_T_x100 ((long)(ALPHA*T1_FREQ*100))     // (ALPHA / T1_FREQ)*100
#define T1_FREQ_148 ((int)((T1_FREQ*0.676)/100)) // divided by 100 and scaled by 0.676
#define A_SQ (long)(ALPHA*2*10000000000)         // ALPHA*2*10000000000
#define A_x20000 (int)(ALPHA*20000)              // ALPHA*20000
 
// Speed ramp states
#define STOP  0
#define ACCEL 1
#define DECEL 2
#define RUN   3
 
// Pin numbering
#define en_pin 13
#define dir_pin 12
#define step_pin 11
 
// Motor direction 
#define CW  0
#define CCW 1
 
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;
 
 
void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void computation_of_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void timer1_setup(void);
void output_pin_setup(void);
#endif





main

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "speed_profile.h"
 
 
void setup() {
  // put your setup code here, to run once:
  cli();
  output_pin_setup();
  timer1_setup();
  sei();
}
 
void loop() 
{
      int motor_steps = 1000;//-9600; //23400 -  100%
      // Accelration to use.
      int motor_acceleration = 500;//500;
      // Deceleration to use.
      int motor_deceleration = 500;//500;
      // Speed to use.
      int motor_speed = 1000; // 1000
      compute_speed_profile(motor_steps, motor_acceleration, motor_deceleration, motor_speed); 
}



I wasn't able to attach the files somehow...
 
Last edited:

Post the code here with syntax tags.

Syntax tag = syntax=c in square brackets and then code and then /syntax in square brackets.

Post all the three codes separately.
 

should be fixed now.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top