Advarsel: Meget langt indlæg.Giver det bedre mening nu ? 
Jeg forstår godt metoden med at finde værdien (eks 71), men aner ikke hvordan jeg skal kode det, og får jeg ikke en masse floating med alle de divisioner?
Hvis du får floating point kode med de viste divisioner, har du en dårlig compiler, for den skal for det første selv reducere konstante tal, dvs. tal, som den kan regne værdien ud af på forhånd.
Compileren kan fx. reducere udtrykket
uint16_t plads;
plads = ((4 + 12) / 2) * 3.
Dette kan du nemlig også selv reducere.
Så uanset om du skriver ovenstående, eller...
...vil resultat-koden være nøjagtig den samme.
Men compileren kan ikke reducere udtrykket
uint16_t plads;
plads = ((kaniner + elefanter) / marsvin) * salater.
Dog kan intelligente compilere reducere følgende:
uint16_t kaniner;
uint16_t elefanter;
uint16_t marsvin;
uint16_t salater;
uint16_t plads;
plads = ((kaniner + elefanter) / marsvin) * salater;
Det kan være svært i starten, at gennemskue hvad der foregår i en compiler, men efterhånden som du bruger den, vil du få en bedre fornemmelse af 'hvordan de tænker'.

Bemærk: Koden til at finde disse konstante tal er kun beregnet til dip-switches og knapper med modstande, ikke potmetrene.
værdien i nedenstående er så konstanten #define ADC2_CALIBRATION; eller hva?
Denne kode er til kalibrering af eks adc2
værdien value hvor kommer den fra? for hvis getADCvalue er en aflæsning af spænding (som du skrev for nogle posts siden) så skal jeg jo have en omregning til 10 bit værdien et eller andet sted.
Inden nævnte kode, skal du bare aflæse ADC'en på denne måde...
value = getADC#value();
if(value >= 0 && value < ((0 + 127) / 2))
{
/* setting 1 */
}
else ...
Skal det så gøres ved en beregning der f.eks ser således ud
void calculation (int16_t value)
{
calc = 0,2048 * getADC2Value;
return(calc);
}
(de 0,204 er en omregning af 1024 / 5000 til en konstant, for at undgå divisioner i programmet til gengæld er det et komma tal som jo også er noget skidt)
I ovenstående kode returnerer du void (ingenting), hvilket vil sige at du kan ikke returnere et tal.
calc er ikke defineret. Hvis calc er en float, så vil du få floating-point kode, hvilket du ikke ønsker.
value bliver ikke brugt til noget, den kan udelades fra argumenterne.
getADC2Value skal have paranteser på, for ellers får du adressen på funktionen (dvs. du får at vide hvor i hukommelsen funktionen ligger).
Derimod, hvis calc er et heltal, vil du altid få resultatet 0, da 0.2048 vil blive rundet ned af compileren før der ganges med getADC2Value().
Denne stump burde kunne virke:
uint16_t calculation()
{
uint32_t calc;
/* simpel: */
calc = (5000 * getADC2Value()) >> 10;
/* eller med op/nedrunding: */
/* calc = (((5000 * getADC2Value()) >> 9) + 1) >> 1; */
return(calc);
}
Desværre kommer vi helt op på 32 bits midlertidigt, men det må så være det, det er.
Her får du så resultatet i millivolt.
Men du kunne også gøre det omvendte, nemlig regne millivolt om til ADC-værdi:
if(value > (1023 * 1500 / 5000))
{
/* value is 1.5V */
}
På den måde vil din kode blive mindre og hurtigere, fordi compileren kan reducere de konstante tal.
Bemærk: Vi ganger før vi dividerer, for at vores resultat skal blive så præcist som muligt.
Dette gør vi pga. at vi regner med heltal.
1023 / 5000 = 0.
1023 * 1500 = 1534500
1534500 / 5000 = 306
Man kan lave et hjælpeværktøj til dette...
#define MILLIVOLT2ADC(a) (1023 * (a) / 5000)
Eller endnu bedre, et, som kan runde op eller ned til nærmeste heltal:
#define MILLIVOLT2ADC(a) (((1023 * (a) / 2500) + 1) / 2)
Her lægger jeg 1 til, og dividerer med 2; det er det samme som hvis man kunne lægge 0.5 til det færdige resultat.
Man kan bruge bitskift til at dividere med 2:
#define MILLIVOLT2ADC(a) (((1023 * (a) / 2500) + 1) >> 1)
...Så de sidste 2 MILLIVOLT2ADC vil give de samme resultater.
og i tilfælde af at det skulle være så heldigt at være denne måde hvorpå jeg skal gøre det. bør det så gøres i min adc.c eller i min dosing.c
Jeg anbefaler at lave det i dosing.c, for adc.c er stort set kun aflæsning. Prøv at forestil dig det som om adc.c bruges i 10 andre programmer der har med ADC at gøre.
-På den måde vil det være lettere for dig at se hvor du bør lægge tingene.
Jeg beklager og er ked af hvis jeg er lidt tung i det her lige nu (hader at føle mig så tabt bag vognen)
Helt iorden.

og lige et spørgsmål mere, jeg er ikke sikker på om du så det jeg skrev i min tidligere post så tillader mig lige at gentage spørgsmålet her
kan jeg ikke splitte dippen op i 2 og så køre antal doseringer pr dag ind på pa1 og repeats ind på pa4 hvis jeg så bruger 300 k og 150k samt en 150k fra pb2 og en fra pa1 til gnd, så får jeg da en foreskel i værdier fra 1.6 volt til 3 og kan nøjes med 4 cases for hver funktion istedet for 16 cases på 1 funktion ??
Det kan du godt, men modstandenes værdier bør ikke ændres. 150K og 300K er nok for store.
Du bør normalt bruge modstande under 10K, da støj ellers kan påvirke dit kredsløb.
Jeg anbefaler stadig at køre med de nævnte værdier: 0.5K, 1K, 2K, 4K.
Jeg vil tro at hvis du sætter 1K på den ene switch og 2K på den anden switch og 2K på output (istedet for 3k9), så ville det kunne fungere. -Og så lave to stk af dem i alt.
Jeg tror du har fejl i dine værdier (0 + 127), (128 + 191), osv.
Grunden er at vores modstands-netværk ikke leverer linære værdier.
Derfor kan vi ikke bare 'dividere med 2' hele vejen; ellers havde der været en simplere metode.

Men i stedet for den lange 'if/else if' kode, kan du gøre koden kortere, ved at aflæse en tabel.
Udførslen tager et par ekstra clock-cycles (hvilket ikke betyder noget i dette tilfælde).
Mit skud er at denne kode vil fylde lidt over 48 bytes, hvilket er en hel del kortere end tidligere nævnte kode:
Følgende #include bør indsættes i toppen af dosing.c, fx. nede under #include <avr/io.h>:
#include <avr/pgmspace.h>
Dernæst, et eller andet sted, du synes er passende:
uint8_t calculateSetting(uint16_t aValue)
{
const uint16_t convTab[] PROGMEM = { ((1023 + 523) / 2), ((523 + 349) / 2), ((349 + 262) / 2), ((262 + 209) / 2),
((209 + 174) / 2), ((174 + 149) / 2), ((149 + 131) / 2), ((131 + 116) / 2), ((116 + 105) / 2), ((105 + 95) / 2),
((95 + 87) / 2), ((87 + 80) / 2), ((80 + 75) / 2), ((75 + 70) / 2), ((70 + 65) / 2), 0 }; /* 3K9, 5% */
uint8_t i;
i = 0;
while(aValue <= pgm_read_word(convTab[i]))
{
i++;
}
return(i);
}
Tabellen er beregnet efter VCC=5.00V, men den er checket op ad VCC=5.05V med en 3K9, 5% modstand (3k86), og værdierne er ikke langt fra hinanden.
Include-filen pgmspace.h indeholder macroer, som gør det nemt at læse tabeller der ligger i Flash-memory, frem for at de først lægges over i RAM. Dette sparer både RAM og reducerer kode-størrelsen.
... Koden er afprøvet som program på min Mac, og giver korrekte resultater.
Tabellen er baseret på en 3K9 modstand.
Her er en tabel, som er baseret på en 4K/0% modstand. Du kan fx. bruge 2 stk. 2K modstande på 1% ved udgangen:
const uint16_t convTab[] PROGMEM = { ((1023 + 512) / 2), ((512 + 341) / 2), ((341 + 256) / 2), ((256 + 205) / 2),
((205 + 171) / 2), ((171 + 146) / 2), ((146 + 128) / 2), ((128 + 114) / 2), ((114 + 102) / 2), ((102 + 93) / 2),
((93 + 85) / 2), ((85 + 79) / 2), ((79 + 73) / 2), ((73 + 68) / 2), ((68 + 65) / 2), 0 }; /* 4K, 0% */
Tabellen er beregnet efter VCC=5.00V, men den er checket op ad en 4K, 1% modstand.
Det er bedst at bruge de beregnede tabeller, frem for en tabel baseret på målte værdier, fordi hvis du har en modstand der ligger på -5%, og du baserer værdien på denne, vil du få fejl, den dag du bruger en modstand på +5%. Er tabellen baseret på +0%, vil du undgå fejlen.
Her er et par små formler, som du kan bruge til at beregne tabellerne:
voltage = VCC * 1000 / ((r1 + r2) / 8
) / (setting + 1)
* 1000 er for at lave volt om til millivolt
r1 er din udgangs-modstand i ohm, fx. 3900.
r2 er værdien på den største modstand der sidder til en switch i ohm, fx. 4000.
setting er et tal mellem 0 og 15.
Her går jeg selvfølgelig ud fra, at modstandsværdierne bliver halveret efterhånden som der sættes flere switches på.
Formlen kan skrives om til en lidt mere lommeregner-venlig udgave:
voltage = VCC * 1000 * 8 / (r1 + r2) / (setting + 1)
Du kan så omregne voltage til ADC værdi:
adcValue = 1023 * voltage / 5
Formlerne kan reduceres yderligere og de kan også kombineres til én formel der giver dig adcValue.
og tusind tak for arbejdet med dip readings
Velbekomme.
