PDA

View Full Version : Math operations execution time



rasciodc
- 23rd January 2012, 23:34
Hi!

I am new to the forum (actually always have used the forum for searching and consulting but never registered...) and I´d like to know if you can help me out.

I am designing a rocket altimeter using pic 12F683 and reading a MPX4115 pressure sensor. What I need to do is to read de ADC value, convert it to height using a equation and compare the values obtained as the rocket goes up. Then, when the height measured is lower than the previous one, a servo is activated.

All of this is already implemented and ""working"" (I am very very new to this) except for the fact that the servo is being activated during the "ascent of the rocket" (I am simulating the circuit in proteus) because the AD reading is changing faster than the PIC can do the conversion of AD to height. I know that because I put a 200ms pause after the conversion and it worked just fine. Without the pause I think it gets "confused" about the value to use to make the comparision.

The problem is that I don´t want to use this 200ms pause because I´m data logging the values in eeprom and 200ms diference between values is too much for a 15 seconds flight. With the 200ms pause I can write only 78 values of height into eeprom, while a 20ms pause allows me to write 242 values (wich is great for a 256 addresses available in eeprom).

So my question (finally) is, how can I contour this problem? Is that a problem with the conversion time (math operations) or the AD reading time? Is there any way to make the conversion faster? I know that the equation I am using (height = (((835-adin)*104)+35)/10) requests some time to be processed but, what would you do in this situation?

As I said, my experience with this stuff is very limited and I hope someone can put some light on this! Thanks a lot!
PS: I didn´t put the code here because it only does that: reads AD, calculates height and compare to previous values to activate (or not) the servo.

Jumper
- 24th January 2012, 07:06
Hi,


I am far from a math genious but WHY do you even calculate the height?

The ADC value is the only thing that changes in your formula and then I think you can use the raw value.

I inserted your formula in an Excel sheet and I am not really sure it is correct. When ADC is 0 your calculated height is 8687 and with ADC 256 the height is 6025. So it seems as long as the adc value is getting smaller the height goes up. A quick look in the datasheet gives the formula

Vout = Vs * (.009*P-.095) where P is in Kpa and Vs=5.1V Looking at the graph this makes Vout vs Kpa shows that when the Kpa becomes lower the Vout should be lower.. so you need to double check your formula..

I still think you can use the raw adc value to find when the rocket stops going up. The higher it goes the smaller the adc value will be and when the ADC gets bigger again it is time to activate the parachute servo.


BUT

ADC sampling is not a one shot activity (average the values or allow for a threshold or it will not be very stable)

Then you can also store the adc value where the servo was activated in the EEprom you you later can know how high you went.

Why do you need speed for this? When the rocket has slowed down because it can get any higher it will slowly start to accelerate towards the ground .. and the first 50-100 meters it falls will take at least 5-6 seconds. I am a skydiver and we usually dont deploy our parachutes until we have reached a reasonable speed to allow the parachute to open in a more reliable way. If we deploy it too early it can open too slowly and twist the lines and that is not that great.

Dave
- 24th January 2012, 11:46
Rasciodc, Just curious, Why do you need to do the calculation during the flight? How are you using the data stored in eeprom and why dont you do the conversion after the flight?. If you only want to delpoy the chute using the a/d values then just compare the values during the flight and deploy the chute when the first 2 or so readings (depending on the filtering) are the lowest. Store the raw a/d values and do the conversion after re-entry and data download...

ScaleRobotics
- 24th January 2012, 12:01
Hi rasciodc,

Something seems out of whack with your 200 ms timing. Not sure what is taking so long. The eeprom write cycles should take the longest at 5ms. For an example, I did an altimeter for this chip using a 16 bit oversampling routine (where 4096 samples are averaged an "upconverted" to a 16 bit result) with this same chip using an internal 8 mhz osc. The oversampling part with the altitude math took a little more than 100 ms. Just the oversampling I was doing took 99 ms. So, about 40,000 samples per second. If you are taking one sample at 8 or 10 bits, then things can definitely be sped up.

You can do as Jumper suggested, editing out your math to see how much speed you gain, just from using raw ADC data. But I have a feeling something else it taking up time. There is a useful tool called codetimer.bas. I have used this on PIC18 chips. Not sure it will work on a PIC12 though. You could upgrade to the PIC12F1822 or PIC12F1840. This chip can run at 8 million instructions per second, rather than the PIC12F863 at 5 million instructions per second. And EEprom write cycles are sped up by about 20 percent (to 4 ms). It would be interesting to see your code for an idea of where the bottle neck is. Are you sure what speed you are running the osc at? Another thing you could do would be to change to a faster type of memory to write to. But again, this part should take 5 ms per sample, so that should not slow you down too much. Seems like you should be able to obtain 20 ms with the hardware you have.

http://ramtron.com/about-us/what-is-f-ram.aspx Fast memory to write to, with more space.
http://www.picbasic.co.uk/forum/content.php?r=249-Oversampling-analog-to-digital-readings Oversampling
http://www.picbasic.co.uk/forum/content.php?r=423-Timer-for-PBP-code CodeTimer (but built on a PIC18) author says should work on a PIC16
http://www.picbasic.co.uk/forum/content.php?r=184-MPX4115A-picbasic-code My PIC12F863 MPX4115 project

rasciodc
- 24th January 2012, 19:50
Jumper, thanks for helping!

All you said is right, I can use the ADC raw data to deploy the chute and actually my intent is to deploy 50m below maximum height. About the formula, I had to "simplify" it because height is not linear with respect to pressure variation so, this equation fits reasonably well for 2000m and I don´t want use polynomial equations in the code. Other aspect is the Vref value, I am using Vref=Vdd and the sensor output is 4.8V maximum, this difference was taken into account on that equation.

But, using the raw data to deploy will (or should) solve all those issues. I just thought the PIC could handle this task, as it is not doing anything else than that. I´ll modify tge code to work with raw data and then I´ll let you know!

Thanks a lot!

rasciodc
- 24th January 2012, 20:02
Dave, thanks for the tip, it seems like it is the right way to go! As it is the same sugestion that Jumper gave, maybe you both could help me with this: how can I obtain stable raw data? because the values keep going up and down usually +-2 ADC values. It´s not good for comparing values...is there a way to solve this?

ScaleRobotics, very very nice your altimeter project. As I said, I am very new to programming and I am trying to learn. Let me ask you something, I set the internal osc to 4MHz, should I use 8? And I am using rs232 for recovering data, will it work at 8MHz?
I guess that 8MHz would make things easier for this case...

If it´s not asking too much, I´ll translate my code and post here, then you could give me some tips if you guys have some time...Because I must be doing something very wrong, the pic was supposed to make this kind of calculation flawlessly.

Thanks!!!

rasciodc
- 24th January 2012, 20:30
Here goes the code! Please don´t laugh, it´s my first time! lol... It´s not good, but actually I am kind of proud of my first kid...:witless:
Sorry about the the "portuguese variables" it was a little easier to "think" in my mother language....

So, suggestions are welcome!



'************************************************* ***************
'* Name : Altimeter_12F683 *
'* Author : Daniel Rascio *
'* Date : 21/01-2012 *
'* Version : *
'* Notes : *
'************************************************* ***************
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
' OSC1 e OSC2 are I/O, MCLR off
'************************************************* ******************************
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3 'internal osc
DEFINE ADC_SAMPLEUS 250
DEFINE OSC 4 'internal 4MHz osc
'************************************************* ******************************
OSCCON = %01100111 '110 4mhz / osts internal osc / HFINTOSC stable
TRISIO = %00001111 ' GPIO.0,1,2,3 input, GPIO.4,5 output
ANSEL = %00010001 'GPIO.0 - A/D in ,rest are digital /fosc/8 /right justify
WPU = 0 ' Internal pull-ups = off
CMCON0 = 7 'comparators off
ADCON0 = %10000001 ' right justify/vref=vdd/input on AN0/
GPIO = %0001111
'************************************************* ******************************
n var byte 'counter for-next
B0 var byte 'open button
B1 var byte 'close button
B2 var byte 'start rs232 button
k var byte 'eeprom eraser counter
adin var word 'raw data at gpio.0
altitude var word 'actual height
anterior var word 'previous height
maxima var word 'maximum height
inicial var word 'initial height at ground
disparo var word 'deployment height
m0 var byte 'stores data to write eeprom
m1 var byte 'stores data to write eeprom
contador var byte 'eeprom counter
contador2 var byte 'initial height counter
t var word 'eeprom address counter
dado var word 'eeprom read data
'************************************************* *****************************
pause 500 'stabilization time at startup
Main:

button gpio.1,0,255,10,B0,1,Abrir 'opens parachute hatch
button gpio.3,0,255,10,B1,1,Fechar 'closes parachute hatch
button gpio.2,0,255,10,B2,1,Serial 'starts rs232 com.

ADCIN 0, adin 'sensor reading at AN.0

if adin > 833 then
adin=833
endif 'avoids negative values for height
if adin < 206 then
adin=206
endif

altitude = (((835-adin)*104)+35)/10 'height conversion
pause 200 'time to do calculations

if contador2 < 2 then
inicial = altitude 'stores ground height
contador2=contador2+1
endif

if (altitude-inicial) > 40 and t < 254 then
'writes eeprom if actual height is 40m higher than ground
m0 = altitude.byte0
m1 = altitude.byte1
write t,m0
write t+1,m1
t=t+2
endif

if altitude > anterior and altitude > maxima then
maxima=altitude 'stores max height if actual height is higher than
disparo=altitude-50 'previous height and maximum
write 254,maxima.byte0 'deploy height is maximum - 50
write 255,maxima.byte1
endif

if altitude < disparo then
goto Abrir 'opens parachute hatch if actual height is lower than maximum-50
endif

anterior = altitude 'stores previous height
goto Main

'************************************************* *****************************
'routine for open parachute
Abrir:
maxima=0
disparo=0
anterior=0
for n=1 to 2 step 1
pulsout gpio.5,150 '1,5ms keeps servo at central position (opened)
pause 22 '22ms interval between pulses
next
goto Main

'routine for close parachute
Fechar:
maxima=0
disparo=0
anterior=0
for n=1 to 2 step 1
pulsout gpio.5,100 '1ms pulse keeps servo at -90° (closed)
pause 22 '22ms interval between pulses
next
goto Main

'RS232 com. routine
Serial:

for n=0 to 254 step 2
read n,m0 'reads eeprom
read n+1,m1
dado.byte0 = m0
dado.byte1 = m1
serout gpio.4,4,[1,#n,2," ",3,#dado,4," ",13] 'prints address and value
next

t=0 'resets eeprom writer counter

serout gpio.4,4,[1,"PRESS AGAIN TO ERASE!",13]

for n=1 to 25 step 1 'waits button to be pushed to erase eeprom
pause 200
if gpio.2=0 then
serout gpio.4,4,[1,"ERASING MEMORY...PLEASE WAIT",13]
for k=0 to 255 step 1
write k,0
next
serout gpio.4,4,[1,"EEPROM ERASED!",13]
serout gpio.4,4,[1,"BACK TO MAIN PROGRAM....",13]
goto Main
endif
next
serout gpio.4,4,[1,"BACK TO MAIN PROGRAM....",13]'if button is not pushed...
goto Main

ScaleRobotics
- 24th January 2012, 20:44
Thats a neat project, and you should feel proud of it! Especially for a first project!

Durring a pause statement, the micro just sits there counting time. It can do no math, or anything. What happens if you set this to something like 14 ms? The idea is that the epprom write takes another 5 ms, and we'll give the math 1 ms.

It would be a little faster doing it with 8 mhz, so you might as well set it there. I have to get back to work, but I will comment some more tonight.

HenrikOlsson
- 24th January 2012, 21:29
Yeah, the problem, as I see it, isn't that the PIC and your math is too slow...the problem is it's "too fast". This makes the ADC sample the signal very quickly so that between two samples the difference in altitude (or at least in the result given by the ADC) is so small that the actual change may drown in the noise. This fools the deployment algorithm into thinkin the altitude decreased.

When you introduce the PAUSE 200 the ADC only samples the signal 5 times per second (or there abouts) so the difference in signal from the pressure sensor is large enough not to allow the noise on the signal to trip the deployment algorithm.

There are several ways around this. The easiest is to do what you've done but tweak the PAUSE time to make sure the signal actually changes enough AND allow you to store enough samples depending on estimated time of flight. Another aproach might be to take 10 ADC samples and average them to filter the signal a bit, and then make sure that the a certain number of concecutive samples shows a decrease in height - not just one.

/Henrik.

rasciodc
- 24th January 2012, 22:03
Yeah, Henrik, I think the problem is exactly what you said, because I´ve just implemented the code to use ad raw data in comparision (to skip the math) and the result is the same!

The best result I got is with 190ms, which is the minimum pause that will not cause a false trigger. But it is still too high for a 15 second period of logging.

The filter is a good idea but I´ve also thought about using a higher adc sample time (ADC_SAMPLEUS 500 or something like that..) do you think that it would work?

Anyway, I think it´s a good idea to start thinking about a filter...

Thanks a lot!

Dave
- 24th January 2012, 23:59
One question I have is, How do you have the pressure sensor mounted? If it mounted in such way that the thrust is being impressed on the sensing element then the pressure readings will be offset. I would mount the sensor so that the sensing element is perpindicular to the rockets thrust. It should give you a much more stable and reliable reading. I would also take about 64 readings and do a right shift 4 places to the give you a 12 bit reading. I do this as a mater of fact for all of my A/D readings from the PIC internal A/D. I only use a 40uS. delay when changing channels. You should easily be able to captute the data at 100 Hz.

rasciodc
- 25th January 2012, 00:10
Well, I think the problem is finally solved! The problem was indeed the lack of a filter algorithm. Searching about this kind of issue I´ve found this: http://www.pbpgroup.com/modules/wfsection/article.php?articleid=7
This algorithm by Darrel Taylor solved the false deployment in my circuit.

I just changed the number of averaged samples from 16 to 8. Now I can fullfill my eeprom using the desired amount of time on "PAUSE" depending on the interval between samples I need.

This problem I think is solved, but you know how things go with programming... I´ll keep looking for bugs before I breadboard it and finally build the final circuit.

I´d still appreciate any comments and sugestions on my code. An "outsider" always has better view than the author himself (looking the same code for hours and hours...).

Thanks guys!!

rasciodc
- 25th January 2012, 00:13
One question I have is, How do you have the pressure sensor mounted? If it mounted in such way that the thrust is being impressed on the sensing element then the pressure readings will be offset. I would mount the sensor so that the sensing element is perpindicular to the rockets thrust. It should give you a much more stable and reliable reading. I would also take about 64 readings and do a right shift 4 places to the give you a 12 bit reading. I do this as a mater of fact for all of my A/D readings from the PIC internal A/D. I only use a 40uS. delay when changing channels. You should easily be able to captute the data at 100 Hz.

Yes Dave, you´re right! I still have to think about how the circuit will be disposed inside the rocket, calculate the pressure vents in the fuselage and etc...
Anyway, as I said, I am very noob to this so, is there any material where I can read about this 12bit reading with a 10bit AD?

spcw1234
- 25th January 2012, 00:14
I would also take about 64 readings and do a right shift 4 places to the give you a 12 bit reading. I do this as a mater of fact for all of my A/D readings from the PIC internal A/D. I only use a 40uS. delay when changing channels. You should easily be able to captute the data at 100 Hz.

Can you explain this in more detail? Sounds like an interesting trick to me. Thanks!

Dave
- 25th January 2012, 11:45
Just accumulate 64, 10 bit readings in a row into the same word variable, then do a shift to the right by 4 places which will give you a 12 bit result. Here is an example:
'************************************************* ********************
READAD: 'READ SYSTEM A/D VOLTAGES (AVERAGE 64 READINGS) 18F2620
'************************************************* ********************
TMPCHAN = CHANNEL 'COPY CHANNEL DATA
IF CHANNEL = 3 THEN TMPCHAN = 4 'SKIP CHANNEL 3 AS IT IS USED AS REFERENCE
ADCON0 = $01 | (TMPCHAN << 2) ' Set A/D to Channel X, On
PAUSEUS 40
VOLTS(CHANNEL) = 0 'CLEAR A/D READINGS
SCRATCH = 0
WHILE SCRATCH < 64 'SUM 64 READINGS
ADCON0.1 = 1 ' START CONVERSION
WHILE ADCON0.1 = 1 'WAIT FOR A/D TO FINISH
WEND
VOLTS(CHANNEL) = VOLTS(CHANNEL) + (((ADRESH & $3) << 8) + ADRESL) 'BUILD SENSOR WORD
SCRATCH = SCRATCH + 1
WEND
VOLTS(CHANNEL) = VOLTS(CHANNEL) >> 4 'TURN INTO 12 BIT RESULT

RETURN

gadelhas
- 25th January 2012, 15:40
Hi;

Following what Dave has said, take a look at this link, by Darrel Taylor;
http://www.darreltaylor.com/DT_Analog/

By the way rasciodc, i'm Portuguese too, i'm from Maia.

spcw1234
- 25th January 2012, 15:58
Thank you Dave, and Gadelhas! I am excited to try this!

rasciodc
- 28th January 2012, 18:26
Hi;

Following what Dave has said, take a look at this link, by Darrel Taylor;
http://www.darreltaylor.com/DT_Analog/

By the way rasciodc, i'm Portuguese too, i'm from Maia.

Thanks, gadelhas, for the link! very useful!! mainly for beginners like me!
And, actually I´m Brazilian! living in São Paulo at the time....


Just accumulate 64, 10 bit readings in a row into the same word variable, then do a shift to the right by 4 places which will give you a 12 bit result.
Dave, thanks for the explanation! How much time would this algorithm take to do this, any idea? (just wondering if I can use it in my altimeter...)
Thanks!

amgen
- 28th January 2012, 19:41
Isn't the 12-14-16 bit reading just a guess about being between the 2- 10 bit readings which could be off the expanded factor bits ??
If the a/d values do not bounce in the 64 samples, the actual voltage could be up or down on that step but the guess would be middle.
Don
amgen

ScaleRobotics
- 28th January 2012, 20:16
If the a/d values do not bounce in the 64 samples, the actual voltage could be up or down on that step but the guess would be middle.


Yes, but in practice the numbers jump around enough so oversampling can extract more data from the result. The main drawback is speed, but it is very effective.

Here's some sources of info:
http://www.atmel.com/dyn/resources/prod_documents/doc8003.pdf
http://ww1.microchip.com/downloads/en/AppNotes/Achieving Higher ADC Resolution Using Oversampling 01152A.pdf