Reading adc input on Serial terminal Atmel

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

Here i want to read raw adc values on serial terminal. I am trying to read Atmega328 on chip temparature sensor data.

How can i display the received input data on serial monitor?

 

#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

volatile int adcValue;

void setupADC()
{    
    ADMUX = (1<<REFS0)|(1<<REFS1)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0); // for temp sensr,internal 1.1v, 8bit adc8
    ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);        //adc enabled, 128 prescalar
//    startConversion();
}

void startConversion()
{
    ADCSRA = (1<<ADSC);
}

void USART_Init()
{
    /*Set baud rate */
    /* UBRR0H contains the 4 most significant bits of the
    baud rate. UBRR0L contains the 8 least significant
    bits.*/  
    //UBRR0H = (unsigned char)(ubrr>>8);
    UBRR0L = 1;        // 8mhz/128 = 62.5khz so for 9600baudrate UBBR=1
    

    /*Enable transmitter */
    UCSR0B = (1<<RXEN0) | (1<<TXEN0) ;
    
    /* Set frame format: 8data */
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}

void USART_Transmit( unsigned int data )
{
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) );
    
    /* Put data into buffer, sends the data */
    UDR0 = data;
}

unsigned int USART_receive(void){
    
    while(!(UCSR0A & (1<<RXC0)));
    return UDR0;
    
}

int main(void)
{    
    DDRD = 0x00;
    USART_Init();
    setupADC();
    
    while(1)
    {            
        startConversion();
        while ((ADCSRA & (1<<ADIF))==0);
        adcValue = ADC ;
        USART_Transmit(adcValue);
        _delay_ms(1000);
    }
    
}
 

First Fail & then succeed, this is what Engineering teach me.

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

Please see Tip #1 in my signature (below; may not be visigle on mobile) for how to properly post source code.

 

pos11 wrote:
How can i display the received input data on serial monitor?

  1. At the AVR, you transmit the data using the UART
     
  2. You connect the AVR's UART to a COM port on the PC
    (most likely nowadays, that will be a virtual COM port - via a USB-to-UART adaptor)
     
  3. You connect the terminal (or "serial monitor") to the appropriate COM port.
      
  4. You ensure that the terminal is correctly configured to match the AVR UART settings - in particular the Baud Rate.

 

If you have problems, see Tip #2 (which links to a Tutorial) and Tip #3

 

EDIT

 

But first, make sure you have done the basics: https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 08:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First step is to ensure you are using a crystal and not the internal oscillator

Have you connected up your crystal?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

I can see the transmitted data on serial port.

I want to know how the receiving data (adc input from MCU) continously  displayed on serial port.some idea about receive code.

First Fail & then succeed, this is what Engineering teach me.

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

Sorry, that makes no sense!

 

If you can see the  transmitted data on serial port then you have it working - surely?

 

Please clarify!

 

some idea about receive code

You want to write you own app on the PC to receive serial data?

 

Or you want to receive serial data in the AVR?

 

Or what ??

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to write the code to receive data from MCU & display it on serial monitor.

In other words, reading input from atmega328 & displaying it.

First Fail & then succeed, this is what Engineering teach me.

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

Still confused!

In #4, pos11 wrote:
I can see the transmitted data on serial port.

Then, in #6, pos11 wrote:
I want to write the code to receive data from MCU & display it on serial monitor.

But if you can see the transmitted data on serial port, how is that any different?

 

In other words, reading input from atmega328 & displaying it.

Do you mean you want to send a command from the PC to the AVR to say, "send me a reading" ?

Then have the AVR recognise that command, do the reading, and send the result back to the PC ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The avr has an inbuilt temparature sensor & adc . The adc process the data & display the results to the PC.

We don't have to send anything to avr. 

here we have configured the adc so that it will give the temparature value.

We just want to receive readings from avr & see that in pc terminal.

 

First Fail & then succeed, this is what Engineering teach me.

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

pos11 wrote:
The adc process the data & display the results to the PC.

No. The ADC knows nothing about the PC.

 

Your code needs to take the values from the ADC, and send them out of the UART.

 

We just want to receive readings from avr & see that in pc terminal.

But, again, you said:

I can see the transmitted data on serial port.

So if you can see it - where's the problem??

 

This is where I'm confused!

 

EDIT

 

From Tip #6, see the basic steps in getting the UART going:

 

https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 10:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely the thing he's talking about is itoa(). At the moment he sends binary - I imagine he wants to receive something a human can recognise ? sprintf() or itoa() are probably the answer

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

awneil wrote:
Your code needs to take the values from the ADC, and send them out of the UART.

 

This is exactly what is needed.

 

Yes we can use itoa() but nothing gets displayed.

We checked with baud rate but couldn't  find problem with that but may be we are missing something.  

 

First Fail & then succeed, this is what Engineering teach me.

Last Edited: Wed. Feb 19, 2020 - 11:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pos11 wrote:
Yes we can use itoa() but nothing gets displayed.

So now it gets even more confusing!

 

Again, you said:

I can see the transmitted data on serial port.

So, again, if you can see it - where's the problem??

 

Do you, as clawson suggests, want it in "human readable" form ?

 

If so, then you're going to have to show what you actually did with itoa() if you want help with that.

 

EDIT

 

For a start, your  USART_Transmit() function only sends one single byte - so you'll need to extend that if you want to send multiple characters ...

 

EDIT 2

pos11 wrote:
void USART_Transmit( unsigned int data ) {     /* Wait for empty transmit buffer */     while ( !( UCSR0A & (1<<UDRE0)) );          /* Put data into buffer, sends the data */     UDR0 = data; }

Note that an unsigned int is 16 bits - but the UART data register is only 8 ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 11:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 For eg: If I send a character it gets displayed on serial monitor but if I want to send the state of a switch(pressed or not) which is connected to one of the gpio in avr to the uart it doesn't get displayed.

First Fail & then succeed, this is what Engineering teach me.

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

awneil wrote:
Do you, as clawson suggests, want it in "human readable" form ?

That is not so important , any raw data should be displayed.

 

awneil wrote:
Note that an unsigned int is 16 bits - but the UART data register is only 8 ...

Yes I know that but right now 8 bit result is fine.

First Fail & then succeed, this is what Engineering teach me.

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

pos11 wrote:
If I send a character it gets displayed on serial monitor

Well of course it does - the whole point of a terminal is to display text - ie, characters !

 

But nowhere before have you said anything about sending characters - so how on earth were we supposed to work that out?

 

if I want to send the state of a switch(pressed or not) which is connected to one of the gpio in avr to the uart it doesn't get displayed.

Again, nowhere before have you said anything about sending the state of a switch!

 

we have no idea how you've attempted to do that - so cannot comment on why it didn't work for you!

 

But note that the state of a switch is not a human-readable character or text - so your code would have to do something to make it so.

 

If you simply sent a raw, binary value of zero or one,  those are not  human-readable characters - so you would probably not see them on a terminal!

 

That would be expected behaviour!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 12:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pos11 wrote:
any raw data should be displayed.
How exactly. Lets say the ADC reading is 323 (our of a 0..1023 range) so you split that into 2 bytes and send it - what do you expect to see on your terminal?

 

323 is actually 0x0143 so you will send 0x01 and 0x43. Now it just so happens that on a ("normal") serial terminal 0x43 actually displays as capital-C - that is "C" but what do you think appears on screen when 0x01 is received? As it happens while terminals often treat some character code below 0x20 as commands (like 0x07 is "BEL" meaning "beep", 0x0A is "new line" and 0x0D is "carriage return to start of line") the fact is that 0x01 is almost certainly "non-printable". So the ADC geneated 323 and all you actually see is 'C'.

 

Now consider:

uint16_t adcReading = 323;
char buffer[12];

itoa(adcReading, buffer, 10);

for (int i=0; i < strlen(buffer); i++) {
    uart_putchar(buffer[i]);
}

if you do it that way instead the bytes transmitted are 0x33, 0x32, 0x33 and what appears on the terminal is "323" which probably does make quite a bit more sense. So you said:

pos11 wrote:
That is not so important , any raw data should be displayed.
but unless you mean you have a terminal that can display raw hex so that something like 0x0143 really does display as "01 43" (meaning 323) then I think it kind of does matter - you actually want 323 to display as "323" and that's what you need itoa() or sprintf() for.

 

Your mileage may vary.

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

PS oh and the same goes for switches too. Whether you read the switch state as a very simple 0x00/0x01 or whether you read it as a "raw" GPIO reading like 0x00 when no switch pressed or 0x04 when switch on bit 2 is pressed you still aren't going to get much mileage out of sanding 0x00/0x01 or 0x00/0x04 as most terminals will show nothing meaningful. But is you send "Switch not pressed" when the bit is 0 and "Switch has been pressed" when the bit is active then it's pretty difficult for human eyes to mistake such a thing!

 

On the whole when you send anything for "human display" you need to turn it into something a human can recognise and understand before you do.

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

pos11 wrote:
We just want to receive readings from avr & see that in pc terminal.
Microsoft Windows, Atmel Studio 7, Data Visualizer extension, recent Atmel and Microchip debuggers (EDBG protocol) :

Atmel Studio 7 | Microchip Technology

3/4 page

video series, Episode 3

1:44 for about 30s

 

"Dare to be naïve." - Buckminster Fuller

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

I have code for a project that reads two ADC channels and outputs the values to the serial in CSV format, I can post if that would help.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:

I have code for a project that reads two ADC channels and outputs the values to the serial in CSV format, I can post if that would help.

 

Jim

 

 

Ok sure. 

First Fail & then succeed, this is what Engineering teach me.

Last Edited: Thu. Feb 20, 2020 - 01:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

PS oh and the same goes for switches too. Whether you read the switch state as a very simple 0x00/0x01 or whether you read it as a "raw" GPIO reading like 0x00 when no switch pressed or 0x04 when switch on bit 2 is pressed you still aren't going to get much mileage out of sanding 0x00/0x01 or 0x00/0x04 as most terminals will show nothing meaningful. But is you send "Switch not pressed" when the bit is 0 and "Switch has been pressed" when the bit is active then it's pretty difficult for human eyes to mistake such a thing!

 

On the whole when you send anything for "human display" you need to turn it into something a human can recognise and understand before you do.

 

This is quite helpful. I take this into account.

First Fail & then succeed, this is what Engineering teach me.

Last Edited: Thu. Feb 20, 2020 - 01:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your baud rate calculation is completely wrong.  The ATmega328 uses UBRR=(fOSC/(16*baud rate))-1.  For 9600 baud at 8MHz that comes to 51.

 

The temperature sensor measures the temperature internal to the Mega328 die.  It doesn't have a wide range of resolution: @150 units between -40C and 85C.

If you are measuring room temperature or outdoor weather temperature, I recommend getting a three-terminal TS18B20 IC which costs less than a dollar, or euro, or pound.  They are really cheap in anybody's funny money.  And there are lots of demo programs and libraries that can be downloaded and adapted for your use.

 

When in doubt about using a software or hardware solution, I recommend always going with the hardware approach. The big chip companies have spent millions of dollars making sure that their devices work better than ordinary software solutions.  You could spend ten hours or more researching, debugging, troubleshooting, calibrating, etc a software approach.  Since your time is worth at least ten dollars an hour (which is the average global salary for an employed electronics embedded-systems technician, and much more if you are living in the civilized part of the world), you will be spending $100+ for a solution that can be solved by the DS18B20 for less than $1.   Even if you don't think like this, be assured that your boss does.
 

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

You're assuming this is a paid, work project.

 

Simonetta wrote:
DS18B20 for less than $1.   

I think not.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:

Your baud rate calculation is completely wrong.  The ATmega328 uses UBRR=(fOSC/(16*baud rate))-1.  For 9600 baud at 8MHz that comes to 51.

 

The temperature sensor measures the temperature internal to the Mega328 die.  It doesn't have a wide range of resolution: @150 units between -40C and 85C.

 

For running internal temp sensor freq should be between 20-200kHz so you can see in the prog comments;

UBRR0L = 1;        // 8mhz/128 = 62.5khz ,selected 128 prescalar ;which can be used .

ubbr formula

 

So i want to run it with 9600 baudrate so calculated using formula for UBBR where  fosc=62500, baud=9600 so UBBR= 1.

First Fail & then succeed, this is what Engineering teach me.

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

What does the UART baud rate have to do with the operation of the ADC ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

The UART works off of the main system clock ( xxx MHZ); the only dividers affecting it are the UART dividers (config registers).

Be sure to use an external crystal, NOT the internal  8 MHz RC osc...it is not guaranteed to be accurate for UART use & often is not.---resulting in garbage characters sent out, or wrong characters received.

You don't need any additional errors sources to flub you up...you already have enough troubles!

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Feb 21, 2020 - 08:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
What does the UART baud rate have to do with the operation of the ADC ?

we need to see results on serial monitor so need the baud rate.

First Fail & then succeed, this is what Engineering teach me.

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

Yes, of course you need to correctly set the UART baud rate when using the UART - that was not the point!

 

The point was that the UART baud rate had nothing to do with the ADC clock!

 

As  avrcandies explained in #26

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

pos11 wrote:
So i want to run it with 9600 baudrate so calculated using formula for UBBR where  fosc=62500, baud=9600 so UBBR= 1.
You run a whole AVR at 62.5kHz? Very strange indeed. Most people run them at things like 1/2/8/3.6864/16/20 MHz or similar.

 

Actually one of the very first lines in #1 says:

#define F_CPU 8000000

8MHz seems a much more likely value for fosc !!

EDIt: just noticed this comment:

 // 8mhz/128 = 62.5khz

where does this /128 come into things? You aren't mistakenly thinking that because ADPS bits may be set to divide FCPU/fosc down to create a sub-200kHz ADC clock that this divides the operation of the entire AVR and this also affects the UART ?? If you think that you are quite, quite wrong.

Last Edited: Fri. Feb 21, 2020 - 09:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
You aren't mistakenly thinking that because ADPS bits may be set to divide FCPU/fosc down to create a sub-200kHz ADC clock that this divides the operation of the entire AVR and this also affects the UART ??

Yes, that does seem to be the misconception!

 

If you think that you are quite, quite wrong.

Indeed - hence #25, #26, and #28

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
... 3.6864 ...  MHz

 

@ pos11 - think that's a weird number?

 

Then see: https://www.avrfreaks.net/commen...

 

and: https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/*
*  Send ADC value via USART serial
* for Mega48 but any AVR will do
* for Imagecraft C compiler AVR, change includes below as needed
*/
#include <iccioavr.h> //io header compiler specific (ImageCraft C)

//standard C includes
#include <stdio.h>
#include <stdint.h>

#define FCPU       8000000 //8MHz CPU clock
#define ADCAVERAGE 8       //number of samples to average
#define ADCSAMPLE  ADCAVERAGE //number of samples to take (can be > ADCAVERAGE for oversampling
#define BAUD       9600

//useful macros
#define SetBit(x,y) (x|=(1u<<y))
#define ClrBit(x,y) (x&=~(1u<<y))

/*******************************************************
* ADC_read
* input ADC mux channel
* return ADC value (averaged if more then one sample)
*******************************************************/
int16_t ADC_read(uint8_t mux)
{
	uint8_t x;         //loop counter
	uint16_t total=0;  //ADC sample accumulater

	ADMUX = (ADMUX & 0xf0) + (mux & 0x0f); //set ADC channel

	for(x=0; x<ADCSAMPLE; x++)
	{
		ADCSRA |= (1<<ADSC);       // do single conversion
		while(ADCSRA & (1<<ADSC))
		; // wait for conversion done, ADSC flag active
		total += ADC;
	}
	return total/ADCAVERAGE;
}

/********************************
* ADC_init
* input ADC reference (mux defaults to ADC0)
* return none
********************************/
void ADC_init(uint8_t refmux)
{
	/* set a2d prescaler so we are inside the desired 50-200 KHz range */
	#if FCPU >= 16000000 // 16 MHz / 128 = 125 KHz
	SetBit(ADCSRA, ADPS2);
	SetBit(ADCSRA, ADPS1);
	SetBit(ADCSRA, ADPS0);
	#elif FCPU >= 8000000 // 8 MHz / 64 = 125 KHz
	SetBit(ADCSRA, ADPS2);
	SetBit(ADCSRA, ADPS1);
	ClrBit(ADCSRA, ADPS0);
	#elif FCPU >= 4000000 // 4 MHz / 32 = 125 KHz
	SetBit(ADCSRA, ADPS2);
	ClrBit(ADCSRA, ADPS1);
	SetBit(ADCSRA, ADPS0);
	#elif FCPU >= 2000000 // 2 MHz / 16 = 125 KHz
	SetBit(ADCSRA, ADPS2);
	ClrBit(ADCSRA, ADPS1);
	ClrBit(ADCSRA, ADPS0);
	#elif FCPU >= 1000000 // 1 MHz / 8 = 125 KHz
	ClrBit(ADCSRA, ADPS2);
	SetBit(ADCSRA, ADPS1);
	SetBit(ADCSRA, ADPS0);
	#else // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2
	ClrBit(ADCSRA, ADPS2);
	ClrBit(ADCSRA, ADPS1);
	SetBit(ADCSRA, ADPS0);
	#endif
	ADMUX = refmux;    // REF and ADCmux channel
	ADCSRA = (1<<ADEN);

	ADCSRA |= (1<<ADSC);       // do single conversion, throw away result
	while(ADCSRA & (1<<ADSC))
	; // wait for conversion done, ADSC flag active
}

/* putchar() function links stdio.h with micro usart device for output */
int putchar(unsigned char c)
{
	if ( c == '\n')
	putchar('\r'); //send CR first then LF
	while (!(UCSR0A & (1<<UDRE0)));  // UDRE, wait for data register empty
	UDR0 = c;  //send character
	return c;
}

/* initialize UART0 for output */
void initUSART( uint16_t baud )
{
	UBRR0 = (uint16_t) (FCPU / (16 * baud)) - 1; // set the baud rate
	UCSR0B = ( (0<<RXEN0) | (1<<TXEN0) );  // enable UART transmitter
}

void main(void)
{
	/* init adc  AVcc ref + ADLAR bit */
	ADC_init((0<<REFS1)|(1<<REFS0)|(0<<ADLAR));
	initUSART(BAUD);  //8N1

	do
	{
		printf("%u, ", ADC_read(3)); //prints ADC channel 3 value as unsigned integer 0-1023 (CSV file format)
		printf("%u\n", ADC_read(7)); //prints ADC channel 7 value as unsigned integer 0-1023
	}
	while(1); //forever
}

note: this is written for a different compiler (ImageCraft) but should only need the headers changed and or stream output enabled to use it.

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:
should only need the headers changed ... 

 

Also "F_CPU" vs "FCPU" ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...