PIC18f4550 ADC problem

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
[ALV]
Inlägg: 204
Blev medlem: 30 september 2004, 13:55:12
Ort: Stockholm

Re: PIC18f4550 ADC problem

Inlägg av [ALV] »

Är det bara jag som finner detta komiskt?

TomasL: helt riktigt ADCON.F1 låter dig leka med en bit i taget, och i detta fall är bit 1 GO/DONE.

Det fungerar utmärkt, jag får äntligen in siffror.
Tack!
ToPNoTCH
Inlägg: 5152
Blev medlem: 21 december 2009, 17:59:48

Re: PIC18f4550 ADC problem

Inlägg av ToPNoTCH »

Du pratade om en potentiometer förut.

Använd den och testa med nu när det verkar funka.

pin 1 +5
pin 2 AD IN
pin 3 GND
[ALV]
Inlägg: 204
Blev medlem: 30 september 2004, 13:55:12
Ort: Stockholm

Re: PIC18f4550 ADC problem

Inlägg av [ALV] »

hur tänkte du nu?

du får nog förklara lite utförligare om jag ska lyckas med något :P
Användarvisningsbild
jojje
Gått bort
Inlägg: 6380
Blev medlem: 20 januari 2006, 01:53:33
Ort: Stockholms utkant
Kontakt:

Re: PIC18f4550 ADC problem

Inlägg av jojje »

Tom jag fattade. :D

Använd en pot som spänningsdelare, så kan du ändra värdet på ett lätt sätt.
[ALV]
Inlägg: 204
Blev medlem: 30 september 2004, 13:55:12
Ort: Stockholm

Re: PIC18f4550 ADC problem

Inlägg av [ALV] »

Ja, det fungerar bra.
jag vet bara inte hur jag ska läsa av hela ADRESH:ADRESL registret vettigt.

Gjorde en liten labb där jag styr positionen av ett servo med en pot.
Men mikroc vill tydligen inte göra som jag vill när det kommer till delay_us().

Eg:
for(i = 0; i < 1500; i++) {
delay_us(1);
}
motsvarar inte
delay_us(1500)
ToPNoTCH
Inlägg: 5152
Blev medlem: 21 december 2009, 17:59:48

Re: PIC18f4550 ADC problem

Inlägg av ToPNoTCH »

Jag gör ett nytt försök.

Om du vill testa att värdet ändras kan du använda en potentiometer.

En sådan har normalt 3 anslutningar.

Om du kopplar in den som jag beskrev, så har du en variabel spänningsdelare, där du på mittanslutningen får en variabel utspänningen mellan
0V-5V (om du matar med 5V).

Genom att vrida på potentiometern skall du således få ett konverterat värde mellan 0-1023 beroende på läget på potentiometern.

På detta vis kan du testa att allt funkar som det skall.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46986
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: PIC18f4550 ADC problem

Inlägg av TomasL »

Kod: Markera allt

Eg:
for(i = 0; i < 1500; i++) {
delay_us(1);
}
motsvarar inte
delay_us(1500)

Nej naturligtvis inte
Eftersom loopen "for(i = 0; i < 1500; i++)" tar tid att köra, och eftersom loopen är en int, blir det lite krångligare, då den måste itereras i flera steg.
Skulle hissa på, beroende på hur effektiv kompilatorn är, ett 20-tal instruktioner eller så.
därefter hoppet till din delay-rutin
sedan beror det ju på hur smart den är, anger du klockfrekvensen nånstans för kompilatorn?
ToPNoTCH
Inlägg: 5152
Blev medlem: 21 december 2009, 17:59:48

Re: PIC18f4550 ADC problem

Inlägg av ToPNoTCH »

Ähh..
Nu postade jag ju medan du svarade :roll:

Angående din fundering på delay_us så skall egentligen inte jag svara för jag kan inte C.
Men det kan ju vara så att instruktionerna i din loop tar tid.

Det jag menar är att din "for loop" kompileras till flera instruktioner vilka var och en tar en viss tid.
Det är först när den kommer till din delay_us(1) som den väntar en microsekund.

Det blir därmed skillnad mot en delay_us(1500) skulle jag tro.

Du kanske kan byta 1500 mot en variabel istället ? (Som sagt jag kan inte C)
Variabeln borde bli 1250 + (AD-värdet/2) för ett normal servo och skickas med 20ms intervall.
[ALV]
Inlägg: 204
Blev medlem: 30 september 2004, 13:55:12
Ort: Stockholm

Re: PIC18f4550 ADC problem

Inlägg av [ALV] »

ToPNoTCH:
Jag förstod det efter en stunds eftertanke, är inte helt bekväm med uttrycken gällande elektronik.

jag tror som sagt att jag läser av för få bittar eller att min potentiometer beter sig konstigt.
när jag vrider på den så går värdet upp från 0 till 255 och börjar sedan om från 0, detta kan upprepas nästan 4 gånger med fullt vrid.
vet dock inte om detta är ett resultat av 8 bitars avläsningen eller ej.


TomasL:
jag förstod nästan det, tycker dock att det verkar som att det går sjukligt mycket tid åt att iterera i så fall.
picen springer på 48MHz och borde således hinna göra några fler cykler tänker jag.

> sedan beror det ju på hur smart den är, anger du klockfrekvensen nånstans för kompilatorn?
ja, gissar att nästa sak att lära sig är timers eller finns det något bra sätt att kompensera med då det inte verkar som att kompilatorn är allt för smart?


ToPNoTCH:
> Du kanske kan byta 1500 mot en variabel istället ? (Som sagt jag kan inte C)
det finns vdelay_ms() men ingen vdelay_us(), vdelay_ms() till skillnad från delay_ms() klarar av att ta en variabel, där fastnade jag dock på att det inte gick att göra i stil med detta -> vdelay_ms(1.250 + (i / 1000)) och närmare bestämt så är det (i / 1000) som inte funkade.
ToPNoTCH
Inlägg: 5152
Blev medlem: 21 december 2009, 17:59:48

Re: PIC18f4550 ADC problem

Inlägg av ToPNoTCH »

Jo det låter ju som att du inte läser av (bryr dig om) de två höga bitarna i ditt konverterade värde.

Delay loopen överlåter jag till C bröderna att hjälpa dig med.

I ASM hade det varit en annan femma :roll:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PIC18f4550 ADC problem

Inlägg av sodjan »

> när jag vrider på den så går värdet upp från 0 till 255 och börjar sedan om från 0, detta
> kan upprepas nästan 4 gånger med fullt vrid. vet dock inte om detta är ett resultat
> av 8 bitars avläsningen eller ej.

Ja, det hela pekar ju på att du inte läser korrekt.
Det enklaste är väl att göra i = (ADRESH * 256) + ADRESL.
Kolla också så att det inte är så att man ska läsa ADRESH/L i en viss ordning...


> jag förstod nästan det, tycker dock att det verkar som att det går sjukligt mycket tid åt att iterera i så fall.
> picen springer på 48MHz och borde således hinna göra några fler cykler tänker jag.

Varför tycka en massa ! Det är bara att ta ASM listan från kompilatorn och räkna !

Men för att göra ett litet överslag...
Vid 48 MHz (om du faktiskt har verifierat att den går med det) så hinner den
*ca* 48/4 = 12 instruktioner / us. Vissa instruktioner tar 2 Tcyc, så säg 10 inst/us.

Ta och kolla i ASM listan från kompilatorn hur många instruktioner din loop
genererar, säg att det är 10 st (jag gissar mellan 10 och 20 instruktioner).
Alltså tar loopen i sig 1-2 us. Sedan har du en delay på 1 us. Hela loopen tar
alltså mellan 2-3 us. Gånger 1500 gånger blir det 3.0 - 4.5 ms. Alltså lite längre
än det andra exemplet som tar ca 1.5 ms. Är du med ?

> ADCON2 = 0b10111000; // Right just, ??

Varför frågetecken ?
Det är bara att kolla upp dina bitar mot ADCON2.

Du kör "A/D Conversion Clock Select bits" som 000 = FOSC/2.
Jag vet inte, men är inte det lite väl snabbt för 48 MHz ?
Jämför med "TABLE 21-1: TAD vs. DEVICE OPERATING FREQUENCIES",
där använder man 110 = FOSC/64 för 48 MHz.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46986
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: PIC18f4550 ADC problem

Inlägg av TomasL »

För att "förenkla" det lite så du kan se exakt vad du får ut från AD-omvandlren kan du skapa en liten typdef

Kod: Markera allt

Typedef union AD_RESULT 
{   unsigned int Val;
     unsigned char v(2);
}ADRESULT;
   
Sedan skapar du variabeln

Kod: Markera allt

ADRESULT adresult;
Vad du får är är en variabel som dels är en int och samtidigt är en array av char

Du kan då läsa in AD-värdet

Kod: Markera allt

adresult.v[0]=ADRESL;
adresult.v[1]=ADRESH;
Nu kommer du åt både den höga och låga bytarna utan att förvanska dem, samtidigt som du kan hantera hela resultatet som en int.

Dock är det naturligtvis snabbare och effektivare att läsa in det direkt till en int, och skifta.

men ur debughänseende kan det ge dig lite klarhet
bos
Inlägg: 2311
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: PIC18f4550 ADC problem

Inlägg av bos »

[ALV] skrev:jag vet bara inte hur jag ska läsa av hela ADRESH:ADRESL registret vettigt.
Definiera "vettigt".

Jag visade ju hur du skulle göra: i = (ADRESH << 8) | ADRESL. Är det så att 8-bit upplösning räcker för dig så kan du skrota de två lägsta bitarna. Det kan du göra på två sätt: i = (ADRESH << 6) | (ADRESL >> 2) om du kör Right Justified, eller i = ADRESH om du kör Left Justified.
[ALV]
Inlägg: 204
Blev medlem: 30 september 2004, 13:55:12
Ort: Stockholm

Re: PIC18f4550 ADC problem

Inlägg av [ALV] »

Efter en del felsökande så tror jag att det är uart som strular för mig.
både

Kod: Markera allt

i = (ADRESH << 8) | ADRESL
och

Kod: Markera allt

i = (ADRESH * 256) + ADRESL
verkar fungera om jag styr ett servo med resultatet som delay (bortsett från drifting av dålig kod).

Min terminal ger dock bara 0-255 och börjar om från 0 igen, det har nog med att göra att jag inte skickar resultatet som ascii.

>Men för att göra ett litet överslag...
>Vid 48 MHz (om du faktiskt har verifierat att den går med det) så hinner den
>*ca* 48/4 = 12 instruktioner / us. Vissa instruktioner tar 2 Tcyc, så säg 10 inst/us.
>Ta och kolla i ASM listan från kompilatorn hur många instruktioner din loop
>genererar, säg att det är 10 st (jag gissar mellan 10 och 20 instruktioner).
>Alltså tar loopen i sig 1-2 us. Sedan har du en delay på 1 us. Hela loopen tar
>alltså mellan 2-3 us. Gånger 1500 gånger blir det 3.0 - 4.5 ms. Alltså lite längre
>än det andra exemplet som tar ca 1.5 ms. Är du med ?
Ja, jag borde således kunna skriva en egen vdelay_us funktion för detta men frågan är dock om det inte är lättare att använda sig av en timer?

Mitt försök till funktionen som inte verkar fungera såbra:

Kod: Markera allt

void vdelay_us(unsigned time_us) {
  time_us = (time_us * 48)  * 4 // time * MHz * 4 instructions 
  while(time_us--)
    asm nop;
  }
}

Efter mycket sökande i mikroc:s forum och här så hittar jag inget om hur jag kan omvandla exempelvis en integer till ett ascii array.

hur gör ni andra? har någon gjort ett enklare protokoll för att skicka kommandon och ta emot resultat i ascii från en pic?
bos
Inlägg: 2311
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: PIC18f4550 ADC problem

Inlägg av bos »

> det har nog med att göra att jag inte skickar resultatet som ascii.

Varför spekulera? Det är rätt uppenbart varför det blir fel: Din USART_Write() som du inte har källkod till tar med stor sannolikhet emot en char som parameter, medan ditt ADC-värde ligger i en int. Varför du får fel värde i överföringen kan du nog lista ut själv.
Skriv svar