ATmega48 and ADC

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

I have a problem to get sensible read out from adc to the lcd... well, actually it doesn't work at all. Otherwise the code works just fine... for example, I can save timer2 content and place that to lcd. So, I think the ADC is a problem.

init:
1. Reference is taken from the AVcc and AREF -pin is floating.
2. single conversio mode
3. first ADC7 selected
4. ADC enable
5. interrupt enable
6. prescaled by 4

; ********************** ADC  *******************************
lds temp, PRR		; write locigal "0" to PRADC(Power Reduction Register)
cbr temp, PRADC
sts PRR, temp
;--------------------------------------------------------------------------
ldi temp, 0x47		; AVcc WITH EXT.CAP AT AREF, ADC7 selected
sts admux, temp		; ADC6(xxxx 0110) ADC7(xxxx 0111)
;--------------------------------------------------------------------------
ldi temp, 0x8a		; ADC enable, interrupt enable, prescale 4(1000 1010)
sts adcsra, temp
;--------------------------------------------------------------------------

Interrupt rutine doesn't contain any lines except reti , save sreg and temp.

Whats wrong with the picture? ...except it's small without the mouse right click and choosing: show picture

Regards
heguli

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

You can simplify the problem by not using the interrupt for now. Can you write the simple 'flash one pin at a known rate' program? This proves whole development chain is correct. Next program could call a subroutine that starts conversion, polls the ADSC bit, then returns the ADC value. You could stick this in a port with leds (like on the stk500?) and if they wiggle, you're almost there. Only part left is the LCD!

Imagecraft compiler user

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

Quote:
ldi temp, 0x8a
The first thing you need to do is to dump the use of hex numbers and use bit labels so that we don't have to mentally compute the bit numbers. Then just try a simple loop waiting for the ADIF and when it fires read the ADC.
Finally have you enabled the Interrupts with a SEI instruction somewhere? Can't tell from the code snippet.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Finally have you enabled the Interrupts with a SEI instruction somewhere? Can't tell from the code snippet.

He's not doing anything in the interrupt anyways, so he should either drop the ISR entirely, or change the code to actually use it.

Quote:
simple loop waiting for the ADIF

It is much easier to use the ADCS bit for this.

@Helgui, I'm not sure why you are using the T bit. It is unnecessary, drop it. Also because of the way you used the T bit and the way you are checking for a completed conversion, you end up continually writing to the LCD even though nothing has changed. It would be much cleaner like this:

1. Start a conversion
2. Wait until the conversion is done
3. Write the value to the LCD
4. Change channels
5. Repeat from step 1

Regards,
Steve A.

The Board helps those that help themselves.

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

Ok, now I get one result from adc7. Propably the first one and thats it, no matter how much I turn the trimmer. I changed the code to work with only one channel without interrupt. It's all basic now.

init:
;********************** ADC  ********************************
lds temp, PRR		; write locigal "0" to PRADC(Power Reduction Register)
cbr temp, (1<<PRADC)
sts PRR, temp
;--------------------------------------------------------------------------
ldi temp, 0x47		; AVcc WITH EXT.CAP AT AREF, ADC7 selected(0100 0111)
sts admux, temp		; ADC6(xxxx x110) ADC7(xxxx x111)
;--------------------------------------------------------------------------
ldi temp, 0x87		; ADC enable, interrupt disable, prescale 128(1000 0111)
sts adcsra, temp	; bit6 starts conversio
;--------------------------------------------------------------------------



start:
start_conversion:
;--------------------------------------------------------------------------
lds temp, adcsra	; start conversio
sbr temp, (1<<adsc)
sts adcsra, temp
;--------------------------------------------------------------------------
waitconversion:
lds temp, adcsra	; wait adc flag
sbrs temp, adif
rjmp waitconversion
;--------------------------------------------------------------------------
clrflag:
lds temp, adcsra	; clr flag
sbr temp, (1<<adif)
sts adcsra, temp

nop
nop

lds temp, adcsra	; check that flag is really clear
sbrc temp, adif		; ...if not clear again
rjmp clrflag
;--------------------------------------------------------------------------
inc testloop		; testloop
ldi temp, 0xff		; before led orange is on, these lines must
cpse temp, testloop	; be through 255 times
rjmp testloop_two
clr testloop
led_or
testloop_two:		; end of testloop
;--------------------------------------------------------------------------
lds fbinH, ADCH		; load adc content to registers
lds fbinL, ADCL

;lds temp, tcnt2	; test for sub rutines: write_lcd, bin_to_bcd, write_voltage2lcd
;mov fbinL, temp	; write tim2 content to fbinL

; ***** voltage input *****
;--------------------------------------------------------------------------
; mul=> fbinL x 0x19 = r1 high; r0 low
; multiply with 25 both register

ldi temp, 0x19		; multiply adc result with 26(dec)

mul fbinL, temp
mov fbinL, r0
mov r2, r1

mul fbinH, temp
add r0, r2
mov fbinH, r0

rcall bin_to_bcd	; convert to 5 digit BCD
rcall write_voltage2lcd ; write content to sram
;--------------------------------------------------------------------------
rcall write_lcd		; write lcd
;--------------------------------------------------------------------------
rjmp start

Regards
heguli

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
waitconversion:
lds temp, adcsra   ; wait adc flag
sbrs temp, adif
rjmp waitconversion
;--------------------------------------------------------------------------
clrflag:
lds temp, adcsra   ; clr flag
sbr temp, (1<<adif)
sts adcsra, temp

nop
nop

lds temp, adcsra   ; check that flag is really clear
sbrc temp, adif      ; ...if not clear again
rjmp clrflag

This can be simplified to:

waitconversion:
lds temp, adcsra   ; wait adc flag
sbrc temp, adsc
rjmp waitconversion

This is wrong:

lds fbinH, ADCH      ; load adc content to registers
lds fbinL, ADCL

It should be:

lds fbinH, ADCL      ; load adc content to registers
lds fbinL, ADCH

Regards,
Steve A.

The Board helps those that help themselves.

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

WOW... thanks Steve. That shows that adc works. Reading is grazy but that's all right. I try to figure out why that change works. I've spend a lot of time with the problem.
Steve the king! :D

Regards
heguli

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

When ADCL is read the registers are locked and cannot be changed, even when another conversion comes through, until ADCH is read. Since there isn't going to be a conversion coming through between reading ADCH and ADCL in your code the registers never change. It's in the datasheet for your chip.

Edward

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

:D :D :D :D IT WORKS!!!!!!!!! :D :D :D :D
Lot of thanks guys

Regards
heguli

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

Quote:
This is wrong:
Code:
lds fbinH, ADCH ; load adc content to registers
lds fbinL, ADCL

It should be:
Code:
lds fbinH, ADCL ; load adc content to registers
lds fbinL, ADCH

It should be....

lds fbinL, ADCL
lds fbinH, ADCH

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

yep, that I figure out myself 8) ...now I notice there is some gain error involve and that error is multiplyed with 25 in software :?
Power supply starts at 1.25V and AVR shows the right voltage. However in a highest voltage that PS can put out error is significant. AVR show 25.5 volt and the real value is 23.67 V. Also AVR is powered from the regulator 7805 and it seems to be in stress, it's very hot and output is close to 4.8 volt. ADC7 pin is near the 5 volt. And while I'm writing this text I have found the error! :lol:

Regards
heguli

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

What does your circuit look like that is connected to the ADC pin?

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


That resistor system R5, R8 and R11 could be better. I mean some sort of OP-amp circuit powered by the 7805 could be more reliability.

Regards
heguli

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

Moi Heguli,

note that the other GND pin on the AVR is not grounded (pin 21).

- Jani

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

Quote:

Also AVR is powered from the regulator 7805 and it seems to be in stress, it's very hot and output is close to 4.8 volt

If I read your schematic correcly (IC5 is the 7805, right?), the voltage drop across the regulator is 19 volts. Do you have a heatsink on it? The regulator powers the AVR and the LCD, so the current is probably large enough to make it very hot if there is no heatsink.

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

Mortonki Jani,

Quote:
note that the other GND pin on the AVR is not grounded (pin 21).
now look at that! Also pin 21 GND is floating... forgot to connect those ones. I placed few zero ohm jumpers and now they are in order.

Hi mrono,

Quote:
If I read your schematic correcly (IC5 is the 7805, right?), the voltage drop across the regulator is 19 volts. Do you have a heatsink on it? The regulator powers the AVR and the LCD, so the current is probably large enough to make it very hot if there is no heatsink.
Yep, IC5 is the 7805. At the beginning I didn't tought that LCD comes with the led-backlight. It draws 110mA and rest of the 5V circuit takes maybe 10-20mA. So 19V and 120mA is 2.3W over the regulator. It's a lot without heatsink, almost burn my finger when I touch it :shock: Then I attach a steel bar with a silver paste as a heatsink... wasn't enough. I add few PC back plate bracets:

:lol: There is a textbook example how to make a heatsink. I'll have to do the board again and make changes. Every ideas will be notice.

Regards
heguli

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

Heguli, you did fine on the decoupling of AVcc, but Vref-pin is still floating. For maximum noise-immunity, I'd suggest an extra 0.1 uF to Agnd.
Are you building a smart battery-charger? Or a bench power supply with battery-charging capabilities ? Looks like fun!
The 110 mA for the backlight is pretty high IMO. 40 mA is a more "normal" value. You could use OC2 with a small FET to control backlight-brightness. As a bonus you get some disco-effects during programming :)

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Yep, 10nF to 100nF from Aref to GND would be nice, or if AVCC is used as Aref, they can be connected together.

I've seen LCD backlights specified to take up to 300mA. I think that was a red one.

Heguli, you might want to share the 2 watts between the regulator and a series power resistor, so that both heat up 1 watt. Just make sure the 7805 gets at least 8 volts on its input.

So if input is around 20V, output is 5V, so around 15 volts must be dropped over the resistor and regulator. Make the other drop 7 volts and the other 8 volts, so R=8 volts per 100mA or 200mA is around 47 ohms in series before the regulator.

- Jani

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

Jani wrote:

Quote:
.... if AVCC is used as Aref, they can be connected together.
No need to, and not recommendable. Simply set the appropriate bits in the register ADMUX.
From the datasheet:
Quote:
Internal reference voltages of nominally 2.56V or AVCC are provided On-chip. The voltage reference may be externally decoupled at the AREF pin by a capacitor for better noise performance.

300 mA for backlight? OMGoodness :shock: ....

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Plons wrote:
No need to, and not recommendable. Simply set the appropriate bits in the register ADMUX.
From the datasheet:
Quote:
Internal reference voltages of nominally 2.56V or AVCC are provided On-chip. The voltage reference may be externally decoupled at the AREF pin by a capacitor for better noise performance.

300 mA for backlight? OMGoodness :shock: ....

Nard

I know, no need, but can be connected if wanted. But why it is not recommended? Is it because weird things and smoke might happen if you select 2.56 in software while there is AVCC externally on the Aref pin?

Yes, but it was a red backlight. Typical max or absolute max was 315mA, minimum was well over 100mA anyway. Must use more current with a red backlight to get same apparent brightness than with a green backlight.

- Jani

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

Jani wrote:

Quote:
Is it because weird things and smoke might happen if you select 2.56 in software while there is AVCC externally on the Aref pin?
Weird things: possible ..... internal Vref is generated from the internal bandgap-reference. And that one is responsible for more things, like brownout. Smoke? Hmmm, I guess not. Correction: hope not :)

In general: it gives you more flexibility if you just connect a capacitor to Vref. Then it's up to the software which source to use for reference.

Personally I only apply an external voltage on Vref if there is an absolute need for: f.i., if I need a 4.096V as reference, like an MCP1541

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Quote:

Is it because weird things and smoke might happen if you select 2.56 in software while there is AVCC externally on the Aref pin?

That's probably one reason. Another one is that some AVRs cannot handle an external reference as high as AVCC. This is typically true for the ATtiny series where the AREF-pin can alternatively be used as a regular I/O-pin.

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

Quote:

Another one is that some AVRs cannot handle an external reference as high as AVCC. This is typically true for the ATtiny series where the AREF-pin can alternatively be used as a regular I/O-pin.

I never noticed that before. I did indeed find in the Tiny24 datasheet that Vref max was AVcc - 0.5. The others that I looked at have Vref max of AVcc, or no mention. The weird part is that all can use AVcc as Aref.

Do you have a bigger list of the "some AVRs"?

Lee

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

Quote:

Do you have a bigger list of the "some AVRs"?

Actually the tiny44 was the one I had in mind. I was sure I read that tiny45 would have the same restriction, but re-reading the datasheet revealed that it was only if one uses differential channels.
Quote:
When differential channels and gain are used, using VCC or an external AREF higher than (VCC - 1V) as a voltage reference is not recommended

The tiny261 family seems to have the same restriction with differential channels.

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

I'll put that cap to next board. This is just a basic PS to my hobbies.
I do like the idea about flashing backlight. There are few pins still unused and some sort of current limiter could be possible to add, with the flashing "CURRENT LIMIT" -notice ...jeah man!

Quote:
As a bonus you get some disco-effects during programming
I have disco effects during programming even without OC2... after lights are all off janitor change the main fuse from the aparment building. :lol:
Quote:
Heguli, you might want to share the 2 watts between the regulator and a series power resistor, so that both heat up 1 watt. Just make sure the 7805 gets at least 8 volts on its input.
...sense I have to do the board again I was thinking about step-down regulator. That way I don't waste that much energy to heat?!

I still have to thing about the voltage measuring... that resistor system won't do. There has to be a better way. Some system what follows the AVR voltage level.

Regards
heguli

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

A step-down regulator is a good idea. Much better than the 7805 dissipating 2.5 Watt.

For the voltage measuring: add a capacitor (it almost looks now as if I'm a shareholder ....) of 10 nF to the ADC-input. That will help. The non-linearity is puzzling me. It's a good idea to test first with a simple potmeter between AVCC and ground (barnacle gave that tip somewhere else on the forum ... and it's a good one, so I spread the news :) )
I am using a simular setup as you for PS-voltage-measurement, and no problem ...

Cheers

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Now it's working properly, I just adjust the multiplier and disconnect the lcd backlight. I will also try Neil's trimmer system. But that's later, cause sun is shining :D

Regards
heguli