5 years ago.

Strange behaviour of "if" statements in continuous loop

Good day, colleagues. I am afraid, my limited knowledge of subject yet again forces me to ask help from the community.

//Servo motor rotary position should be defined by analogue voltage input.
#include "mbed.h"
PwmOut PWM1(p21); //PWM signal output. Thats what controls position of the arm.
AnalogIn ain (p20); //Analogue voltage input. Depending on the voltage supplied, PWM output should change, hence changing position
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
int main()
{
    wait(2);
    PWM1.period_ms(20);
    PWM1.pulsewidth_us(500); //Servo motor resting point
    wait (2);
while (1)
    {
        if (ain<0.02) //0-15 PSI range
        {
            wait(2);
            myled1=1;
            myled2=0;
            myled3=0;
            myled4=0;         
            PWM1.period_ms(20);
            PWM1.pulsewidth_us(500);
        }
        else if (ain>0.02 and ain<0.79) //
        {
            wait(2);
            myled1=0;
            myled2=1;
            myled3=0;
            myled4=0;
            PWM1.period_ms(20);
            PWM1.pulsewidth_us(833);
        }
        else if (ain>0.80 and ain<1.64) //
        {
            wait(2);
            myled1=0;
            myled2=0;
            myled3=1;
            myled4=0;
            PWM1.period_ms(20);
            PWM1.pulsewidth_us(1166);
        }
        else if (ain>1.65 and ain<2.10) //
        {
            wait(2);
            myled1=0;
            myled2=0;
            myled3=0;
            myled4=1;
            PWM1.period_ms(20);
            PWM1.pulsewidth_us(1500);
        }
        else if (ain>2.11 and ain<3.3); //
        {
            wait(2);
            myled1=1;
            myled2=1;
            myled3=1;
            myled4=1;
            PWM1.period_ms(20);
            PWM1.pulsewidth_us(1833);
        }
    }
}

So, the idea is that servo motor position should be changing depending on the analogue voltage applied, and postilion should be changing only when I change the analogue voltage. And only then. Hence the continuous loop. But what I am getting is quite weird:

1) Servo goes to its starting, "zero" point waits for couple of seconds (as it should)

2) It proceeds to change the position depending on the voltage I supply to ain, waits a couple of seconds

3) Without me changing anything, it jumps straight to the last "else if" statement in the ladder (where all LED's are lit)

4) Returns to stage (2)

... and so on continuously. Is there a conflict somewhere that I just cant see? When at the same time there are two statements that satisfy the condition, so it jumps back and forth? That is the only reason I can think of.

Thanks in advance.

For some details on analog input noise, see https://developer.mbed.org/users/chris/notebook/Getting-best-ADC-performance/

posted by David Smart 11 Feb 2016

2 Answers

5 years ago.

Two issues. First, the reason you are getting the results you have is the extra ; on the end of line 57. Remove that and the if should work correctly.

Secondly things won't work right because AnalogIn outputs between 0 and 1 not 0 and 3.3, you need to scale your ranges appropriately.

Accepted Answer

Right. Sorry, I just read that mbed is able to read analogue voltage as long as it does not exceed 3.3 volts brought to the pin. So, if I have a system that has a maximum output of 10 volts DC and I want it to be working with mbed, I need to implement a circuit that divides the output voltage by 10, rather then 3 (as I had done in the example above)?

posted by Ros Salostejs 11 Feb 2016
5 years ago.

I'd ask you to think about the cases where ain = 0.8, 1.65, 2.11 What does your logic do? Is there a *simple* way to address this? Hint: make sure you don't skip over any values. Use <= or >= in the correct conditions and you'll solve one major problem. And no, you don't need to add any more conditional tests.

I would also make sure the Analog class handles ain as a volatile variable.

Also think about the possibility of noise on the input. One reading it may be 0.795, the next 0.801 and then 0.780. Rather than using ain in the if statements read the input once and save the result in a variable. Then use that variable for the if statements. This way you use the same value for all the comparisons. It will also run a LOT faster.

And as bill indicated if ( < 0.4 ) else if ( => 0.4 ) in order to ensure all values are covered.

posted by Andy A 10 Feb 2016