/* * File: main.c * Author: Mike Mellitt * Ben Coffey * Jake Thordahl * Pat Bowlds * Alex Toombs * * Main file for program to read voltage from battery resistor divider to * monitor charge, MPH, other peripherals * * Analog pinout on board: * A7: Battery Stack Voltage (through divider) * A6: Break sensors * * Created on April 23, 2013, 4:35 PM * * Last Modified: April 23, 2013 */ #include #include #include #include "configbits.h" #include #include #include #include "Other.h" #define A 0x41 #define B 0x42 #define C 0x43 #define D 0x44 #define E 0x45 #define F 0x46 #define G 0x47 #define H 0x48 #define I 0x49 #define J 0x4A #define K 0x4B #define L 0x4C #define M 0x4D #define N 0x4E #define O 0x4F #define P 0x50 #define Q 0x51 #define R 0x52 #define S 0x53 #define T 0x54 #define U 0x55 #define V 0x56 #define W 0x57 #define X 0x58 #define Y 0x59 #define Z 0x5A #define LED 0x50 #define LEDREG 0xFE #define DAC 0xC0 #define LEDCLR 0x51 #define LEDRIGHT 0x4A #define ZERO 0x30 #define ONE 0x31 #define TWO 0x32 #define THREE 0x33 #define FOUR 0x34 #define FIVE 0x35 #define SIX 0x36 #define SEVEN 0x37 #define EIGHT 0x38 #define NINE 0x39 #define COLON 0x3A #define EQUAL 0x3D #define DECIMAL 0x2E #define CON 0x52 #define true 1 #define false 0 // voltage reading from battery sensor analog pin double Battery_volt=0; // voltage reading from break sensor through divider double Break_volt=0; int ChargeOn,Phase2,ChargeDone; int On2,Haz,Night; int Right,Left; int But1,But2; int breaking=0; int flash=1,error=0; int startcount=0; // Loops continuously to adjust current source output int main(int argc, char** argv) { // Timer Interrupts ConfigTime(); // Analog Config pin B7 ConfigAnalog(); // I2C Config ConfigI2C(); // disable JTAG so pin 12-15 can be used DDPCONbits.JTAGEN = 0; AD1PCFGbits.PCFG12 = 1; AD1PCFGbits.PCFG13 = 1; AD1PCFGbits.PCFG14 = 1; AD1PCFGbits.PCFG15 = 1; // Configure input ports------------------------------------------------ //Status TRISEbits.TRISE0 = 1; //charger connected //Logic Done TRISEbits.TRISE1 = 1; //phase2 TRISEbits.TRISE2 = 1; //charger done //Switches TRISBbits.TRISB12 = 1; //night TRISBbits.TRISB13 = 1; //hazards TRISBbits.TRISB14 = 1; //on2 TRISDbits.TRISD5 = 1; //right TRISDbits.TRISD4 = 1; //left //Buttons TRISBbits.TRISB10 = 1; //but2 TRISBbits.TRISB11 = 1; //but1 // Configure output ports----------------------------------------------- TRISEbits.TRISE3 = 0; //voltage div on LATEbits.LATE3 = 1; //Turn on voltage divider TRISDbits.TRISD1 = 0; //Motor Controller on LATDbits.LATD1= 0; //Motor START off TRISBbits.TRISB5 = 0; //LeftLED LATBbits.LATB5 = 0; //Start off TRISBbits.TRISB4 = 0; //RightLED LATBbits.LATB4 = 0; //Start off TRISBbits.TRISB3 = 0; //WarnLED LATBbits.LATB3 = 0; //Start off TRISBbits.TRISB2 = 0; //NEULED LATBbits.LATB2 = 0; //Start off TRISBbits.TRISB8 = 0; //Plate light LATBbits.LATB8 = 0; //Start off TRISBbits.TRISB9 = 0; //Tail light LATBbits.LATB9 = 0; //Start off // Create Variables SendI2C4(LED,LEDREG,CON,0x1E); // run continously to keep program running while(1) { //User Inputs ChargeOn=PORTEbits.RE0; Phase2=PORTEbits.RE1; ChargeDone=PORTEbits.RE2; On2=PORTBbits.RB14; Haz=PORTBbits.RB13; Night=PORTBbits.RB12; Right=PORTDbits.RD5; Left=PORTDbits.RD4; But1=PORTBbits.RB11; But2=PORTBbits.RB10; //Outputs if(On2&!ChargeOn){ LATDbits.LATD1= 1; //Turn on motor error=0; } else if(On2&ChargeOn){ LATDbits.LATD1= 0; //Turn off motor error=1; } else{ LATDbits.LATD1= 0; //Turn off motor error=0; } if(Night){ LATBbits.LATB8 = 1; //Turn on plate light } else LATBbits.LATB8 = 0; //Turn off plate light } return (EXIT_SUCCESS); } //------------------------------------------------------------------------------- // TO-DO: Configure timer and present message over I2C to display void __ISR(8, IPL3AUTO) Timer2Hand(void) { INTClearFlag(INT_T2); if(((Haz|error)|(Right|Left))&flash){ //Causes hazards to flash on and off if(Haz|error) LATBbits.LATB3 = 1; //Warning display On else if(Right) LATBbits.LATB4 = 1; //Right Light On else LATBbits.LATB5 = 1; //Left Light On if(!error) LATBbits.LATB9 = 1; //Tail Light On flash=0; } else{ LATBbits.LATB3 = 0; //Warning display OFF LATBbits.LATB5 = 0; //Left Light OFF LATBbits.LATB4 = 0; //Right Light OFF if(!breaking) LATBbits.LATB9 = 0; //Tail Light OFF if not breaking flash=1; } // write logic to communicate values to peripherals // Display Status on I2C display if(startcount<25){ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,L); SendI2C2(LED,I); SendI2C2(LED,G); SendI2C2(LED,H); SendI2C2(LED,T); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,B); SendI2C2(LED,I); SendI2C2(LED,K); SendI2C2(LED,E); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,S); SendI2C2(LED,T); SendI2C2(LED,A); SendI2C2(LED,R); SendI2C2(LED,T); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,U); SendI2C2(LED,P); startcount++; } else if(ChargeDone){ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,D); SendI2C2(LED,O); SendI2C2(LED,N); SendI2C2(LED,E); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,C); SendI2C2(LED,H); SendI2C2(LED,A); SendI2C2(LED,R); SendI2C2(LED,G); SendI2C2(LED,I); SendI2C2(LED,N); SendI2C2(LED,G); } else if(Phase2){ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,T); SendI2C2(LED,R); SendI2C2(LED,I); SendI2C2(LED,C); SendI2C2(LED,K); SendI2C2(LED,L); SendI2C2(LED,E); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,C); SendI2C2(LED,H); SendI2C2(LED,A); SendI2C2(LED,R); SendI2C2(LED,G); SendI2C2(LED,I); SendI2C2(LED,N); SendI2C2(LED,G); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,E); SendI2C2(LED,S); SendI2C2(LED,T); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,T); SendI2C2(LED,I); SendI2C2(LED,M); SendI2C2(LED,E); SendI2C2(LED,COLON); SendI2C3(LED,LEDREG,LEDRIGHT); } else if(ChargeOn){ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,C); SendI2C2(LED,H); SendI2C2(LED,A); SendI2C2(LED,R); SendI2C2(LED,G); SendI2C2(LED,I); SendI2C2(LED,N); SendI2C2(LED,G); SendI2C3(LED,LEDREG,LEDRIGHT); } else if (!On2){ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,R); SendI2C2(LED,E); SendI2C2(LED,A); SendI2C2(LED,D); SendI2C2(LED,Y); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,T); SendI2C2(LED,O); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,T); SendI2C2(LED,U); SendI2C2(LED,R); SendI2C2(LED,N); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,O); SendI2C2(LED,N); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,B); SendI2C2(LED,A); SendI2C2(LED,T); SendI2C2(LED,T); SendI2C2(LED,E); SendI2C2(LED,R); SendI2C2(LED,Y); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,V); SendI2C2(LED,O); SendI2C2(LED,L); SendI2C2(LED,T); SendI2C2(LED,A); SendI2C2(LED,G); SendI2C2(LED,E); SendI2C2(LED,COLON); SendI2C3(LED,LEDREG,LEDRIGHT); } else{ SendI2C3(LED,LEDREG,LEDCLR); SendI2C2(LED,D); SendI2C2(LED,R); SendI2C2(LED,I); SendI2C2(LED,V); SendI2C2(LED,I); SendI2C2(LED,N); SendI2C2(LED,G); SendI2C3(LED,LEDREG,LEDRIGHT); SendI2C2(LED,M); SendI2C2(LED,O); SendI2C2(LED,D); SendI2C2(LED,E); SendI2C3(LED,LEDREG,LEDRIGHT); } } // Configure bits for Timer operation void ConfigTime() { // Stops Timer and Clears register T2CON = 0x0; TMR2 = 0x0; // Set PR to 65535 originally 16000 with 3E80 PR2 = 0xAFFF; // Set prescaler at 1:256 T2CONSET = 0x0070; // Start Timer T2CONSET = 0x8000; INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR); // Enables Global Interrupts INTEnableInterrupts(); // Enables Timer2 Interrupts INTEnable(INT_T2, INT_ENABLED); // Clears timer2 flag INTClearFlag(INT_T2); // Timer2 has priority 3 INTSetVectorPriority(INT_T2,3); } //---------------------------------------------------------------------------------------------------------------------------- // Configure analog registers to read value from sensors void ConfigAnalog() { // ensure the ADC is off before setting the configuration CloseADC10(); // Turn module on |ouput in integer| trigger mode auto | enable autosample #define PARAM1 ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON // ADC ref external | disable offset test | disable scan mode // | perform 8 samples | use dual buffers | use alternate mode #define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON // use ADC PB clock| set sample time | auto #define PARAM3 ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15 // AN7 as analog inputs #define PARAM4 ENABLE_AN6_ANA | ENABLE_AN7_ANA // do not assign channels to scan #define PARAM5 SKIP_SCAN_ALL // configure to sample AN7 B7 and AN8 SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN6| ADC_CH0_NEG_SAMPLEB_NVREF | ADC_CH0_POS_SAMPLEB_AN7); // configure ADC using the parameters defined above OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // Note the 65 NS minimum TAD from datasheet, don't use FRM //AD1CON3bits.ADCS=0x01; EnableADC10(); } // Read analog pin values for battery stack voltage and break voltage void getAnalog() { while ( ! mAD1GetIntFlag() ) { // wait for the first conversion to complete so there // will be vaild data in ADC result registers } Battery_volt = ReadADC10(7)*.003185; // pin 7 stack voltage Break_volt = ReadADC10(6)*.003185; // pin 6 break voltage mAD1ClearIntFlag(); // Clear ADC interrupt flag } //------------------------------------------------------------------------------------------------------------------------------------ // Configure I2C registers void ConfigI2C() { //1 USES RD10 AS SCL1 AND RD 9 AS SDA1 /// I2CxCON I2CxSTAT I2CxADD I2CxMSK I2CxTRN I2CxRCV I2C1BRG=0x030; //390 for 80MHz to 100KHz I2C1CONbits.A10M=0; //Use 7-bit addresses I2C1CONbits.DISSLW=1; //disable slew control for standard I2C1CONbits.ACKDT=0; //Use and ACK not NACK I2C1ADD=22; //Sets slave address for PIC32 TRISD=1; //Sets Port D to input I2C1CONbits.ON=1; //turn on I2C } // Start I2C void I2C_start(void) { I2C1CONbits.SEN=1; //send start while(I2C1CONbits.SEN){} //waits till start bit detected } // Restart I2C void I2C_restart(void) { I2C1CONbits.RSEN=1; //send restart while(I2C1CONbits.RSEN){} //waits till start bit detected } // Stop I2C void I2C_stop(void) { I2C1CONbits.PEN=1; //send stop while(I2C1CONbits.PEN){} //waits till stop bit detected } // Write char of data to I2C line char I2C_write(char data) { I2C1TRN=data; //sends data to transmit register while(I2C1STATbits.TRSTAT==1){} //waits to finsh transmission return(I2C1STATbits.ACKSTAT); //returns 0 for ack received } // Check for acknowledgement void mAckI2C1(void) { I2C1CONbits.ACKDT=0; I2C1CONbits.ACKEN=1; while(I2C1CONbits.ACKEN){} } // Check for lack of acknowledgement void mNAckI2C1(void) { I2C1CONbits.ACKDT=1; I2C1CONbits.ACKEN=1; while(I2C1CONbits.ACKEN){} } // Read data back from I2C line char I2C_read(char ack) { I2C1CONbits.RCEN=1; while(I2C1CONbits.RCEN){} //Reception is started, send ack/nack after read if(ack==0) {mNAckI2C1();} else {mAckI2C1();} //Reception should be complete - pull out data return(I2C1RCV); } // Make I2C line wait for registers to clear void I2C_idle() { while((I2C1CON&0x001F)!=0){} // Wait for Acken, Rcen, Pen, Rsen and Sen to clear } // Send data to I2C line at given address void SendI2C3(char addrs,char regis, char data) { char ack; I2C_start(); ack=I2C_write(addrs); //Address for LED is 0x50 ack=I2C_write(regis); //0xFE for LED ack=I2C_write(data); //0x20to0x7F standard I2C_stop(); } void SendI2C4(char addrs,char regis, char data, char con) { char ack; I2C_start(); ack=I2C_write(addrs); //Address for LED is 0x50 ack=I2C_write(regis); //0xFE for LED ack=I2C_write(data); //0x20to0x7F standard ack=I2C_write(con); //0x20to0x7F standard I2C_stop(); } // Writes to standard registers void SendI2C2(char addrs, char data) { char ack; I2C_start(); ack=I2C_write(addrs); //Address for LED is 0x50 ack=I2C_write(data); //0x20to0x7F standard I2C_stop(); }