ADC is not working!

Go To Last Post
80 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

 

I know I'm doing a stupid mistake right now, but I couldn't find it. I tried to look for codes online.

 

I just tested my hardware with Arduino code and the ADC is working so the wiring is OK for a start.

 

This is my code:

void adc_init(void)
{
	ADCSRA|=0x80;								// enable ADC
	DIDR0=0x01;								// disable PC0 dig buffer
}

uint16_t adc_read(void)
{
	uint16_t joystick_AN_x;
	ADMUX=0x40;								// vRef & CH0
	ADCSRA|=0x40;							        // start ADC
	while(!(ADCSRA&(1<<ADIF)));       					// wait until process is finished
	ADCSRA |= (1<<ADIF);							// clear flag bit
	return ADC;
}

 

This topic has a solution.

Last Edited: Fri. Sep 14, 2018 - 04:19 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

wolfrose wrote:
This is my code:

Show a complete test program.  Tell toolchain and build settings.  Show schematic, and tell connections.  Tell clock speed and Vcc level.  Tell how you are testing; tell what you expect to happen; tell what >>is<< happening.

 

Your code doesn't look too bad, except for the gratuitous |= in the ADC initialization.  Also, for any useful results (depending on your clock speed) you will need a prescaler for the ADC clock.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Why do you intermix bit names (ADIF) with hard numbers (0x80 0x40)?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

Why do you intermix bit names (ADIF) with hard numbers (0x80 0x40)?

I was going to ask that question but was too lazy.  So now I'll second it.

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

It would help if you specified which AVR8 you are using. (The ADC modules in the AVR8 family are very similar, but .... )
Anyway.,

Quote:
ADMUX=0x40; // vRef & CH0
is probably selecting the AVCC supply as the Vref. Is your AVCC connected ?

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

theusch wrote:

Show a complete test program.  Tell toolchain and build settings.  Show schematic, and tell connections.  Tell clock speed and Vcc level.  Tell how you are testing; tell what you expect to happen; tell what >>is<< happening.

 

Your code doesn't look too bad, except for the gratuitous |= in the ADC initialization.  Also, for any useful results (depending on your clock speed) you will need a prescaler for the ADC clock.

 

Sorry, the test program:

#include "sensors.h"             // this library has the adc functions

uint16_t adc_val;                // for the adc data

int  main(){
  Serial.begin(9600);            // Arduino serial init
  adc_init();                    // adc init
  while(1){
    adc_val=adc_read();          // call adc function
    Serial.println(adc_val);     // print data on serial monitor
  }
}

Tool chain is AVR-GCC but written in Arduino IDE.

Clock is 16MHz and VCC is 5V are Arduino uno board values.

 

The schematics and connections are OK, because when I test the my setup with Arduino code it works.

 

Image result for arduino joystick

 

It's the same as this diagram, except I'm only testing the x-axis just to get my code work.

 

 

 

mikech wrote:
It would help if you specified which AVR8 you are using.
 

 

It's the Atmega328p of the Arduino uno board.

 

Quote:
ADMUX=0x40; // vRef & CH0
is probably selecting the AVCC supply as the Vref. Is your AVCC connected ?

 

Is the AVCC an external one? I'm guessing it's the internal one. If it's not, then this could be the problem.

 

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

REFS1 REFS0 Voltage Reference Selection
0 0 AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
1 1 Internal 1.1V Voltage Reference with external capacitor at AREF pin

 

According to the datasheet, if the AN voltage is external then I should clear the ADMUX register. Modifying the original code to:

void adc_init(void)
{
	ADCSRA|=(1<<ADEN);										// enable ADC
	DIDR0|=(1<<ADC0D);									// disable PC0 dig buffer
}

uint16_t adc_read(void)
{
	uint16_t joystick_AN_x;
	ADMUX=0x00;											// vRef & CH0
	ADCSRA|=(1<<ADSC);									// start ADC
	while(!(ADCSRA&(1<<ADIF)));       					// wait until process is finished
	ADCSRA |= (1<<ADIF);								// clear flag bit
	return ADC;
}

 

With the same previous application code. But the same result.

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

We keep getting parts and pieces.

 

Show the >>complete test program<< you are using.

 

For a sanity check, show the >>Arduino program<< that you say works.

 

Your test program is still an Arduino sketch, right?  Does Arduino initialize the ADC?  Then indeed the mentioned |= becomes important.

 

What voltage is on the channel 0 pin?  What results do you get with the Arduino sketch?  What results do you get with your test program?

 

I cannot see the connections from that picture.

 

Do you really have functions in your .H file?

 

Arduino people:  Is the chip-include already done, so the source sketch does not need i

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Sep 14, 2018 - 12:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

while(!(ADCSRA&(1<<ADIFADSC)));

 

BR,

M

 

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

I think what Menahem is trying to tell you is that you are better off blocking on ADSC low rather than ADIF high. So this:

	ADCSRA|=(1<<ADSC);									// start ADC
	while(!(ADCSRA&(1<<ADIF)));       					// wait until process is finished
	ADCSRA |= (1<<ADIF);								// clear flag bit

becomes this:

	ADCSRA |= (1 << ADSC);									// start ADC
	while((ADCSRA & (1 << ADSC)));       					// wait until process is finished

ADIF is no longer involved in any of this and therefore there's no need to include code to try and reset the flag.

 

(the above works because once you have set ADSC it remains set until the conversion completes)

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

clawson wrote:
...is that you are better off blocking on ADSC l...

Now, y'all are certainly free to make recommendations.  Even applauded for doing so.  But first, I'd like to see you list the reason that OP's problem arose, rather than simply proposing an alternate method of doing an operation.  Is there a flaw or typo in OP's ADIF-blocking handling?  If so, what is it?  If not, how will changing to observation of ADSC help?

 

Heck, we do not even know what "doesn't work" means.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

• Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the Data Registers are updated. The ADC Conversion
Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set.
 

The ADIE bit was not mentioned in the OP's code.

M

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

Menahem wrote:
The ADIE bit was not mentioned in the OP's code.
Why would it need to have been? He was using ADIF synchronously not asynchronously.

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

Menahem wrote:

while(!(ADCSRA&(1<<ADIFADSC)));

It's been a long time since I used the ADC, but is this really the difference between working and not-working code?  Atmel example code shows checking ADIF just as OP is doing.

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

Ok, sorry, never mind, I thought this bit worked only in interrupt context.

 

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

theusch wrote:
you will need a prescaler for the ADC clock.

 

This is the solution, the code doesn't work without prescaler bits!

 

Why it's not mentioned in the datasheet? I didn't know they are so important for the operation of the ADC module.

 

It's working now!!

 

This is the code:

void adc_init(void)
{
	ADMUX = 0x40;
	ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
}

uint16_t adc_read(void)
{
	ADCSRA|=(1<<ADSC);									// start ADC
	while(!(ADCSRA&(1<<ADIF)));       					// wait until process is finished
	ADCSRA |= (1<<ADIF);								// clear flag bit
	return ADC;
}

So simple! 

Last Edited: Fri. Sep 14, 2018 - 04:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

wolfrose wrote:
Why it's not mentioned in the datasheet?
Oh come on - there's a whole section on ADC clocking. If you were too lazy to read the whole chapter on ADC what do you expect ??

Last Edited: Fri. Sep 14, 2018 - 04:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

wolfrose wrote:

theusch wrote:
you will need a prescaler for the ADC clock.

 

This is the solution, the code doesn't work without prescaler bits!

 

Why it's not mentioned in the datasheet? I didn't know they are so important for the operation of the ADC module.

Well, if you see a clock divider configuration setting that varies from 2 to 128, that should be a hint to look for further information on what setting is appropriate for your situation.  For every configuration register for every module you use, you need to account for every bit, having a reason to either leave it in the default state or to change it.

 

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

wolfrose wrote:
This is the solution, the code doesn't work without prescaler bits!

Well sure it does.  But YOU NEVER TOLD US WHAT NOT-WORKING MEANT.  Since you say "doesn't work" we can guess, now, that the result isn't what you expected.  How many times did I ask the same questions?

 

wolfrose wrote:
Why it's not mentioned in the datasheet? I didn't know they are so important for the operation of the ADC module.

In particular

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Sep 14, 2018 - 05:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
But YOU NEVER TOLD US WHAT NOT-WORKING MEANT.  Since you say "doesn't work" we can guess, now, that the result isn't what you expected.  How many times did I ask the same questions?

 

Sorry! I mean it gives me 1023 all the time, no change in the result.

 

 

kk6gm wrote:
Well, if you see a clock divider configuration setting that varies from 2 to 128, that should be a hint to look for further information on what setting is appropriate for your situation.  For every configuration register for every module you use, you need to account for every bit, having a reason to either leave it in the default state or to change it.

 

OK, how to know the original input clock to the ADC? To count the range required which is between 50-200kHz.

 

The best prescaler I got until now is:

 

ADCSRA = (1<<ADEN)|(1<<ADPS2);

Which means the clock is divided by 8.

 

clawson wrote:
Oh come on - there's a whole section on ADC clocking. If you were too lazy to read the whole chapter on ADC what do you expect ??

 

LOL I'm sorry you're right, that's embarrassing I tend to get reading the datasheet as fast as I can, and when I go back to check it again I go to the register description section, didn't check this part thoroughly.

 

I think like, "what are the bits to get this thing to work?" didn't thought that the prescaler bits are so important. I thought about the prescaler bits, but I thought like "oh it should work with no prescaler bits to get the fastest results".

 

Also said to myself "why would they need to slow it down with prescaler bits? I guess anyone like to get ADC results very fast!"

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

I have another hardware problem.

 

 

The SW button of the joystick is flickering all the time, how to fix it?

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

wolfrose wrote:
Sorry! I mean it gives me 1023 all the time, no change in the result.

So then running the ADC too fast/out of specification surely makes sense.  Why couldn't you have told us the voltage on the pin, the "good" results, and the "bad" results?

 

wolfrose wrote:
LOL I'm sorry you're right, that's embarrassing I tend to get reading the datasheet as fast as I can, and when I go back to check it again I go to the register description section, didn't check this part thoroughly.

I'll get, say, a new device and use it without reading all the instructions, perhaps.  But when there is a puzzling situation I take care to read the manuals thoroughly, at least for the area of interest.

 

Think about all the time you spent struggling with the situation, when a bit of orderly thinking along with some research into printed materials would have eliminated that.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

 

 

The voltage on the SW is 1.5V! It's like floating.

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

I do not know what "SW" is.  "Software"?  But that makes no sense to me.  It is >>you<< that is measuring some signal.  What signal is it?  What does your picture have to do with ADC not working?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

I do not know what "SW" is. 

It's the push button of the joystick module. It's logic ON/OFF switch.

 

 

"Software"? 

This is the software for reading this pin:

    if (PINC&(1<<PINC2))
    {
        PORTD |= (1<<PD5);          // button with pullup resistor 
    }
    else 
    {
        PORTD &= ~(1<<PD5);
    }

 

 

It is >>you<< that is measuring some signal.  What signal is it? 

What does your picture have to do with ADC not working?

I'm sorry I didn't provide enough information about this issue.

 

As I resolved the ADC problem, which is I was testing with the joystick in the picture, this joystick has 3 pins, 2 analog for xy-axis and 1 digital pin for ON/OFF as press button.

 

This button should have either 5V or 0V but not 1.5V.

 

 

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

OK, sorry again this pin has to be pulled-up.

 

https://www.youtube.com/watch?v=MlDi0vO9Evg

 

Just noticed this man pulled the input pin high and realized the problem I have.

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

So reading the SWitch is an entirely different topic than the "ADC doesn't work?

 

Haven't you gotten the hints from earlier?

theusch wrote:
Show a complete test program. Tell toolchain and build settings. Show schematic, and tell connections. Tell clock speed and Vcc level. Tell how you are testing; tell what you expect to happen; tell what >>is<< happening.

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

OK, I resolved both problems of the ADC and the button.

 

Also now I have a question regarding the same code, which is a function containing both measurements, 2 ADC and 1 switch. It's about the speed of the function, the button press misses my presses.

 

Is it OK to continue investigating this issue here?

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

wolfrose wrote:

OK, how to know the original input clock to the ADC? To count the range required which is between 50-200kHz.

 

The best prescaler I got until now is:

 

ADCSRA = (1<<ADEN)|(1<<ADPS2);

Which means the clock is divided by 8.

Surely you know the clock rate that your AVR is running at.  Pick a prescaler that reduces that to 50-200 kHz.  If you're running an Arduino-type board at 16 or 20 MHz, your only choice is a prescale of 128.

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

kk6gm wrote:

Surely you know the clock rate that your AVR is running at.  Pick a prescaler that reduces that to 50-200 kHz.  If you're running an Arduino-type board at 16 or 20 MHz, your only choice is a prescale of 128.

 

OK, my Arduino uno runs at 16MHz, does that mean the input clock to the ADC module is 16MHz?

 

If so then I don't know how things are working!

 

I did a prescaler of ADPS2, which divides the clock by 8, so the input clock is 2MHz!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
uint16_t adc_read(uint8_t chan)
{
        ADMUX = (1<<REFS0) | chan;      //select max channel and AVCC for ref
    
	ADCSRA |= (1<<ADSC);		// start ADC
	while((ADCSRA & (1<<ADSC)));    // wait until process is finished

	return ADC;
}

even simpler and more effective.

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

If you want 10 bit accuracy you need the ADC clock between 50kHz and 200kHz.
.
With a CPU clock of 16MHz you need to set ADPS to /128 which means the ADC will be clocked at 125kHz. As it takes 13 clocks to make a reading this means your sample rate will be 9.6kHz.

Last Edited: Sat. Sep 15, 2018 - 11:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hello,   

    In regards to this problem, I don't believe that it is necessary to set the ADIF flag by software after the completion of the conversion.  Having the ADC clock run between 50 and 200 KHz is important, and by doing so, the ADC starts working.

 

   I must question WHY you are doing this ADC test using the writes to internal AVR registers.   The entire purpose of having the Arduino keyword extensions is to avoid working with internal registers in the main program.   Arduino is designed to make these specific microcontroller operations invisible.  Arduino code is portable between microprocessors so that all the details of getting an ADC conversion are internal to the analogRead() library code.  You don't have to bother with the microprocessor is doing it.   I don't recommend using references to a microprocessor's internal registers unless there is at least a 5X gain in speed by changing the registers directly instead of using the Arduino keywords.  

 

   Some guys say that they like to learn how the CPU works on a register level and that this makes them better programmers.  I respectfully disagree.  There is a sequence of difficulty in programming:  machine code (1 and 0 entered directly _not done since 1975),  assembler,  C or other high-level languages, and C++ (Arduino).   Using direct register access to replace Arduino keywords is like buying a new car and then taking it apart in your driveway in order to see how it works.   Every hour spend studying the internal register operations of a microprocessor is an hour that is not being spent developing the operation and user-interface of the program.  Which is where the money and the action is.   Plus, when you change to a more powerful processor, you have to learn the internal register structure for the new CPU.  Which is crazy if you already have a language that already handles internal common embedded system functions for that CPU, like Arduino.   Who cares HOW analogRead(pin) works as long as you get a correct ADC result from using it?

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

Simonetta wrote:
In regards to this problem, I don't believe that it is necessary to set the ADIF flag by software after the completion of the conversion.

That line does not >>set<< the ADIF flag.  It clears it.  Please clarify your claim for future readers.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

There are two ways to read the ADC. Either you set ADSC then wait for it to automatically clear that signals the end of conversion. Or you wait for ADIF to become set that signals completion. If you do the latter you have to manually clear it, which is what he's trying to do in the initial code here.
.
As for the argument against trying to learn things and improve ones education. That is just madness. Why do any of us bother programming AVRs at all in that case?

Last Edited: Sat. Sep 15, 2018 - 01:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

yeah right, and having all this layers of abstractions killing the CPU throughput. I worked with Arduino ecosystem for a while, until the point where it just reached saturation. That said, it is inconsistent environment to learn something in-depth rather copy-pasting back-packs, and booster-pack and whatever plug-ins from other people and porting the code, Hence it can't be considered as learning platform rather outsourcing platform. But these days everything is being ab(used) even our language so programs become sketched, then outsourcing becomes easy2use, and so on. ^_^))))

 

release the tension through breathing....

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

Kartman wrote:

even simpler and more effective.

Absolutely!

 

clawson wrote:
If you want 10 bit accuracy you need the ADC clock between 50kHz and 200kHz. . With a CPU clock of 16MHz you need to set ADPS to /128 which means the ADC will be clocked at 125kHz. As it takes 13 clocks to make a reading this means your sample rate will be 9.6kHz.

 

According to this table:

Image result for ADPS prescaler

 

 

I got these results only by setting ADPS2 which is 16MHz/16 = 1MHz. I'm here pulling the y-axis to the max and min ranges for testing.

 

 

The results are OK, but it works with 1MHz input clock? Is there another clock divider before the ADC module?

 

 

 

Simonetta wrote:

 

   I must question WHY you are doing this ADC test using the writes to internal AVR registers.   The entire purpose of having the Arduino keyword extensions is to avoid working with internal registers in the main program.   Arduino is designed to make these specific microcontroller operations invisible.  Arduino code is portable between microprocessors so that all the details of getting an ADC conversion are internal to the analogRead() library code.  You don't have to bother with the microprocessor is doing it.   I don't recommend using references to a microprocessor's internal registers unless there is at least a 5X gain in speed by changing the registers directly instead of using the Arduino keywords.  

 

   Some guys say that they like to learn how the CPU works on a register level and that this makes them better programmers.  I respectfully disagree.  There is a sequence of difficulty in programming:  machine code (1 and 0 entered directly _not done since 1975),  assembler,  C or other high-level languages, and C++ (Arduino).   Using direct register access to replace Arduino keywords is like buying a new car and then taking it apart in your driveway in order to see how it works.   Every hour spend studying the internal register operations of a microprocessor is an hour that is not being spent developing the operation and user-interface of the program.  Which is where the money and the action is.   Plus, when you change to a more powerful processor, you have to learn the internal register structure for the new CPU.  Which is crazy if you already have a language that already handles internal common embedded system functions for that CPU, like Arduino.   Who cares HOW analogRead(pin) works as long as you get a correct ADC result from using it?

 

I agree with your point of view with the speed of programming development. And how things are more simpler and I have to move to the ready libraries to save the time in developing more complicated projects.

But before I had issues with pre-written Arduino libraries and at that time I decided to write my own code, to reach a decent level in the basics of programming.

 

 

 

clawson wrote:
There are two ways to read the ADC. Either you set ADSC then wait for it to automatically clear that signals the end of conversion. Or you wait for ADIF to become set that signals completion. If you do the latter you have to manually clear it, which is what he's trying to do in the initial code here. . As for the argument against trying to learn things and improve ones education. That is just madness. Why do any of us bother programming AVRs at all in that case?

 

I agree with the two ways, also just modified my code to Kartman's recommendation yes

 

And for your 2nd point I agree with you, the basics are important. I didn't reach the level to evaluate which is better to go with pre-written libraries or do your own libraries.

 

But I've worked with Arduino libraries, but I had issues so that I have to modify the code for my goals, so I knew that I better learn how to write libraries.

Maybe after some time, when I feel that I got a good grasp of the basics and do intermediate to advanced projects in C and then transfer that to C++ which is a good powerful learning curve, then I might go with the libraries, as I have enough experience to deal with them confidently.

Last Edited: Sat. Sep 15, 2018 - 02:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You can run faster than 50..200kHz but then you can't guarantee the full size 10 bit accuracy. But if you only rely on 8 bit (say) then 1MHz will probably be OK.

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

clawson wrote:
You can run faster than 50..200kHz but then you can't guarantee the full size 10 bit accuracy. But if you only rely on 8 bit (say) then 1MHz will probably be OK.

 

Didn't understand what you mean exactly!

 

You mean that I can go faster than 50-200kHz, but I can't get the full size 10 bit accuracy? But in the pictures I posted those values are full 10-bit with the speed of 1MHz.

 

I know you said I can't guarantee, which means that there's a chance to get the full 10-bit accuracy.

 

Also the 2nd part of the reply isn't so clear.

 

 

 

============================================================================================================

 

Beside the clock investigation I have another problem of the button press of the joystick.

 

I can't get it precisely, I miss the press, because I use _delay_ms(500);

 

But how to improve my function to by pass this problem?

 

This is the functions:

void joystick_init(void)
{	
	DDRC=0xF8;								// x,y,button PC0,PC1,PC2 inputs rest output
	DDRB=0x20;								// PB5 output
	PORTC=0x04;								// Pull 3rd pin HIGH for button press
}

void joystick_read(void)
{
    uint16_t joystick_AN_xy[2];

    joystick_AN_xy[0] = adc_read(0);		 			// read AN0
    joystick_AN_xy[1] = adc_read(1);       				// read AN1

    if (!(PINC&(1<<PINC2)))
	{
		PORTB |= (1<<PB5);     			// button with pullup resistor 
	}
    else
	{
		PORTB &= ~(1<<PB5);
	}
	
    sprintf(val_arr,"%d",joystick_AN_xy[0]);
    LCD_string("x value:");
    move_cursor(1,10); 
    LCD_string(val_arr);
    sprintf(val_arr,"%d",joystick_AN_xy[1]);
    move_cursor(2,1);
    LCD_string("y value:");    
    move_cursor(2,10);      
    LCD_string(val_arr);
    _delay_ms(500);
    clr_dis();
}

 

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

wolfrose wrote:
Didn't understand what you mean exactly!

I was determined to stay out, but...  I'm the tuna on the lower right.  The quote above is the "baited hook or lure".

Image result for trolling

 

How many times has someone mentioned "what does the datasheet say"?    Often.  How are most questions answered here on this forum?  By looking at the datasheet, and parroting the applicable excerpt.  Besides that, Cliff >>posted<< the part of the datasheeet that addresses your query in #17.  Did you read that?  Is there a great language barrier?  How many times where you asked what speed your AVR is running at?  What was my response to your "it doesn't work without a prescaler"?  I said  something like "Sure it does, but you probably are not getting the results that you expect".  How many times were you asked what voltage is on the pin?  How many times were you asked "what results do you expect"?   How may times were you asked "what results are you getting"?  How many times were you asked to provide a complete test program that demonstrates the symptoms?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sat. Sep 15, 2018 - 03:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You will always READ 10 bits.  But how many of those bits are valid, and how many are essentially random?  If you get a result of b1011010011, is the LSB valid?  The 3rd LSB?  The only way you can have any assurance that all 10 bits are valid is to run the ADC clock within the specified range.

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

theusch wrote:

How many times has someone mentioned "what does the datasheet say"?    Often.  How are most questions answered here on this forum?  By looking at the datasheet, and parroting the applicable excerpt.  Besides that, Cliff >>posted<< the part of the datasheeet that addresses your query in #17.  Did you read that?  Is there a great language barrier?  How many times where you asked what speed your AVR is running at?  What was my response to your "it doesn't work without a prescaler"?  I said  something like "Sure it does, but you probably are not getting the results that you expect".  How many times were you asked what voltage is on the pin?  How many times were you asked "what results do you expect"?   How may times were you asked "what results are you getting"?  How many times were you asked to provide a complete test program that demonstrates the symptoms?

 

Yes, but I also said that I'm not sure what's the input clock to the ADC module? Is it the same like the system clock which is 16MHz? If so then I understand clawson points.

.....

 

OK, a quick revision of the datasheet, there's no clarification that the clock input to the ADC is modified. So, the input clock is 16MHz to the prescaler.

 

So, my calculations are right. At 1MHz I can get 10-bit resolution.

 

 

But I still have another issue regarding the button of the joystick, can I ask about it here, or open a new thread?

Last Edited: Sat. Sep 15, 2018 - 04:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

You will always READ 10 bits.  But how many of those bits are valid, and how many are essentially random?  If you get a result of b1011010011, is the LSB valid?  The 3rd LSB?  The only way you can have any assurance that all 10 bits are valid is to run the ADC clock within the specified range.

 

Yes, I'm getting the readings OK with this speed. I tried lower speeds but I can say they are similar in the aspect of accuracy, didn't encounter glitches or wrong readings.

So I can say I'm pretty much comfortable with this speed as it's quick.

 

If I go into a more complicated project, I don't know with more code that could be errors with this speed. But for now it works OK.

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

wolfrose wrote:

Yes, I'm getting the readings OK with this speed. I tried lower speeds but I can say they are similar in the aspect of accuracy, didn't encounter glitches or wrong readings.

So I can say I'm pretty much comfortable with this speed as it's quick.

 

If I go into a more complicated project, I don't know with more code that could be errors with this speed. But for now it works OK.

Well, it's your funeral, as the saying goes.  If you really need 75k samples/sec @ 10 bits, pick a different chip family.  If this is a one-off hobby project that's one thing, knock yourself out.  Anything more demanding of correct and repeatable results, just don't do this (run the ADC at 1 MHz).  If AVR actually thought their ADCs would work at 1 MHz, I promise you that they would tell us!

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

kk6gm wrote:

If you really need 75k samples/sec @ 10 bits, pick a different chip family. 

I actually don't need 75k samples/sec @ 10 bits.

 

 

If this is a one-off hobby project that's one thing, knock yourself out.  

This code would be a base for my project I''m working on right now, which is a set of sensors functions. Which would be of course a source of functions for my next advanced projects.

 

Anything more demanding of correct and repeatable results, just don't do this (run the ADC at 1 MHz).  If AVR actually thought their ADCs would work at 1 MHz, I promise you that they would tell us!

LOL you're right! Of course I know the limits that AVR proved for the stable well working range of speed for ADC, I'm just surprised that it works at 1MHz.

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

Why are you ‘surprised’ it ‘works’? Again, the datasheet tells you what to expect. Have you considered that your observations are not correct? What you consider is ‘working’ is really just hiding a defect? There is a difference between working by design and working by divine intervention.

Regarding your problem with detecting the button press - we’ve been through this many times before as I’ve suggested you read a tutorial I wrote regarding multitasking. If you follow my simple example that i describe in the tutorial, then this should allow you to solve your problem and many others you might encounter. I’ve given the links before or you might Google avrfreaks kartman multitasking

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

As others have said, after a conversion you will always read some 10 bit value but how many of those bits can you trust? If you want to rely on all 10 bits then you have to run the ADC at 200kHz or less and that will give you a max 15.3kHz sample rate. This is a design limitation of the Tiny/mega AVR. If you need faster samples/better accuracy switch to another chip. The first obvious choice may be to the Xmega range which can offer 1Msps. Be warned though that while they call them AVR you will not recognize the ADC (or the timers or anything else) so it's very like switching to a whole new chip range so you might want to consider widening your horizon and looking at something different. Perhaps Cortex in some form?

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

clawson wrote:

As others have said, after a conversion you will always read some 10 bit value but how many of those bits can you trust? If you want to rely on all 10 bits then you have to run the ADC at 200kHz or less and that will give you a max 15.3kHz sample rate. This is a design limitation of the Tiny/mega AVR. If you need faster samples/better accuracy switch to another chip. The first obvious choice may be to the Xmega range which can offer 1Msps. Be warned though that while they call them AVR you will not recognize the ADC (or the timers or anything else) so it's very like switching to a whole new chip range so you might want to consider widening your horizon and looking at something different. Perhaps Cortex in some form?

Absolutely! I really like your recommendation, and I like one day to work with another chip, but for now I'm still working with the 8-bit architecture. I'm not interested learning different architecture. Working with AVR and PIC is enough for now.

 

Also I'm not interested in higher speeds, I'm just testing things out, it just that it worked at 1MHz was interesting to me, but running in the recommended range would be the best setting for my projects.

 

 

Kartman wrote:
Why are you ‘surprised’ it ‘works’? Again, the datasheet tells you what to expect. Have you considered that your observations are not correct?
 

 

What you consider is ‘working’ is really just hiding a defect?

Of course I know I'm not writing very optimized code, just getting it to work is good. But for example, I got the joystick to work, but the button press misses all the time because I'm using a delay in the function. So I have to search for the solution maybe using pin or timer interrupts and so on.

 

 

There is a difference between working by design and working by divine intervention.

LOL I guess I'm working with the second type :)

 

Regarding your problem with detecting the button press - we’ve been through this many times before as I’ve suggested you read a tutorial I wrote regarding multitasking. If you follow my simple example that i describe in the tutorial, then this should allow you to solve your problem and many others you might encounter. I’ve given the links before or you might Google avrfreaks kartman multitasking

OK, thanks.

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

wolfrose wrote:

Also I'm not interested in higher speeds, I'm just testing things out, it just that it worked at 1MHz was interesting to me, but running in the recommended range would be the best setting for my projects.

"Worked" for a particular chip, at a particular temperature and voltage, with a particular (and non-varying or slow varying, I'm guessing) input voltage.  Once you narrow down the operating range that way then yes, the hardware might surprise you at how much it can exceed the published specs.  And you can get away with that for individual hobby projects.  But "real" devices may be required to operate over large temperature and voltage ranges, using any chip that's not DOA (no hand-selecting), with much more rapidly varying input signals.  That's when you stick to the published specs, live longer and keep more of your hair.

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

 it just that it worked at 1MHz was interesting to me,

 

You are missing the point.

 

It didn't "work".

 

The fact that you have a number in a register doesn't mean that it is accurate, or that it will appear to give a close answer on another board with another chip.

 

The data sheet tells you the maximum sampling speed to be "in spec", and one uses the pre-scaler to slow the micro's clock down so that the ADC's clock is running in spec.

 

Learn good habits now, which is running your hardware in spec!

 

You need to really, really, understand the hardware in great detail before you begin intentionally designing out of spec.

 

JC

  

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

Kartman wrote:
Why are you ‘surprised’ it ‘works’? Again, the datasheet tells you what to expect. Have you considered that your observations are not correct? What you consider is ‘working’ is really just hiding a defect? There is a difference between working by design and working by divine intervention. Regarding your problem with detecting the button press - we’ve been through this many times before as I’ve suggested you read a tutorial I wrote regarding multitasking. If you follow my simple example that i describe in the tutorial, then this should allow you to solve your problem and many others you might encounter. I’ve given the links before or you might Google avrfreaks kartman multitasking

 

ISR(PCINT1_vect)
{
	if (!(PINC&(1<<PINC2)))
	{
		PORTB |= (1<<PB5);     			// button with pullup resistor
	}
    else
	{
		PORTB &= ~(1<<PB5);
	}
}

 

I used this as a start, I've looked into your tutorial, yes that looks pretty much a sketch for a big embedded system program; like, car system, more complicated device or other devices which use a lot of functions and need multitasking.

 

I followed this video:

https://www.youtube.com/watch?v=...

 

Very helpful,

Pages