CodeVision / Proteus POT-HG display value inVirtual terminal

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to write up a code that would read interactive potentiometer via ATMEGA 8535 ADC functionality and display it on Virtual Terminal via RS232 communication.

This is my circuit I prepared in PROTEUS software attached below to the question.

Below is my code I coded in CodeVision AVR:

#include 
#include 

void usart_init (void)
{
    UBRRH = 0x00;
    UBRRL = 0x0c;

    UCSRA = 0x02;
    UCSRB = 0x98;
    UCSRC = 0x86;
}

/*The above code is to initialize USART communication at baud rate 9600 bits per second.*/

void usart_tx (char data)
{
    UDR = data;
    while(UCSRA.UDRE == 0);
}

/*The above code is to send a character to RS232 communication i.e. to virtual terminal.*/


void main(void)
{
int temp = 0;
ADMUX  = 0b11000000;
ADCSRA = 0b10000000;
/*ADC at PORT 0*/
usart_init();
while(1)
      {          
       ADCSRA.6 = 1;
       while (ADCSRA.ADIF != 1);
       temp = ADCW;
/* The idea is to display the values to virtual terminal. I am assuming that value at ADC port should be 47 so I would first display value 4 and then 7 - one by one numeric digits in character*/
       while(temp >= 10)
       {    
            temp  = (ADCW/10) + 48;     
            usart_tx(temp);
            temp = ADCW - (temp*10);
            delay_ms(1000);
       }                       
       usart_tx(temp + 48);
       }
}

But unexpectedly I am not seeing in virtual terminal the values as expected. I am getting un-expected values:

Character Value Display at VT:

P"P"P"P"P"P"

Hexadecimal Values Display at VT:

50 94 50 94 50 94 50 94

Actually I may be wrong in understanding what POT-HG value is sending -

In case if it is send ing 47 % of 1 K value then I should be getting around 2.3 value

In case if it is sending the % value then it should be 47.

So what value does POT-HG component provides as input to 8535 ADC and how I can read / display the same.

Please let me what wrong am I doing and how to correct the same.

Thanks in advance.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The CodeVision Wizard will provide functions for reading the ADC and initialising USART etc. You just use for writing to the USART (printf(), putchar() etc).

Compare your "usart_tx()" function with any other working program. Or read the data sheet.

If you trace your code with pencil and paper, you will see why you get the wrong characters.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, first you should try to send a character (in a loop), then you should try to send a decimal (character) representation of , say :
3 '03', then 23 '23', then 230 ... should be '230';

BTW if your potentiometer value is half, if you do not convert into volts or in percentage , you should get about 512 (1024/2 for a 10 bits converter, reference being an end of the potentiometer).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot for the suggestion. I modified the code to us sprintf and it worked fine to display '03', '23' & '230' values.

BTW I am not sure how to convert the values in ADCW to volts or % - what I need to do? I am getting variable values when input changes say -

400 400 400 400 460 540 580 580 [as I change the value of POT-HG during simulation]

Is there any formula to convert it back to volts / resistance?

Thanks once again in advance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, looking at the ATmega8535 data sheet, 0b11000000 means 2.56V internal voltage reference.

So since ADCW is 0 .. 511

(2.56 * ADCW / 512) will give you the answer.

It is always wise to use the BIT_NAMES and SFR_NAMES in your source code.
For a start, it means that at least you have read the data sheet.

Note that my "formula" is a floating point value. So you need to enable f-p for printf().

It is often simpler to just work in milliVolts. Then you only need integer maths:
(2560uL * ADCW / 512)

This gives a long result but will be in range for a regular int.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, to convert it into % (I assume that you use, as reference, AVCC -which would be logical with a potentiometer- and hope your UC can select this reference)

percentage = 100 * ADCW /512 = (25 * ADCW) / 128

ADCW *25 cannot have more 14 bits (fits in a 16 bit integer)
Dividing by 128 -2**7- can be transformed in a shift, in some direction ( ">> 7").

uint16_t temp= 25*ADCW;
percentage= temp >> 7;// or percentage = (temp +64) >> 7; to remove bias...

might work (and be faster than divides).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks to all for the details as provided. It really helped me a lot. I am going with the (2560uL * ADCW / 512) formula to calculate the volts / resistance where ever required.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

try
5uL *ADCW (saves a divide, if you have no optimizer-else, optimizer does it for you; I donot know about Codevision)