Im using the PIC 18 microcontroller to control the speed of a DC Motor using PWM. I have managed to get it to spin using the code below. And I have tested that my H-Bridge is 100% functional.
However, when I switch on my circuit, 12V to the Motor and 5V to the logic, And I send a command to the circuit using my RS232 communication module, (which I have tested and it recieves and transmits correctly), the program resets and the current on the bench power supply falls to 0A. Sometimes the motor jerks slighty, almost as if its trying to spin, but then stops.
Any ideas where I could be going wrong?
/*
* File: serial.c
* Author: Chris Lombaard
*
* Created on September 13, 2013, 2:39 PM
*/
#pragma config FOSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = OFF // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (WDT is always enabled. SWDTEN bit has no effect)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2 // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
#include <P18F45K22.h>
#include <xc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#define length(x) (sizeof(x) / sizeof(x[0])) //Length of array
void writeUART(const unsigned char string[]);
void setup(void);
void inputCheck(void);
void stepF(void);
void stepB(void);
unsigned char buffer[8] = {'\0'};
unsigned char prevPos = 0;
unsigned char currPos = 0;
unsigned char bufferLength;
unsigned char direction = 0;
unsigned char speed = 0;
unsigned char isSetup = 0;
char main(void){
if(isSetup == 0){
setup();
writeUART("ERD 320 Practical 2 ----- Group 1\n");
writeUART("JC Lombaard - 11028786\n");
writeUART("VFDC Henriques - 11100232\n");
writeUART("William Reeler - 11228866\n");
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
PORTAbits.RA6 = 0;
}
while(1){
if(PORTEbits.RE1 == 1)
stepB();
if(PORTEbits.RE0 == 1){
writeUART("\nFan calibrated!\n");
break;
}
}
bufferLength = 0;
while (1);
return (EXIT_SUCCESS);
}
void interrupt high_priority isr_high(void) {
if(PIR1bits.RC1IF == 1){
if(RCREG1 == '\n'){
buffer[bufferLength++] = '\0';
bufferLength = 0;
inputCheck();
}else{
buffer[bufferLength++] = RCREG1;
PIR1bits.RC1IF = 0;
}
}
}
void interrupt low_priority isr_low(void){
PIR1bits.TMR2IF = 0;
TMR2 = 0;
}
void inputCheck(void) {
const unsigned char commands[11][3] = {"S0", "S1", "S2", "S3", "S4", "P1", "P2", "P3", "P4", "R", "F"};
unsigned char choice = 0;
for(; choice < 11; choice++)
if (strcmp(buffer, commands[choice]) == 0){
break;
}
switch(choice){
case 0:
writeUART("FAN SPEED: 0% DC");
PORTA = 0b00111111;
speed = 0;
if(direction == 0){
CCPR1L = 0x00;
}else{
CCPR2L = 0x00;
}
break;
case 1:
writeUART("FAN SPEED: 10% DC");
PORTA = 0b00000110;
speed = 0b01101110 ;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b01101110 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b01101110 ;
}
break;
case 2:
writeUART("FAN SPEED: 30% DC");
PORTA = 0b01011011;
speed = 0b10001100;
if(direction == 0){
CCPR1L = 0b11010000;
__delay_ms(100);
CCPR1L = 0b10001100;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10001100 ;
}
break;
case 3:
writeUART("FAN SPEED: 60% DC");
PORTA = 0b01001111;
speed = 0b10101101;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b10101101 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10101101 ;
}
break;
case 4:
writeUART("FAN SPEED: 90% DC");
PORTA = 0b01100110;
speed = 0b11010000 ;
if(direction == 0){
CCPR1L = 0b11010000;
}else{
CCPR2L = 0b11010000;
}
break;
case 5:
currPos = 1;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
}
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 6:
prevPos = currPos;
currPos = 2;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 2");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 1;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 7:
prevPos = currPos;
currPos = 3;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 3");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 1;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 8:
prevPos = currPos;
currPos = 4;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 4");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 1;
prevPos = currPos;
break;
case 9:
direction = 1;
CCP1CON = 0b00000000;
CCP2CON = 0b00111100;
CCPR2L = speed;
writeUART("FAN DIRECTION: REVERSED");
break;
case 10:
direction = 0;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
CCPR1L = speed;
writeUART("FAN DIRECTION: FORWARD");
break;
default:
break;
}
}
void stepF(void){
for(int i = 0; i < 1; i++){
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
}
}
void stepB(void){
for(int i = 0; i < 1; i++){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
}
void defaultPos(void){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
void writeUART(const unsigned char string[]){
for(unsigned char j = 0; j < strlen(string); j++){
TXREG1 = string[j];
__delay_us(1000);
}
}
void setup(void){
isSetup = 1;
//PORTC
PORTC = 0x00;
LATC = 0x00;
TRISC = 0xC0; //Set RC6 & RC7 as inputs for EUSART
TRISCbits.RC6 = 0;
TRISCbits.RC7 = 1;
ANSELC = 0x00;
//PORTD
PORTD = 0x00;
LATD = 0x00;
TRISD = 0x00;
ANSELD = 0x00;
//PORTE
PORTE = 0x00;
LATE = 0x00;
TRISEbits.RE0 = 1;
TRISEbits.RE1 = 1;
ANSELE = 0x00;
//PORTB
PORTB = 0x00;
LATB = 0x00;
TRISB = 0x00;
ANSELB = 0x00;
PORTA = 0x00;
LATA = 0x00;
TRISA = 0x00;
ANSELA = 0x00;
//Oscillator
OSCCON = 0b01011100; //4 MHz oscillator
//EUSART
TXSTA1bits.BRGH = 1; //Highspeed baudrate
BAUDCON1bits.BRG16 = 0;
SPBRG1 = 12; //Baudrate of 19230 (FOSC = 4 MHz, BRGH = 1, BRG16 = 0)
TXSTA1bits.SYNC = 0; //Asynchronous
RCSTA1bits.SPEN = 1; //Enable rx & tx pins as serial pins
RCSTA1bits.CREN = 1; //Enable continuous reception, enable receiver
TXSTA1bits.TXEN = 1; //Enable transmitter
TXREG1 = 0x00;
RCREG1 = 0x00;
//Interrupts
RCONbits.IPEN = 1; //Enable priorities
INTCONbits.GIE_GIEH = 1; //Enable high priority interrupts
INTCONbits.PEIE_GIEL = 1; //Enable low priority interrupts
PIE1bits.TMR2IE = 1;
IPR1bits.TMR2IP = 0;
PIE1bits.RC1IE = 1; //Enable RX interrupt
PIR1bits.RC1IF = 0; //Clear interrupt flag
IPR1bits.RC1IP = 1; //High priority for RX interrupts
//PWM
PR2 = 0b11111001 ;
T2CON = 0b00000100; //1 KHz pulse frequency on CCP1 pin
CCPR1L = 0x00;
CCPR2L = 0x00;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
TMR2 = 0;
}