CCS does not monitor this forum on a regular basis. Please do not post bug Reports on this forum. Send them to support@ccsinfo.com
 Reversing Direction in For() statement Goto page 1, 2  Next
Author Message
rovtech

Joined: 24 Sep 2006
Posts: 258

Reversing Direction in For() statement
Posted: Wed Jul 15, 2020 2:18 pm

I need to drive a stepper motor and graphic sweep in sync.
Integer i is used to calculate angles and step sets.
Running CCW I can use:
 Code: for(i=0; i<20; i++)      // 0 to 19, total 20  {    // code here same as running forward  }

Running CW this works:
 Code: for(i=19; i>=0; i--)      // 19 to 0, total 20 // for(i=20; i>0; i--)      // 20 to 1, total 20  {    // code here same as running backward  }

Note that the line commented out will mess up i for the following code in the CW direction.
How can I write this using a simple
 Code: if(direction)  {run CCW} else  {run CW}

to select the correct loop where direction is just a one bit flag.
I also need to use other start and stop points between 0 and 180 degrees
This (partial) code is an example that works but I don't want to repeat a whole lot of identical code. I can use a function if I use global variables or it becomes complicated.
 Code: for (i=7;i<15;i++)          // lines to be drawn CCW   {     angle=i*.175;               // 10i deg converted to radians     xx=63*cos(angle);       // use floating     x=63+xx;                    // but convert to integer     xx=63*sin(angle);       // 63 is the radius     y=63-xx;     draw_line(63,63,x,y);   // start bottom middle,                                       // the LCD has 0,0 top left   }

This section of code will become more complicated as only sections, or none, of the line will be drawn representing echos from sonar.
Don't worry about the code, it works. I need a suggestion on how to deal with the general challenge of changing direction. I cannot easily use a start and stop integer in the for() statement unless math is allowed as in
 Code: for(i=stop-1; i>=start; i--)
Mike Walne

Joined: 19 Feb 2004
Posts: 1782
Location: Boston Spa UK

 Posted: Wed Jul 15, 2020 2:46 pm Will something along the lines of (not in CCS code):- if i> stop then i = start; if i< start then i =stop; Someone here may have a clever way of reducing it one line of code. Mike
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Wed Jul 15, 2020 2:49 pm

Maybe something similar to how I reverse the motor
 Code: // Step the motor 10 degrees, 25 steps    for(j=0;j<25;j++)    {    if (direction)            // CW     {      if (n == 4)       n=0;      else       n++;     output_c (step[n]);     }    else                     // CCW     {     if (n == 0)      n=4;     else      n--;     output_c (step[n]);     }     delay_ms(10);    }

This sequences thru a pattern of 4 codes a number of times to turn 10 degrees forward of backward.

Edit: No this still duplicates the code but in this case it is only one line so does not matter.
I tried to mirror x as in
 Code: if(direction)     x=63+xx;    else     x=63-xx;

but it does not redraw the same sector in reverse, it just flips it left to right.
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Wed Jul 15, 2020 6:16 pm

I found a way to do it. I just had to think differently. Sorry for wasting anyone's time.
 Code: // set start and stop  i=start;  while(1)  {   for (k=start;k<=stop;k++)          // lines to be drawn   { // LCD Stuff      angle=i*.175;          // 10 deg/scan, convert to radians     xx=64*cos(angle);    // 63 is radius of scan lines     x=63+xx;     xx=64*sin(angle);    // xx is floating point     y=63-xx;                 // converted to integer     draw_line(63,63,x,y);    // LCD function // Step the motor 10 degrees, 24 steps    for(j=0;j<25;j++)     // geared stepper motor    {    if (direction)            // CW     {      if (n == 4)       n=0;      else       n++;     output_c (step[n]);     // step codes     }    else               // CCW     {     if (n == 0)      n=4;     else      n--;     output_c (step[n]);     }     delay_ms(20);               // time for stepper motor    } // set i according to direction, keep within start/stop    if(direction)    {     i++;     if(i>stop)      i=stop;    }     else    {     i--;     if(i

There is a slight problem that start cannot be 0 unless i is a signed integer.
start and stop reset was wrong, now corrected

Last edited by rovtech on Thu Jul 16, 2020 1:49 pm; edited 1 time in total
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Thu Jul 16, 2020 1:48 pm

When i=0 in the code below, why does y end up being 62 instead of 63?
angle is float and so is xx. So when i is 0, angle should be 0, sin(0) is 0, so xx should be 0, and 63-0 should be 63, not 62.
Am I wrong in using this to convert floating to integer?
 Code: // LCD Stuff      angle=i*.175;          // 10 deg/scan, convert to radians     xx=64*sin(angle);    // xx is floating point     y=63-xx;                 // converted to integer, add offset     draw_line(63,63,x,y);    // LCD function

I have to be careful of my units. For the coordinates the LCD is 0 to 63 but for the radius length to use in the equations it is 64.
The LCD is mapped 0,0 at top left so I have to add 63 to x and subtract y from 63 to get to the locations in normal coordinates.
Mike Walne

Joined: 19 Feb 2004
Posts: 1782
Location: Boston Spa UK

 Posted: Thu Jul 16, 2020 2:27 pm Try printing out the values of all variables which change as you go line by line through the code. Should tell you where the error is! Mike
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Thu Jul 16, 2020 3:03 pm

Thats how I found the problem, xx displayed in float is 0.00 and y is displayed in integer as 0.
If I plug in 0 for xx I get 63-0=63.
With the program the way it is above I get 63-y=62.
C promotes the right side float to the left side integer I thought, and it seems to do that.

Edit: actually I get 0.004 for xx going one way, as i is incremented, and 0.00 going the other way.
As i changes from 0,1,2 then 2,1,0 these values for xx are displayed consistently.

0.00
11.14
21.94
21.94
11.14
0.004
0.00 etc

This is how I display on the LCD:
 Code: angle=i*.175;               // 10 deg = 0.175 radians     xx=64*cos(angle);           // x in floating point     x=63+xx;                    // convert x to integer, add offset     xx=64*sin(angle);           // y in floating point   text_position(0,0);          // line, column   sprintf(buff, "xx = %f", xx);   send_str(buff);   delay_ms(1500);             // for testing     y=63-xx;                    // convert y to integer, add offset     draw_line(63,63,x,y);       // draw line from bottom center of LCD

and I move below "y=63-xx;" and adjust to display y in integer format.
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Thu Jul 16, 2020 6:32 pm

If 64*sin(0) = 0.004 then 63-0.004 = 62.996
When 62.996 is promoted to integer is the fractional part just dropped giving 62?
That does not make much sense. How do I round a small number to 0?
 Code: i=0     angle=i*.175;               // 10 deg = 0.175 radians     xx=64*sin(angle);           // y in floating point     n=xx;                         // to drop the fractional part     y=63-n;                    // convert y to integer, add offset     draw_line(63,63,x,y);       // draw line from bottom center of LCD

now I get for y compared to the original calculation in the second column and fraction dropped in the third column
63 62.996 62
52 51.86 51
42 41.06 41
that seems to be what is happening. sin(0) is resulting in a very small number but a big error when used then promoted to integer.
this is really dumb! There has to be a better way.
PCM programmer

Joined: 06 Sep 2003
Posts: 21508

Posted: Thu Jul 16, 2020 7:07 pm

The program below will display the following in MPLAB vs. 8.92 simulator:
 Quote: value = -63 value = 63

Test program:
 Code: #include <18F46K22.h> #fuses NOWDT  #use delay(internal=4M) #use rs232(UART1, baud=9600, ERRORS) #define round(x) (signed int16)(x<0.0 ? x-0.5 : x+0.5) //================================= void main() { float temp = -62.996; printf("value = %ld \r", round(temp)); temp = 62.996; printf("value = %ld \r", round(temp)); while(TRUE); }
rovtech

Joined: 24 Sep 2006
Posts: 258

 Posted: Fri Jul 17, 2020 7:47 am Thanks PCM programmer. I looked for a rounding function in several of my C books including K&R and it is not in any index. Casting and Promoting are in the index but no Round. I just found it by googling but that should not be where to find it. Maybe we should all throw our books out. https://fresh2refresh.com/c-programming/c-arithmetic-functions/c-round-function/ No wonder the Boeing 737 Max are crashing and please, everyone, don't trust those auto features on your car. My auto braking in cruise control works most of the time but not always. Same with lane keeping and other alerts.
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Fri Jul 17, 2020 9:01 am

OK, I'm stupid. I cannot get round() to work. I tried all the variations below and get
"Error 12 "Scanning Sonar.c" Line 91(13,14): Undefined identifier -- round"

 Code: xx=64*sin(angle);           // y in floating point     xx=round(64*sin(angle));     round(xx)=64*sin(angle);     xx=round(xx);     y=63-xx;                    // convert y to integer, add offset

How am I supposed to use it?
My program has #include <math.h>
Maybe this function does not exist in PCM. I don't see it in the manual.
I just saw your
 Code: #define round(x) (signed int16)(x<0.0 ? x-0.5 : x+0.5)

What is all that about? I will have to study on it.
I was looking at the google reference on how to use it. I cannot find it in my books.
PCM programmer

Joined: 06 Sep 2003
Posts: 21508

 Posted: Fri Jul 17, 2020 10:12 am Do you understand #define statements ? Just copy and paste that line above main() in your program. You've been on this forum since 2006. How can you don't know this ?
rovtech

Joined: 24 Sep 2006
Posts: 258

Posted: Fri Jul 17, 2020 11:21 am

Give me a break I'm 80 years old and not a professional programmer.
Sure I could do that but I don't understand it and it may not work, although it seems to.
What I am understanding is that
1. The function round() does not exist for the CCS C compiler, and maybe not in the K&R definition, so you wrote one
2. Google shows round() as a regular function so it must exist for some compilers.
3. In the function you created round(x) is replaced with (signed int16)(x<0.0 ? x-0.5 : x+0.5)
which means
 Code: if(x<0)  x=x-0.5 else  x=x+0.5

then cast it to a 16 bit signed integer?? I don't understand the () () pair of brackets together. I have not run into that.
So it will do this for a floating point number? Yes it appears to
I am using 8 bit integers so I changed to int8 and it still works.
I appreciate the help but I do like to understand what I'm doing
So my code is now working
 Code: #define round(x) (signed int8)(x<0.0 ? x-0.5 : x+0.5)     angle=i*.175;               // 10 deg = 0.175 radians     x=63+round(64*cos(angle));  // calculate x, convert to integer, add offset     y=63-round(64*sin(angle));  // calculate y, convert to integer, add offset     draw_line(63,63,x,y);       // draw line from bottom center of LCD
gaugeguy

Joined: 05 Apr 2011
Posts: 201

 Posted: Fri Jul 17, 2020 11:49 am Programming and C aside: When converting a float number to an integer there are different methods. One is truncating. Anything after the decimal point is dropped and only the whole number remains. Another method is to do rounding. There are different forms of rounding but the most common is if the decimal portion is 0.5 or larger then the number goes to the next higher integer, if the decimal portion is less than 0.5 then the decimal portion is discarded, or truncated. One way to implement this type of rounding is to add 0.5 to the number before truncating the decimal portion.
Ttelmah

Joined: 11 Mar 2010
Posts: 17478

 Posted: Fri Jul 17, 2020 12:16 pm It casts the result into a signed int8. This truncates. The 'result' is the result of if the value is <0, it subtracts 0.5 from this. otherwise it adds 0.5. So if you start with a float value of (say) 1.4, 0.5 is added to give 1.9, then you get 1 as the integer.. If howver you have 1.5, 0.5 added gives 2.0, which then truncates to '2'. Similarly, -0.5 has 0.5 subtracted, so gives -1 after the truncation, while -0.4, still gives 0.
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT - 6 HoursGoto page 1, 2  Next Page 1 of 2

 Jump to: Select a forum Software----------------General CCS C DiscussionCode LibraryEZ App LynxBest OfKnown Issues Hardware----------------CCS ICD / Mach X / Load-n-Go
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum