Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Non Linear LED and PWM

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Tue Nov 01, 2016 1:39 pm    Post subject: Non Linear LED and PWM Reply with quote

Hello everybody,

I'm trying to control an LED's brightness via PWM, simple job I would think.

An AT Mega 8a is being used in this project along with an LTC6102 current monitor. the problem lies in the fact that there is an Variable resistor on ADC 0 and just spits out 0 to 5 Vdc like it should and the ADC reads it nicely, 0 to 3ff (10 bit). The Led is a 3 watt unit that runs at 2.5 up to 3.9 Vdc and is not linear. So I cant get it to work by just varying the voltage to as normally would be done.

I want to control it by current up to 1000 ma. So it starts to work at to 2.5 Vdc up the 3.9 max rating. When my PWM starts up (10 bit also) it's Variable resistor is at 50% of the way just to get it barely lit up.

What I would like is to somehow re scale the vr to work with the LED, so when the vr is at it's lowest voltage output to the ADC the PWM should be roughly at 50% of is value.

Timer one is configured for PWM=10 and works. I have tried to hard code this in Bascom but the memory is is not enough to hold it in the AVR.

Is there some type of cleaver way to do this? I need to say something like if ADC's value is 0 then output at 50% duty cycle on the PWM.
That's not to bad to implement but I still need to cover the rest of the ADC (what if its 0x3ff (1023)

I'm not sure I can figure this out, I tried using a lookup table, but it would be so big, it does not fit.

Any suggestions?

Robert



(BASCOM-AVR version : 2.0.7.8 )
Back to top
View user's profile Visit poster's website
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Tue Nov 01, 2016 2:08 pm    Post subject: Reply with quote

Hi Robert

could be the way...


int start_adc = 512
int end_adc = 1023

float calc_adc = start_adc / (end_adc - start_adc)

out_adc = ( getadc(0) / calc_adc) + start_adc


best, michael

_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Tue Nov 01, 2016 2:22 pm    Post subject: Reply with quote

Just to make sure I got this right:


Quote:
int start_adc = 512
int end_adc = 1023

float calc_adc = start_adc / (end_adc - start_adc)

out_adc = ( getadc(0) / calc_adc) + start_adc


int is an integer by the name of: "start_adc" and a value of 512
the same for "int end_adc" with a value of 1023


could you shed some light on this, where does "Calc_adc" come from along with "out_adc"?

I take it that they are dimmed variables of the word type?

Can you provide an example of this in code form of your intended usage of this?

Thanks for your help mate, it looks like it just may work.

Robert
Back to top
View user's profile Visit poster's website
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Tue Nov 01, 2016 2:40 pm    Post subject: Reply with quote

Hi Robert,

"out_adc" was not a good name for it... let's rename it to "out_pwm"

Declare start_adc and end_adc as word or as Constant.
Calc_adc is type single and out_pwm is type word variable.

The only part for you is, to do calculation step by step in multiple lines in bascom style Smile


What it does: the whole width of adc is calculated to use it between start and end values and out_pwm will be between start_adc and end_adc (...my hope Laughing )

best, michael

_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Tue Nov 01, 2016 2:47 pm    Post subject: Reply with quote

Thank-you for the clarification,

I'll give it a go..

By the way, your signature is quite cool, ingenues

Robert
Back to top
View user's profile Visit poster's website
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Tue Nov 01, 2016 2:54 pm    Post subject: Reply with quote

...do you have had a look backside your screen? Laughing Laughing Laughing
_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Tue Nov 01, 2016 2:54 pm    Post subject: Reply with quote

....
_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Tue Nov 01, 2016 3:56 pm    Post subject: Reply with quote

Code:
Dim Current_val As Word                                     '- Current sensor reading
Dim Setpoint As Word                                        '- Holds our Thumb-wheel setpoint
Dim Start_adc As Word                                       '- Used in VR's Array look up table
Dim End_adc As Word
Dim Calc_adc As Single
Dim Out_pwm As Word

On Timer2 T2_isr_a                                          '- Fires on Timer2 Compare match A ISR

'- Set items to only run once at startup
Call Configure_adc()                                        '- Setup the ADC registers
Call Timer1_setup()                                         '- Setup Timer1 for 10bit pwm PortB bit 1 only (PB1)
Call Timer2_setup()                                         '- Setup Timer2 compare match A
Enable Interrupts                                           '- Enable global interupts
Enable Timer1                                               '- Start Timer1 (PWM timer)
Compare1a = &H00                                            '- Set the PWM DUTY to 0x00 at start
Enable Timer2                                               '- Start Timer2 (Polarity switching)
Start_adc = 512
End_adc = 1023
Start Adc                                                   '- Start the adc Conversion

'- End Set items to only run once at startup

'-------------------------------------------------------------------------------
'Main program loop
'-------------------------------------------------------------------------------
Do
 '            *** NOTES ***

 '- Led does not lite up until 2.5 Vdc. top = 3.9 Vdc  0 to 1000 Ma of current
 '- 50% of pot will be useless   5 Vdc/1023 = .0048 Mv. per step  1FF (511) = 2/5 Vdc
 '- That leaves 50 of the pot to control the LED brightness
 '- Need to scale pot to the LEDs Current curve and still make it fit in the memory of the ATMEGA8


''Float Calc_adc = Start_adc /(end_adc - Start_adc)
Calc_adc = Start_adc /(end_adc - Start_adc)


Out_pwm =(getadc(0) / Calc_adc) + Start_adc



Loop


Always get:

Error : 242 Line : 88 Data type of source and target variables do not match [ 0] , in File : C:\Users\Robert\Desktop\ATMEGA8\Camera_atmega8.bas
Error : 35 Line : 91 3 parameters expected , in File : C:\Users\Robert\Desktop\ATMEGA8\Camera_atmega8.bas
Error : 124 Line : 91 LOOP expected , in File : C:\Users\Robert\Desktop\ATMEGA8\Camera_atmega8.bas


A code snippet would be ideal here.
Back to top
View user's profile Visit poster's website
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Tue Nov 01, 2016 5:11 pm    Post subject: Reply with quote

Hi,
you can't do that operation in one step, as i mentiond before...

NOT
Calc_adc = Start_adc /(end_adc - Start_adc)

Better
Calc_adc = end_adc - Start_adc
Calc_adc = Start_adc / Calc_adc



NOT
Out_pwm =(getadc(0) / Calc_adc) + Start_adc

BETTER
Out_pwm = getadc(0)
Out_pwm = Out_pwm / Calc_adc
Out_pwm = Out_pwm + Start_adc


AND!
there a more steps to reach goal!

out_pwn now is a value between Start_adc and end_adc.
for your pwm, wich can be at max 255, you have to divide by 4 !

_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Wed Nov 02, 2016 10:17 am    Post subject: Reply with quote

Code:

   Calc_adc = end_adc - Start_adc
   Calc_adc = Start_adc / Calc_adc


   Setpoint = Setpoint / Calc_adc
   if setpoint < Start_Adc then
      Setpoint = Setpoint + Start_adc
   else
      Setpoint = Setpoint
   end if


It seems to work great in the debugger tomorrow I will try it out.

One problem is that it would replace the read adc value with the ADC value + the Start_ adc value.
I added the if/then statement and that resolved the problem.

Thanks for you help mate,

Robert Very Happy
Back to top
View user's profile Visit poster's website
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 550

germany.gif
PostPosted: Wed Nov 02, 2016 7:47 pm    Post subject: Reply with quote

not sure, you're on the right track Robert....

must be look like this

Code:

$regfile = "m328pdef.dat"
$crystal = 20000000

$hwstack = 100
$swstack = 100
$framesize = 50


Dim Current_val As Word                                     '- Current sensor reading
Dim Start_adc As Word                                       '- Used in VR's Array look up table
Dim End_adc As Word
Dim Calc_adc As Single
Dim Out_pwm As Word


Enable Interrupts                                           '- Enable global interupts

Start_adc = 512
End_adc = 1023
Start Adc                                                   '- Start the adc Conversion

'prepare variables
Calc_adc = End_adc - Start_adc                              'calculate usable range
Calc_adc = Start_adc / Calc_adc                             'calculate spread factor

'-------------------------------------------------------------------------------
'Main program loop
'-------------------------------------------------------------------------------
Do



Out_pwm = Getadc(0)                                         'get the adc value
Out_pwm = Out_pwm / Calc_adc                                'fit value from adc to usable range
Out_pwm = Out_pwm + Start_adc                               'add the value where output is starting from

Out_pwm = Out_pwm / 4                                       'because ADC is 0..1023 and PWM is only quarter of it (0..255) so we have to divide by 4

Compare1a = Out_pwm                                         ' now set PWM to out_pwm value....

Loop
End
 


hope you can read my comments... english is not my native language Laughing

_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Robert_d1968

Bascom Member



Joined: 18 Dec 2012
Posts: 64
Location: China

usa.gif
PostPosted: Wed Nov 02, 2016 8:56 pm    Post subject: Reply with quote

Yes on the right track, it reads the right way.

As for dividing by 4 it's not needed, as the adc and pwm are both 10 bit.

It works well thus far in the debugger, tomorrow I will test it out on the real circuit... Your code looks just like mine, I will post up the results
from the test and what ever needs to be changed on my end.

Once again, Thanks for your help,

Robert
Back to top
View user's profile Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum