Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to generate 50hz frequency from PIC16F84A or 877A

Status
Not open for further replies.

babatundeawe

Full Member level 5
Joined
Apr 12, 2007
Messages
244
Helped
16
Reputation
32
Reaction score
12
Trophy points
1,298
Location
Nigeria
Activity points
2,727
highest period of pwm in pic16f

i am working on a project to construct an inverter using PIC16F84A or 877A. the micro is to control the whole operation of the inverter and also to generate the frequency and also using pulse width modulation regulation. pls any idea, circuit diagram and source code will be appreciated. thanks in anticipation.
 

deepu_ttc

Member level 5
Joined
Jun 10, 2006
Messages
89
Helped
3
Reputation
6
Reaction score
2
Trophy points
1,288
Activity points
1,893
howto generate a frequency with pic

y dont u use 2 timer( in pic ) to generate a pwm signal and generate another square wave with other timer use a ckt that have a logic such that it has 2 i/p's and 2 o/p's and the behaviour will be if square wave is 1 then o/p-1 will be pwm and o/p-2 will be 0 and when square wave is 0 then o/p-1 will be 0 and o/p-2 will be pwm then connect these 2 o/p's to 2 bjts connected in series so u get required frequency
 

VVV

Advanced Member level 5
Joined
Nov 26, 2004
Messages
1,582
Helped
384
Reputation
768
Reaction score
87
Trophy points
1,328
Activity points
19,971
how to program a servo with 877a

You can use the CCP modules in the PIC16F877A, together with TMR2. Both can be used to produce PWM pulses.
What kind of inverter are you going to design? There are newer parts that can handle the bridge. For example PIC16F690. Check the datasheet.
 

progart

Newbie level 4
Joined
Nov 1, 2007
Messages
7
Helped
2
Reputation
4
Reaction score
0
Trophy points
1,281
Activity points
1,340
how to generate 50hz ac

You can use MCU's interrupt (from TMR)function for your project and get stronger results.
Calculate your TMR prescaler values which MCU's oscillator and write basic interrupt program...
 

xorcise

Full Member level 2
Joined
Sep 27, 2007
Messages
124
Helped
20
Reputation
40
Reaction score
1
Trophy points
1,298
Location
NYC
Activity points
2,169
configure ccp module as 50hz pwm output

I have written tons of 50Hz PWM code for servos. The following might be helpful for some of your own ideas. It runs 8 servos at super high resolution using mikroBasic.

SERVO8_10000 occupies less than 200 ROM and can individually position 8 servos to within 1/10000th of an 180 degree arc +/- 0.1%...if you have such a type of 50Hz servo. Add USART easily and without jitter and interruptions. This code example will work on P16's running @ 20Mhz. It is easily ported to P18's and uses NO INLINE ASSEMBLER.

Code:
Code:
program SERVO8_10000
'*********************************************************************************
' SERVO8_10000 by Warren Schroeder on October 3, 2006
' Program successfully compiled using mikroBASIC 5.0.0.0
' Tested on 16F877A @ 20MHz

' Servo8_10000 is a demonstration of managing 8 servos every 20ms with more
' than 13-bit position resolution without using inline assembler code.
' You can theoretically achieve 10,000 servo positions per servo if using
' 500us to 2500us range servos and a 20MHz oscillator. Any servo timing range
' is possible up to maximum of 2500us.
'
' Theory of operation is to give each servo an exact 2500us frame to do its
' position duty-cycle.  The servo turns ON at the start of the 2500us frame,
' completes its duty-cycle, turns OFF, and then waits for the next frame. At
' the next 2500us frame a new servo is then turned ON and the cycle is repeated.
' Each of the 8 servos occupies a 2500us slot and refreshed sequentially.  All
' 8 servos thus require 20ms to complete.  At this point, we go back to the first
' servo and repeat this whole process. This method creates exact 20ms periods
' between same servo time frames, which is required for 50Hz servos.
'
' The example below assumes using servos with a timing range of 900us to 2100us
' Timer1 is setup for 0.2us per count (no prescaler @ 20MHz).  Therefore, the min
' and max position values for this servo would be 4500 to 10,500.  To acheive 90
' degrees of motion, or 1500us, the formula is 1500 x 5 = 7500.
'
' ABOUT USING RX.
' To use RX with USART I recommend using the mB USART library commands.  These
' commands do not implement the USART Interrupts and are ideal for this program.
' Put the USART_DATA_READY and USART_READ function in the two wait loops in the
' MAIN program.  USART has a 2-byte buffer which will not fill up and is not
' affected by the Timer interrupts as long as you take advantage of reading it
' regularly.  Using the two wait loops is the best time to check the RX buffer.
'**********************************************************************************

symbol T1_Switch = T1CON.TMR1ON
symbol T1_Int_Flag = PIR1.TMR1IF
symbol T1_Int_En = PIE1.TMR1IE
symbol T0_Int_Flag = INTCON.TMR0IF
symbol T0_Int_En = INTCON.TMR0IE
const IsEnabled = 1
const IsDisabled = 0
const IsSet = 1
const IsRst = 0
const IsOn = 1
const IsOff = 0
dim intflag as boolean
dim servo as byte
dim T1 as word absolute $0E
dim T0 as byte absolute $01
dim pos as word[8]

sub procedure interrupt
   If T0_Int_Flag = IsSet Then      ' if Timer0 interrupt
      T0 = -196                     ' load Frame 196 x 12.8us = 2508us interrupt cycle
      Clearbit(PORTB, servo)        ' force servo off...in case value was wrong
      servo = inc(servo) And 7      ' next servo
      Setbit(PORTB, servo)          ' turn on next servo
      T1 = 0 - pos[servo]           ' load servo position...each count is 0.2us
      T1_Switch = IsOn              ' turn Timer1 On
      T1_Int_Flag = IsRst           ' reset Timer1 Interrupt Flag
      T0_Int_Flag = IsRst           ' reset Timer0 Interrupt Flag
   Else                             ' if Timer1 interrupt
      Clearbit(PORTB, servo)        ' turn off servo
      T1_Switch = IsOff             ' turn Timer1 Off
   End If
   intflag = not(intflag)           ' interrupt flag status
end sub

main:
   TRISB = 0
   OPTION_REG = $85                 ' Timer0 prescaler = 64 = 12.8us
   PORTB = 0
   INTCON = $E4                     ' GIE, PEIE, Timer0 Enabled; Timer0 Flag Set
   T1CON = 0                        ' Timer1 Off; No prescaler
   For servo = 0 to 7
      pos[servo] = 7500             ' set for 1500us mid-point
   Next servo
   intflag = False
   servo = 0
   T1 = 0 - 4500                    ' load Timer1
   T1_Int_Flag = IsRst              ' reset Timer1 Interrupt Flag
   T1_Int_En = IsEnabled            ' Timer1 Interrupt Enabled
   T1_Switch = IsOn                 ' Timer1 On
   T0 = -196                        ' load TMR0 for 2500us Interrupt Cycle Count
   T0_Int_En = IsEnabled            ' reset Timer0 Interrupt Flag
   Setbit(PORTB, 0)                 ' turn on first servo

   While 1=1
      While intflag = False         ' WAIT until Timer1 Interrupt
       nop                          ' place USART Read routines in here
      Wend
      While intflag = True          ' WAIT until Timer0 Interrupt
       nop                          ' place USART Read routines in here
      Wend
   Wend
   
end.
 

babatundeawe

Full Member level 5
Joined
Apr 12, 2007
Messages
244
Helped
16
Reputation
32
Reaction score
12
Trophy points
1,298
Location
Nigeria
Activity points
2,727
pic 50 hz inverter source code

VVV said:
You can use the CCP modules in the PIC16F877A, together with TMR2. Both can be used to produce PWM pulses.
What kind of inverter are you going to design? There are newer parts that can handle the bridge. For example PIC16F690. Check the datasheet.

thanks for your post. i really appreciate the way you put it pls can you be more explanatory the way you did with the sg3525. pls i will appreciate if i can see a little source code and scematics. because i ve not tried anything on ccp and pwm with any micro. thanks in anticipation
 

xorcise

Full Member level 2
Joined
Sep 27, 2007
Messages
124
Helped
20
Reputation
40
Reaction score
1
Trophy points
1,298
Location
NYC
Activity points
2,169
how to generate 50hz sine wave for 100 points

VVV said:
You can use the CCP modules in the PIC16F877A, together with TMR2. Both can be used to produce PWM pulses.
What kind of inverter are you going to design? There are newer parts that can handle the bridge. For example PIC16F690. Check the datasheet.

You cannot get 50Hz (20ms period) from the CCP PWM module, unless you run the PIC with less than 1MHz oscillator.
 

VVV

Advanced Member level 5
Joined
Nov 26, 2004
Messages
1,582
Helped
384
Reputation
768
Reaction score
87
Trophy points
1,328
Activity points
19,971
pic16f84 pwm code

xorcise is right about the oscillator frequency for 50Hz output.
But I don't think the inverter will be running at 50Hz. That is the output frequency, which is really just a modulation for the HF signal.

I will try to dig up some schematics.
 

mpopovics

Junior Member level 1
Joined
Jan 15, 2006
Messages
15
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,281
Location
Hungary
Activity points
1,357
generate a pulse signal with pic16f84

Is there any way to generate sine wave?
Means, real sinewave.
 

VVV

Advanced Member level 5
Joined
Nov 26, 2004
Messages
1,582
Helped
384
Reputation
768
Reaction score
87
Trophy points
1,328
Activity points
19,971
servo8_10000 by warren schroeder

babatundeawe,

Can you give more details on this inverter? Input/ output voltages, power and desired waveform?
 

Mike K8LH

Full Member level 2
Joined
Jun 6, 2005
Messages
129
Helped
19
Reputation
38
Reaction score
3
Trophy points
1,298
Location
Michigan, USA
Activity points
2,400
pwm pic 50hertz

xorcise said:
I have written tons of 50Hz PWM code for servos. The following might be helpful for some of your own ideas. It runs 8 servos at super high resolution using mikroBasic.

SERVO8_10000 occupies less than 200 ROM and can individually position 8 servos to within 1/10000th of an 180 degree arc +/- 0.1%...if you have such a type of 50Hz servo. Add USART easily and without jitter and interruptions. This code example will work on P16's running @ 20Mhz. It is easily ported to P18's and uses NO INLINE ASSEMBLER.
Nice example and method.

Here's another 8 channel (port b) method that uses the CCP "compare" mode with a 4 MHz clock for 1 usec pulse width resolution and 20 msec Servo period;

Code:
static unsigned char n = 0;
static unsigned int Pulse [] = { 1500, 1500, 1500, 1500,
                                 1500, 1500, 1500, 1500,
                                 20000 };
static unsigned char Servo = 1;


void isr_hi ()
{
 /****************************************************************
  *  K8LH Crazy-8 Hi-Rez Soft 8-channel (PORTB) Servo Algorithm  *
  ****************************************************************/

  if (PIR1bits.CCP1IF == 1)     // if CCP1 "compare" interrupt
  { LATB = Servo;               // output new Servo pulse and
    CCPR1 += Pulse[n];          // setup next "compare" value

    PIR1bits.CCP1IF = 0;        // clear CCP1 interrupt flag

    Pulse[8] -= Pulse[n++];     // adjust end-of-cycle off time
    Servo <<= 1;                // and prep for next channel

    if (n == 9)                 // if end of a 20-msec cycle
    { n = 0;                    // reset array index
      Pulse[8] = 20000;         // reset the 20.0-msec period
      Servo++;                  // reset Servo shadow to Servo 1
    }
  }
}

Added after 44 minutes:

xorcise said:
VVV said:
You can use the CCP modules in the PIC16F877A, together with TMR2. Both can be used to produce PWM pulses.
What kind of inverter are you going to design? There are newer parts that can handle the bridge. For example PIC16F690. Check the datasheet.
You cannot get 50Hz (20ms period) from the CCP PWM module, unless you run the PIC with less than 1MHz oscillator.
Actually you can. Sort of (grin).

The secret is to break up the 20 msec Servo period into smaller PWM "frames" and stuff the PWM duty cycle register during the period match interrupt with the value for the next "frame".

Here's a 4-pin 8 channel example using a 4 MHz clock and a 74HC238 decoder IC which is modulated by the PWM CCP1 pin (this is not the code for the 12F683 design shown below);

Code:
unsigned char select = 0;       // Servo channel number, 0..7
unsigned char frame = 10;       //
unsigned int pulse1;

/*                                                               *
 *  Servo[] array elements contain Servo pulse width values in   *
 *  the range of 3000..9000 (250-nsec 'ticks') which represent   *
 *  extended Servo pulse width ranges of 750 to 2250-usecs       *
 *                                                               */

static unsigned int Servo [] = { 6000, 6000, 6000, 6000,
                                 6000, 6000, 6000, 6000 };

/*****************************************************************
 *  K8LH 8-Channel 74HC238 Hi-Rez 'PWM' Servo Algorithm Example  *
 *****************************************************************/
#pragma interrupt isr_hi

void isr_hi ()
{ if(PIR1bits.TMR2IF)
  { PIR1bits.TMR2IF = 0;            // clear TMR2 interrupt flag

   /**************************************************************
    *  setup 74HC238 address lines and our work variables for    *
    *  the next servo channel interval during the final (10th)   *
    *  frame of the current servo channel interval (the final    *
    *  frame in each interval will always have a 0% duty cycle   *
    *  and all 74HC238 outputs are 'off' so it will be safe to   *
    *  change the address lines)                                 *
    *                                                            */
    if(frame == 10)             // 10 PWM frames/Servo interval
    { frame = 0;                // reset PWM frame number
      select %= 8;              // 8 Servo intervals/20-msec cycle
      pulse1 = Servo[select];   // setup 'pulse' work variable

      LATB = (LATB & 0b11111000) | select;  // set address lines

      select++;                 // preset for next interval
    }
    frame++;                    // bump for next interrupt

   /**************************************************************
    *  setup CCP1 PWM duty cycle for next 250-usec PWM 'frame'   *
    *                                                            */

    if(pulse1 > 1000)           // if pulse1 > 250-usecs
    { CCPR1L = 250;             // do a 100% duty cycle frame
      pulse1 -= 1000;           // subtract 250-usecs
    }
    else                        // do a variable or 0% frame
    { CCP1CONbits.CCP1Y = (pulse1 & 1);
      CCP1CONbits.CCP1X = (pulse1 & 2);
      CCPR1L = (pulse1 >>= 2);
      pulse1 = 0;               // remaining frames are %0
    }
  }
}
 

xorcise

Full Member level 2
Joined
Sep 27, 2007
Messages
124
Helped
20
Reputation
40
Reaction score
1
Trophy points
1,298
Location
NYC
Activity points
2,169
pic16f84a frequency tmr0

You certainly have a talent for this. I hadn't considered the CCP module in the first application... very nice. I've been programming PIC's for a couple years now and still learn something new every day.
 

ldanielrosa

Member level 4
Joined
Feb 24, 2007
Messages
71
Helped
8
Reputation
16
Reaction score
2
Trophy points
1,288
Activity points
1,722
pic16f84 square wave

I suppose I jumped in a bit late.

My approach would be similar to what progart said. Whatever the crystal frequency (I will assume 20MHz), I would assign a timed interrupt for 1024 Tosc (256 Tins) which is the highest frequency that would allow the full resolution of the PWM. This would give me 390.625 PWM periods (51.2 uS) per AC output cycle.

The '877 has two PWM outputs that share the same period, but have independent duty cycles. I would use them in tandem- one controlling the positive half cycles and the other for the negative, only one would be active at a time.

The means of determining the instantaneous period would be by adding a constant to a rolling sum. In this case a 24 bit sum should be accurate to about 0.001Hz. At each timed interrupt I would add 42,950 (0x00A7C6) to the sum, use the most significant 9-11 bits (depending on the resolution you want) to determine which phase (PWM output) and fetch a value from a lookup table for the PWM period.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top