Shop OBEX P1 Docs P2 Docs Learn Events
C if loop, using float values — Parallax Forums

C if loop, using float values

RsadeikaRsadeika Posts: 3,837
edited 2016-12-17 20:44 in Propeller 1
I am trying to get this segment of code too work correctly, but having no success. This is using the simpletools adc function, and v0 is a float value. I am trying to turn on an LED when the battery gets to 6.0V or less. I have changed the check value too 6.0, by that is not working, not sure how to code this.

Thanks

Ray
float v0;
    v0 = adc_volts(0);
    v0 = (v0*2);
    if(v0 <= 6) high(7);

Comments

  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-12-17 21:12
    Have you tried?:
        float v0;
    
        v0 = adc_volts(0);
        v0 = (v0*2.0);
        if(v0 <= 6.0) high(7);
    

  • Yes, in fact I was trying to be even more precise with a value of 6.11. The adc_volts() presents a number like 6.433210, still trying to figure out how to get that down to two decimal places, but that is another subject.

    Now I am wondering if the value should be 6.000000? So, if v0 is something like 6.433210, then the comparison value should be the same amount of digits, at 6.000000?

    Ray
  • The amount of digits you specify doesn't matter. "6.", "6.0", "6.000000", and "6e0" all mean exactly the same thing to any compliant C compiler. Just "6" (an integer, unlike the others, which are all floats) could theoretically compile to something different, but if you have any level of optimizations turned on, which you most likely do, it will almost certainly compile to the same thing as the float ones.
  • I verified that the adc_volts() function works, even when it is run in its own COG. I had similar piece of code in a larger program, there it is not working as expected. Now to figure out what is causing it to fail in the larger program.

    Ray
    /*
      test3.c
     
    */
    #include "simpletools.h"
    #include "adcDCpropab.h"
    
    void cogedf();
    
    volatile float v0;
    
    int main()
    {
      // Add startup code here.
      adc_init(21, 20, 19, 18);
      pause(250);
      cog_run(cogedf,128);
    
       
      while(1)
      {
        // Add main loop code here.
        pause(1000);
      }  
    }
    
    void cogedf()
    {
      while(1)
      {
        v0 = adc_volts(0);
        v0 = (v0*2);
        if(v0 <= 6.21) high(7);
        else if(v0 > 6.22) high(8);     
        pause(100);
      }    
    }  
    
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-12-17 22:11
    In this line...
      v0 = (v0*2);
    
    ...you're multiplying a float by an int -- could this be causing an unflagged problem? I don't know the details of the compiler, but I do know C is finicky about types.

    And, honestly, as you're using constant values for thresholds, why not divide them in half?
  • The setup that I have is, a 6V SLA battery where I have a voltage divider to read the state of the battery. Of course I have an Activity Board that is being powered by this setup.

    The voltage divider uses two 10K resistors, in this setup the value that v0 read out is 3, assuming the battery voltage is 6, half of the expected value. So, for convenience, I multiply it by 2 to get the real value.

    The reason for using float values, I want to setup a metering method using three LEDs, red, green, and yellow. If the battery voltage is >6.5V, the green LED is on. If the battery voltage is between 6.1 and 6.4, then the yellow LED is on. Less than 6.1V the red LED is on. And of course this will run in its own COG, because I have an interactive user program with the XBee working in the main() function.

    I will have to debug my original program to see why the ADC is not working as expected. Something is affecting the ADC function, but not sure what it is a the moment.

    Ray
  • Rsadeika wrote: »
    The setup that I have is, a 6V SLA battery where I have a voltage divider to read the state of the battery. Of course I have an Activity Board that is being powered by this setup.

    The voltage divider uses two 10K resistors, in this setup the value that v0 read out is 3, assuming the battery voltage is 6, half of the expected value. So, for convenience, I multiply it by 2 to get the real value.

    The reason for using float values, I want to setup a metering method using three LEDs, red, green, and yellow. If the battery voltage is >6.5V, the green LED is on. If the battery voltage is between 6.1 and 6.4, then the yellow LED is on. Less than 6.1V the red LED is on. And of course this will run in its own COG, because I have an interactive user program with the XBee working in the main() function.

    I will have to debug my original program to see why the ADC is not working as expected. Something is affecting the ADC function, but not sure what it is a the moment.

    Ray

    Glad you were able to get this working in a smaller program to verify the hardware and basic software functionality. Feel free to post the larger program now if you're unable to find the difference and we might be able to help you find the irregularity.
  • Ray,Does your ADC actually put out a float value or is it putting out a series of integers like 301 that you are turning into 3.01 as a float. If such is the case then just do your comparisons as integers.
    Jim
  • RS_Jim wrote: »
    Ray,Does your ADC actually put out a float value or is it putting out a series of integers like 301 that you are turning into 3.01 as a float. If such is the case then just do your comparisons as integers.
    Jim

    The adc_volts function is part of the Simple libraries, and it outputs a float. The documentation for the function does not describe the precision, but here it is: http://david.zemon.name/PropWare/api-develop/adcDCpropab_8h.xhtml#a3e2df0dd371eb7524ed35115e9bf1770
    In short:
    float adc_volts	(	int 	channel	)
    
    Get a voltmeter style floating point voltage measurement from one of the A/D converter's input channels.
    
  • Rsadeika wrote: »
    I verified that the adc_volts() function works, even when it is run in its own COG. I had similar piece of code in a larger program, there it is not working as expected. Now to figure out what is causing it to fail in the larger program.

    Don't know if you verified, this is the adc_volts function from the library source I have:
    float adc_volts(int channel)
    {
      return ((float) adc_in(channel)) * 5.0 / 4096.0;
    }
    

    Looks like it assumes a 5 volt range and 12 bit precision, is that your case ?
  • I think I solved the mystery, for now. It makes a difference as to where you place 'adc_init(21, 20, 19, 18);
    '. As shown below, the 'adc_init(21, 20, 19, 18);' has to be placed just about first in line, for it to work correctly. Luckily I did not have a whole bunch more code in there, I probably would have spent days trying too figure that one out, but I am still not completely confident that the issue has been resolved.

    I also have to be very careful about these functions in terms of COG use, I am not sure if the ADC function uses a COG to run.

    Ray

    Original code lines:
    volatile float v0, v1, vx;
    
    int main()
    {
      // Add startup code here.
      //high(8);
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(250);
    //  adc_init(21, 20, 19, 18);
    //  pause(250);
      cog_run(irrem,128);
      pause(250);
      adc_init(21, 20, 19, 18);
      pause(250);
      cog_run(pwrmon,128);
      pause(250);
    
          
      char inBuff[40];
      //low(8);
      
      while(1)
      {
    
    Moved code lines, now works as expected.
    volatile float v0, v1, vx;
    
    int main()
    {
      // Add startup code here.
      //high(8);
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(250);
      adc_init(21, 20, 19, 18);
      pause(250);
      cog_run(irrem,128);   // This runs the remote control.
      pause(250);
    //  adc_init(21, 20, 19, 18);
    //  pause(250);
      cog_run(pwrmon,128);  // This runs the LEDs.
      pause(250);
    
    
          
      char inBuff[40];
      //low(8);
      
      while(1)
    
  • This is the full program, and the ADC seems to be working as expected.

    I put all the ADC activity into one COG, if I need access to any of the ADC data, I use the global variables vx and vy. It seems that the ADC function works best when it is running and being accessed, in one place. When I tried to use the ADC, for instance, within the main() function, the data gets corrupted.

    Looking at the way pwrmon() COG is developing, I wonder if the program should be done in C++, although I am not sure about Class structures. Do these things run like a background thread, which would save me COGs?

    Because of the limited RAM of the Propeller, I am now going to try adding a Raspberry Pi to the mix. This way the Propeller will just deal with the battery, DC motors, IR, XBee and other sensors, while the RPi can deal with data acquisition/storge and manipulation.

    First I have to see how to deal with the two units, will they cooperate the way I am thinking they should.

    Ray
    /*
      rb5x_ab.c
      
      December 9, 2016
      
      Control program for the RB5X chasis.
     
    */
    #include "simpletools.h"
    #include "simpletext.h"
    #include "fdserial.h"
    #include "sirc.h"
    #include "adcDCpropab.h"
    
    serial *xbee;
    
    volatile int myLock;
    
    /*COGed functions*/
    void irrem();
    void pwrmon();
    /******************************/
    
    /*DC motor control*/
    void RBstop();
    void RBfore();
    void RBback();
    void RBleft();
    void RBrite();
    /******************************/
    
    /* Battery monitor*/
    void RBcharge();
    /******************************/
    
    
    void menu();
    
    volatile float v0, v1, vx, vy;
    
    int main()
    {
      // Add startup code here.
      //high(8);
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(250);
      adc_init(21, 20, 19, 18);
      pause(250);
      cog_run(irrem,128);// This runs the remote control.
      pause(250);
      cog_run(pwrmon,128);  // This runs the LEDs.
      pause(250);
          
      char inBuff[40];
      //low(8);
      
      while(1)
      {
        // Add main loop code here.
    
        writeStr(xbee,">");
        readStr(xbee,inBuff,40);
        if(!strcmp(inBuff, "help")) menu();
        else if(!strcmp(inBuff, "rbstop")) RBstop();
        else if(!strcmp(inBuff, "rbfore")) RBfore();
        else if(!strcmp(inBuff, "rbback")) RBback();
        else if(!strcmp(inBuff, "rbrite")) RBrite();
        else if(!strcmp(inBuff, "rbleft")) RBleft();
        else if(!strcmp(inBuff, "ckcharge"))
        {
          writeFloat(xbee,vx);
          writeStr(xbee," Volts\n");
        }
        // Debug, check if charger probes are contacting charger.
        else if(!strcmp(inBuff, "rbposts"))
        {
          //v1 = adc_volts(1);
          writeFloat(xbee,(vy*5.15));
          writeStr(xbee," Charger Voltage\n");
        }            
        else
        {
          writeLine(xbee,"Invalid Command");
        }                
      }  
    }
    
    /* COGed functions */
    void irrem()
    {
      int button = 0;  
      while(1)
      {    
        button = sirc_button(9);
        if(button < 100) RBstop();
        {
        switch(button)
        {
          case 21:    // Pwr, Stop robot.
            RBstop();  
            break;
          case 16:    // Ch+, Foreward. 
            RBfore();
            break;
          case 17:    // Ch-, Backward. 
            RBback();
            break;
          case 18:    // Vol+, Right turn.
            RBrite();
            break;
          case 19:
            RBleft(); // Vol-, Left turn.
            break;
          
          //default: CRstop();
        }
        }    
        button = 0;      
      }  
    }
    
    /* Check the battery state. */  
    void pwrmon()
    {
    
      while(1)
      {
        v1 = adc_volts(1);  // Charger probes.
        vy = v1;
        pause(100);
        //while(lockset(myLock));
        v0 = adc_volts(0);
        vx = (v0*2);
        if(vx < 6.0) high(7);  // Battery is less than 6.0 Volts.
        else if(vx > 6.10) high(8);
        //lockclr(myLock);    
        pause(100);    
      }   
    }  
    /******************************/
    
    
    /*Control of the DC motors.*/
    void RBstop()
    {
      low(15);
      low(14);
      low(13);
      low(12);
    }
    
    void RBfore()
    {
      low(14);
      low(13);
      high(15);
      high(12);
    }
    
    void RBback()
    {
      low(15);
      low(12);
      high(14);
      high(13);
    }
    
    void RBleft()
    {
      low(15);
      low(13);
      high(14);
      high(12);
    }
    
    void RBrite()
    {
      low(14);
      low(12);
      high(15);
      high(13);
    }          
    /******************************/
    
    
    void menu()
    {
      writeStr(xbee,"Menu -  help,   \n");
      writeStr(xbee,"rbstop, rbfore, rbback, rbleft, rbrite \n");
      writeStr(xbee,"rbposts, ckcharge, \n");
    }  
    
Sign In or Register to comment.