Professional Documents
Culture Documents
r
A
c
|
c
N
2
Or it can be written as
L =
N
2
3
c
+3
g
=
A
c
|
g
+
|
c
r
N
2
As We know
N =
LI
0
=
LI
B
c
A
c
Gives
N =
LI
2
0
=
LI
2
B
c
A
c
So
A
p
= W
a
A
c
=
LI
2
1
4
B
c
K
u
j
Substituting J we get
A
p
= _
LI
2
1
4
B
c
K
u
K
j
_
1
1-x
The number of turns will be
64
D. Source Code
We used PIC16F877A microcontroller for controlling all the operations in project. The
language used for programming is C and compiler used is CCS PCWH C Compiler. We
edited header file to add some register names according to datasheet.
The Source Code is divided into many files. Below are all the files and the code contained in
them.
D.1 16F877A_modified.h
/********************************************************
* *
* This portion of header file is from CCS C Compiler *
* *
********************************************************/
#ifndef _16F877A_h
#define _16F877A_h
//////// Standard Header file for the PIC16F877A device
////////////////
#device PIC16F877A
#nolist
//////// Program memory: 8192x14 Data RAM: 367 Stack: 8
//////// I/O: 33 Analog Pins: 8
//////// Data EEPROM: 256
//////// C Scratch area: 77 ID Location: 2000
//////// Fuses:
LP,XT,HS,RC,NOWDT,WDT,NOPUT,PUT,PROTECT,DEBUG,NODEBUG
//////// Fuses:
NOPROTECT,NOBROWNOUT,BROWNOUT,LVP,NOLVP,CPD,NOCPD,WRT_50%
//////// Fuses: NOWRT,WRT_5%,WRT_25%
////////
//////////////////////////////////////////////////////////////
//// I/O
// Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(),
INPUT_x(),
// PORT_B_PULLUPS(), INPUT(),
// OUTPUT_LOW(), OUTPUT_HIGH(),
// OUTPUT_FLOAT(), OUTPUT_BIT()
// Constants used to identify pins in the above are:
#define PIN_A0 40
#define PIN_A1 41
#define PIN_A2 42
#define PIN_A3 43
#define PIN_A4 44
#define PIN_A5 45
#define PIN_B0 48
65
#define PIN_B1 49
#define PIN_B2 50
#define PIN_B3 51
#define PIN_B4 52
#define PIN_B5 53
#define PIN_B6 54
#define PIN_B7 55
#define PIN_C0 56
#define PIN_C1 57
#define PIN_C2 58
#define PIN_C3 59
#define PIN_C4 60
#define PIN_C5 61
#define PIN_C6 62
#define PIN_C7 63
#define PIN_D0 64
#define PIN_D1 65
#define PIN_D2 66
#define PIN_D3 67
#define PIN_D4 68
#define PIN_D5 69
#define PIN_D6 70
#define PIN_D7 71
#define PIN_E0 72
#define PIN_E1 73
#define PIN_E2 74
//////////////////////////////////////////////////////////////
//// Useful defines
#define FALSE 0
#define TRUE 1
#define BYTE int
#define BOOLEAN short int
#define getc getch
#define fgetc getch
#define getchar getch
#define putc putchar
#define fputc putchar
#define fgets gets
#define fputs puts
//////////////////////////////////////////////////////////////
//// Control
// Control Functions: RESET_CPU(), SLEEP(), RESTART_CAUSE()
// Constants returned from RESTART_CAUSE() are:
#define WDT_FROM_SLEEP 3
#define WDT_TIMEOUT 11
#define MCLR_FROM_SLEEP 19
#define MCLR_FROM_RUN 27
#define NORMAL_POWER_UP 24
#define BROWNOUT_RESTART 26
66
//////////////////////////////////////////////////////////////
//// Timer 0
// Timer 0 (AKA RTCC)Functions: SETUP_COUNTERS() or
SETUP_TIMER_0(),
// SET_TIMER0() or SET_RTCC(),
// GET_TIMER0() or GET_RTCC()
// Constants used for SETUP_TIMER_0() are:
#define RTCC_INTERNAL 0
#define RTCC_EXT_L_TO_H 32
#define RTCC_EXT_H_TO_L 48
#define RTCC_DIV_1 8
#define RTCC_DIV_2 0
#define RTCC_DIV_4 1
#define RTCC_DIV_8 2
#define RTCC_DIV_16 3
#define RTCC_DIV_32 4
#define RTCC_DIV_64 5
#define RTCC_DIV_128 6
#define RTCC_DIV_256 7
#define RTCC_8_BIT 0
// Constants used for SETUP_COUNTERS() are the above
// constants for the 1st param and the following for
// the 2nd param:
//////////////////////////////////////////////////////////////
//// WDT
// Watch Dog Timer Functions: SETUP_WDT() or SETUP_COUNTERS()
(see above)
// RESTART_WDT()
//
#define WDT_18MS 8
#define WDT_36MS 9
#define WDT_72MS 10
#define WDT_144MS 11
#define WDT_288MS 12
#define WDT_576MS 13
#define WDT_1152MS 14
#define WDT_2304MS 15
//////////////////////////////////////////////////////////////
//// Timer 1
// Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1
// Constants used for SETUP_TIMER_1() are:
// (or (via |) together constants from each group)
#define T1_DISABLED 0
#define T1_INTERNAL 0x85
#define T1_EXTERNAL 0x87
#define T1_EXTERNAL_SYNC 0x83
#define T1_CLK_OUT 8
#define T1_DIV_BY_1 0
#define T1_DIV_BY_2 0x10
#define T1_DIV_BY_4 0x20
67
#define T1_DIV_BY_8 0x30
//////////////////////////////////////////////////////////////
//// Timer 2
// Timer 2 Functions: SETUP_TIMER_2, GET_TIMER2, SET_TIMER2
// Constants used for SETUP_TIMER_2() are:
#define T2_DISABLED 0
#define T2_DIV_BY_1 4
#define T2_DIV_BY_4 5
#define T2_DIV_BY_16 6
//////////////////////////////////////////////////////////////
//// CCP
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
// Constants used for SETUP_CCPx() are:
#define CCP_OFF 0
#define CCP_CAPTURE_FE 4
#define CCP_CAPTURE_RE 5
#define CCP_CAPTURE_DIV_4 6
#define CCP_CAPTURE_DIV_16 7
#define CCP_COMPARE_SET_ON_MATCH 8
#define CCP_COMPARE_CLR_ON_MATCH 9
#define CCP_COMPARE_INT 0xA
#define CCP_COMPARE_RESET_TIMER 0xB
#define CCP_PWM 0xC
#define CCP_PWM_PLUS_1 0x1c
#define CCP_PWM_PLUS_2 0x2c
#define CCP_PWM_PLUS_3 0x3c
long CCP_1;
#byte CCP_1 = 0x15
#byte CCP_1_LOW= 0x15
#byte CCP_1_HIGH= 0x16
long CCP_2;
#byte CCP_2 = 0x1B
#byte CCP_2_LOW= 0x1B
#byte CCP_2_HIGH= 0x1C
//////////////////////////////////////////////////////////////
//// PSP
// PSP Functions: SETUP_PSP, PSP_INPUT_FULL(),
PSP_OUTPUT_FULL(),
// PSP_OVERFLOW(), INPUT_D(), OUTPUT_D()
// PSP Variables: PSP_DATA
// Constants used in SETUP_PSP() are:
#define PSP_ENABLED 0x10
#define PSP_DISABLED 0
#byte PSP_DATA= 8
//////////////////////////////////////////////////////////////
//// SPI
// SPI Functions: SETUP_SPI, SPI_WRITE, SPI_READ, SPI_DATA_IN
// Constants used in SETUP_SSP() are:
#define SPI_MASTER 0x20
#define SPI_SLAVE 0x24
#define SPI_L_TO_H 0
#define SPI_H_TO_L 0x10
#define SPI_CLK_DIV_4 0
68
#define SPI_CLK_DIV_16 1
#define SPI_CLK_DIV_64 2
#define SPI_CLK_T2 3
#define SPI_SS_DISABLED 1
#define SPI_SAMPLE_AT_END 0x8000
#define SPI_XMIT_L_TO_H 0x4000
//////////////////////////////////////////////////////////////
//// UART
// Constants used in setup_uart() are:
// FALSE - Turn UART off
// TRUE - Turn UART on
#define UART_ADDRESS 2
#define UART_DATA 4
//////////////////////////////////////////////////////////////
//// COMP
// Comparator Variables: C1OUT, C2OUT
// Constants used in setup_comparator() are:
#define A0_A3_A1_A3 0xfff04
#define A0_A3_A1_A2_OUT_ON_A4_A5 0xfcf03
#define A0_A3_A1_A3_OUT_ON_A4_A5 0xbcf05
#define NC_NC_NC_NC 0x0ff07
#define A0_A3_A1_A2 0xfff02
#define A0_A3_NC_NC_OUT_ON_A4 0x9ef01
#define A0_VR_A1_VR 0x3ff06
#define A3_VR_A2_VR 0xcff0e
#bit C1OUT = 0x9c.6
#bit C2OUT = 0x9c.7
//////////////////////////////////////////////////////////////
//// VREF
// Constants used in setup_vref() are:
//
#define VREF_LOW 0xa0
#define VREF_HIGH 0x80
// Or (with |) the above with a number 0-15
#define VREF_A2 0x40
//////////////////////////////////////////////////////////////
//// ADC
// ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka
SETUP_PORT_A),
// SET_ADC_CHANNEL(), READ_ADC()
// Constants used for SETUP_ADC() are:
#define ADC_OFF 0 // ADC Off
#define ADC_CLOCK_DIV_2 0x10000
#define ADC_CLOCK_DIV_4 0x4000
#define ADC_CLOCK_DIV_8 0x0040
#define ADC_CLOCK_DIV_16 0x4040
#define ADC_CLOCK_DIV_32 0x0080
#define ADC_CLOCK_DIV_64 0x4080
#define ADC_CLOCK_INTERNAL 0x00c0 // Internal 2-
6us
69
// Constants used in SETUP_ADC_PORTS() are:
#define NO_ANALOGS 7 // None
#define ALL_ANALOG 0 // A0 A1 A2
A3 A5 E0 E1 E2
#define AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF 1 // A0 A1 A2
A5 E0 E1 E2 VRefh=A3
#define AN0_AN1_AN2_AN3_AN4 2 // A0 A1 A2
A3 A5
#define AN0_AN1_AN2_AN4_VSS_VREF 3 // A0 A1 A2
A5 VRefh=A3
#define AN0_AN1_AN3 4 // A0 A1 A3
#define AN0_AN1_VSS_VREF 5 // A0 A1
VRefh=A3
#define AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF 0x08 // A0 A1 A5
E0 E1 E2 VRefh=A3 VRefl=A2
#define AN0_AN1_AN2_AN3_AN4_AN5 0x09 // A0 A1 A2
A3 A5 E0
#define AN0_AN1_AN2_AN4_AN5_VSS_VREF 0x0A // A0 A1 A2
A5 E0 VRefh=A3
#define AN0_AN1_AN4_AN5_VREF_VREF 0x0B // A0 A1 A5
E0 VRefh=A3 VRefl=A2
#define AN0_AN1_AN4_VREF_VREF 0x0C // A0 A1 A5
VRefh=A3 VRefl=A2
#define AN0_AN1_VREF_VREF 0x0D // A0 A1
VRefh=A3 VRefl=A2
#define AN0 0x0E // A0
#define AN0_VREF_VREF 0x0F // A0
VRefh=A3 VRefl=A2
#define ANALOG_RA3_REF 0x1 //!old only
provided for compatibility
#define A_ANALOG 0x2 //!old only
provided for compatibility
#define A_ANALOG_RA3_REF 0x3 //!old only
provided for compatibility
#define RA0_RA1_RA3_ANALOG 0x4 //!old only
provided for compatibility
#define RA0_RA1_ANALOG_RA3_REF 0x5 //!old only
provided for compatibility
#define ANALOG_RA3_RA2_REF 0x8 //!old only
provided for compatibility
#define ANALOG_NOT_RE1_RE2 0x9 //!old only
provided for compatibility
#define ANALOG_NOT_RE1_RE2_REF_RA3 0xA //!old only
provided for compatibility
#define ANALOG_NOT_RE1_RE2_REF_RA3_RA2 0xB //!old only
provided for compatibility
#define A_ANALOG_RA3_RA2_REF 0xC //!old only
provided for compatibility
#define RA0_RA1_ANALOG_RA3_RA2_REF 0xD //!old only
provided for compatibility
#define RA0_ANALOG 0xE //!old only
provided for compatibility
#define RA0_ANALOG_RA3_RA2_REF 0xF //!old only
provided for compatibility
// Constants used in READ_ADC() are:
70
#define ADC_START_AND_READ 7 // This is the default if
nothing is specified
#define ADC_START_ONLY 1
#define ADC_READ_ONLY 6
//////////////////////////////////////////////////////////////
//// INT
// Interrupt Functions: ENABLE_INTERRUPTS(),
DISABLE_INTERRUPTS(),
// EXT_INT_EDGE()
//
// Constants used in EXT_INT_EDGE() are:
#define L_TO_H 0x40
#define H_TO_L 0
// Constants used in ENABLE/DISABLE_INTERRUPTS() are:
#define GLOBAL 0x0BC0
#define INT_RTCC 0x0B20
#define INT_RB 0x0B08
#define INT_EXT 0x0B10
#define INT_AD 0x8C40
#define INT_TBE 0x8C10
#define INT_RDA 0x8C20
#define INT_TIMER1 0x8C01
#define INT_TIMER2 0x8C02
#define INT_CCP1 0x8C04
#define INT_CCP2 0x8D01
#define INT_SSP 0x8C08
#define INT_PSP 0x8C80
#define INT_BUSCOL 0x8D08
#define INT_EEPROM 0x8D10
#define INT_TIMER0 0x0B20
#define INT_COMP 0x8D40
#list
/*************************************************************
*******
* *
* This portion of header file is from HI-TECH PICC-STD
Compiler *
* *
**************************************************************
******/
#define _16F877A
/*
* Header file for the Microchip
* PIC 16F873A chip
* PIC 16F874A chip
* PIC 16F876A chip
* PIC 16F877A chip
* Midrange Microcontroller
*/
71
#if defined(_16F874A) || defined(_16F877A)
#define __PINS_40
#endif
#byte INDF = 0x00
#byte TMR0 = 0x01
#byte PCL = 0x02
#byte STATUS = 0x03
#byte FSR = 0x04
#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#ifdef __PINS_40
#byte PORTD = 0x08
#byte PORTE = 0x09
#endif
#byte PCLATH = 0x0A
#byte INTCON = 0x0B
#byte PIR1 = 0x0C
#byte PIR2 = 0x0D
#byte TMR1L = 0x0E
#byte TMR1H = 0x0F
#byte T1CON = 0x10
#byte TMR2 = 0x11
#byte T2CON = 0x12
#byte SSPBUF = 0x13
#byte SSPCON = 0x14
#byte CCPR1L = 0x15
#byte CCPR1H = 0x16
#byte CCP1CON = 0x17
#byte RCSTA = 0x18
#byte TXREG = 0x19
#byte RCREG = 0x1A
#byte CCPR2L = 0x1B
#byte CCPR2H = 0x1C
#byte CCP2CON = 0x1D
#byte ADRESH = 0x1E
#byte ADCON0 = 0x1F
/* bank 1 registers */
#byte OPTION = 0x81
#byte TRISA = 0x85
#byte TRISB = 0x86
#byte TRISC = 0x87
#ifdef __PINS_40
#byte TRISD = 0x88
#byte TRISE = 0x89
#endif
#byte PIE1 = 0x8C
#byte PIE2 = 0x8D
#byte PCON = 0x8E
#byte SSPCON2 = 0x91
#byte PR2 = 0x92
#byte SSPADD = 0x93
#byte SSPSTAT = 0x94
#byte TXSTA = 0x98
#byte SPBRG = 0x99
72
#byte CMCON = 0x9C
#byte CVRCON = 0x9D
#byte ADRESL = 0x9E
#byte ADCON1 = 0x9F
/* bank 2 registers */
#byte EEDATA = 0x10C
#byte EEADR = 0x10D
// Alternate definition
#byte EEADRL = 0x10D
#byte EEDATH = 0x10E
#byte EEADRH = 0x10F
/* bank 3 registers */
#byte EECON1 = 0x18C
#byte EECON2 = 0x18D
/* STATUS bits */
#bit IRP = STATUS.7
#bit RP1 = STATUS.6
#bit RP0 = STATUS.5
#bit TO = STATUS.4
#bit PD = STATUS.3
#bit ZERO = STATUS.2
#bit DC = STATUS.1
#bit CARRY = STATUS.0
/* PORTA bits */
#bit RA5 = PORTA.5
#bit RA4 = PORTA.4
#bit RA3 = PORTA.3
#bit RA2 = PORTA.2
#bit RA1 = PORTA.1
#bit RA0 = PORTA.0
/* PORTB bits */
#bit RB7 = PORTB.7
#bit RB6 = PORTB.6
#bit RB5 = PORTB.5
#bit RB4 = PORTB.4
#bit RB3 = PORTB.3
#bit RB2 = PORTB.2
#bit RB1 = PORTB.1
#bit RB0 = PORTB.0
/* PORTC bits */
#bit RC7 = PORTC.7
#bit RC6 = PORTC.6
#bit RC5 = PORTC.5
#bit RC4 = PORTC.4
#bit RC3 = PORTC.3
#bit RC2 = PORTC.2
#bit RC1 = PORTC.1
#bit RC0 = PORTC.0
/* PORTD bits */
#ifdef __PINS_40
#bit RD7 = PORTD.7
73
#bit RD6 = PORTD.6
#bit RD5 = PORTD.5
#bit RD4 = PORTD.4
#bit RD3 = PORTD.3
#bit RD2 = PORTD.2
#bit RD1 = PORTD.1
#bit RD0 = PORTD.0
/* PORTE bits */
#bit RE2 = PORTE.2
#bit RE1 = PORTE.1
#bit RE0 = PORTE.0
#endif
/* INTCON bits */
#bit GIE = INTCON.7
#bit PEIE = INTCON.6
#bit T0IE = INTCON.5
#bit INTE = INTCON.4
#bit RBIE = INTCON.3
#bit T0IF = INTCON.2
#bit INTF = INTCON.1
#bit RBIF = INTCON.0
// alternate definitions
#bit TMR0IE = INTCON.5
#bit TMR0IF = INTCON.2
/* PIR1 bits */
#ifdef __PINS_40
#bit PSPIF = PIR1.7
#endif
#bit ADIF = PIR1.6
#bit RCIF = PIR1.5
#bit TXIF = PIR1.4
#bit SSPIF = PIR1.3
#bit CCP1IF = PIR1.2
#bit TMR2IF = PIR1.1
#bit TMR1IF = PIR1.0
/* PIR2 bits */
#bit CMIF = PIR2.6
#bit EEIF = PIR2.4
#bit BCLIF = PIR2.3
#bit CCP2IF = PIR2.0
/* T1CON bits */
#bit T1CKPS1 = T1CON.5
#bit T1CKPS0 = T1CON.4
#bit T1OSCEN = T1CON.3
#bit T1SYNC = T1CON.2
#bit TMR1CS = T1CON.1
#bit TMR1ON = T1CON.0
/* T2CON bits */
#bit TOUTPS3 = T2CON.6
#bit TOUTPS2 = T2CON.5
#bit TOUTPS1 = T2CON.4
#bit TOUTPS0 = T2CON.3
74
#bit TMR2ON = T2CON.2
#bit T2CKPS1 = T2CON.1
#bit T2CKPS0 = T2CON.0
/* SSPCON bits */
#bit WCOL = SSPCON.7
#bit SSPOV = SSPCON.6
#bit SSPEN = SSPCON.5
#bit CKP = SSPCON.4
#bit SSPM3 = SSPCON.3
#bit SSPM2 = SSPCON.2
#bit SSPM1 = SSPCON.1
#bit SSPM0 = SSPCON.0
/* CCP1CON bits */
#bit CCP1X = CCP1CON.5
#bit CCP1Y = CCP1CON.4
#bit CCP1M3 = CCP1CON.3
#bit CCP1M2 = CCP1CON.2
#bit CCP1M1 = CCP1CON.1
#bit CCP1M0 = CCP1CON.0
/* RCSTA bits */
#bit SPEN = RCSTA.7
#bit RX9 = RCSTA.6
#bit SREN = RCSTA.5
#bit CREN = RCSTA.4
#bit ADDEN = RCSTA.3
#bit FERR = RCSTA.2
#bit OERR = RCSTA.1
#bit RX9D = RCSTA.0
/* CCP2CON bits */
#bit CCP2X = CCP2CON.5
#bit CCP2Y = CCP2CON.4
#bit CCP2M3 = CCP2CON.3
#bit CCP2M2 = CCP2CON.2
#bit CCP2M1 = CCP2CON.1
#bit CCP2M0 = CCP2CON.0
/* ADCON0 bits */
#bit ADCS1 = ADCON0.7
#bit ADCS0 = ADCON0.6
#bit CHS2 = ADCON0.5
#bit CHS1 = ADCON0.4
#bit CHS0 = ADCON0.3
#bit ADGO = ADCON0.2
// Alternate definition for compatibility with other devices
#bit GODONE = ADCON0.2
#bit ADON = ADCON0.0
/* OPTION bits */
#bit RBPU = OPTION.7
#bit INTEDG = OPTION.6
#bit T0CS = OPTION.5
#bit T0SE = OPTION.4
#bit PSA = OPTION.3
#bit PS2 = OPTION.2
75
#bit PS1 = OPTION.1
#bit PS0 = OPTION.0
/* TRISA bits */
#bit TRISA5 = TRISA.5
#bit TRISA4 = TRISA.4
#bit TRISA3 = TRISA.3
#bit TRISA2 = TRISA.2
#bit TRISA1 = TRISA.1
#bit TRISA0 = TRISA.0
/* TRISB bits */
#bit TRISB7 = TRISB.7
#bit TRISB6 = TRISB.6
#bit TRISB5 = TRISB.5
#bit TRISB4 = TRISB.4
#bit TRISB3 = TRISB.3
#bit TRISB2 = TRISB.2
#bit TRISB1 = TRISB.1
#bit TRISB0 = TRISB.0
/* TRISC bits */
#bit TRISC7 = TRISC.7
#bit TRISC6 = TRISC.6
#bit TRISC5 = TRISC.5
#bit TRISC4 = TRISC.4
#bit TRISC3 = TRISC.3
#bit TRISC2 = TRISC.2
#bit TRISC1 = TRISC.1
#bit TRISC0 = TRISC.0
#ifdef __PINS_40
/* TRISD bits */
#bit TRISD7 = TRISD.7
#bit TRISD6 = TRISD.6
#bit TRISD5 = TRISD.5
#bit TRISD4 = TRISD.4
#bit TRISD3 = TRISD.3
#bit TRISD2 = TRISD.2
#bit TRISD1 = TRISD.1
#bit TRISD0 = TRISD.0
/* TRISE bits */
#bit IBF = TRISE.7
#bit OBF = TRISE.6
#bit IBOV = TRISE.5
#bit PSPMODE = TRISE.4
#bit TRISE2 = TRISE.2
#bit TRISE1 = TRISE.1
#bit TRISE0 = TRISE.0
#endif
/* PIE1 bits */
#ifdef __PINS_40
#bit PSPIE = PIE1.7
#endif
#bit ADIE = PIE1.6
76
#bit RCIE = PIE1.5
#bit TXIE = PIE1.4
#bit SSPIE = PIE1.3
#bit CCP1IE = PIE1.2
#bit TMR2IE = PIE1.1
#bit TMR1IE = PIE1.0
/* PIE2 bits */
#bit CMIE = PIE2.6
#bit EEIE = PIE2.4
#bit BCLIE = PIE2.3
#bit CCP2IE = PIE2.0
/* PCON bits */
#bit POR = PCON.1
#bit BOR = PCON.0
/* SSPCON2 bits */
#bit GCEN = SSPCON2.7
#bit ACKSTAT = SSPCON2.6
#bit ACKDT = SSPCON2.5
#bit ACKEN = SSPCON2.4
#bit RCEN = SSPCON2.3
#bit PEN = SSPCON2.2
#bit RSEN = SSPCON2.1
#bit SEN = SSPCON2.0
/* SSPSTAT bits */
#bit SMP = SSPSTAT.7
#bit CKE = SSPSTAT.6
#bit DA = SSPSTAT.5
#bit STOP = SSPSTAT.4
#bit START = SSPSTAT.3
#bit RW = SSPSTAT.2
#bit UA = SSPSTAT.1
#bit BF = SSPSTAT.0
#ifdef __STAT_BACKWARD_COMPATIBILITY
#define STAT_SMP SMP
#define STAT_CKE CKE
#define STAT_DA DA
#define STAT_P STOP
#define STAT_S START
#define STAT_RW RW
#define STAT_UA UA
#define STAT_BF BF
#endif
/* TXSTA bits */
#bit CSRC = TXSTA.7
#bit TX9 = TXSTA.6
#bit TXEN = TXSTA.5
#bit SYNC = TXSTA.4
#bit BRGH = TXSTA.2
#bit TRMT = TXSTA.1
#bit TX9D = TXSTA.0
/* CMCON Bits */
//#bit C2OUT = CMCON.7 //already defined above
77
//#bit C1OUT = CMCON.6 //already defined above
#bit C2INV = CMCON.5
#bit C1INV = CMCON.4
#bit CIS = CMCON.3
#bit CM2 = CMCON.2
#bit CM1 = CMCON.1
#bit CM0 = CMCON.0
/* CVRCON Bits */
#bit CVREN = CVRCON.7
#bit CVROE = CVRCON.6
#bit CVRR = CVRCON.5
#bit CVR3 = CVRCON.3
#bit CVR2 = CVRCON.2
#bit CVR1 = CVRCON.1
#bit CVR0 = CVRCON.0
/* ADCON1 bits */
#bit ADFM = ADCON1.7
#bit ADCS2 = ADCON1.6
#bit PCFG3 = ADCON1.3
#bit PCFG2 = ADCON1.2
#bit PCFG1 = ADCON1.1
#bit PCFG0 = ADCON1.0
/* EECON1 bits */
#bit EEPGD = EECON1.7
#bit WRERR = EECON1.3
#bit WREN = EECON1.2
#bit WR = EECON1.1
#bit RD = EECON1.0
#define CONFIG_ADDR 0x2007
/*osc configurations*/
#define RC 0x3FFF // resistor/capacitor
#define HS 0x3FFE // high speed crystal/resonator
#define XT 0x3FFD // crystal/resonator
#define LP 0x3FFC // low power crystal/resonator
/*watchdog*/
#define WDTEN 0x3FFF // enable watchdog timer
#define WDTDIS 0x3FFB // disable watchdog timer
/*power up timer*/
#define PWRTEN 0x3FF7 // enable power up timer
#define PWRTDIS 0x3FFF // disable power up timer
/*brown out reset*/
#define BOREN 0x3FFF // enable brown out reset
#define BORDIS 0x3FBF // disable brown out reset
/*Low Voltage Programmable*/
#define LVPEN 0x3FFF // low voltage programming enabled
#define LVPDIS 0x3F7F // low voltage programming
disabled
78
/*data code protected*/
#define DP 0x3EFF // protect data code
// alternately
#define DPROT 0x3EFF // use DP
#define DUNPROT 0x3FFF // use UNPROTECT
/* Flash memory write enable/protect */
#define WRTEN 0x3FFF /* flash memory write enabled */
#define WP1 0x3DFF /* protect 0000 - 00FF */
#define WP2 0x3BFF /* protect 0000 - 07FF(76A/77A) /
03FF(73A/74A) */
#define WP3 0x39FF /* protect 0000 - 1FFF(76A/77A) /
0FFF(73A/74A) */
/*debug option*/
#define DEBUGEN 0x37FF // debugger enabled
#define DEBUGDIS 0x3FFF // debugger disabled
/*code protection*/
#define PROTECT 0x1FFF /* protect program code */
#define UNPROTECT 0x3FFF /* do not protect the code */
#endif //#ifndef _16F877A_h
79
D.2 Allocations.h
This file mainly contains pin allocations. If we need to change the purpose of a pin, we
simply change pin allocation in this file. In all the code coming after, we use names declared
in this file
#ifndef Allocations_h
#define Allocations_h
#ifndef _16F877A_h
#include "16F877A_modified.h"
#endif //end #ifndef _16F877A_h
/****************** Resource Allocation
***************************\
*
*Sun Tracking:
*-------------
* ==> Three A/D channels are allocated to 3 sensor
pairs(input)
* ==> Four motor pins are allocated(output)
* ==> One pin provided to control power of related
circuitry(output)
* ==> Three pins for sensing 3 breaks
*
* PINS:
* RA0/AN0,RA1/AN1,RA2/AN2 to measure 3 sensors
* RC0,RC2,RC3,RC4 to control motors
* RC5 to control power of Sun Tracking circuit(ON/OFF)
*
*MPPT:
*-----
* ==> CCP2 Module for PWM/MPPT
* ==> PWM module will use Timer2
* ==> Two A/D channels provided for panel's I and V
measurement
* ==> CCP2 output pin RC1 is utilized
* ==> One pin to control analog switch. To take Ipv
sample at same time when
* taking Vpv sample, we will use external analog mux.
this will be turned
* Off when starting Vpv conversion
*
* PINS:
* RA5/AN4 and RE0/AN5 to measure I and V
* RC1/CCP2 for PWM
*
80
*LCD:
*----
* PINS:
* PORTD for Data
* RB1,RB4 for RS,E pins of LCD
*
*Communication To PC:
*--------------------
* ==> USART used
*
* PINS:
* RC6/Tx,RC7/Rx
*
*Battery:
*--------
* ==> Two A/D pins provided for battery I and V
measurement
*
* PINS:
* RE1/AN6 to measure battery voltage
* RE2/AN7 to measure battery current
*
*Generic:
*--------
* ==> Timer1(16-bit) for global time keeping (if
required)
* ==> CCP1 to to control the period of Timer1 (if
Timr1 used)
*
* PINS:
* RB5 to control power of other interfacing circuitry
*
\*************************************************************
************/
/*********************** Pin Definitions
*****************************/
//SunTracking:
//------------
#define channelSensorAz 0
#define channelSensorAlt 1
#define channelSensor3rd 2
#define pinMotor1a RB1 //Motor Pin Definitions
#define dirMotor1a TRISB1
81
#define pinMotor1b RB2
#define dirMotor1b TRISB2
#define pinMotor2a RB4
#define dirMotor2a TRISB4
#define pinMotor2b RB5
#define dirMotor2b TRISB5
#define pinAzBreak RC0
#define dirAzBreak TRISC0
#define pinAltBreak1 RC4
#define dirAltBreak1 TRISC4
#define pinAltBreak2 RC5
#define dirAltBreak2 TRISC5
//#define pinSunTrackerPower RC5
//#define dirSunTrackerPower TRISC5
//MPPT:
//-----
#define channelVpv 6
#define channelIpv 5
//#define pinIpvSwitch RB0
//#define dirIpvSwitch TRISB0
//#define IpvSwitchOFF 0
//#define IpvSwitchON 1
#define pinPWM RC1
#define dirPWM TRISC1
//LCD:
//----
#define LCDdataPort PORTD
#define LCDdataDir TRISD
//#define pinLCDBusy RD7
//#define dirLCDBusy TRISD7
#define pinRS RC2
#define dirRS TRISC2
//#define pinRW RB2
//#define dirRW TRISB2
#define pinE RC3
#define dirE TRISC3
//RS232 Communication:
//--------------------
#define pinTx RC6
#define dirTx TRISC6 //needs to be set: page 111, col 2 of
DataSheet
82
#define pinRx RC7
#define dirRx TRISC7
//Battery:
//--------
#define pinBatteryVoltage RE1
#define dirBatteryVoltage TRISE1
#define pinBatteryCurrent RE2
#define dirBatteryCurrent TRISE2
#define channelBatteryVoltage 6
#define channelBatteryCurrent 7
//Generic:
//--------
#define pinTestLed RB5
#define dirTestLed TRISB5
#endif //end #ifdef Allocations_h
83
D.3 SpecsAndDefs.h
This file contains the things like oscillator frequency and many other circuit specific
declarations. If we decide to change, for example, the oscillator frequency, well change
declaration here and then there will be no effect on remaining code. For example, the timer1
will overflow after 1ms regardless of oscillator if we duly change #define Fosc 20000000
duely. The file also contains some global definitions
#ifndef SpecsAndDefs_h
#define SpecsAndDefs_h
#ifndef _16F877A_h
#include "16F877A_modified.h"
#endif //end #ifndef _16F877A_h
#fuses
NOLVP,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NODEBUG,NOCPD,NOWRT,HSp
eed
//Configuration Bits(word) is defined below
//#rom 0x2007={0x3FB2}
#define Fosc 20000000
#use delay(clock=Fosc)
#use rs232(baud=57600, xmit=PIN_C6,rcv=PIN_C7)
#define MaxTimer1Value (unsigned int16)(1e-3*Fosc/4) //
equals 1ms
#define MaxMilliSeconds (unsigned int16) 60000 //
equals 1min
#define Timer1CountsPer_us (Fosc * 1e-6)/4
#define PWMPeriod 40e-6 //25KHz
#if (((((int16)(PWMPeriod*Fosc))>>2)-1) <= 255)
#define Timer2Prescale T2_DIV_BY_1
#define Timer2Period
(int8)((((int16)(PWMPeriod*Fosc))>>2)-1)
#else
#define Timer2Prescale T2_DIV_BY_4
#define Timer2Period
(int8)(((((int16)(PWMPeriod*Fosc))>>2)-1)>>2)
#endif
#define DefaultDuty (int16)( (Timer2Period << 2) * .5)
#if (Fosc <= 20000000)
#define AdcClock ADC_CLOCK_DIV_32
84
#else
#define AdcClock ADC_CLOCK_DIV_64
#endif
#define IpvSensorOffsetInVolts 1.9
#define IpvSensorGain 22
#define Rsense 0.237
#define IpvSensorOffset
(int16)(1024*(float)IpvSensorOffsetInVolts/5)
#define IpvThatMaps5V (int16) 1000*(float)(5-
IpvSensorOffsetInVolts)/(float)(IpvSensorGain*Rsense)
#define VpvThatMaps5V 28500
#define Pos 0
#define Neg 1
//Global Variables Definitions
int32 t; // Global Variable for keeping global time
//It will be incremented each millisecond
unsigned int16 Vpv, Ipv, Vbat, Ibat;
unsigned int32 Ppv;
// #separate
// void MeasureVpvAndIpv(int16 &Vpv, int16 &Ipv);
#endif //End #ifndef SpecsAndDefs_h
85
D.4 Main.c
This file contains main function and some related global functions. Each needy function is
called in sequence in a loop and the function decides whether to do some function or not
depending upon the time elapsed after previous call to that function. For example, LCD
function will only update LCD after at least 1500 milliseconds. Global variable is used to
keep the global time in milliseconds.
#include "Allocations.h"
#include "SpecsAndDefs.h"
#include "MPPT.c"
#include "SunTrack.c"
#include "LCD.c"
#include "Misc.c"
void initialize(void)
{
//Most of the functions and Variables below are Built-in
ones of CCS C Compiler
enable_interrupts( GLOBAL );
////////////////////////CCP1 and Timer1 Modules
initialization
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); //Built-in
function&variables
disable_interrupts( INT_TIMER1 ); //Built-in
set_timer0(0x0000);
setup_ccp1( CCP_COMPARE_RESET_TIMER ); //built-in
CCP_1 = MaxTimer1Value; //"MaxTimer1Value" defined in
"SpecsAndDefs.h"
enable_interrupts( INT_CCP1 );
t = 0;
////////////////////////CCP2 and Timer2 Modules
initialization
setup_timer_2 ( Timer2Prescale, Timer2Period,
2);//Variables defined in
//"SpecsAndDefs.h",Built-in
function
disable_interrupts( INT_TIMER2 ); //built-in variables
setup_ccp2( CCP_PWM ); //built-in
86
set_pwm2_duty(DefaultDuty); //DefaultDuty defined
in SpecsAndDefs.h
set_timer2(0x00); //Reset Timer2
/////////////////////////Setup ADC
SETUP_ADC_PORTS( ALL_ANALOG );
SETUP_ADC( AdcClock ); //"AdcClock" is defined
in "SpecsAndDefs.h"
ADFM = 1; //Right justify A/D
result,bit7 of ADCON1 Reg
//dirIpvSwitch = 0; //Make the pin output
port_b_pullups(TRUE);
/////////////////////////Setup SunTrack
dirMotor1a = 0;
dirMotor1b = 0;
dirMotor2a = 0;
dirMotor2b = 0;
dirAzBreak = 1;
dirAltBreak1 = 1;
dirAltBreak2 = 1;
////////////////////////Setup LCD
LCDdataDir = 0x00;
dirRS = 0;
//dirRW = 0;
dirE = 0;
lcdcmd(0x38);
lcdcmd(0x0C);
lcdcmd(0x01);
lcdcmd(0x06);
///////////////////////Generic
dirTestLed = 0;
}
// General Idea of the main function below is that it will
call every function
// sequentially and each function, when it is called, will
determine what it
// has to do? Even to do something or not depending on time
elapsed between
// present and previous call. For example, LCD() function will
only do something
87
// when considerable time has been elapsed after previous
update of LCD.
void main(void)
{
initialize();
while(1)
{
// All the functions below are inline functions with
// all parameters as reference parameters (without
pointer)
// Both these are features of C++ but supported by CCS C
compiler
// Howerver syntax of inline function definition is
different from
// standard C++
// Prototypes of all the functions below are defined in
"SpecsAndDefs.h"
//SunTrack();
CalculateVpvIpv();
MPPT();
//CalculateVbatIbat();
LCD();
//RS232();
//TriggerTestLed();
}
}
#int_ccp1
void IncrementMilliSeconds(void)
{
// This is ISR for timer1 overflow, which occurs after 1ms
t++;
if(t > 0x7FFFFFFD)
t = 0;
}
88
D.5 MPPT.c
//------ PROTOTYPES ---------
void CalculateVpvIpv();
void PerturbAndObsVI();
void CalculateIncrement();
void CalculateDuty();
//----- Variables related to this file --------
unsigned int16 Vperturb,Iperturb;
unsigned int32 Pperturb;
unsigned int16 Increment = 5;
unsigned int16 Duty = DefaultDuty; // will be adjusted
automatically
void MPPT()
{
static int32 MPPTtime = 0;
// Ensure enough time has been elapsed after last call to
MPPT function
if(t >= MPPTtime) //t will be less when it will overflow to
0
{
if((t - MPPTtime) < 500)
return;
}
// store Current time for future use
MPPTtime = t; //t is global time
// Calculate Vpv, Ipv. Take care that both are sampled at
same time
CalculateVpvIpv();
// Ppv = Vpv*Ipv
Ppv = _mul(Vpv, Ipv);
// Perturb by turning sw OFF and calculate Vperturb,
Iperturb and Pperturb
PerturbAndObsVI();
// Restore old duty till new duty is calculated
set_pwm2_duty((int16)Duty);
Pperturb = _mul(Vperturb, Iperturb);
89
// calculate increment
//CalculateIncrement();
// calculate new duty
CalculateDuty();
// set new duty
set_pwm2_duty((int16)Duty);
}
/*
void SetDuty8(int8 Duty)
{
CCP2CON &= 0xCF; // Make two LSBits of duty zero
CCPR2L = Duty; // Higher 8bits equal to Duty
}
void SetDuty()
{
int8 a;
a = Make8(Duty,0);
a >>= 2;
a |= (Make8(Duty,1)<<6);
CCPR2L = a;
CCP2CON &= 0xCF;
CCP2CON |= (Make8(Duty,0) << 4) & 0x30;
}
*/
void PerturbAndObsVI()
{
int32 t1;
int1 TimeOut = 0;
// PWM switch OFF
set_pwm2_duty((int16)0x0000);
// select voltage channel as A/D input
set_adc_channel(channelVpv);
t1 = t; //t is global time
// do-while(Vpv >= Vperturb);
do
{
// turn on current sampling switch
90
//pinIpvSwitch = IpvSwitchON;
// wait for sampling time
delay_us(200);
// start A/D conversion
ADGO = 1;
// turn off current sampling switch
//pinIpvSwitch = IpvSwitchOFF;
// check if time elapsed since entry to this function is
within limits
if((t >= t1) && ((t-t1) > 100))
{
TimeOut = 1;
break;
}
// wait for conversion to complete
while(ADGO == 1);
// assign conversion result to Vperturb
Vperturb = Make16(ADRESH,ADRESL);
}while(Vpv >= Vperturb);
//if timeout occured, try by decreasing voltage
if(TimeOut == 1) //Try to decrease Voltage
{
t1 = t;
set_pwm2_duty((int16)0x3FF);
do
{
// turn on current sampling switch
//pinIpvSwitch = IpvSwitchON;
// wait for sampling time
delay_us(200);
// start A/D conversion
ADGO = 1;
// turn off current sampling switch
//pinIpvSwitch = IpvSwitchOFF;
// check if time elapsed since entry to this function
is within limits
if((t >= t1) && ((t-t1) > 100))
{
TimeOut = 1;
set_pwm2_duty(DefaultDuty);
break;
91
}
// wait for conversion to complete
while(ADGO == 1);
// assign conversion result to Vperturb
Vperturb = Make16(ADRESH,ADRESL);
}while(Vperturb >= Vpv );
}
if(TimeOut == 1) //still timeout
{
//Vperturb = Vpv, so that dVpv = 0 later
Vperturb = Vpv;
Iperturb = Ipv;
}
//else
else
{
// select 'panel current' channel as A/D input
set_adc_channel(channelIpv);
// wait for aquisation time
delay_us(20);
// start A/D conversion
ADGO = 1;
// wait for conversion to complete
while(ADGO == 1);
// assign conversion result to Iperturb
Iperturb = Make16(ADRESH,ADRESL);
if(Ipv > IpvSensorOffset)
Ipv -= IpvSensorOffset; //CurrentSensorOffset is
defined in SpecsAndDefs.h
else
Ipv = 0;
// select voltage channel as A/D input
// turn on current sampling switch
//pinIpvSwitch = IpvSwitchON;
}
}
void CalculateIncrement()
{
// This algorithm will work correctly if 6 MSBits of 20bit
dPpv are zero
int32 dPpv;
92
int16 dV;
if(Ppv > Pperturb)
dPpv = Ppv - Pperturb;
else
dPpv = Pperturb - Ppv;
if(Vpv > Vperturb)
dV = Vpv - Vperturb;
else
dV = Vperturb - Vpv;
if(dV == 0) // avoid divide by
zero
{
Increment = 0; // to avoid
change in duty
}
else if(dV == 1) // don't waste time in
division
{
Increment = dP >> 4;
}
else if(dV == 2) // Most of the
times, dV is 1 or 2
{
Increment = dP >> 5;
}
else
{
Increment = dP / ((int32)dV << 4);
}
/** Below are optional lines to adjust Increment**/
Increment >>= 2;
if(dP != 0 && Increment == 0)
Increment = 1;
}
void CalculateDuty()
{
if(Vperturb > Vpv)
93
{
if(Pperturb > Ppv) // +ve
derivative
{
if(Increment > Duty)
Duty = 0; // Min Possible
duty
else
Duty -= Increment; // reduce
duty
}
else
{
#define Period ((int16)(Timer2Period) << 2) +
(int16)0x0003
if((Duty + Increment) > Period) //
preprocessor will calculate Period
// to avoid
calculation in controller
{
Duty = Period; // Max. Possible
duty
}
else
{
Duty += Increment; // increase
duty
}
#undef Period
}
}
else if(Vperturb < Vpv)
{
if(Pperturb < Ppv) // +ve
derivative
{
if(Increment > Duty)
Duty = 0; // Min Possible
duty
else
Duty -= Increment; // reduce
duty
}
94
else
{
#define Period ((int16)(Timer2Period) << 2) +
(int16)0x0003
if((Duty + Increment) > Period) //
preprocessor will calculate Period
// to avoid
calculation in controller
{
Duty = Period; // Max. Possible
duty
}
else
{
Duty += Increment; // increase
duty
}
#undef Period
}
}
}
95
D.6 SunTrack.c
#define MinVal4High (unsigned
int16)((float)((float)2.6/5)*1024)
#define MaxVal4Low (unsigned
int16)((float)((float)2.4/5)*1024)
#define ON 1
#define OFF 0
#define TimeOutInterval 1500 // Max allowed time for this
function in milliseconds
void SunTrack(void)
{
static int1 dir = 0;
static int1 ReverseTheDir = 0;
static int1 BalancedAfterBreak = 0;
//static int1 AzBreakState = 0;
//static int1 PrevAzBreakState = 0;
static int1 Balanced180DegOut = 0;
int16 a;
static int32 SunTrackTime = 0;
if((t >= SunTrackTime) && (t-SUNTRACKtime < 100))
return;
SunTrackTime = t;
// Track Sun Azimuth first
while(1)
{
if( (t >= SunTrackTime) && (t - SunTrackTime) >
TimeOutInterval )
{
break;
}
if(pinAzBreak == 1)
{
ReverseTheDir = 1;
BalancedAfterBreak = 0;
}
// Take reading of Azimuth sensor
96
set_adc_channel(channelSensorAz);
delay_us(20);
ADGO = 1;
while(ADGO == 1);
a = Make16(ADRESH,ADRESL);
if( MaxVal4Low < a && a < MinVal4High)
{
BalancedAfterBreak = 1;
if(ReverseTheDir == 0 && Balanced180DegOut == 0)
{
break; //Azimuth Correctly tracked now
}
}
else if( a <= MaxVal4Low)
{
Balanced180DegOut = 0; // Now panel is unbalanced and
will go to right dir
if(BalancedAfterBreak)
// Az has been balanced once after break, which was
surely wrong balance
// Now After unbalancing again, Panel will tend to
right direction
{
ReverseTheDir = 0;
}
if(ReverseTheDir == 0)
{
dir = 1;
}
else
{
dir = 0;
}
}
else //a >= MinVal4High
{
Balanced180DegOut = 0; // Now panel is unbalanced and
will go to right dir
if(BalancedAfterBreak)
// Az has been balanced once after break, which was
surely wrong balance
97
// Now After unbalancing again, Panel will tend to
right direction
{
ReverseTheDir = 0;
}
if(ReverseTheDir == 0)
{
dir = 0;
}
else
{
dir = 1;
}
}
if(dir == 0)
{
pinMotor1a = ON;
pinMotor1b = OFF;
}
else
{
pinMotor1a = OFF;
pinMotor1b = ON;
}
}
// Azimuth tracking sensors balanced or timeout occured.
Turn Off the motor now
pinMotor1a = OFF;
pinMotor1b = OFF;
// Now Track Sun Altitude
while(1)
{
if( (t >= SunTrackTime) && (t - SunTrackTime) >
TimeOutInterval )
{
break;
}
set_adc_channel(channelSensorAlt);
delay_us(20);
98
ADGO = 1;
while(ADGO == 1);
a = Make16(ADRESH,ADRESL);
if(a > MaxVal4Low && a < MinVal4High) // Alt sensor
balanced
{
break;
}
else if(a >= 512)
{
if(pinAltBreak1)
{
Balanced180DegOut = 1;
break;
}
pinMotor2a = ON;
pinMotor2b = OFF;
}
else
{
if(pinAltBreak2) //Maximum possible downward
tracking done
break;
pinMotor2a = OFF;
pinMotor2b = ON;
}
}
pinMotor2a = OFF;
pinMotor2b = OFF;
}
#undef MinVal4High
#undef MaxVal4Low
#undef ON
#undef OFF
#undef TimeOutInterval
99
D.7 LCD.c
void lcdcmd(unsigned char value){
LCDdataPort = value; //put the value on the pins
pinRS = 0;
pinE = 1; //strobe the enable pin
delay_us(60);
pinE = 0;
return;
}
void lcddata(unsigned char value){
LCDdataPort = value; //put the value on the pins
pinRS = 1;
pinE = 1; //strobe the enable pin
delay_us(60);
pinE = 0;
return;
}
void UpdateMsg1(unsigned char Msg[])
{
//ActualVpv = Vpv*25/1024
unsigned char i;
int32 temp;
temp = _mul(Vpv, VpvThatMaps5V);
temp >>= 10;
for(i = 13; i >= 11; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
for(i = 9; i >= 8; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
}
void UpdateMsg2(unsigned char Msg[])
{
//ActualIpv = Ipv*(Current which maps to 5V)/(1024-
CurrentSensorOffset)
unsigned char i;
int32 temp;
100
#define Multiplier
(int16)((float)10*IpvThatMaps5V*(float)1024/(float)(1024 -
IpvSensorOffset))
// IpvSensorOffset and IpvThatMaps5V are defined in
SpecAndDefs.h
// 1024 is multiplied in above #define to make quantity
large. It will be >> by 10 later
// 10 is multiplied to display current upto 1 decimal point
in mA
temp = _mul(Ipv, Multiplier);
#undef Multiplier
temp >>= 10;
Msg[12] = temp % 10 + 0x30;
temp /= 10;
for(i = 10; i >= 8; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
}
void UpdateMsg3(unsigned char Msg[])
{
// To calculate Power, find ActualIpv and Actual Ipv
separately and then mult
unsigned char i;
int32 temp, ActualIpv;
// First calculate Actual Current and store it in temp
#define Multiplier
(int16)((float)10*IpvThatMaps5V*(float)1024/(float)(1024 -
IpvSensorOffset))
// IpvThatMaps5V and IpvSensorOffset are defined in
SpecAndDefs.h
// 1024 is multiplied in above #define to make quantity
large. It will be >> by 10 later
// 10 is multiplied to display current upto 1 decimal point
in mA
ActualIpv = _mul(Ipv, Multiplier);
#undef Multiplier
ActualIpv >>= 10;
// Now Calculate ActualVpv
101
temp = _mul(Vpv, VpvThatMaps5V);
temp >>= 10;
// Now temp contains Actual Vpv, Multiply it with ActualIpv
temp *= ActualIpv;
// ActualIpv contained (current in mA)* 10 and ActualVpv is
100 times
temp /= 10000;
for(i = 13; i >= 11; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
for(i = 9; i >= 8; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
}
void UpdateMsg4(unsigned char Msg[])
{
}
void UpdateMsg5(unsigned char Msg[])
{
}
void UpdateMsg6(unsigned char Msg[])
{
int16 temp = Timer2Period << 2;
int8 i;
for(i = 13; i >= 9; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
}
temp = Duty;
for(i = 5; i >= 1; i--)
{
Msg[i] = temp % 10 + 0x30;
temp /= 10;
102
}
}
void LCD(){
static unsigned char Msg1[] =
{'V','p','a','n','e','l','=',' ','0','0','.','0','0','0','
','V'};
static unsigned char Msg2[] =
{'I','p','a','n','e','l','=',' ','0','0','0','.','0','
','m','A'};
static unsigned char Msg3[] =
{'P','p','a','n','e','l','=',' ','0','0','.','0','0','0','
','W'};
static unsigned char Msg4[] = {'V','b','a','t','=','
','0','0','.','0','0','0',' ','V',' ',' '};
unsigned char TotalMsgs = 4;
static unsigned char i,Iteration = 0;
static int32 LCDtime = -1000;
if(t >= LCDtime && (t - LCDtime) < 1500)
return;
LCDtime = t;
switch (Iteration)
{
case(0):
UpdateMsg1(Msg1);
lcdcmd(0x80); //line 1, position 0
for(i = 0; i < 16; i++)
{
lcddata(Msg1[i]);
if ( i==7)
lcdcmd(0xC8);
}
break;
case(1):
UpdateMsg2(Msg2);
lcdcmd(0x80); //line 1, position 0
for(i = 0; i < 16; i++)
{
lcddata(Msg2[i]);
if ( i==7)
lcdcmd(0xC8);
}
break;
case(2):
103
UpdateMsg3(Msg3);
lcdcmd(0x80); //line 1, position 0
for(i = 0; i < 16; i++)
{
lcddata(Msg3[i]);
if ( i==7)
lcdcmd(0xC8);
}
break;
case(3):
UpdateMsg4(Msg4);
lcdcmd(0x80); //line 1, position 0
for(i = 0; i < 16; i++)
{
lcddata(Msg4[i]);
if ( i==7)
lcdcmd(0xC8);
}
break;
default:
break;
}
Iteration ++;
if(Iteration >= (TotalMsgs))
Iteration = 0;
}
104
D.8 Misc.c
void CalculateVpvIpv()
{
// select Voltage channel as adc input channel
set_adc_channel(channelVpv);
// turn on Current sampling switch
//pinIpvSwitch = IpvSwitchON;
// wait for sampling time
delay_us(200);
// start A/D conversion (Voltage will be A/D converted)
ADGO = 1;
// turn off Current sampling switch
//pinIpvSwitch = IpvSwitchOFF;
// wait for conversion to complete
while(ADGO == 1);
// select current channel as A/D input channel
set_adc_channel(channelIpv);
// assign previous A/D result to Vpv
Vpv = Make16(ADRESH,ADRESL);
// wait for sampling time
delay_us(20);
// start A/D conversion
ADGO = 1;
// wait for conversion to complete
while(ADGO == 1);
// Assign new A/D result to Ipv
Ipv = Make16(ADRESH,ADRESL);
// turn on current sampling switch
//pinIpvSwitch = IpvSwitchON;
if(Ipv > IpvSensorOffset)
Ipv -= IpvSensorOffset; //CurrentSensorOffset is defined
in SpecsAndDefs.h
else
Ipv = 0;
// select voltage channel as A/D input
set_adc_channel(channelVpv);
}
void CalculateVbatIbat(void)
{
set_adc_channel(channelBatteryVoltage);
105
delay_us(20);
ADGO = 1;
while(ADGO == 1);
Vbat = Make16(ADRESH,ADRESL);
set_adc_channel(channelBatteryCurrent);
delay_us(20);
ADGO = 1;
while(ADGO == 1);
Ibat = Make16(ADRESH,ADRESL);
}
void RS232(void)
{
static int32 RS232time = 0;
if((t>=RS232time) && (t-RS232time < 1000))
return;
RS232time = t;
printf("%c%c",Make8(Vpv,1),Make8(Vpv,0));
printf("%c%c",Make8(Ipv,1),Make8(Ipv,0));
printf("\r\n");
}
void TriggerTestLed(void)
{
static int32 testTime = 0;
if((t >= testTime) && (t - testTime) < 1000)
return;
testTime = t;
pinTestLed = ~pinTestLed;
}
106
References
[1] Mazidi M.A., McKinlay R.D. and Causey D., PIC Microcontroller and Embedded, Using
Assembly and C for PIC18, 1
st
ed., Prentice-Hall, 2006
[2] Sedra A.S. and Smith K.C., Microelectronic Circuits, 5
th
ed., 2008
[3] M.H. Rashid, Power Electronics: Circuits, Devices and Applications, 3
rd
Edition, 2004.
Pearson Education, Inc
[4] Dorin O. Neacsu, Power Switching Converters, 2006 by Taylor & Francis Group, LLC
[5] Simone Buso and Paolo Mattavelli,Digital Control in Power Electronics, 2006 by
Morgan & Claypool
[6]Bimal .K. Bose, Modern Power Electronics and AC Drives, 2002, Pearson Education
[7] N. Mohan T. M. Undeland and W. P. Robbins, Power Electronics: Converters,
Applications, and Design, 3rd Edition
[8] Muhammad H. Rashid, Power Electronics Handbook: Devices, Circuits and
Applications, 2nd Edition, Academic Press, New York, 2006.
[9] http://www.howstuffworks.com/solar_panel
[10] http://en.wikipedia.org/wiki/Buck_converter
[11] http://en.wikipedia.org/wiki/battery(electrical)
[12] Proteus VSM official website,
http://www.labcenter.co.uk
[13] CCS Compiler official website,
http://www.ccsinfo.com/
[14] Microchip official website,
http://www.microchip.com/