// Electric vehicle double closed-loop program, using double closed-loop mode to control the motor for optimal speed performance and can limit the maximum current of the motor. This application uses two CCP components: CCP1 is used for PWM output to control motor voltage; CCP2 is used to trigger AD, timer TMR2, TMR1, INT interrupt, RB port level change interrupt, watchdog, and 6 general-purpose I/O ports.
#define AND 0xe0 // Status acquisition bits 5, 6, 7
#define CURA 0x0a // Sum of current loop ratio and integral coefficient
#define CURB 0x09 // Current loop proportional coefficient
#define THL 0x6400 // Current loop maximum output
#define FULLDUTY 0x0FF // High time when duty cycle is 1
#define SPEA 0x1d // Sum of speed loop ratio and integral coefficient
#define SPEB 0x1c // Speed loop proportional coefficient
#define GCURHILO 0x0330 // Maximum output of the speed loop
#define GCURH 0x33 // Maximum given current
#define GSPEH 0x67 // Maximum speed reference
#define TSON 0x38 // Handle opening voltage is 1.1V, TSON*2 is the handle opening voltage after braking (2.2V)
#define VOLON 0x4c // Low voltage protection reactivation voltage (3.0V or 33V)
#define VOLOFF 0x49 // Low voltage protection shutdown voltage (2.86V or 31.5V)
volatile unsigned char DELAYH, DELAYL, oldstate, speed,
speedcount, tsh, count_ts, count_vol, gcur, currenth,
voltage; // Register definition
static bit sp1, spe, ts, volflag, spepid, lowpower,
off, shutdown, curpid; // Flag definition
static volatile unsigned char new[10] = {0xaf, 0xbe, 0xff, 0x7e, 0xcf,
0xff, 0xd7, 0x77, 0xff, 0xff}; // Status register table
//------------ PIC16F877 initialization subroutine ------------
void INIT877()
{
PORTC = 0X0FF; // Turn off all MOSFETs
TRISC = 0X02; // Set C port as output
PIE1 = 0X00; // Initialize interrupt registers, disable all interrupts
TRISA = 0XCF; // Set RA4, RA5 as output
TRISB = 0XEF; // RB port high three bits as input, collect motor three-phase Hall signal
PORTC = new[(PORTB & AND) >> 5]; // Collect first Hall signal, output corresponding signal, turn on two MOSFETs
T2CON = 0X01; // TMR2 prescaler set to 4
CCPR1L = 0X0FF; // Initial PWM output full duty
CCP1CON = 0X0FF; // CCP1 set to PWM mode
CCP2CON = 0X0B; // CCP2 set to special mode to trigger AD
ADCON0 = 0X81; // AD clock divided by 32, enable AD, select AN0 channel for handle voltage
TMR2 = 0X00; // Initialize TMR2 register
TMR1H = 0X00; // Initialize TMR1 register
TMR1L = 0X00;
T1CON = 0X00; // TMR1 prescaler set to 1
CCPR2H = 0X08;
CCPR2L = 0X00; // Current sampling period set to TAD = 512μs
PR2 = 0XC7; // PWM frequency set to 5kHz
ADCON1 = 0X02; // AD results left-aligned
OPTION = 0XFB; // INT rising edge trigger
TMR2ON = 1; // Start PWM
INTCON = 0XD8; // Enable global and peripheral interrupts, RBIE
ADIE = 1; // Enable AD interrupt
speedcount = 0x00; // Speed count register
speed = 0x7f; // Speed holding register
spe = 1; // Low speed flag
sp1 = 1; // Low speed flag
oldstate = 0x0ff; // Initial state settings, different from other states
count_ts = 0x08; // Current sampling 8 times, collect 1 handle
count_vol = 0x00; // Sample 256 handles, collect 1 battery voltage
ts = 1; // Flag to collect handle value
ADGO = 1; // Enable AD sampling
TMR1ON = 1; // Start CCP2 parts
}
//------------ Delay subroutine ---------------
#pragma interrupt_level 1
void DELAY1(char x)
{
DELAYH = x; // Delay parameter setting
#asm
DELAY2 MOVLW 0X06
MOVWF_DELAYL
DELAY1 DECFSZ_DELAYL
GOTO DELAY1
DECFSZ_DELAYH
GOTO DELAY2
#endasm
}
//----------- Status collection subroutine ----------------------
void sample()
{
char state1, state2, state3, x;
do {
x = 1;
state1 = (PORTB & AND); // Hall signal acquisition
DELAY1(x);
state2 = (PORTB & AND);
} while (state1 - state2); // Continue collecting if three samples are different
if (state1 != oldstate) // If the result is different from last time
{
oldstate = state1; // Set this state as the old state
state1 = (oldstate >> 5);
PORTC = new[state1]; // Output corresponding signal to trigger two MOSFETs
if (sp1 == 1) {
spe = 1;
sp1 = 0;
}
else {
spe = 0;
sp1 = 0;
speedcount <<= 1;
state3 = (TMR1H >> 2); // Count speed
speed = speedcount + state3; // Add 1 every 256μs
}
speedcount = 0;
}
}
//-----------------AD sampling subroutine --------------------
void AD()
{
char x;
ADIF = 0; // Clear AD interrupt flag
if (ts == 1) { // If handle is sampled, sample handle value
CHS0 = 1; // Select current sampling channel
count_vol = count_vol + 1; // Battery sample count register
spepid = 1; // Set speed closed-loop operation flag
ts = 0;
tsh = ADRESH; // Save handle value
if (count_vol == 0) { // If battery sampling is done, select AN2 and collect battery voltage
CHS0 = 0;
CHS1 = 1;
volflag = 1;
x = 1;
DELAY1(x);
ADGO = 1;
}
}
else if (volflag == 1) { // Process battery sampling
CHS1 = 0;
CHS0 = 1;
volflag = 0;
voltage = ADRESH;
lowpower = 1;
}
else { // Other, it's a current sampling interrupt
speedcount = speedcount + 1; // Increment speedcount for speed measurement
if (speedcount > 0x3d) sp1 = 1; // If speed is lower than 1000000μs/(512μs*3eh*3), consider it low speed
currenth = ADRESH;
curpid = 1;
count_ts = count_ts - 1;
if (count_ts == 0) { // If handle time is up, switch to handle sampling channel
CHS0 = 0;
count_ts = 0x08;
ts = 1;
x = 1;
DELAY1(x);
ADGO = 1;
}
}
}
//-------------Brake processing subroutine ------------------
void BREAKON()
{
char x;
off = 0; // Clear off flag, if interference, don't reset
shutdown = 0;
if (RB0 == 1) { // If brake signal is true, stop output voltage
ADIE = 0; // Disable AD interrupt
INTE = 0; // Disable brake interrupt
CCPR1L = FULLDUTY; // Output voltage 0
TMR1ON = 0; // Disable CCP2, no longer trigger AD
for (; ADGO == 1;) continue; // Wait for sampling to finish
ADIF = 0; // Clear ADIF bit
CHS0 = 0; // Select channel 0 for handle sampling
CHS1 = 0;
x = 1;
DELAY1(x);
do {
ADGO = 1;
for (; ADIF == 0;) continue;
ADIF = 0;
CCPR1L = FULLDUTY;
asm("CLRWDT");
tsh = (ADRESH >> 1);
} while (tsh > TSON || RB0 == 1); // Execute while handle value > 2.2V or brake continues
off = 1; // Reset flag
}
}
//---------Underprotected subroutine -------------------
void POWER()
{
char x;
lowpower = 0;
voltage >>= 1; // Convert voltage to 7 bits for single-byte operation
if (voltage < voloff) {
ADIE = 0;
INTE = 0;
TMR1ON = 0;
CCPR1L = FULLDUTY;
for (; ADGO == 1;) continue;
ADIF = 0;
CHS0 = 0;
CHS1 = 1;
x = 1;
DELAY1(x);
do {
ADGO = 1;
for (; ADIF == 0;) continue;
ADIF = 0;
voltage = (ADRESH >> 1);
CCPR1L = FULLDUTY;
asm("CLRWDT");
} while (voltage < volon);
off = 1; // Reset flag
}
}
//------------ Current loop operation subroutine -----------------
void CURPI()
{
static int curep = 0x00, curek = 0x00, curuk = 0x00;
union data {
int pwm;
char a[2];
} b; // Define current loop arithmetic register
curpid = 0; // Clear current operation flag
curep = curek * CURB; // Calculate product of last deviation and scale factor
if (currenth < 2) currenth = 2; // If current is zero, consider small current to help speed drop
currenth >>= 1;
curek = gcur - currenth; // Calculate current deviation
curuk = curuk + curek * CURA - curep; // PI operation for current loop
if (curuk < 0x00) { // If output is less than zero, treat as zero
curuk = 0;
CCPR1L = FULLDUTY;
CCP1X = 0;
CCP1Y = 0;
}
else if (curuk - THL >= 0) { // If output exceeds limit, output max voltage
curuk = THL;
CCPR1L = 0;
CCP1X = 0;
CCP1Y = 0;
}
else { // Otherwise, output proportionally
b.pwm = THL - curuk;
b.pwm <<= 1;
CCPR1L = b.a[1]; // High nibble of PWM register
if (b.pwm & 0x80) CCP1X = 1;
else CCP1X = 0;
if (b.pwm & 0x40) CCP1Y = 1;
else CCP1Y = 0;
}
}
//---------------Speed loop operation subroutine -----------------------
void SPEPI()
{
static int speep = 0x00, speek = 0x00, speuk = 0x00;
int tsh1, speed1; // Define speed register
spepid = 0; // Clear speed calculation flag
if (spe == 1)
speed1 = 0x00; // If speed is too low, consider it zero
else
speed1 = 0x7f - speed; // Calculate actual speed
if (speed1 < 0) speed1 = 0;
speep = speek * SPEB;
tsh1 = tsh - 0x38; // Get handle value for calculation
speek = tsh1 - speed1;
if (tsh1 < 0) {
speuk = 0;
gcur = 0;
}
else {
if (tsh1 >= GSPEH) // Limit maximum speed
tsh1 = GSPEH;
speuk = speuk + speek * SPEA - speep; // Calculate speed loop output
if (speuk <= 0X00) {
speuk = 0x00;
gcur = 0x00; // Process speed loop output
}
else if (speuk > GCURHILO) { // Limit speed loop output, i.e., limit maximum current around 12A
speuk = GCURHILO;
gcur = GCURH;
}
else {
gcur = (speuk >> 4) & 0x0ff; // Output in speed state
}
}
}
//----------- main program -------------------------
void main()
{
for (;;) {
INIT877(); // After MCU reset, initialize first
off = 0; // Clear reset flag
for (; off == 0;) { // If reset flag is zero, execute the following program, otherwise reset
if (curpid == 1) CURPI(); // Current PI operation
else if (spepid == 1) SPEPI(); // Speed PI operation
else if (lowpower == 1) POWER();
else if (shutdown == 1) BREAKON();
asm("CLRWDT");
}
}
}
//---------Interrupt service subroutine ---------------------
#pragma interrupt_level 1
void interrupt INTS(void)
{
if (RBIF == 1) {
RBIF = 0;
sample();
}
else if (ADIF == 1) AD();
else if (INTF == 1) {
shutdown = 1;
INTF = 0; // Brake interrupt, set brake flag
}
}Traffic Signal Pole
we offer a wide selection of traffic Steel Pole structures in standard and custom designs.
Yixing Futao Metal Structural Unit Co. Ltd. is com manded of Jiangsu Futao Group.
It is located in the beach of scenic and rich Taihu Yixing with good transport service.
The company is well equipped with advanced manufacturing facilities.
We own a large-sized numerical control hydraulic pressure folding machine with once folding length 16,000mm and the thickness 2-25mm.
We also equipped with a series of numerical control conveyor systems of flattening, cutting, folding and auto-welding, we could manufacture all kinds of steel poles and steel towers.
Our main products: high & medium mast lighting, road lighting, power poles, sight lamps, courtyard lamps, lawn lamps, traffic signal poles, monitor poles, microwave communication poles, etc. Our manufacturing process has been ISO9001 certified and we were honored with the title of the AAA grade certificate of goodwill"
Presently 95% of our products are far exported to Europe, America, Middle East, and Southeast Asia, and have enjoyed great reputation from our customers,
So we know the demand of different countries and different customers.
We are greatly honored to invite you to visit our factory and cheerfully look forward to cooperating with you.
Traffic Signal Pole,Traffic Light Pole,Led Traffic Signals,Solar Traffic Signal Pole,Traffic Steel Pole
JIANGSU XINJINLEI STEEL INDUSTRY CO.,LTD , https://www.chinasteelpole.com