Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Picbasic pro manipulating numbers - addition problem

Status
Not open for further replies.

bigal_scorpio

Active Member
Hi to all,

I have written a program to display 2 different voltages and below to display the sum of the voltage. My code works ok up to a point. Both numbers are from 10 bit ADC and they are ok when displayed separately, or so I thought!

If both numbers are below xx.5 then the result is correct but if for instance one is 12.6 and the other is 12.5 the sum would show 24.1 instead of 25.1.

This is probably something stupid as that is what I seem to do best! But I just can't see it and I am not really an expert at working with numbers. Many of my projects consist of turning things on and off when conditions are met, so I don't have a lot of experience with the math part.

Anyone help?

Al

PS please ignore the 'LCDOut $fe,$c0,"portC=",DEC disp lines, they were just to test something and will be deleted eventually.



Code:
'****************************************************************
'*  Name    : 16f872 multi ADC.BAS                              *
'*  Author  : Platform = PicBasicPro Program written by BigAl   *
'*  Notice  : With help from many, too numerous to list         *
'*          : No Rights Reserved                                *
'*  Date    : 18/06/2012                                        *
'*  Version : 3.0                                               *
'*  Notes   : Program to display both negative and positive of  *
'*          : PSU 15-0-15                                       *
'****************************************************************


DEFINE OSC 8

' Define LCD pins
Define  LCD_DREG        PORTB
Define  LCD_DBIT        4
Define  LCD_RSREG       PORTB
Define  LCD_RSBIT       2
Define  LCD_EREG        PORTB
Define  LCD_EBIT        3

' Define ADCIN parameters
DEFINE  ADC_BITS        10     	' Set number of bits in result
DEFINE  ADC_CLOCK       3     	' Set clock source (3=rc)
DEFINE  ADC_SAMPLEUS    50    	' Set sampling time in uS
TRISC = %00001111
TRISA = %00011111
'  variables
therm        var     word
posval       var     WORD
negval       var     WORD
static       var     WORD
adval	     Var     Word		' Create variables to store results
five         var     word
disp         var     byte
temp         var     byte
varamp       var     word
        ADCON1 = %10000010      ' Set PortA  to A/D inputs


        Pause 100               ' Wait for LCD to start

        Goto    mainloop        ' Skip subroutines


' Subroutine to read a/d converter
getad:
        PAUSEuS 50                      ' Wait for A/D channel acquisition time
        ADCON0.2 = 1                    ' Start conversion
        WHILE ADCON0.2
        WEND                  ' Wait for it to complete
        adval.highbyte = ADRESH         'Write conversion result
        adval.lowbyte = ADRESL
        adval = (adval */ 500)>>2 	     ' Equates to: (adval * 500)/1024 

        PAUSEUS 50
        disp = PORTC & $0f
        pause 2
        Return

' Subroutine to get pot x value
getposval:
        ADCON0 = $41            ' Set A/D to Fosc/8, Channel 0, On
        Gosub getad
        posval = (adval * 41) 
        Return

' Subroutine to get pot negval value
getnegval:
        ADCON0 = $49             ' Set A/D to Fosc/8, Channel 1, On
        Gosub getad
        negval = (adval * 46)
        Return
        
' Subroutine to get 5v current value
getfive:
        ADCON0 = $51            ' Set A/D to Fosc/8, Channel 2, On
        Gosub getad
        five = adval
        Return


' Subroutine to get temperature value
gettherm:
        ADCON0 = $59            ' Set A/D to Fosc/8, Channel 4, On
        Gosub getad
        therm = adval
        Return
        
        ' Subroutine to get variable amps value
getvaramp:
        ADCON0 = $61            ' Set A/D to Fosc/8, Channel 4, On
        Gosub getad
        varamp = adval
        Return


mainloop:
        Gosub   getposval            ' Get + value
        Gosub   getnegval            ' Get - value
        Gosub   getfive           ' Get 5v rail amps
        Gosub   getvaramp           ' Get variable amps

select case disp

    case 1 
    goto volts
    
    case 2 
    goto amps
    
    case 4 
    goto temper
    
    case 8 
    goto sumvolt
    
end select

volts:
        LCDOut $fe,1,"POS Volts=+",DEC (posval/1000),".", DEC2 posval	' Display the decimal value
        LCDOut $fe,$c0,"NEG Volts=-",DEC (negval/1000),".", DEC2 negval	' Display the decimal value
        'LCDOut $fe,$c0,"portC=",DEC disp
        Pause   200
        Goto    mainloop

amps:
        if five >1023 then five = 0
        if five <0 then five = 0        
        LCDOut $fe,1,"+5 Rail = ",DEC (five*4 - 40),"mA"	' Display the decimal value
        LCDOut $fe,$c0,"Var Rail = ",DEC (varamp*4 - 40),"mA"	' Display the decimal value
        'LCDOut $fe,$c0,"portC=",DEC disp
        Pause   200
        Goto    mainloop

temper:        
        temp = ((((therm-131)*100)/323)-4)
        LCDOut $fe,1,"Temp ",$df,"c= ",DEC temp,".", DEC1 temp	' Display the decimal value
        if temp > 20 then goto fanon
        LCDOut $fe,$c0,"Cooling Fan OFF"	' Display fan condition
        'LCDOut $fe,$c0,"portC=",DEC disp
        Pause   200
        Goto    mainloop

sumvolt:        
        LCDOut $fe,1,"Sum Volts= ",DEC (posval/1000 + negval/1000),".", DEC2 (posval + negval)	' Display the decimal value
        LCDOut $fe,$c0,DEC (posval/1000),".", DEC2 posval,"v & -",DEC (negval/1000),".", DEC2 negval,"v"	' Display the decimal value
        'LCDOut $fe,$c0,"portC=",DEC disp
        Pause   200             ' Do it about 5 times a second
        Goto    mainloop        ' Do it forever
        
fanon:  LCDOut $fe,$c0,"Cooling Fan ON"	' Display fan condition
        'LCDOut $fe,$c0,"portC=",DEC disp
        Pause   200
        Goto    mainloop
        
        End
 
What happens if you try adding 'posval' and 'negval' then divide by 1000?

Code:
    LCDOut $fe,1,"Sum Volts= ",DEC((posval + negval)/1000),".", DEC2(posval + negval)
 
Last edited:
Hi Mike,

I did try that but got a way big number! It went off the end of my display. Baffled as usual!

Al
 
LCDOut $fe,1,"Temp ",$df,"c= ",DEC temp,".", DEC1 temp ' Display the decimal value

that is a bit strange. you are taking the same number to try and get t portion to the right of the "." but only one digit
 
What happens if you try adding 'posval' and 'negval' then divide by 1000?

Code:
        LCDOut $fe,1,"Sum Volts= ",DEC ((posval + negval)/1000),".", DEC2 (posval + negval)	' Display the decimal value[/QUOTE]

Hi Mike,

Sorry mate, you did solve it but I missed the brackets! I just didn't notice the second set you used, just thought oh I tried that already.  Well done mate.

BTW if you understand the DEC function can you explain it to me!  I read what little there is in the manual but it tells me nothing about how it works, just  a tiny segment and one example. I like PBP but their manuals leave a lot to be desired.

Al
 
Last edited:
that is a bit strange. you are taking the same number to try and get t portion to the right of the "." but only one digit

Hi Mike,

I just did that on that particular line as I only wanted 1 decimal place for the temperature. But as I said to the other Mike, I don't quite understand the DEC function anyway.

Al
 
Hi Al,

I'm not a PBP user but I wonder if your use of the DEC modifier may be wrong?

If your ADC result represents a whole number with three decimal places, such as the number 12456 representing 12.456, then I suspect you may not be printing the decimal digits correctly. When you print the value 12456/1000 it looks like you're printing the integer portion of the result, the "12" digits, because we're using integer math. If you want to print the first digit after the imaginary decimal point, wouldn't you use "DEC1(12456/100)"? If you want to print the first two decimal digits, wouldn't you use "DEC2(12456/10)"? Anyway, if my interpretation of the Manual is correct...

Code:
  LCDOut $fe,1,DEC(12456/1000),".", DEC3(12456)           ' output "12.456" ?
  LCDOut $fe,1,DEC(12456/1000),".", DEC1(12456/100)       ' output "12.4"  ?
  LCDOut $fe,1,DEC(12456/1000),".", DEC1((12456+50)/100)  ' output "12.5"  (rounded) ?
  LCDOut $fe,1,DEC(12456/1000),".", DEC2(12456/10)        ' output "12.45"  ?
  LCDOut $fe,1,DEC(12456/1000),".", DEC2((12456+5)/10)    ' output "12.46" (rounded) ?

Have fun. Cheerful regards, Mike
 
Last edited:
Hi Mike,

When I said you had solved it yesterday, well it did work on that particular set of numbers but when I changed the values it was wrong again.

What I assumed is that it worked like the first line of your example list, but that is obviously not the case.

The manual is really bad at explaining the simple things and really good at explaining the complicated things like serin and I2C etc.

I just wish there was a way of doing it that I could comprehend!

The worst thing is that every time I try one I have ro burn and move the PIC. I wish I had set my circuit up for ISP. Doh!

Any further thoughts or info out there?

Al
 
Status
Not open for further replies.

Latest threads

Back
Top