Sida 1 av 1

PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 17 juli 2013, 13:43:21
av bjornvaktaren
Hej! Jag är rätt så ny på det här med mikroprocessorer. Mitt mål är att styra ett peltierelement för att kontrollera kylningen av en sensor. Jag använder MPLAB med C18 och PicKit2. Jag har fått en termistor att fungera med ADC:n AN0 och skickar ut temperaturen på 3 st 7 segments LED displayer vilkas LED:s drivs av port E och multiplexas av RE0:3.

Nu vill jag kunna trycka ner knappar för att ställa in en önskad temperatur. Första steget är att få knapparna att fungera... Knapparna är kopplade till RA1 och RA2 som på denna bild:
Bild
fast med Vin och Ground bytt så att jag för 5V när jag trycker ner knappen. Resistorerna är på 10K. Knapparna fungerar om jag kopplar in en LED men inte när jag försöker läsa dem med PIC:en. Det kan vara något fel med hur jag sätter bitarna som styr ADC:n... Jag har sökt runt massor på nätet men inte hittat något som löst mitt problem.

Har ni några idéer?

Kod: Markera allt

#include <p18f4550.h>
#include <delays.h>

#pragma config FOSC = HS // High-speed oscillator
#pragma config WDT = OFF // Watchdog timer off

typedef unsigned char uint8_t;

unsigned int adc_in; // Stores the ADC value
unsigned int pe_temp; // Peliter element temperature
int digit; // Digit to display on LED-segment
int digit_res; // The rest of the ADC value when digit has been subtracted
unsigned int i; // used in a for loop
uint8_t n;  // the element to lookup in adc_to_t[64]
static const uint8_t seg_disp[10] = {
	0b11101110,
	0b01100000, 
	0b11001101, 
	0b11101001, 
	0b01100011, 
	0b10101011, 
	0b10101111, 
	0b11100000, 
	0b11101111, 
	0b11100011}; // 10 digits: 0-9
static const uint8_t seg_nbr[4] = {
	0b00000000, // Display off
	0b00000001, // 3rd digit
	0b00000010, // 2nd digit
	0b00000100}; // 1st digit or minus
static const int adc_to_t[64] = { // ADC to temperature for 6 MSBs
	-7047, -7047, -6307, -5841, -5492, -5208, -4966, -4754,
	-4564, -4390, -4230, -4080, -3939, -3805, -3677, -3554,
	-3436, -3321, -3209, -3101, -2994, -2890, -2787, -2685,
	-2585, -2485, -2386, -2288, -2190, -2091, -1993, -1894,
	-1807, -6306, -1593, -1491, -1387, -1282, -1174, -1065,
	-952, -837, -719, -597, -471, -340, -204, -61,
	88, 246, 413, 591, 782, 989, 1215, 1464,
	1742, 2059, 2426, 2865, 3410, 4130, 5187, 7133};

void main(){
	TRISD = 0; // Set port D to output
	TRISE = 0; // Set port E to output
	LATD = seg_disp[0]; // Set the 7-segment display to 0 initially
	LATE = seg_nbr[0]; // Display off
	PORTA = 0b00000110; // Clear port A to prevent if from affecting TRISA
	ADCON1 = 0b00001110; // VSS, VDD ref. AN0  analogue
	TRISA = 0b00000111; // Set port A bit 0-2 to inputs
	ADCON0 = 0b00000001; // channel 0 as input
	ADCON2 = 0b10001000; // ADCON2 setup: Right justified, Tacq=2Tad, Tad=2*Tosc (or Fosc/s)
	pe_temp = 633; // Initially set the desired temperature to -10 C

	while(1){
				
		if(PORTAbits.RA1 == 1) Delay10KTCYx(20); // Delay 10 ms if key is pressed
		if(PORTAbits.RA1 == 1) adc_in = pe_temp; // If key is still pressed display the default peltier temperature
		
		else{ // read thermistor
			ADCON0bits.GO_DONE = 1; // Start A/D Conversion
			while(ADCON0bits.GO_DONE != 0); // Just loop until A/D conversion is done
			adc_in = ADRES; // Take all the 10 bits of the adc
		}
		
		for(i = 0; i < 35535; i++){ // Flash LEDs for a while
			n = adc_in/16; // Lookup table index
			digit_res = adc_to_t[n]/100; // temperature from table
			digit_res += ((adc_in - (int)n*16)*(adc_to_t[n+1] - adc_to_t[n]))/1600; // Temperature correction by interpolation
			if(digit_res > 0){ // If temperature above 0 C
				digit = digit_res/100;
				digit_res = digit_res - digit*100;
				LATD = seg_disp[digit];
			}
			else{ // If temperature below 0 C
				digit = - digit_res/100;
				digit_res = - digit_res - digit*100;
				LATD = 0b00000001; // Set a minus sign
			}	
			LATE = seg_nbr[3]; // Flash digit or minus sign
			Delay10KTCYx(1);

			digit = (unsigned int)digit_res/10;
			digit_res = digit_res - digit*10;
			LATD = seg_disp[digit];
			LATE = seg_nbr[2];
			Delay10KTCYx(1);

			LATD = seg_disp[digit_res];
			LATE = seg_nbr[1];
			Delay10KTCYx(1);
		}
	}
}

Re: PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 17 juli 2013, 14:56:20
av sodjan
> fast med Vin och Ground bytt

Varför det? Det är mer "normalt" att ha en pull *up*.

Har du en extra extern buffer (som på bilden)?
Varför inte köra på pinnen direkt?

> Det kan vara något fel med hur jag sätter bitarna som styr ADC:n...

Kanske, vad har du testat?
Har du testat att stänga av allt utom RA1?
Har du mätt på RA1 (själva pinnen) och sett att nivåerna stämmer?

Re: PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 17 juli 2013, 16:14:08
av bjornvaktaren
Jag bara kopplade det så utan att tänka... Bytte till pull-up nu istället. Jag har ingen extern buffert.

ADC bitarna är jag ganska säker på att dem är rätt egentligen, men hur de inställnigarna påverkar port A som en digital ingång vet jag inte. Jag har testat att stänga av USB:n (UCON = 0b00000000) och komparatorn (CMCON = 0b00000111) enligt tråden här: http://www.mikroe.com/forum/viewtopic.php?t=19832. I den tråden kollar han porten med PORTA.F1 men den finns inte för mig. Jag antog att det var PORTAbits.RA1 som jag ska kolla.

Jag testade att stänga av ADC:n (bara kommenterade bort allt som hade med den att göra) och ha TRISA = 0b00000010 för att bara ha RA1 som input. Det fungerade inte heller. Jag har inte testat att mäta på pinnen med en voltmeter eftersom jag inte har någon men jag kopplade in en LED och den lyste när den skulle.

Re: PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 17 juli 2013, 16:16:16
av sodjan
> Jag antog att det var PORTAbits.RA1 som jag ska kolla.

Där bör dokumentationen för den aktuella kompilatorn vara tydligt.

> ...men jag kopplade in en LED...

Hur då?

Vet du säkert att processorn över huvudtaget kör ??
Eller ja, LCD'en uppdaterades väl i och för sig... :-)

Re: PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 17 juli 2013, 20:55:07
av bjornvaktaren
LED:en kopplade jag bara in för att se att knappen fungerar. Så 5V-knapp-LED-resistor-GND.

Hehe, jo LED-displayen visar temperaturen korrekt. Men inte ens om jag jordar RA1 så blir den 0; den visar 1 hela tiden. Säkert något dumt fel jag har gjort, brukar vara det :)

Re: PIC18F4550: ADC på AN0 och digital in på RA1 och RA2?

Postat: 18 juli 2013, 15:32:53
av bjornvaktaren
Nu fick jag det att fungera! Jag ändrade inställningen av port A till:

Kod: Markera allt

	PORTA = 0b00000000; // Clear port A to prevent if from affecting TRISA
	UCONbits.USBEN = 0; // USB disabled
	CMCON = 0b00000111; // Comparators OFF
	ADCON1 = 0b00001110; // VSS, VDD ref. AN0  analogue
	ADCON0 = 0b00000001; // ADC module enabled. Only AN0.
	ADCON2 = 0b10101000; // ADCON2 setup: Right justified, Tacq=12Tad, Tad=2*Tosc (or Fosc/s)
	TRISA = 0b00000111; // Set port A bit 0-2 to inputs
Jag hade lite fel inställning på ADC:ns acquisistion time och min for-loop för att flasha LED-displayen var ju alldeles för lång också. Jag räknade fel där.