Överhörning mellan analoga ingångar på PIC16F690

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
joharohl
Inlägg: 129
Blev medlem: 2 juli 2009, 13:07:39

Överhörning mellan analoga ingångar på PIC16F690

Inlägg av joharohl »

Har precis svängt ihop en timer till min framkallningsapparat. Den funkar fint förutom något jag upptäckte först jag suttit ihop den. Själva kretsen är väldigt simpel. Valet av tid sker med tre stycken potentiometrar som picen sedan läser av genom ad-omvandling. Problemet är att tiondelarna påverkas av tiotalsdelen. Jag försökte se om jag gjort något galet i mjukvaran (t.ex. glömt någon komparator eller något) men kan inte hitta något uppenbart. Tiotalen läses in på AN7 och tiondelarna på AN9. Har tyvärr inte kunnat läsa av volt på ingångarna så vet inte om det är något galet där.

Min egentliga fråga är om någon har någon erfarenhet av överhörning mellan kanaler när man adomvandlar? Brukar det ske ofta och är det något man måste ha i åtanke när man designar sina lösningar?

film: http://www.youtube.com/watch?v=Mgf9_i0EKSU

Kod: Markera allt

#include <pic.h>

void sjuseg(int siffra);

unsigned long tid = 0;

void main()
{
	//variables that are needed for in the loops
	int j,k,i;
	char ental=0, tiotal=0, hundratal=0;
	int temptid;

	//set the apropiat I/O for the different ports.
	TRISA = 0b00010000;
	TRISB = 0b00000000;
	TRISC = 0b11011000;
	ANSELH =0b00000011;
	ANSEL = 0b10000000;
	WPUA4 = 0;
	
	//init
	//RA4 = 0;
	
	//config TMR0 and intterupt.
	OPTION = 0b01010001;
	INTCON = 0b10100000;

	//config ADC
	ADCON1 = 0b00100000;
	ADCON0 = 0b00001001;

	//wait a short wile for ADC capacitor to charge.
	for(j=0; j< 30000;j++);
		

	j = 0;
	while(1){

		//turn off the timer.
		T0CS = 1;
		RC5 = 1;
		j=0;
		while(tid == 0)
		{
			
			//start a conversion for the first number.
			CHS0 = 1;
			CHS1 = 0;
			CHS2 = 0;
			CHS3 = 1;
			GODONE = 1;
			while(GODONE);
			ental = ADRESH/26;
						
			for(i=0;i<100;i++);

			//do the next one.
			CHS0 = 0;
			CHS1 = 0;
			CHS2 = 0;
			CHS3 = 1;
			GODONE = 1;
			while(GODONE);
			tiotal = ADRESH/26;

			for(i=0;i<100;i++);
			
			//do the next one.
			CHS0 = 1;
			CHS1 = 1;
			CHS2 = 1;
			CHS3 = 0;
			GODONE = 1;
			while(GODONE);
			hundratal = ADRESH/26;
			
			for(i=0;i<100;i++);

			switch(j%3){
			case 0:
				sjuseg(ental);
				RB5 = 0;
				RB6 = 1;
				RA5 = 1;
				break;
			case 1:
				sjuseg(tiotal);
				RB5 = 1;
				RB6 = 0;
				RA5 = 1;
				break;
			case 2:
				sjuseg(hundratal);
				RB5 = 1;
				RB6 = 1;
				RA5 = 0;
				break;
			};
			j++;
			
			if(RC4 == 1 && j>100)
				tid = (ental + tiotal*10 + hundratal*100)*100;
			if(RA4 == 1){
				RC5 = 0;
				while(RA4);
				RC5 = 1;
			}
	
		}

		//turn on the timer.
		T0CS = 0;
		//Turn on the relay	
		RC5 = 0;
		j=0;
		while(tid != 0){
			//calulate current time.
			temptid = tid/100;
			ental = temptid%10;
			tiotal = (temptid%100)/10;
			hundratal = temptid/100;
		

			switch(j%3){
			case 0:
				sjuseg(ental);
				RB5 = 0;
				RB6 = 1;
				RA5 = 1;
			break;
			case 1:
				sjuseg(tiotal);
				RB5 = 1;
				RB6 = 0;
				RA5 = 1;
				break;
			case 2:
				sjuseg(hundratal);
				RB5 = 1;
				RB6 = 1;
				RA5 = 0;
				break;
			};
			j++;

			if(RC4 == 1 && j>200)
				tid=0;
		}
	}
}

void interrupt tmr()
{
	//intterput handling function.
	if(tid != 0)
		tid--;
	
	TMR0 = 24;
	T0IF = 0;
}

void sjuseg(int siffra)
{
	switch(siffra)
	{
		case 0:
			RA0 = 1;
			RA1 = 1;
			RA2 = 1;
			RC0 = 1;
			RC1 = 1;
			RC2 = 1;
			RB4 = 0;
			break;
		case 1:
			RA0 = 0;
			RA1 = 1;
			RA2 = 1;
			RC0 = 0;
			RC1 = 0;
			RC2 = 0;
			RB4 = 0;
			break;
		case 2:
			RA0 = 1;
			RA1 = 1;
			RA2 = 0;
			RC0 = 1;
			RC1 = 1;
			RC2 = 0;
			RB4 = 1;
			break;
		case 3:
			RA0 = 1;
			RA1 = 1;
			RA2 = 1;
			RC0 = 1;
			RC1 = 0;
			RC2 = 0;
			RB4 = 1;
			break;
		case 4:
			RA0 = 0;
			RA1 = 1;
			RA2 = 1;
			RC0 = 0;
			RC1 = 0;
			RC2 = 1;
			RB4 = 1;
			break;
		case 5:
			RA0 = 1;
			RA1 = 0;
			RA2 = 1;
			RC0 = 1;
			RC1 = 0;
			RC2 = 1;
			RB4 = 1;
			break;
		case 6:
			RA0 = 1;
			RA1 = 0;
			RA2 = 1;
			RC0 = 1;
			RC1 = 1;
			RC2 = 1;
			RB4 = 1;
			break;
		case 7:
			RA0 = 1;
			RA1 = 1;
			RA2 = 1;
			RC0 = 0;
			RC1 = 0;
			RC2 = 0;
			RB4 = 0;
			break;
		case 8:
			RA0 = 1;
			RA1 = 1;
			RA2 = 1;
			RC0 = 1;
			RC1 = 1;
			RC2 = 1;
			RB4 = 1;
			break;
		case 9:
			RA0 = 1;
			RA1 = 1;
			RA2 = 1;
			RC0 = 0;
			RC1 = 0;
			RC2 = 1;
			RB4 = 1;
			break;
	};
}	
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av sodjan »

> Problemet är att tiondelarna påverkas av tiotalsdelen.

Påverkas hur mycket ?

För övrigt har jag lika få kommenterar som du har i din kod.
Jag tänker inte gissa vad du har tänkt...
Användarvisningsbild
mrfrenzy
Co Admin
Inlägg: 15566
Blev medlem: 16 april 2006, 17:04:10

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av mrfrenzy »

Ett litet schema kanske kan vara på plats för att utesluta en elektrisk orsak.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av sodjan »

Har du läst på om "acquisition time" ?
Det ser inte ut så av koden att dömma...
joharohl
Inlägg: 129
Blev medlem: 2 juli 2009, 13:07:39

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av joharohl »

Jo, jag vet att koden inte är särkilt kommenterad. En ovana jag lagt mig till med.

Det stör relativt lite. Om tiotalen är på 0 så kan man max vrida tiondelarna till 8. Om tiondelarna har något nollskillt värde så kommer tiondelarna att byta till 4 då tiotalen är 4-5 och sedan gå tillbaka till sitt ursprungliga värde när tiotalen är mer än fem.

Jo jag har kollat det där med aquisitiontime. Som jag förstod det var det bara den tid man behöver vänta när man slagit på adcn. För att ladda kondensatorer och sånt och det väntar jag in. Sedan skall väll GO/DONE registret ta hand om resten, eller måste man vänta aquistiontime varje gång?

Problemet är inte jätteakut att lösa. Så väldigt sällan man använder tiondels sekunder. Min förhoppning var bara att någon hade haft liknande problem och löst dom.

schema:

Det intressanta är väll U3, U4, U5 som är potentiometrarna. Till vänster är för sjuseg-displayerna och längst ner är ett relä.

Bild
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av Icecap »

Aquisitiontime betyder "omvandlingstid" och det betyder att man _måste_ vänta den tid varje gång AD-omvandlaren ska utföra en omvandling, minns inte men det finns väl något register som flaggar att en omvandling är klar, den flagga kan man använda.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av bearing »

Efter varje omvandling måste kondensatorn laddas upp.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av sodjan »

> Jo, jag vet att koden inte är särkilt kommenterad.

Helt ointressant om det är en "ovana" eller inte, men det är lite
korkat att posta kod med diverse sakar som är omöjliga att gissa
vad de gör. Jag kunde inte bry mig mindre om hur kod ser ut som du
aldrig visar någon annan, men det måste du borde ha fattat att det
där såg ut som skit innan du postade det här på forumet ?

> eller måste man vänta aquistiontime varje gång?

RTFM och gör som det står så får vi se om fenomenet kvarstår.
Så vitt jag vet (och såg i går) så finns det summerat i en enda mening.
Jag orkar inte leta reda på det nu igen, men det har ett eget litet stycke
i ADC kapitlet...

> Aquisitiontime betyder "omvandlingstid"

Fel.

> och det betyder att man _måste_ vänta den tid varje gång AD-omvandlaren ska utföra en omvandling,

Också fel.

> Efter varje omvandling måste kondensatorn laddas upp.

Också fel...

Om man tror som Icecap och Bearing så förstår jag att det blir fel.
Som sagt, databladet är tydligt på detta (letatde reda på det).
After the analog input channel is selected (or changed),
an A/D acquisition must be done before the conversion
can be started.
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av mri »

Vad har du för värde på potentiometrarna?
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av bearing »

Vad var fel i det jag skrev?
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av Swech »

Kod: Markera allt

for(i=0;i<100;i++);

         //do the next one.
         CHS0 = 0;
         CHS1 = 0;
         CHS2 = 0;
         CHS3 = 1;
         GODONE = 1;
         while(GODONE);
         tiotal = ADRESH/26;
Borde du inte ändra kanalen
chs0... chs3 innan du pausar? Det är iallafall rekommmenderat på en AVR

Sen skulle jag gjort t.ex. 16 mätningar på samma kanal och räknat ut ett medelvärde
Så som du gör nu är det lite optimistiskt utifrån störsynpunkt..

Swech
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av sodjan »

> Vad var fel i det jag skrev?

Att "Efter varje omvandling måste kondensatorn laddas upp".
Det är fel eftersom kondensatorn (eller igentligen sample&hold kretsen)
inte laddas ur under en omvandling (mer än marginellt).

Om man ligger fast på en kanal och har en insignal som man vet inte
förrändras speciellt snabbt (mellan två omvandlingar) så kan man köra
med betydligt kortare "Aquisitiontime".

Frågan om värdet på pottarna är också (som mri antyder) viktig.
För att hålla sig inom specen så ska Aquisitiontime *och* in-impedanser
ligga inom specen också. Med t.ex 100K pottar så kan man behöva
betydligt länge Aquisitiontime än vad som framgår av databladet.

Det ser ut som om du har förskt lägga till Aquisitiontime i koden, men
som jag *tolkar* det (i brist på kommenterar) så ligger den före
bytet av ADC-kanal, vilket alltså blir helt fel (som Swech också påpekar).
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av sodjan »

En enkel test är att ändra

Kod: Markera allt

         for(i=0;i<100;i++);

         //do the next one.
         CHS0 = x;
         CHS1 = x;
         CHS2 = x;
         CHS3 = x;
         GODONE = 1;
till

Kod: Markera allt

         //do the next one.
         CHS0 = x;
         CHS1 = x;
         CHS2 = x;
         CHS3 = x;
         for(i=0;i<100;i++);
         GODONE = 1;
på varje ställe. Om just den loopen ger korrekt Aquisitiontime
har jag inte en aning om, det får du kolla själv.
joharohl
Inlägg: 129
Blev medlem: 2 juli 2009, 13:07:39

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av joharohl »

Missade meningen att man måste vänta aquistiontime när man byter kanal. Är förmodligen det som är problemet. Skall testa, återkommer med resultat.

Tack så mycket för hjälpen.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Överhörning mellan analoga ingångar på PIC16F690

Inlägg av Icecap »

Jag ska nog börja sköta min sovtid bättre, aquistiontime betyder ju ung. "hämtningstid" och sodjan har rätt.

Dock vill jag tipsa om vad jag har sett lite varstans: en kondensator på varje analog ingång, typ 10-100nF och då speciellt när det är potentiometer. Orsaken är att när kanalen bytas OCH det finns en "betydande" spänningsskillnad mellan den förra och den nyvalda måste kondensatorn i ingången "laddas om", detta ger då en RC-lågpassfilter effekt, med en extern kondensator mellan GND och ingången minskar detta avsevärd och i detta där det är potentiometer (motståndsnätverk) är detta ganska viktigt.

Om vi utgår ifrån att potentiometerna är på 10K kommer de ju i mittställning att ha en impedans på 5k och räknar med de kapaciteter som finns (strökapasitere och S/H-kapaciteten) kan man räkna ut minsta aquistiontime.

Likaväl är jag förundrat över sättet, jag hade tyckt att en impulsgivare ville vara en mycket mer logisk lösning, jag har använd dessa till en frekvensgenerator och det att lägga till en "vrida fort -> stora steg, vrida långsamt -> små steg" är ganska enkelt.
Skriv svar