basic code what am I missing? IF ADC is => increase PWM

Electronics Computer Programming Q&A
bodgy
Posts: 1044
Joined: Tue Dec 04, 2001 1:01 am
Location: Australia
Contact:

Post by bodgy » Fri Oct 20, 2006 5:24 am

Interrupts:
These are generated by the uC - it stops what it has been processing, makes notes about where it was in the program code, and then either performs a task that the hardware in the uC has asked it to do; for example perform an A-D conversion or set an internal flag that the conversion has finished and is now available; or it can divert to a specially written software function by you the programmer and perform tasks that you specify - often used for timers such as button debouncing or RTC's and sometimes more advnaced stuff.

Goto:
Frowned upon by programming purists - though has to be used in Assembler. A goto is where you interrupt the code flow on purpose and continue somewhere else in the code. It is frowned upon because it can very easily get messy, as the programmer can jump all over the place. It makes the code difficult to follow and a mistake in coding can be really hard to trace.

Gosub:

This is part of what is called structured programming. IT breaks the code up into seperate sections - code that might be needed more than once in different places in a program can be re-used without having to wirte it more than once. The compiler will insert code that allows the uC to know at which part of the program you called the subroutine from and when the end of code in the subroutine is reached, the uC will continue running code from the next instruction after the call.

In early versions of BASIC you had no choice but to use goto's - most modern versions rarely require the use of it.

Colin

Exmples follow in the next post.
On a clear disk you can seek forever.

bodgy
Posts: 1044
Joined: Tue Dec 04, 2001 1:01 am
Location: Australia
Contact:

Same samples

Post by bodgy » Fri Oct 20, 2006 5:46 am

Using GOTO's

Code: Select all

goto setup    //setup is a label all labels shown as label name :

init_rtc:
   rtc code here
 and here
 if rtc not working
 goto error_disp

While:
  while true do
  rest of code
  goto While

end of program

setup:

 code here
 more code here
 even more code here

 goto init_rtc 

Using subroutines. // these are also known as functions or procedures depending on the programming language - there is in some languages a subtle difference between a subroutine and a function.

Notice how here, if we wanted to re could use these subroutines anumber of times anywhere we wanted to. With gotos' we'd either have to write the code more than once or confuse ourselves by putting goto's all over the place. Note though this ONLY applies to using languages such as basic, pascal and 'C' and others. Using assembler we can't easily avoid using goto's.

Code: Select all


gosub setup // a call to a subroutine

gosub init_rtc_1337

if rtc not working        
   
   gosub error_disp

endif



while 1 do

        
end of program

sub setup
 
setup code

more setup code
even more setup code

end of setup sub  // note this will return automatically back to the code gosub init_rtc

sub init_rtc

 rtc code here
 and here

 if rtc not working

  gosub error_disp   //on return (automatically) from error_disp() we will get here

// we are now here at the code that will return us to the while loop
end of init_rtc sub 
An interrupt - these will look different depending on the programmming language.

Code: Select all

void Interrupt()
{
  

 if(PIR1&(1<<TMR2IF))  // a bit set in a register within the uC if it's a 1 we do what is inside the curly brackets
  {
    #asmline bcf PIR1,TMR2IF            ;Timer 2 Flag
    SysFlag.Tmr2=1;
  }
  
 if(INTCON&(1<<T0IF)) 		        // Test TMR0 interrupt flag
  {
    #asmline bcf INTCON,T0IF           ;  Clear TMR0 interrupt flag
    SysFlag.Tmr0=1;    		
       
    if(TickMid!=0)			//Has TickMid reached zero
      {
    	if(--TickMid!=0)	
        return;               	        //if not decrease and check for zero
      }
    else				//Tickmid was zero so decrease TickHigh
      {
    	 --TickHigh;
    	 if(--TickMid!=0);		//Has Tickmid reached zero now?	
     	 return;
      }	
     
     if(TickHigh==0)			//TickMid is zero so check TickHigh if
       { 				//zero reload counter
          TickHigh=COUNTH;
          TickMid=COUNTM;
          TickLow+=COUNTL;		//Load counter with initial+ remainder
          #asmline btfsc STATUS,C	;Has a carry occurred from low to mid
          TickMid++;			//yes so increase TickMid
          sec++;
       }    
     }
   if(PIR1&(1<<CCP1IF))
   {
      #asmline bcf PIR1,CCP1IF
      SysFlag.Tmr1E=1; 
   }    
    
}  this is the end of the interrupt. the uC will continue doing whatever it was doing before one of these registers had told the uC they had done something.

Just a note there is in some languages a special type of goto it is called break.

The difference to you writing goto's is this will always branch to the end of a subroutine.

Colin
On a clear disk you can seek forever.

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Fri Oct 20, 2006 7:33 am

So you would recommend interrupts over gosubs? Both return to the same section of code they left correct? What book would you recommend to give a beginner some uselul "C" basics? Thank You Much. Emmett

ecerfoglio
Posts: 108
Joined: Thu Nov 25, 2004 1:01 am
Location: Buenos Aires Argentina
Contact:

Post by ecerfoglio » Fri Oct 20, 2006 10:38 am

What is the difference between a goto or gosub statement, and an interrupt?

So you would recommend interrupts over gosubs?
An interrupt is trigered by an external event

It may be a sensor detecting something, a switch pressed, a cero crossing in the AC voltage or even a timer that reaches its preset count (the timer may be inside the microcontroller but it is external to the main program)

subroutines (gosub, functions, etc) execute when the main program tell them to.
E. Cerfoglio
Buenos Aires
Argentina

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Fri Oct 20, 2006 11:35 am

Ah, OK. Is that a big difference as far as processor usage goes? And is that the main advantage?

bodgy
Posts: 1044
Joined: Tue Dec 04, 2001 1:01 am
Location: Australia
Contact:

Post by bodgy » Sat Oct 21, 2006 2:32 am

cwaugs wrote: Is that a big difference as far as processor usage goes? And is that the main advantage?

I think this needs to be looked at from a different angle.

1. If you are relatively new to uC programming, then avoiding interrupts is the way to try and go, as it can be difficult to locate misbehaving code.

Having said that, a general rule of thumb would be to think of interrupts as something that is time sensitive.

So code that requires repeatable timing will often use interrupts - such as RS232 (serial) communications, I2C, SPI and more esoteric types of comms. Here an interrupt would be used to ensure that the timing of the individual bits were exact.

Another use of what are called external interrupts, such as waiting for something to occur on a port pin might be used for emergency purposes. As the processor stops whatever code it was processing and zaps off to the interrupt code it could be used for equipment that has emergency stop buttons for example.

Now from a code usage and efficiency point of view what are called internal or hardware interrupts will save you code space and in some instances a lot of hard work.

This will be down to the type of uC you choose. Many chips have inbuilt serial or I2C etc transmission generators. These will always use interrupts and will save you having to work out timing issues and writing time sensitive code. With these you just have to put the data to be transmitted into a uC's special transmit register and it does the rest, and interrupt flag will tell your program that it has sent the data byte and is ready for the next one, same for reception.

Perhaps to help you better here, what sort of project are trying to design, then we can offer specific help to show you the differences.

From an earlier question about books explaining 'C', the first thing I would suggest is to decide what processor or manufacturer you are aiming for, as there will be books that are aimed at that particular processor as not all 'C's are equal.

However some reasonably easy books are.

1.Learning to Progam in 'C' (this is aimed at PC's but the general idea will be the same for uC' Babani Publishing BP258 ISBN 0859342034 the ISBN might be different for the US.

Learning to program in FED 'C' downloadable from www.fored.co.uk - not the best of manuals but again it does 'whisk' you through the basics.

A reasonably good one is PIC C 'An introduction to programming the Mchip PIC in C" by Nigel Gardener. Unfortunately this book is hard to get it is available from RS Components at an RS price, it might still be available from BlueBird Electronics website the ISBN is 1899013040.

Another book that might be useful is 'C for the 8051' by Rigels Press in the US - however if you are not US based it is a pain getting them to send it to you - you'll need to sign a declaration that you will not use your new found knowledge of 'C' to build an explosive device or take the book to In dia. You might have guessed I've already been all throught that some years ago.

There are also some books by Ibrahim Doogan from the UK however they only teach you 'c' by presenting you with beginners programs for the 8051 processor.

If you are serious about learning 'C' then the book by the 'godfathers' of 'C' Kernow and Ritchie is the way to go.

Also check out Peter Ansersons webpage - he has tutorials from his uni classes available for download (at a small cost). www.phanderson.com

Colin
On a clear disk you can seek forever.

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Sat Oct 21, 2006 3:45 pm

Good information Colin, As to what I am trying to design, Basically the heart of it, (around which I believe I can figure out the other minor details) is a ATMega48, running three frequencies, multiples of each other, I.E. 1-1Khz/2-4Khz/4-8Khz in an a/c shaped square wave centered on top of each other like a pyramid. This is put out by the supposed six PWM's on the chip. A first conflict that I see according to which documentation you read. (The width of the pulse stays the same only the frequency varies by 5-10 Khz depending on the ADC sample that is looking at temperature). If temp goes up, then frequency needs to come down. And the opposite if temp goes down then freq up. In PBP programming a 16F877, I understand what controls the frequency and have no problem building code to do that with one timer. The thing is three timers and a different language (or syntax even in Bascom) leaves me hanging. I coded a Bascom program that (according to the bascom simulator) compiles and runs and might be running three of the PWM's but there is very limited documentation and some that is conflicting as to how the three timers interact with each other. Also I also see that there is limited frequency ranges depending of course on the crystal. I have an STK500 board and another one made by Avro and a Maverick128 board.
Thanks again for putting up with my inexperience Sir! Emmett

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Tue Oct 24, 2006 5:55 am

I think I have a test program, running all three timers, in Bascom. Seems to do what is needed in the simulator anyhow. Tried loading it on a 48 last night but It's different than what I'm used to in PBP. Need to get some more time hopefully this weekend. I'll be back. Ordering a book on "C".

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Tue Oct 31, 2006 12:45 pm

Still researching the accuracy that the timer frequency resolution can be set to and varied from. What i'm not understanding is how to change the freq from 10khz to 10.5khz with the same oscillator. there HAS to be a way. I HAVE to be overlooking something obvious. My understanding so far is that timer frequency is purely a division of crystal frequency and can be no other? If that were so then the PIC16F877 wouldn't work like it does. In PBP I can change low frequencies one Hz. at a time with no problem, I realize 300Hz to 301Hz 302Hz ... is a lot less resolution than 10, 10.5, 11, 11.5, 12Khz.etc. For example setting the registers (In Bascom ATMega48) TCCR0 = &B01100001 +1 will simply change the prescaler? but it should be able to step up from there to the next prescaler with some kind of smaller step, (hence the term PREscaler)? There's no way to set the timer to any other frequency without using an external oscillator or changing the oscillator that runs the uP? Thinking of using a uP controlled oscillator to run the Micro? AAAAAAAAHHHHHHHHH!!!
I hate not understanding parts of this stuff. I'll pull my hair out some more, that always seems to help. Gonna try to set the O-Scope up tinight and squirt my latest code into it and see what actually comes out! Thanks again patient ones!!! Emmett

User avatar
MrAl
Posts: 3862
Joined: Fri Jan 11, 2002 1:01 am
Location: NewJersey
Contact:

Post by MrAl » Tue Oct 31, 2006 3:16 pm

Hi there,

I havent worked with the 877 yet, but from what i see in the other
chips you cant change the run frequency in small increments like
that without using an external osc. You can however use timing
in your code to delay things and thus get a section of your code
running at a selected frequency, as long as that frquency isnt
too high.
For example, i can get sections of my code to run at
f=5.08305715 Hz, or
f=5.08297964 Hz, or
f=5.08290213 Hz

which means each inc is about 8e-5 Hz.


At around 10kHz i can get these:

10000Hz, 10638.299Hz

but the second number can be 'tuned' to get close to 10.5kHz if
needed by adding software delays.


There's also the timer interrupts, which i think you can set to interrupt
at any timer count by presetting the timer and waiting for an interrupt.
LEDs vs Bulbs, LEDs are winning.

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Thu Nov 02, 2006 6:11 am

It's slowly but finally starting to soak in. I need to squirt the latest code I piled, onto the chip, and stick a scope on it and actually see what is coming out of it. Thank you again for your time Sir!

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Sun Nov 19, 2006 3:54 pm

HPWM 1,127,1000 is the command in PicBasicPro that allows code to control the HPWM Channel,Dutycycle,Frequency on a 16F877. The duty cycle and channel are easy but I have yet to understand what would do the same thing on a Atmel Mega88 when it comes to frequency. I can handle the rest of the code in Bascom (still trying to get a handle on "C") but no matter what I try, the smallest frequency jump I can make is 10KHz to 44KHz to 86KHz according to my TDS 350 Tektronics. Evidently, I'm simply messing with the prescalers but there HAS to be a finer adjustment of frequencies. I can make a PIC move one Hz at a time at lower frequencies (200-900Hz), and don't expect that fine of adjustment at higher frequencies (10KHz to 40KHz) but I'd be pleased with 1KHz at a time. I can't understand why it can't be done. Emmett

User avatar
MrAl
Posts: 3862
Joined: Fri Jan 11, 2002 1:01 am
Location: NewJersey
Contact:

Post by MrAl » Sun Nov 19, 2006 4:53 pm

Hi again,

Are you generating your own PWM (ie pulsing the output pin
and then calling a delay routine, etc.) or are you using a built
in periph PWM to generate your PWM?

If you are using the on chip PWM periph then you can find out
the resolutions by looking at the data sheet under the section
for PWM. You can find resolutions like 10 bit, 8 bit, 6 bit.
This will give you a good idea what you can get out of it.
I dont know how much you can vary the frequency itself though,
and not sure why you would want to do this anyway.
Normally you would select a frequency and stick with it, varying
only the duty cycle...that's what PWM is. If you vary the
frequency then you are using PPM, which is not the same thing.

If you are doing your own delays and pulsing the output,
then you need to look at your delays better most likely.

If you need some sort of custom PWM that involves changing the
frequency then you probably have to generate your own delays
and flip the output pin when it's time.

You're not by any chance trying to control an AC motor of some sort
are you?
LEDs vs Bulbs, LEDs are winning.

cwaugs
Posts: 28
Joined: Thu Sep 01, 2005 1:01 am
Contact:

Post by cwaugs » Mon Nov 20, 2006 7:50 am

No no a/c motor. I'm pulsing the output into a coil. Yes, using the hardware PWM's Need to be able to vary it from 56KHz to 61KHz by 1KHz steps. Using the prescalers is too huge of a step though. I'll look into PPM. Thanks much Emmett

User avatar
MrAl
Posts: 3862
Joined: Fri Jan 11, 2002 1:01 am
Location: NewJersey
Contact:

Post by MrAl » Mon Nov 20, 2006 11:51 am

Hi there,

You could get some accuracy by calling a delay routine,
one for 56kHz, one for 57kHz, etc., up to 61kHz, then
flipping the output.
Using a 20MHz crystal oscillator 41 clocks would be half
of a 61kHz period (60976Hz).

Assuming a square wave output:

(Delay) Freq
-------- --------
(45) 55556Hz
(44) 56818Hz
(43) 58140Hz
(42) 59524Hz
(41) 60976Hz

As you can see the resolution isnt that good, but if it is good enough
for your app then you can use this. If not you'll have to resort
to a VCO. Since you dont need that many steps maybe you can
use a digital output code to set the VCO. The digital code
could come from the uC chip. Because you only need 6 different
frequencies you can get away with only 3 bits.
LEDs vs Bulbs, LEDs are winning.

Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests