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.

Measuring negative voltages with a PIC

Status
Not open for further replies.
...
If it is difficult to do the math in basic would it be better to go with the setup Eric suggested with the op-amp?
...

Hi BigAl if you are talking about using the voltage divider referenced to Vdd 5v the math should be quite easy.

The voltage measured by the divider->ADC will be referenced to +5v.
-12v in = 17v less than ref
-5v in = 10v less than ref
as you can see there is an offset of 5v you need to subtract from both ADC values.

Then you just scale the result with one scaling value (which fixes the resistor divider and also convers ADC units to real volts in one scaling operation).

The easy way is to setup the divider and connect it to 0v, it will display the ADC offset which you can then subtract. Then connect it to -12v etc and display the result, and that gives you the scaling factor.

If you want to work it all out in math first before trimming it then you need to provide the Vref voltage and the 2 resistor values. But you may still need to trim the values later in testing anyway. :)
 
Last edited:
Hi Giys,

At the moment I am swayed towards the op-amp design as it means I can use my original board and math with no offsets and such. With that in mind I have been looking through my components for a good while and am missing one part.

Eric, a quick question. The nearest zener I have is 18v instead of 17.5v. Will this make any significant difference to the circuit or readings?

Al
 
Hi Giys,

At the moment I am swayed towards the op-amp design as it means I can use my original board and math with no offsets and such. With that in mind I have been looking through my components for a good while and am missing one part.

Eric, a quick question. The nearest zener I have is 18v instead of 17.5v. Will this make any significant difference to the circuit or readings?


Al

hi Al,

The 18Vzener will be fine., no change to readings.

E.
 
Hi to all,

Thanks to you guys I now have a functioning unit. Though its not yet quite finished it is near enough that I can use it again, its been a pain since I stripped the original PSU, no power source to try things on etc.

Anyway below is my code that is working just about perfectly, though I am open to suggestions on how to tweek the conversion values in code better.

Thanks again to all you guys and please advise me how to go about linking this finale to the other two threads I started that are connected to this subject, just so anyone reading any of them could see that the hard work put in was not for nothing.

PS. Photo's will follow, as soon as the wife gets the camera out I promise.

Al
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

TRISA = %00000111
'  variables
posval       var     WORD
negval       var     WORD
static       var     WORD
adval	     Var     Word		' Create adval to store result

        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                  ' Wait for it to complete
        adval.highbyte = ADRESH         'Write conversion result
        adval.lowbyte = ADRESL
        adval = (adval */ 500)>>2 	     ' Equates to: (adval * 500)/1024 
        WEND
        Return

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

' Subroutine to get pot negval value
getnegval:
        ADCON0 = $41             ' Set A/D to Fosc/8, Channel 1, On
        Gosub getad
        negval = (adval * 46)
        Return

' Subroutine to get static value  : not implemented yet
getstatic:
        ADCON0 = $51            ' Set A/D to Fosc/8, Channel 2, On
        Gosub getad
        static = adval
        Return


mainloop:
        Gosub   getposval            ' Get + value
        Gosub   getnegval            ' Get - value
        'Gosub   getstatic           ' Get 5v value


        LCDOut $fe,1,"POS Volts= ",DEC (posval/1000),".", DEC3 posval	' Display the decimal value
        LCDOut $fe,$c0,"NEG Volts= ",DEC (negval/1000),".", DEC3 negval	' Display the decimal value
        
        Pause   200             ' Do it about 5 times a second

        Goto    mainloop        ' Do it forever

        End

Pics as promised.

The centre knobs will eventually be the same as the others and will control what the display shows, current or voltage, rail to rail voltage etc. Just need a bit more work on the other bits.

The front panel is entirely cut by hand, well a stanley knife anyway and will be having decals on it to show what the knobs and switches do. There will also be a couple more switches somewhere to turn off various parts of the PSU when not required as cleverly suggested by Eric Gibbs.

Well I hope that you all think the pain of teaching me things was worth it and thanks again to all.

Al

PPS. I've been waiting about 4 years to use that neon illuminated mains switch I got from RS and this seemed just the right project!
 
Last edited:
Kudos for an excellent project. If you still have some energy left and some sleepless nights :) , document your progress/steps in the Blog section (or Article section). It allows you to show all the steps you took, assumptions, pitfalls, etc.
 
hi Al,
Nice looking Bench PSU, I didn't realise you were so close to having it finished.!;)

Lets know how the 5V current sensing circuit/display turns out.

E.
 
Hi Eric and languer,

Thanks for the compliments guys. This is part of a sort of vision I had some time ago that started because my old PSU was such a weird and awkward shape. It also has to do with the fact that my old one didn't have a display until I made an LED 4 digit one and fitted it into the front. The only problem with that was that it probably used more power than most of the projects I build! hehehe

So the idea for a new supply was born! Using most of the parts inside my own and the majority of the controls and switches I drew one up. The only things I omitted were switches for each rail as Eric suggested, but that was soon cured last night by putting them on the back.

There are a few cosmetic touches to finish like all the legends etc. What I would like is comments on my code and ideas on integrating the other features I envisioned like cooling and summing. The summing is simple enough once I fine tune the actual ADC readings.

One question I would like to ask is if there is an accepted way in the community of multiplying by decimal points I.E. in my code I multiply by 41 and 46 to get the conversion when it should ideally be 41.2 and 46.33?

Though the integer gives reasonable accuracy I would like to get it exact. How do you do it?

Anyway guys I' off for a joyful half hour of bathroom cleaning with She who must be obeyed! So have a ponder on my code and stuff and give me some options of how to do the things I've done but better!

BTW here is my original drawing of my PSU and its displays, you can see how I intend to show the details etc.

Al
 
One question I would like to ask is if there is an accepted way in the community of multiplying by decimal points I.E. in my code I multiply by 41 and 46 to get the conversion when it should ideally be 41.2 and 46.33?

Hi Al,

One option, if your Basic allows, is to multiply the ADC count value by 10 [ or a 100] , then do your 'sums' .

Insert the decimal point in the appropriate position in the display, to 'divide' the result by 10 or 100.

E
 
Hi Eric,

Doh! I seem to always miss these obvious bits. Strangely enough I have done a similar thing to put the decimal point in too.

What do you think of the four display options? Have I missed anything or could I have used better names etc?

Al
 
... in my code I multiply by 41 and 46 to get the conversion when it should ideally be 41.2 and 46.33?

Though the integer gives reasonable accuracy I would like to get it exact. How do you do it?
...

To multiply by 46.33 you can multiply by 4633, then keep the data stored at that same *100 resolution until you need to display it.

Then if you need to display rounded to the integer (need to divide by 100) you add half the divisor before dividing down, which will round up or down to the nearest integer;
blah = 4633;
final_int = ((blah + 50) / 100)

If you are after accuracy in the display you should multiply up using the largest value you can to make use of your variable's maximum size. If you are using a 32bit var that can go up to >1billion, and your max ADC value is 1023, you can use a multiplier like 463333 (and your data will be stored with a resolution *10000).
 
Last edited:
Then if you need to display rounded to the integer (need to divide by 100) you add half the divisor before dividing down, which will round up or down to the nearest integer;
blah = 4633;
final_int = ((blah + 50) / 100)

Hi Roman,

This is not a dig mate but I just don't get the add half divisor thing at all. Doing that gives 46.83 instead of without it 46.33. How is that rounding the integer? I could have understood it if the formula gave a result of 46.3 that to me would be rounding off.

Al
 
Hi to all,

Eric. A quick question mate. Since the op-amp I used for the neg sense is a dual one can I use the other side of it for measuring the current on the 5v rail. I am just worried that it would then have a 23v supply rather than the 8v on the schematic. Would this make any difference to the result or is it even possible?

Al
 
Hi to all,

Eric. A quick question mate. Since the op-amp I used for the neg sense is a dual one can I use the other side of it for measuring the current on the 5v rail. I am just worried that it would then have a 23v supply rather than the 8v on the schematic. Would this make any difference to the result or is it even possible?

Al

hi Al,
The OPA will be OK with a single 23V supply.

E.
 
Hi Eric,

I have just made and tested the 5v sense circuit and I am getting some strange results.

At 1A load I set the ADC pot to give 4.8v but when I unhook the load the reading goes up slightly to 4.9.

What should I be expecting at any particular place? If there is anything I can check to find the problem let me know.

I think the circuit is as your schematic. I have checked and rechecked it and find no errors. Any ideas mate?

Al
 
... Doing that gives 46.83 instead of without it 46.33. How is that rounding the integer?
...

Hi Al, adding half the divisor rounds up or down to the nearest integer;
4600 +50 / 100 = 46.50 (integers always round down to); 46
4649 +50 / 100 = 46.99 (integers always round down to); 46
4650 +50 / 100 = 47.00 (integers always round down to); 47
4699 +50 / 100 = 47.49 (integers always round down to); 47
:)
 
Last edited:
I just don't get the add half divisor thing at all
This is one of those old numerical tricks in software computing. Before floating point processors and all that jazz, to round up or down you would simply add 5 to the resolution you were trying to achieve. Just like Roman showed it.

If you want to round to the nearest integer; you want to make sure that you break into the next integer boundary for anything half way there or more.

As an example:
39.4 and 39.5 would both be represented in integer as 39; rounding to the nearest integer
39.4 + 0.5 = 39.9 is still integer 39;
39.5 + 0.5 = 40 which is integer 40. Notice the rounding effect.

If you want to round to the nearest 1st decimal place: 39.54 and 39.55
39.54 + 0.05 = 39.59; rounded to the nearest 1st decimal place is 39.5
39.55 + 0.05 = 39.60; rounded to the nearest 1st decimal place is 39.6

Now to do all this in integer logic; you need to convert the fractional part into integer and carry it all the way through until you're ready to display it. The easiest way to do this (if you have enough numerical resolution to carry this through) is to multiply by the number of decimal places you require. That is: if you need one decimal place you multiply everything by 10 and perform all your calculations in this new numerical system; when you're ready to display it you can get the integer by dividing by ten and the decimal by using the modulus. The same goes for two decimal places - multiply by 100, calculated everything, and at the end divide by 100 (and modulus if you require decimal places). If you need to round; you do the rounding on the new number system (i.e. after the multiplication and before the final division).
 
Hi Eric,

I have just made and tested the 5v sense circuit and I am getting some strange results.

At 1A load I set the ADC pot to give 4.8v but when I unhook the load the reading goes up slightly to 4.9.

What should I be expecting at any particular place? If there is anything I can check to find the problem let me know.

I think the circuit is as your schematic. I have checked and rechecked it and find no errors. Any ideas mate?

Al

hi Al,
If you recall I did point out [ in the MAX IC posts] as you are using a 0.1R as the series sense resistor, it will drop 0.1 volt when passing a 1 amp current into the external load, so the output voltage across the load would fall by 0.1 volt.

When you remove the 1 amp load, there will be no voltage drop across the 0.1R sense resistor , so the output voltage will rise by 0.1 volt , to 4.9V

The only way to 'reduce' this voltage drop would be to reduce the Rsense to say 0.01R, in that way you would only lose 0.01V at 1 amp loading.

Problem with that is that Vadc would would be only one tenth of its present value.

If you you have a 0.01Rsense resistor, let me know and I will try to modify the OPA circuit.

Eric
 
Hi Roman and Languer,

I think I get it now guys. I have never heard of it before and I was overthinking it. I was thinking it involved the decimal points too not just the integer. :)

Al
 
Hi again guys,

Eric,

I have just made a 0.01r resistor. It does have a small inductance of 0.7uH, will this be a problem?

Al
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top