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.

PIC 16f690 MATH Problem......

Status
Not open for further replies.

vortexmc

New Member
Hi there guys. I am currently working on a distance measurement application using the sharp rangefinder. I am using a PIC 16F690 microcontroller to read in the analogue voltage signal from the rangefinder. The maximum distance measured by this sensor is 30cm. The problem I am have is writing the math routine to convert the adc value too distance. For this project, I must use PIC assembly language. The equation for the conversion is :

volts = analogRead(IRpin)*0.0048828125
distance = 12.21*exp(volts -1.15)

I am a newbie at PIC assembly, so any help would help me greatly assist me. The ADC is 10 bit. The exp is short for exponent.
 
Question:

Do you actually need 10 bit resolution on a 30cm max measurement? Could you just just 255 measurement points? This would give you 1.17mm resolution and allow you to write a REALLY long lookup table with the answered already there (done in say, excel, for each possible measurement point).

Or I think you could algebraiclly manipulate those formulas so they would be easier to work with in assembly.
 
Thanks wannaB for your input. The Chip allocated by my supervisor was the PIC 16F690. How i would use the distance measured is as follows. The measuring application is of a water level measurement in an enclosed tank. The tank is 40cm in height, so when the water level hits the maximum boundary of the sensor, which is 30 cm, the lowest voltage reading would be indicated by the ADC. As the water gets closer to the sensor, the voltage would get stronger. What i need too achieve is really the distance measured in relation to the total distance between the sensor and the water level,excluding the dead zone of the sensor which gives a total measurable distance of 26cm ,in essence a percentage. That is were the math comes in. I have established the formula from testing the sensor. This in totality is my approach. If you feel this method is flawed, would you please elaborate on your method so I could understand it better. Thank you again for your assistance. It really is appreciated.
 
Last edited:
I wouldn't say your method is flawed, I just don't know how to do exponent math in assembly. You could maniuplate it around to a logaritmic problem, but again, I have no clue how to do that in assembly.

What I suggested is just a work around for the problem.

You basically figure out the voltage range of the sensor from max measurement to minimum measurement. You then set your voltage reference on the pic close to the max. I'd suggest using just the 8 bit ADC measurement b/c the 10 bit would require a ridiculously long lookup table (this is already going to be very long)

Say the voltage range was from 0 volts to 1.5 volts. Take 1.50 volts and divide it by the 255 points of resolution in an 8 bit ADC. From here you would know that is 5.882353. You then figure up in excel or some other spreadsheet program what 5.882353 x 1, 5.882353 x 2, etc (all the way to 255) is equal to in terms of distance.

You then write a lookup table that basically does this:
BSF ADCCON,GO ;take measurement

WAIT
BTFSC ADCCON,GO ;see if measurement is done
GOTO WAIT ;not done
MOVF ADRESL,W ;move ADC 8 bit result into W register
CALL LUTABLE ;call the lookup table where your answers are stored

LUTABLE
ADDWF PC,F ;add adc result to program counter
RETLW 0 ;pre-calculated distances to return to W
RETLW 1
RETLW 2
RETLW 3
.
.
.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


I'll let you play games with how you want to deal with decimals and what not. The registers in my code above may not be correct. Keep the memory page in mind when you do lookup tables. The program counter (PC) is 8 bit, so theres a good change you could end up in the wrong place if you are adding W to the PC, so you may need to load PCLATH with the correct memory page (I think that's the terminology).

This is just a work around and probably isn't the best solution. You can probably find some exponent and logarithm routines in PIC ASM on the net.
 
What is the output voltage range of the sensor? 1.15 to 5.00 volts? How does that voltage range relate to distance? 30cm (1.15v) to 4cm (5.00v)?
 
Last edited:
With those equations you input range is 1.15-2.15 volts which will give a reading from 229 to 439. Subtract 229 from your reading and use a lookup table.

BTW, it is always better to write volts = analogRead(IRpin)*5/1024 than volts = analogRead(IRpin)*0.0048828125 as then people understand where the equation came from.

Mike.
 
Here is a possible method. It is linear interpolation from a much smaller lookup table.

Over a limited range, the exp() function doesn't change slope too much, and it's a smooth function. Multiplication isn't too difficult in a PIC16F690, and various routines are available at piclist.com

Split the number into a most significant part and a least significant part. I suggest 4 bits for the most significant part.

Use a lookup table with 17 entries to find the exp() of the most significant part, and store as the result, for now.
Lookup the exp() of one more than the most significant part, and subtract the other exp()
Multiply the least significant part by this difference and add to the result.

Example.
If you want exp(n/256-1)*256
(That gives a result in the range 94 - 256)

Your lookup table is:-
0 94
1 100
2 106
3 113
4 120
5 128
6 137
7 145
8 155
9 165
A 175
B 187
C 199
D 212
E 225
F 240
10 256

So if you want the to lookup 213, which is 0xD5, you use the lookup table to find the result for 0x0D which is 212.

You then lookup the result for 0x0E, which is 225. Calculate the difference 225 - 212 which is 13
Multiply that by the 5 from 0xD5 and you get 65 or 0x41. You need to divide that by 16, but that's just 0x04, and you add that to the 212 to give your final answer of 216.

This method does need a divide, but only a divide by a fixed number. If you chose the fixed number to be a power of 2, the divides can be done easily by the PIC16F690. I've used this method to work out arctan. It is based on this **broken link removed**
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top