You are on page 1of 7

Birin Yucesan Lab 8 3581450 Lab 8: ATD and Serial Abstract The purpose of this lab was to create

a Digital Voltmeter (DMV) and transmit the data through a serial port to a computer. The power supply was used to supply the voltage to be measured. The voltage from the power supply was analog so an analog to digital conversion was needed. The analog to digital conversion result was then used to calculate the voltage and sent to a computer through a serial port to be displayed on the computer monitor using 4 decimal places. Introduction This lab requires an application that will measure the voltage supplied by a power supply and display it on a computer monitor via the use of a serial port. To solve this problem a series of steps needed to be taken. The first thing was to set up several registers. These registers included ADCON0, ADCON1, TXSTA, RCSTA, and SPBRG. These registers were needed in order to convert the analog signal and output the correct result at the correct rate to the computer monitor. Also data direction needed to be set up so that the proper inputs and outputs could be used. The next thing was to determine how to convert the analog to digital conversion result to a meaningful voltage. The analog to digital converter produces a 12 bit result however the most significant two bits are always zero. This makes the range of hex values are from 0x00 to 0x400, or in decimal from 0 to 1023. Using this and the fact that the voltage supplied can only range from 0 volts to 5 volts an equation was created that converted the binary number from the analog to digital conversion to a voltage value. This process will be explained in the main body. The next thing was to write the program. The first part of this stage was to read the AD result 128 times and keep a running total of all the conversions. The reason the AD needed to be averaged is because a potentiometer was used to vary the voltage read by the microcontroller. The average of the running total was taken by dividing by 128. However before the result could be divided it needed to be multiplied by 1000 so that the value would not be truncated. This value was then used to convert to a voltage. This will also be explained in more detail in the main body. This converted value was then put into a character array. Multiplying the result by 1000 as stated above gave a decimal number with for decimal digits. Each one of these digits was stored in the proper index of the character array. The most significant digit was stored in the zero element. The next digit was stored in the 2nd element because the first element was a decimal point. This continued until all decimal numbers were in the array. This array was 6 elements long, 4 for the decimal numbers, 1 for the decimal point, and the last for the carriage return. Using an array like this allowed values such as 2.343 and 4.893 to be displayed. This array was outputted to the computer through the use of a for loop. Each element was a

character so it needed to be sent individually to the computer via the serial port. Lastly the AD conversion was started again and the process began all over again. Main Body Converting from AD result to meaningful voltage As stated above integer arithmetic needed to be performed on the AD result to convert it to a meaningful value. Since the AD converter provides a 12 bit result where the most significant 2 bits are always zero the possible range of this result is from 0 to 2^10 – 1 or 0 to 1023 in decimal. Using equation N=Cx where N is the decimal number from AD conversion, C is the correction factor, and x is the voltage representation of N. The maximum value of the AD conversion is 1023. This would correspond to 5 volts because the voltage references were ground and Vdd which is 5 volts. Re-arranging the equation for C, C=N/x. Plugging in 1023 for N and 5 for x C is found to be 1023/5. Then solving the equation for x yields x=N/C which equals x=N*5/1023. An average of N is needed so N equals N/128, before the division occurs N needs to be multiplied by 5000 instead of 5 so bits don't get truncated. Multiplying the equation by an extra factor of 1000 gives a 4 digit value that can be converted into a decimal number with 3 decimal places to the right of the decimal point. Leaving the equation x=(5000*N)/(1023*128). Subroutines In this program does not have multiple subroutines, in fact it only has the main function. To better explain the code I will split it up into 4 parts: setting up of registers, reading the AD conversion, converting the AD result and storing it into an array, and sending the converted value to the computer. Since this lab requires the use of the analog to digital converter and the USART several registers needed to be set up. The registers to set up the AD conversion were ADCON0 and ADCON1. These set up the AD with the correct processing speed, select which pin was the analog input, choose the voltage references, set up the pin as an analog input, and turn on the converter. Next the data direction registers needed to be set up. Pin AN0 that has the analog input needed to be configured as input by writing a 1 to the appropriate bit of the TRISA register. Also since the USART is needed PORTC pin 7 was needed to be an input by writing a 1 to TRISC pin 7 and PORTC pin 6 needed to be an output by writing a 0 to TRISC pin 6. Lastly since serial communication was used the registers dealing with data transmission to the computer needed to be set up. The first is the transmit status and control register (TXSTA). This was used to select asynchronous mode, 8 bit transmission, and to determine when the data has been transmitted. The next register was the receive status control register (RCSTA). This register was only needed to enable the port that the serial communication is on. Lastly a value of 64 needed to be written to SPBRG so that a baud rate of 9600 was used. Next the running total of 128 AD conversions needed to be done. This was done simply within an if statement that would execute 128 times. Each time it would start the AD conversion, wait for it to be done then add the result to a variable called ADresult.

After the if statement has been executed 128 times ADresult contains the sum of all the individual AD conversions. Next this result was converted into a meaningful value as described in the section, Converting from AD result to meaningful voltage. As stated above the AD result was converted to a meaningful value that represents a voltage. This value is 4 digits long. This number needed to be converted to a decimal number however integer arithmetic does not have decimal places, it truncates the number. This is why the result was multiplied by 1000 so that a not so obvious method could by used to convert the number. The process would modulo the number with 10 and store that result in the 4th element of the array as a character. That result was then divided by 10 so that it was only 3 digits long. Again the operation modulo 10 was performed and stored that result in the 3rd element of the character array. This process was repeated to more times where the next number was stored in the 2nd element of the array and the following digit was stored in the 0th element of the array. The reason it was not stored in the 1st element is because this is where the decimal point occurs. The result is that it converted a 4 decimal long number to a decimal number with decimal point 3 places from the left (i.e. 4356 to 4.356). Lastly the converted value needed to be sent to the computer through the serial port. To do this each character element of the array was written to TXREG 1 at a time. Before a new character could be sent the previous transmission needed to be complete. This was done by waiting for the transmit shift register to be empty. This was done in a for loop that would execute 6 times sending the 0th element first and the 5th element last, the 5th element being a carriage return. Results Using the potentiometer to change the voltage supplied to the microcontroller it was found that the range displayed on the computer was from zero to five volts which is correct because that is the range of the power supply. It was also found that the number displayed would constantly update as the potentiometer was turned up or down (by up or down I mean allowing a higher voltage or only allowing a lower voltage to be read by the microcontroller). It was also found that the result displayed was 4 digits long with 3 decimal places to the right of the decimal point which was the desired accuracy. 1) Using the simulator it was found that it outputs a voltage value to the computer every 6.4189 milliseconds. This is a sampling rate of 1/(6.4189*10^-3 s) which equals a frequency of 156 Hz. 2) To find out what digital 10-bit value an analog input of 2.3 volts corresponds to the equation N=Cx needs to be used. As stated earlier C is 1023/5 and x = 2.3 volts. Plugging these values in N=(1023/5)(2.3) which equals 470 truncated. Converting this to binary it equals 111010110. 3) The accuracy of the DVM is limited by the number of bits in the AD conversion. The resolution is 1 divided by the correction factor or 1/C. In this case C=1023/5 so the accuracy would be 1/(1023/5) which equals 5/1023, an accuracy of .0048 or 0.48%.

Conclusion This lab emphasized how to set up registers to perform an AD conversion and serial communication. When using the hyper terminal on the computer to connect to the microcontroller it was found that the voltage displayed on the screen would vary from 0 volts to 5 volts. This value would vary anywhere in this range as the potentiometer was adjusted. The value displayed was converted from the AD result through the equation x=N/C using integer arithmetic. This value was 4 digits long with a decimal point 3 places from the right (i.e. 3.309). Having a 12 bit result where the upper 2 bits are always zero gives you a range from 0 to 1023 and an accuracy of .48%. Using the simulator to determine how long it takes to output one value to the computer it was found that it took 6.4189 milliseconds which is a sampling rate of 156 Hz.

#include <p18f452.h> void main(void) { char array[6]={'0','.','0','0','0',0x0D}; unsigned char temp=0; unsigned long int ADresult=0; unsigned long int average,send; char i; ADCON0=0x01; ADCON1=0b11000000; TRISAbits.TRISA0=1; TRISCbits.TRISC7=1; TRISCbits.TRISC6=0; TXSTA=0b00100010; RCSTA=0b10000000; SPBRG=64; for(i=12;i>0;i--); while(1) { if(temp<128) { ADCON0bits.GO=1; while(ADCON0bits.GO); ADresult+=ADRESL; //store 128 results of AD conversion //start AD conversion //wait for conversion to be done //add result to ADresult //setting up AD registers to use Fosc/4 //use channel AN0 clear go bit, turn on A/D converter //right justified, use Fosc/4, set up AN0 as anolog input //use voltage references as Vdd and Vss //make RA0 an input //make portC pin 7 input //make portC pint 6 output //set up in asynchronous mode //set baud rate at 9600 bits per second //wait acquisition time

ADresult+=((unsigned int)ADRESH<<8); temp++; for(i=2;i>0;i--) //wait acquisition time { _asm NOP _endasm; _asm NOP _endasm; _asm NOP _endasm; } } else { /*using equation N=Cx where N is the number from AD conversion, C is the correction factor and x is the voltage representation of N. C is found to be 1023/5. Then solving for x=N/C which equals x=N*5/1023. But an average of N is needed so N equals N/128 and need to multiply by 5000 instead of 5 so bits don't get truncated. Leaving the equation x=(5000*N)/(1023*128)*/ send= ((unsigned long int)5000) * ((unsigned long int)ADresult); send= send / 130944; array[4]=send%10 + '0'; //store appropriate char into array send=send/10; array[3]=send%10 + '0'; send=send/10; array[2]=send%10 + '0'; send=send/10; array[0]=send%10 + '0'; temp=0; ADresult=0;

for(i=0;i<6;i++) { while(!PIR1bits.TXIF); TXREG=array[i]; } ADCON0bits.GO=1; } } }

//wait for char to be send //send i'th element of array //start another AD conversion