Fixed point uträkning i C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Håller helt med Schnegel.....'s utlägg och vill lägga till lite:
I de 3-prosessor system som jag nämnde i flygjärn är programmen till varje dator gjord i olika (verifierade) språk samt av olika företag/grupper utan något samarbete. Detta medför att de inte "låner" kod av varandra och därmed inte risikerar att kopiera logiska bomber.

I ditt fall är det livsuppehållande system vi pratar om och ha som backup att ta den yttersta reserv är fet-fel tänkt! Därmed kan du lika väl ge upp och låta bli, du planerar alltså att göra ett system som fungerar lite sådär.....

Det är inte lönt att oja sig över risk för saltkristaller osv, inpackningen av elektroniken blir mycket svår att lösa ändå.

Jag hade INTE byggt ett system som är livsviktigt för mig (bokstavligen) med den säkerhet att den nog börjar pipa strax innan det skiter sig!

Jag gillar att göra saker som kan få andra att rygga tillbaka men jag vill inte dö på grund av egen dumhet!

Jag kan ge dig ett aktuellt exempel:
En kompis, dykare (numera yrkes-) dök med en kompis på 40m+. Kompisens regulator började friflöda och släppte ut allt men de upptäckte det inte förrän det var kört. Lugna puckar, tänkte polarn, jag ger honom min 6L pony och sen går vi upp.
Tyvärr hade han glömt att fylla den.....
Plötsligt ska de klara sig på 1 rig med deko-tid modell lång och de blir tvungen att "tänja" kraftigt på tabellen för att klara sig med luft. Inte bra!

Din backup kan paja, då har du inget! Ett fel kommer sällan ensamt!

Edit: Lite stavfel samt: När man lagar rost på gammal bil ser man hur mycket det är, multiplicerar med 2 och lägger till godtyckligt tal, då vet man hur mycket det egentligen är. Samma sak med elektronik: det är inte 1 sak kan kan knasa lite, det kommer att bli en hel del mer...på samma gång!

Exempel: jag var i Suezbukten (via Kairo) för att laga styrningen på en släpbåt modell större (120m lång, ryssbygge). Hela felet bestod i att en diod (1N4001) hade blivit varm och ramlat ut! Den diod såg till att det alltid fanns ström till stryrningen av hydrauliksolenoiderna till rodret!

Väldig säkerhet! Jag monterade ny och böjde benen så att om lödningerna bjev mjuka ville den sitta ändå, inte bra men bättre. Den felfunktion hände i storm, de hade haft det.....intressant (kan man väl kalla det) fram till deras mekaniker fick byglat "tjuvström" på igen.

Du ska tänka igenom HELA systemet och fundera KRAFTIGT på att allt kan paja och ge helt fel signaler, om 2 system motarbeter varandra, vem har då rätt? Ett 3;dje system kan övervaka vissa funktioner (t.ex. O2-ventilens drivning) och bara, hårdvaramässigt, tillåta att ventilen är öppen en viss max. tid, om den överskrids är det katastroflarm och ventilen stängs osv.
Senast redigerad av Icecap 24 augusti 2005, 11:52:52, redigerad totalt 1 gång.
Användarvisningsbild
Schnegelwerfer
Inlägg: 1863
Blev medlem: 8 november 2004, 13:46:56

Inlägg av Schnegelwerfer »

Icecap: Du har så rätt när det gäller mjukvaruutvecklingen.

Hur mjukvaruutvecklingen i sådana här projekt ska bedrivas finns beskrivet i CENLECs standarder, och det bygger på att olika personer MÅSTE utföra själva programmeringen och valideringen.

Man även använda två helt separata program skrivna av olika personer, men det är inte nödvändigt om man istället lägger ner större resurser på validering av systemet.

Viktigt att komma ihåg i detta fall är att trots att systemet bara ska larma så är funktion livskritisk. Ett uteblivet larm kan ju innebära livsfara.

Vad jag kommer ihåg om syrgasförgiftning, är att den inträffar utan förvarning och manifesterar sig i okontrollerbara kramper som kan medföra att man drunknar.

Om du får akut syrgasförgiftning är det således inte säkert att du KAN använda ditt reservsystem.
gille
Inlägg: 69
Blev medlem: 28 november 2004, 18:06:09
Ort: Stockholm
Kontakt:

Inlägg av gille »

Beskrivningen av syrgasförgiftningen stämmer rätt så bra vad jag vet.
Samma sak med hypoxi, den kommer smygande den med.

Två system skrivet av två olika personer används inom tåg.

Om man ska bygga något liknande så ska man väl inte ha något som måste "styras" till larm utan tvärt om, om man inte får rätt styrsignal så larmar man.

Men är det inte enklare, (billigare?) och säkrare att köpa en annan rebreather?
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

jag har inte planerat att göra ett system som "fungerar sådär" Jag bygger ett system som gör massor av självtester och kontroller för att få reda på början till fel. Däremot vet jag systemets begränsningar och spelar efter dem.

Jag har inte tänkt göra några decodykningar eftersom jag vet att om det blir fel i syrgastillförseln så måste jag kunna gå raka vägen upp till ytan.

Jag vet även att man brukar räkna på att när man dyker, så skall partialtrycket för syrgas inte överstiga 1.4. MEN jag har även utbilding inom försvaret där det står klart och tydligt att man kan klara partialtryck upp till 2.2 i upp till 10 minuter. Det finns med andra ord en ganska stor marginal.

Jag bygger inte systemet helt själv. utan har en kompis som oxå håller på och bygger ett liknande system. Ni påpekar att det skall vara olika personer som skriver koden, och det går absolut att lösa.

Båda systemen har varsin summer, så jag förlitar mig på 2st summrar och två transistorer. Båda systemen har egen strömtillförsel och är inkapslade var för sig.

Om båda systemen spottar ut olika svar. då är nått fel, jag avbryter dyket och går upp mot ytan.

Om ena systemet slocknar och startas om, går larmet och man går upp till ytan.

osv..

Om man åker en båt ute till havs och styrningen pajjar under en storm. Vad gör man då?
Om styrningen till ett flygplan går sönder uppe i lufen, vad gör man då??
Ytan finns alltid 30-40m från mig..

givet vis måste man vara otroligt försiktig och följa checklistor osv innan jag utför mitt dyk. Allt kan hända. Ni må tycka att jag är rent ut sagt dum om jag gör detta. Det är möjligt, men det är inte hela min uppfattning. Jag lyssnar gärna på era synpunkter.

Jag borde egentligen presentera mitt projekt på ett mer begripligt sätt innan ni sågar min ide'e :wink:

en annan rebrader kostar runt 30kkr och uppåt beroende på modell och vad den klarar av. Det har inte jag råd med. Jag gör abolut inte detta enbart för att spara pengar. Jag gör det för att jag har ett brinnande intresse för både dykning och elektronik och tyckte att detta var en rolig utmaning. Upptäcker jag att mitt system är livsfarligt, så dyker jag givetvis inte med det. livet är mer värt
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jag tycker faktisk att det är en bra idé, det är bara mycket att tänka på. Att en rebreather (lyx modellen så att säga) är grisdyr är ju säkert och jag tycker att du ska köra vidare i spåret men nu vet du om hur du ska tänka, vad som kan gå fel osv.
gille
Inlägg: 69
Blev medlem: 28 november 2004, 18:06:09
Ort: Stockholm
Kontakt:

Inlägg av gille »

Jag sågar inte, jag tycker det verkar tufft och om du känner att du har kompetens samt provar ut det på lämpligt djup (jag är själv dykintresserade med ett AOW och intresserad av rebreathers).


Vad gick den här på?

Men annars om du planerar in ordentliga failsafes så bör det ju fungera.
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

ja, jag har fått lite nytt att tänka på, definitivt! tackar för responsen!
problemet är nu att elektroniken är i stort sätt färdigdesignad och jag har inte längre tillgång till elektroniklabb om jag skulle vilja göra om något kretskort. Jag måste komma på något smart sätt att lösa det hela på..

rebradern köpte jag i julas, ett riktigt kap. jag gav 10kkr för den. Då fick jag med en extra 5l flaska och en helt ny ponybottle från poseidon. Fullständig kursliteratur för både nauis utbildning och drägers egen. Dessutom fick jag med massor av extra packningar och lite reservdelar + annat lullull som e bra att ha.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Låter som en jävla bra deal!

Och sen heter det "rebreather" enligt vad jag har lärt mig.
gille
Inlägg: 69
Blev medlem: 28 november 2004, 18:06:09
Ort: Stockholm
Kontakt:

Inlägg av gille »

Om du är helt säker på att det är så du vill ha ditt kort på gör olimex.com billiga kort.
Annars finns det säkert nån här som kan tillverka ett kort eller två till självkostnadspris.
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Re: Fixed point uträkning i C

Inlägg av Kaggen »

dangraf skrev:Just nu har jag ett uttryck på formen f(x) = k*x+m
som jag skrivit ner till

Kod: Markera allt

     po2 = 0.0449*(float)tempres+8.7860;
Där po2 står för "partial pressure oxygen" (partialtrycket för syrgas)

0.0449 är mitt "k" värde som jag multiplicerar med resultatet från AD omvandlaren.

8.7860 är min konstant "m" eftersom det finns en viss "bias" i systemet.

Just nu så spottar systemet ur sig tal mellan ca 0- 190 vilket motsvarar %syrgas. 160% syrgas kan man andas om man använder 100% syrgas att dyka med ner till 6m djup.

AD omvandlaren jag använder har en upplösning på 12 bitar. (ger värden från 0-4095).
Du skriver att ditt maxvärde är 190, men 0.0449 * 4096 är ju 183.91? Du kan alltså inte få ut mer än 183 (heltal) när A/D:n maxar och inte 190 som du skriver ovan.

Om inte jag totalt missförstått allt borde du ju ha en konstant på c.a. ~0.04639 (190 / 4096). Detta under förutsättning att 190 är det mesta du nånsin behöver få ut. Du har väl funderat på implikationerna ifall det "verkliga" värdet överskrider 190?

Mitt önskväda mål är att ha en pressition på 1%.
I ovan nämnda fall borde du enligt mig få en precission på c.a. 0.0244%. Någon får rätta mig om jag har fel.
Jag har märkt att om jag har ett litet fel på "k" värdet, som knappt märks när man mäter syrgasen i luften (20.9%) så kan det bli åt helvete fel åt nått håll när man får större värden från AD omvandlaren då man når 160-190% syrgas. och det är VÄLDIGT VIKTIGT att det inte diffar några 10% när man når höga koncerntrationer eftersom kan leda till olyckor.
Är du säker på att kurvan från 0 - 190 är linjär?
Mina frågor:
Hur gör jag för att använda fixed point uträknigar på ett smidigt sätt i C?
Tja! Om du nöjer dig med heltal så går väl följande att göra...

Om du har en konstant (ett tal som aldrig ändras i dina formler) säg 0.04639, kan du multiplicera med 65536 för att få en fraktion av värdet, d.v.s i detta fall ~3040. Du multiplicerar sedan ditt tal med 3040 och shiftar det höger 16 steg: result = (3040 * value) >> 16; vilket är det samma som: result = int(0.04639 * value);.

Rotera 16 bitar höger är detsamma som att dividera med 65536, skillnaden för en processor är att det är snabbare (i de flesta fall) än att använda en generell rutin som utför heltalsdivision.
Efter som du måste ha en 24-bitars variabel för att lagra produkten av 3040*value och varje byte måste roteras genom carry för att föras över till nästa lägre byte så blir det iofs 16 * 3 = 48 RRF kommandon i assembler (48 instruktionscykler = 192 klockcykler = 192 us vid 4MHz klocka).

Jag skall inte påstå att detta är det bästa sättet dock. Någon får gärna föreslå en bättre ide. Det går iofs att ändra konstanten till en fraktion av 256 (8-bitar) istället för 65536, men upplösningen/precisionen blir då betydligt sämmre.

mvh Mats
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Tackar kaggen!!

Kod: Markera allt

 result = (3040 * value) >> 16; 
Det var just den där jag var ute efter.
Jag testade din variant och sparade mitt resultat som en unsigned long (4byte). Enligt debuggerns stoppklocka lyckas räkna ut talet på sju(7) klockcykler.

Testade tidigare med att skriva

Kod: Markera allt

	o2sensor = (unsigned long)result<<14;
	o2sensor = o2sensor/3694+907;
men det var ingen förbättring jämfört med flyttal eftersom den där divitionen tar förbaskat mycket processorkraft! (fortfarande ca 500 klockcykler)

Tackar igen!!

Angående det där med att jag skrev att mitt maxvärde blev 190, så tror jag du missade mitt "ca" som står före.I din uträkning missade du dessutom min konstan på 8.7 vilket ger ett resultat på 192,652 för att vara exakt ;-)

Jag vet att kurvan är i stort sätt helt linjär.
jag kan redovisa nedan hur jag gjorde.

Eftersom jag inte hade någon kalibrerad syrgassensor som referens fick jag göra köra en liten uträkning med "least squares method".

Jag hade ungefär 100% syrgas (observera att syrgashalten är något osäker) i en påse tillsammans med syrgassensorn.
Därefter lät jag lite luft att sakta sippra in i påsen. Under tiden skrev jag upp syrgassensorns utsignal vs utsignalen på AD omvandlaren.

mitt mål var att kunna beräkna f(x) = k*x+m

f(x) = utsignal från sensorn
x = utsignal från AD omvandlaren
m = konstant

jag skapade 2 vektorer

X = Y =
x1 y1 1
x2 y2 1
x3 y3 1
. .
. .
. .
xn yn 1

Anledningen till att jag lägger till 1 or i Y vektorn är för att jag vill ha en linjäroperator "s" så att jag kan skriva
Y *s = X
s innehåller alltså mitt k och m värde ( s = { k , m} )

För att kunna beräkna s gjorde jag följande beräkning
(Y' = transponatet av Y)

Y'*Y*s = Y'*X =>
s = (Y'*Y)^-1*Y'*X


Därefter testade jag min formel med att köra

uppskattade värdena = Y*S

och fick fram att mina uppskattade värden var nästintill exakt samma som de i min X vektor. (har plottat i matlab)

Det enda kända kända värdet jag har är luften som jag andas, och kalibrerade mitt k värde efter det.
Därefter kunde jag räkna fram vilken den högsta syrgashalten var i påsen, vilket visade sig vara 99.2% syrgas.

Hoppas ni hängde med.

Är det något jag missat eller förbisett, säg gärna till.


/Daniel Grafström
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

Kom på en sak!

Om man skriver i assembler är det totalt onödigt att rotera ner 16 bitar i ex.vis ett 32-bitars heltal med 16 * 4 rrf instruktioner som jag dillade om i förra inlägget. Det är ju bara att ta de övre två byten och använda dem direkt eller flytta dem med fyra mov instruktioner dit man vill ha dem. :lol:

Ibland ser man inte skogen för alla träd! :oops:

Antagligen så optimerar C kompilatorn sådana fall på liknande vis, vilket förklarar de 7 klockcyklerna du nämner.

Dessutom behöver det ju inte vara just 16 eller 8 bitar man roterar med, men enligt ovan så torde det ju bli mest optimalt.

Mats
Skriv svar