1

I am using a PIC to control a 28BYJ-48 stepper motor using a ULN2003 driver board. I have found a code that works perfectly but trying to understand what one line of code is doing.

Having searched I have not come across this being raised in the past. I am a new comer to C programming and learning from other peoples code. I came across this in a code which works as I would expect it to.

if(Wait > 0) /* Wait is set in the void main void which calls this in the function*/
{
    delay = Wait;  /*delay takes the value of wait*/
    do {
       while(INTCONbits.T0IF == 0) {} 
       INTCONbits.T0IF = 0;
    } while (--delay > 0);
}

The while (--delay > 0);.

Has me stumped as the delay is taken from a know value and passed into a function call so what does the -- have to do with it.

I know is some languages its used to decrement the variable either after it has been read but as far as I am aware the value is not being lowered.

Any help or pointer would be appreciated.

Edited to show more of the code.

void StepMotor(int16_t Count, uint8_t Wait)
{
    static uint8_t state = 0;
    /*  values for half step             0001, 0011, 0010, 0110, 0100, 1100, 1000, 1001*/
    static const uint8_t HalfSteps[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09};
    uint8_t delay;

    do
    {
        if (Count > 0)
        {
            PORTC = HalfSteps[state];   /* drive stepper to select state */
            state++;                    /* step one state clockwise */
            state &= 0x07;              /* keep state within HalfStep table */
            Count--;                    /* update step count */
        }
        else if (Count < 0)
        {
            PORTC = HalfSteps[state];  /* drive stepper to select state */ 
            state--;                   /* step one state counterclockwise */ 
            state &= 0x07;             /* keep state within HalfStep table */ 
            Count++;                   /* update step count */ 
        }
        /* Wait between steps */
        if(Wait > 0) /* Wait is set in the void main void which calls this in the function*/
        {
            delay = Wait;  /*delay takes the value of wait*/
            do {
               while(INTCONbits.T0IF == 0) {} 
               INTCONbits.T0IF = 0;
            } while (--delay > 0);
        }
    } while (Count != 0);
}

void main(void) 
{
    /*
     * Application initialization
     */
    Init_PIC();
    /*
     * Application process loop
     */
    while(1)
    {
        StepMotor(4076, 4);     /* step about 1/2 a revolution clockwise at 4.096 milliseconds per step (about 8 seconds) */
        __delay_ms(1000);
        StepMotor(-2038, 2);    /* step about 1/2 a revolution counterclockwise at 2.048 milliseconds per step (about 4 seconds) */
        __delay_ms(1000);
        StepMotor(-2038, 2);    /* step about 1/2 a revolution counterclockwise at 2.048 milliseconds per step (about 4 seconds) */
        __delay_ms(1000);
    }
}

Maybe this is more helpful to get an answer to my question what is the "while (--delay > 0); "

doing.

johnnyh20
  • 71
  • 6
  • "as far as I am aware the value is not being lowered" why? Did you check that with a debugger? – MikeCAT Mar 17 '23 at 12:53
  • 1
    If you learn from other people's code (as opposed to [books](https://stackoverflow.com/q/562303/11683)), how do you know that the code you learn from is good? How do you decipher the basic language elements such as `--` or `while`? Do you just assume what they do and come up with some rules of your own which you then stick to?.. – GSerg Mar 17 '23 at 12:53
  • 1
    Please clarify your question, it's not really clear what you're asking. Do you understand how pre-decrement and post-decrement work in C and how they can be used in the conditions for loops and if statements? – saxbophone Mar 17 '23 at 12:55
  • "value and passed into a function call" There is no function call shown in your code. Those brackets enclose the condition of your loops. No function is called, no parameters are passed here. – Gerhardh Mar 17 '23 at 13:34
  • MikeCat At the moment I do not know how to use that part of programming the PIC16F676 chip or if the debugger even works with it. – johnnyh20 Mar 17 '23 at 13:42
  • GSerg I am looking for a good book that covers Microchip programming written in C but maybe that is the right way to go. I am always open minded and when I use other peoples code I try to make sure I have understood what they are doing and if require change parts if required. So do you have the answer to the question or not? – johnnyh20 Mar 17 '23 at 13:46
  • Hi Saxbphone I have the basic understanding of pre-decrement and post-decrement work in C when used in a for loop. But this does not seem to be used in that way. – johnnyh20 Mar 17 '23 at 13:49
  • Gerhardh I have added the extra code to my original question so maybe that will help with an explanation. – johnnyh20 Mar 17 '23 at 13:55
  • You can use pre- and post decrementation anywhere, it is not something limited to for loops. Basically `a++;` is equivalent to `a = a + 1;`. You really need to learn the basics of C first, get some beginner's book, read it and do the exercises – Jabberwocky Mar 17 '23 at 14:03
  • 2
    @johnnyh20, your question is not being well received because `--` is a well-known C operator. Any C textbook or introductory C course, including online ones, would cover it early on. Our perception, therefore, is that you are not putting in the appropriate kind or amount of work to learn a new language. – John Bollinger Mar 17 '23 at 14:04
  • Thank you everyone who have commented and I will accept the answer given by EvilTeach. It maybe a very basic part of C but its the first time I have come across it in this way. So it was worth asking to confirm the answer. I will carry on with my journey into PIC programming which so far has gone very well. as can be seen by the work I have done so far ref https://www.youtube.com/playlist?list=PL2Mz1GBib5Av_d1pUuTq7zQki3rvrgMcg – johnnyh20 Mar 17 '23 at 14:27
  • I have now been going through a number a Youtube tutorials for beginners into C and yes they gave me a better understanding of -- and ++ also the 3 different loop methods. The main thing for me is the time people have spent actually helping me with what was a basic thing to some people is so valuable in helping other who may read this thread in the future. The examples that have been made available using the different loops has enriched my knowledge for sure. Would I have learnt this from a book? PIC programming is a mind field and the small steps I make is getting me up the long learn curve. – johnnyh20 Mar 18 '23 at 12:00
  • Thanks to all the assistance of members here I have now cracked a lot more knowledge and hopefully learnt some of the XC8 compiler requirement. Shows what a bit of studying can do for you. – johnnyh20 Mar 22 '23 at 23:26

7 Answers7

3

It decrements the delay value, then checks to see if the value is still greater than zero. If it is, the body of the loop executes again.

EvilTeach
  • 28,120
  • 21
  • 85
  • 141
2

The test (--delay > 0) first decrements delay and compares the result with 0. The do/while loop iterates delay times exactly if it is entered with a value of delay that is > 0, hence the initial test if (Wait > 0) {

These do / while loops are confusing and error prone.

The first fragment in the question is more readable as:

    for (delay = 0; delay < Wait; delay++) {
        while (INTCONbits.T0IF == 0)
            continue;
        INTCONbits.T0IF = 0;
    }

Or possibly:

    for (delay = Wait; delay > 0; delay--) {
        while (INTCONbits.T0IF == 0)
            continue;
        INTCONbits.T0IF = 0;
    }

Similarly, because of the do/while loop, in the StepMotor, the function will wait even if the initial value of Count is 0, which seems unnecessary since the step motor does not move at all.

Here is an alternative:

void StepMotor(int16_t Count, uint8_t Wait) {
    static uint8_t state = 0;
    /*  values for half step             0001, 0011, 0010, 0110, 0100, 1100, 1000, 1001*/
    static const uint8_t HalfSteps[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09};
    uint8_t delay;

    while (Count != 0) {
        if (Count > 0) {
            Count--;                   /* update step count */
            PORTC = HalfSteps[state];  /* drive stepper to select state */
            state++;                   /* step one state clockwise */
            state &= 0x07;             /* keep state within HalfStep table */
        } else {
            Count++;                   /* update step count */ 
            PORTC = HalfSteps[state];  /* drive stepper to select state */ 
            state--;                   /* step one state counterclockwise */ 
            state &= 0x07;             /* keep state within HalfStep table */ 
        }
        /* Wait between steps */
        for (delay = Wait; delay > 0; delay--) {
            while (INTCONbits.T0IF == 0)
                continue;
            INTCONbits.T0IF = 0;
        }
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    Chqrlie I have tested this also and yes it works also Thank you for taking the time to come up with this possible solution. Its all getting noted and added to my note book. – johnnyh20 Mar 17 '23 at 22:02
  • This `for (delay = Wait; delay-- > 0;) {` seems not a clear way to use the `for` statement. A better way would be `for (delay = Wait; delay > 0; delay--) {` as the `for` statement uses three expressions to control the behavior. The "setup", "conditional" and "iterate" expressions. – Dan1138 Mar 17 '23 at 23:13
  • @Dan1138: for this particular case, you are correct because `delay` is not used inside the loop body. Answer amended. When iterating `i` from the last index to the first index of an array the `for (i = len; i-- > 0;)` is a useful idiom that works for both signed and unsigned types. – chqrlie Mar 17 '23 at 23:22
  • 1
    I am over whelmed by the great solutions that have been shown by you both and I can assure you it has not been time wasted. – johnnyh20 Mar 18 '23 at 12:03
1

--i is close to i --, or i = i - 1.

Although, it has differences! E.g.: (in this case)
while(i-- > 0) something(); is close to: while(i > 0) { i --; something(); }, but
while(--i > 0) something(); is close to: i --; while(i > 0) { something(); i --; }.

I'm sure there are some other weird differences between them, you can just look up pre-increment & post-increment, as was already suggested by Saxbophone.

while(--i > 0); simply decrements the value of i until it reaches 0.
do; while(--i > 0); does everything, then decrements i, so it loops until i reaches 0, however i is only 0 after the loop, minimum i inside of the loop is 1.

int i = 4; // uint8_t and int are SIMILAR
do {
  printf("%d, ", i);
} while(--i > 0);
printf("after: %d", i);

outputs: 4, 3, 2, 1, after: 0.

uint8_t is unsigned 8 bit integer. In this case, unsigned means the number is ALWAYS positive, it doesn't have minus sign.

Ulti
  • 514
  • 3
  • 5
1

Let's do it another way, I hope that will help.

if(Wait > 0) /* Wait is set in the void main void which calls this in the function */
{
    delay = Wait;  /* delay takes the value of wait */
    do {
        while(INTCONbits.T0IF == 0) {} 
        INTCONbits.T0IF = 0;
        delay = delay - 1;
    } while (delay > 0);
}
Toni
  • 3,296
  • 2
  • 13
  • 34
Huafeng Yu
  • 11
  • 3
  • Thank you so much Huafeng That hit the nail on the head for me. I am aware I really need to go back to night school and try and get on with some of the basic at 62 learning some of this has been a good experience. I am now able to move on and do more with the help of a few members who have taken the time to give a valid solution to maybe a stupid question in the first place. A big thank you again. – johnnyh20 Mar 17 '23 at 16:57
  • Thanks Huafeng I have tested this version out on my test board and it also works so again thank you for sharing this suggestion. – johnnyh20 Mar 17 '23 at 21:53
1

The origin of John's question starts with this topic on the Microchip forum.

John seemed to be struggling with some of the fundamental syntax and concepts of the C programming language. To help John I created an MPLABX project to demonstrate how I would format the C language file and implement a process loop to perform the animation sequence described.

There are some concepts that John will need to consider to fully understand the code and the choices to use the specific syntax. In general there are three ways to loop in C:

  • The for(sss;ccc;iii); statement
  • The while(ccc){} statement
  • The do {} while(ccc); statement

Consult any C language reference for more details on how these differ.

Having used the Microchip C compilers for a long time I have found they generate better code for counting down an unsigned value to zero using a do {} while(ccc); statement.

The reason for the less than clear } while (--delay > 0); syntax is the XC8 C compiler will generate slightly more efficient machine code. In all honesty I write this kind of looping structure so often it's just a reflex now. I apologize for using a syntax that is pushing you up the learning curve too fast.

It's really excellent that you received such good answers to your question. It seems a shame that some narrow minded bigots have down voted your question. To me it seems better written than a lot of questions that show up here.

To address the debugging issue raised in the comments. Microchip no longer sells the AC162052 hardware debug header for the PIC16F676. Without it In-Circuit-Debug of this target is impossible.

Dan1138
  • 1,150
  • 8
  • 11
  • Hi Thanks no apology is required for the methods you have used in helping me achieve the knowledge I have gained already. If not pushed it is easy to get stuck in bad practices when learning new item be it software for programming or other things I am currently trying to learn. I will certain go through all the 3 ways of loop in C. My note book is already getting a lot of tips in it for working with this PIC. Unlike some people who find code and then just use it I do make sure I understand it and learn from it. Picking this PIC may have been the biggest mistake as not many people post about it – johnnyh20 Mar 17 '23 at 20:46
1

The reason I am adding my answer to this thread is from the initial question on the Microchip website which was a for loop question which got answered very quickly. I showed my first attempt at controlling the stepper motor. However this was starting the stepper motor in one direction and when I pressed a button the motor changed direction, on releasing the button the motor returned to its original rotation.

I then mentioned I would like to be able to set the steps and the speed of the stepper motor without the use of a button. I was after something similar to the Arduino stepper.h library.

Dan created the first version of his code to do a number of actions with the stepper motor. This solution was excellent and allowed me to have direction and steps and speed control of the stepper motor with the PIC16F676 chip.

Then I mentioned the use of a simple homing function so the motor would home first and then move in the direction and speed I could set in the code.

Dan quickly came up with that solution as well and this now has given me every thing the stepper.h library could do The code on his github will help others trying to work with the 28 BYJ-48 bi polar stepper motor using the ULN2003 driver module. Which makes it great for model animation.

It is working on a bread board at the moment but will be shown in the next week once I have created the diorama for it.

The are no doubt other functions that could be added in the future as so far it is using only 38% of the program words and 22% of the data memory of the PIC.

Dan's github page is https://github.com/dsoze1138/16F676_Frameworks

I have also added a video to my Youtube channel explaining with the help of Dan how to work with the Pic16F676 and the 28 BYJ- 48 stepper motor. This is version 2 before the use of the Homing function added by Dan. See https://youtu.be/XVpI7lcXJQg

johnnyh20
  • 71
  • 6
0

The final version 2 code can be seen in my github page.

https://github.com/johnmholmes/PIC16F676_Basic_C-programming_Pickit_3_MPLAB_X_IDE

This cover getting started on my journey with the Pickit 3 and the Pic16F676 micro controller.

This is part 10

johnnyh20
  • 71
  • 6