void checkCBS(unsigned int *voltageArray, unsigned char *currentModule, unsigned char numModules) { //* unsigned char action = BALANCEOFF; unsigned char dataReceived[8]; //maximum length that can be recieved unsigned char lengthReceived, flagsReceived; unsigned long addressReceived = 0; unsigned int my_CAN_id = ((unsigned int) *currentModule) << 2; unsigned int lowestVoltage = 50000; unsigned char lowestModule = *currentModule; unsigned char i; //determine the lowest module for(i=0; i<numModules;++i) { if(voltageArray[i]<lowestVoltage) { lowestVoltage = voltageArray[i]; lowestModule = i; } } //turn off CBS power to the previously low module if it's actually charging //check to see if we have received a comfirm message from the slave if(*currentModule != MODULE_ID_NULL) { while(addressReceived != (MASK_CBS | my_CAN_id)) { //keep sending the message until something responds while(!ECANSendMessage(MASK_BPS_MASTER | MASK_CBS | my_CAN_id, &action, 1, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); //read message while(!ECANReceiveMessage(&addressReceived, &dataReceived, &lengthReceived, &flagsReceived)); } } //turn on CBS power to the new low module if low module is low enough if(lowestVoltage < (CUTOFF_VOLTAGE_HIGH - 3000)) { my_CAN_id = ((unsigned int)lowestModule) << 2; addressReceived = 0; action = BALANCEON; //check to see if we have received a comfirm message from the slave while(addressReceived != (MASK_CBS | my_CAN_id)) { //keep sending the message until something responds while(!ECANSendMessage(MASK_BPS_MASTER | MASK_CBS | my_CAN_id, &action, 1, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); //read message while(!ECANReceiveMessage(&addressReceived, &dataReceived, &lengthReceived, &flagsReceived)); } *currentModule = lowestModule; } else { *currentModule = MODULE_ID_NULL; } //print out the result printf("CBS=%d\n\r",*currentModule); while(!ECANSendMessage((MASK_BPS_MASTER|MASK_BPS_READING|MASK_CBS), currentModule, 1, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); //*/ return; }
void main() { unsigned long id; BYTE cpt_RB4; BYTE cpt_RB5; BYTE data_envoi; BYTE data_recu[8]; BYTE dataLen; int i; ECAN_RX_MSG_FLAGS flags; init(); cpt_RB4 = 0; cpt_RB5 = 0; data_envoi = 0; for (i = 0; i < 8;i++) data_recu[i] = 0xFF; printf(NL NL "début programme" NL); ECANInitialize(); ECANSetBaudRate(2, 4, 8, 8, 8); while(1) { if(TRUE == ECANReceiveMessage(&id, data_recu, &dataLen, &flags)) { PIC1_ONLY printf("ECAN: reçu %u octet(s) : %u" NL, dataLen, data_recu[0]); led_afficher_int(data_recu[0]); } if(bouton_RB4_pressed()) { cpt_RB4 = cpt_RB4 + 1; data_envoi = (BYTE)cpt_RB4; while (!ECANSendMessage(0, &data_envoi, 1, 0)); PIC1_ONLY printf("compteur de RB4 : %u" NL, cpt_RB4); led_afficher_int(cpt_RB4); } if(bouton_RB5_pressed()) { cpt_RB5 = cpt_RB5 + 1; data_envoi = (BYTE)cpt_RB5; while (!ECANSendMessage(0, &data_envoi, 1, 0)); PIC1_ONLY printf("compteur de RB5 : %u" NL, cpt_RB5); led_afficher_int(cpt_RB5); } } }
void sendData(long current,unsigned char currentModule, long energy) { printf("BC=%ld\n\r",current); while(!ECANSendMessage((MASK_BPS_MASTER|MASK_BPS_READING), ¤t, 4, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); while(!ECANSendMessage((MASK_BPS_MASTER|MASK_BPS_READING|MASK_CBS), ¤tModule, 1, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); while(!ECANSendMessage((MASK_BPS_MASTER|MASK_BPS_READING|MASK_ENERGY), &energy, 4, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); printf("CBS=%d\n\r",currentModule); //printf("E=%ld\n\r",energy); return; }
/** * void send_fast_can(void) * * Samples and sends fast speed sensor channels on CAN if the interval has passed */ void send_fast_can(void) { if (millis - fast_send_tmr >= FAST_MSG_SEND) { #if FRONT // Sample and send FRONT fast speed sensor channels double spfl_samp = (double) sample(ADC_SPFL_CHN); uint16_t spfl = (uint16_t) ((10.0 * (5.0 - ((spfl_samp / 4095.0) * 5.0))) / SUS_POT_SCL); double spfr_samp = (double) sample(ADC_SPFR_CHN); uint16_t spfr = (uint16_t) ((10.0 * (5.0 - ((spfr_samp / 4095.0) * 5.0))) / SUS_POT_SCL); double bpf_samp = (double) sample(ADC_BPF_CHN); uint16_t bpf = (uint16_t) (((62.5 * ((bpf_samp / 4095.0) * 5.0)) - 31.25) / BRK_PRS_SCL); double bpr_samp = (double) sample(ADC_BPR_CHN); uint16_t bpr = (uint16_t) (((62.5 * ((bpr_samp / 4095.0) * 5.0)) - 31.25) / BRK_PRS_SCL); ((uint16_t*) data)[SPFL_BYTE / 2] = spfl; ((uint16_t*) data)[SPFR_BYTE / 2] = spfr; ((uint16_t*) data)[BPF_BYTE / 2] = bpf; ((uint16_t*) data)[BPR_BYTE / 2] = bpr; ECANSendMessage(ANALOG_FRONT_ID + 0x1, data, 8, ECAN_TX_FLAGS); #elif REAR // Sample and send REAR fast speed sensor channels double sprl_samp = (double) sample(ADC_SPRL_CHN); uint16_t sprl = (uint16_t) ((10.0 * (5.0 - ((sprl_samp / 4095.0) * 5.0))) / SUS_POT_SCL); double sprr_samp = (double) sample(ADC_SPRR_CHN); uint16_t sprr = (uint16_t) ((10.0 * (5.0 - ((sprr_samp / 4095.0) * 5.0))) / SUS_POT_SCL); uint16_t eos = 0; //TODO double bcd_samp = (double) sample(ADC_BCD_CHN); uint16_t bcd = (uint16_t) (((187.5 * ((bcd_samp / 4095.0) * 5.0)) - 468.75) / CUR_DRAW_SCL); ((uint16_t*) data)[SPRL_BYTE / 2] = sprl; ((uint16_t*) data)[SPRR_BYTE / 2] = sprr; ((uint16_t*) data)[EOS_BYTE / 2] = eos; ((uint16_t*) data)[BCD_BYTE / 2] = bcd; ECANSendMessage(ANALOG_REAR_ID + 0x1, data, 8, ECAN_TX_FLAGS); #endif fast_send_tmr = millis; } }
/** * void send_diag_can(void) * * Sends the diagnostic CAN message if the interval has passed. */ void send_diag_can(void) { if (millis - diag_send_tmr >= DIAG_MSG_SEND) { ((uint16_t*) data)[UPTIME_BYTE / 2] = seconds; #if FRONT ECANSendMessage(ANALOG_FRONT_ID + 0x0, data, 2, ECAN_TX_FLAGS); #elif REAR ECANSendMessage(ANALOG_REAR_ID + 0x0, data, 2, ECAN_TX_FLAGS); #endif diag_send_tmr = millis; } }
void can_send(Command c, BYTE param) { BYTE data_envoi[2]; data_envoi[0] = c; data_envoi[1] = param; while (!ECANSendMessage(0, data_envoi, 2, 0)); }
/** * void send_slow_can(void) * * Samples and sends slow speed sensor channels on CAN if the interval has passed */ void send_slow_can(void) { if (millis - slow_send_tmr >= SLOW_MSG_SEND) { #if REAR // Sample and send REAR slow speed sensor channels double ctri_samp = (double) sample(ADC_CTRI_CHN); double ctri_volt = ((ctri_samp / 4095.0) * 5.0); int16_t ctri = (int16_t) (convert_ntc_res(ctri_volt, M12H_COEFF) / TEMP_SCL); double ctro_samp = (double) sample(ADC_CTRO_CHN); double ctro_volt = ((ctro_samp / 4095.0) * 5.0); int16_t ctro = (int16_t) (convert_ntc_res(ctro_volt, M12H_COEFF) / TEMP_SCL); double ctsp_samp = (double) sample(ADC_CTSP_CHN); double ctsp_volt = ((ctsp_samp / 4095.0) * 5.0); int16_t ctsp = (int16_t) (convert_ntc_res(ctsp_volt, PSTF_COEFF) / TEMP_SCL); ((int16_t*) data)[CTRI_BYTE / 2] = ctri; ((int16_t*) data)[CTRO_BYTE / 2] = ctro; ((int16_t*) data)[CTSP_BYTE / 2] = ctsp; ECANSendMessage(ANALOG_REAR_ID + 0x2, data, 6, ECAN_TX_FLAGS); #endif slow_send_tmr = millis; } }
/** * void send_med_can(void) * * Samples and sends medium speed sensor channels on CAN if the interval has passed */ void send_med_can(void) { if (millis - med_send_tmr >= MED_MSG_SEND) { #if FRONT // Sample and send FRONT medium speed sensor channels double strp_samp = (double) sample(ADC_STRP_CHN); uint16_t strp = (uint16_t) (((90.0 * ((strp_samp / 4095.0) * 5.0)) - 45.0) / STRP_SCL); double apps0_samp = (double) sample(ADC_APPS0_CHN); uint16_t apps0 = (uint16_t) (((25.0 * ((apps0_samp / 4095.0) * 5.0)) - 12.5) / APPS_SCL); double apps1_samp = (double) sample(ADC_APPS1_CHN); uint16_t apps1 = (uint16_t) (((25.0 * ((apps1_samp / 4095.0) * 5.0)) - 12.5) / APPS_SCL); double ptdp_samp = (double) sample(ADC_PTDP_CHN); uint16_t ptdp = (uint16_t) (((3.06458 * ((ptdp_samp / 4095.0) * 5.0)) - 1.53229) / PTDP_SCL); ((uint16_t*) data)[STRP_BYTE / 2] = strp; ((uint16_t*) data)[APPS0_BYTE / 2] = apps0; ((uint16_t*) data)[APPS1_BYTE / 2] = apps1; ((uint16_t*) data)[PTDP_BYTE / 2] = ptdp; ECANSendMessage(ANALOG_FRONT_ID + 0x2, data, 8, ECAN_TX_FLAGS); #elif REAR // Sample and send REAR medium speed sensor channels double cpsp_samp = (double) sample(ADC_CPSP_CHN); uint16_t cpsp = (uint16_t) (((1.37552 * ((cpsp_samp / 4095.0) * 5.0)) - 0.18707) / CPSP_SCL); uint16_t mcd_samp = sample(ADC_MCD_CHN); uint16_t mcd = (uint16_t) (((187.5 * ((mcd_samp / 4095.0) * 5.0)) - 468.75) / CUR_DRAW_SCL); ((uint16_t*) data)[CPSP_BYTE / 2] = cpsp; ((uint16_t*) data)[MCD_BYTE / 2] = mcd; ECANSendMessage(ANALOG_REAR_ID + 0x3, data, 4, ECAN_TX_FLAGS); #endif med_send_tmr = millis; } }
void InterruptServiceHigh() { if (PIR3bits.RXB0IF || PIR3bits.RXB1IF) { //si message dans un buffer CAN lit le message // unsigned long id; // BYTE data[8]; // BYTE dataLen; // ECAN_RX_MSG_FLAGS msgFlag; // // while (!ECANReceiveMessage(&id, data, &dataLen, &msgFlag)); //remet le flag à 0 // switch (id) { // case 0x123: // // break; // // } } if (PIR1bits.RCIF) { //Reinitialise le flag d'interruption de l'USART PIR1bits.RCIF = 0; } if (INTCONbits.INT0IF) { //si interruption sur INT0/RB0 BYTE data[2]; data[0] = LATDbits.LATD0; data[1] = LATDbits.LATD1; //voir page 117 si erreur ECANSendMessage(0x222, data, 2, 0b00000011); INTCONbits.INT0IF = 0; // Reset flag interruption } // if (INTCON3bits.INT1IF) { //si interruption sur RB1 // INTCON3bits.INT1IF = 0; // Reset flag interruption // } if (INTCONbits.RBIF) { //si interruption sur RB4 à RB7 INTCONbits.RBIF = 0; // Reset flag interruption } if (INTCONbits.TMR0IF) { //Reinitialise le flag d'interruption du timer0 INTCONbits.TMR0IF = 0; //Prescale le timer0 //TMR0H = 0xF3; //TMR0L = 0xC9; } }
void main() { BYTE data = 0; TRISBbits.TRISB0 = 1; // rb0 en entrée (bouton) TRISBbits.TRISB1 = 1; // rb1 en entrée (bouton) //Configure les interruptions externes sur INT0 sur front (1:montant 0:descendant) INTCON2bits.INTEDG0 = 0; //Active les interruptions externes sur INT0 INTCONbits.INT0IE = 1; //Configure les interruptions externes sur INT1 sur front (1:montant 0:descendant) INTCON2bits.INTEDG1 = 0; //Configure l'interruption externe INT1 sur 1:Haut prio 0:Basse prio INTCON3bits.INT1IP = 1; //Active les interruptions externes sur INT1 INTCON3bits.INT1IE = 1; //Active l'interruption sur les changement de RB4 à RB7 p117 INTCONbits.RBIE = 1; //Initialise le flag interruption sur les changement de RB4 à RB7 INTCONbits.RBIF = 0; //Haute priorité sur interruption sur les changement de RB4 à RB7 INTCON2bits.RBIP = 1; //Configure l'oscillateur interne sur 4MHz OSCCON = 0xEE; //Active les priorités sur interruption RCONbits.IPEN = 1; //Active les interruptions de haute prio INTCONbits.GIE = 1; //Active les interruptions de basse prio INTCONbits.PEIE = 1; TRISDbits.TRISD0 = 1; // rb0 en entrée (bouton) TRISDbits.TRISD1 = 1; // rb1 en entrée (bouton) ECANInitialize(); ECANSendMessage(0x224, &data, 8, 0b00000011); while (1) { } }
void main(void) { unsigned long id; BYTE data[4]; BYTE dataLen; ECAN_RX_MSG_FLAGS flags; ECANInitialize(); // This function is for illustration purpose only. // It shows how an application would perform run-time initialization. // Normally, ECANInitialize() would initialize ECAN module // as per ECAN.def options. You would do run-time initialization // only if the ECAN optoins need to be changed at run-time. //RunTimeInitialization(); while( !ECANSendMessage(0x123, data, 0, ECAN_TX_STD_FRAME) ); do { while( !ECANReceiveMessage(&id, data, &dataLen, &flags) ) { // Pushed down RB4 will fill-up FIFO/buffers. while( PORTB_RB4 == 0 ); } id++; while( !ECANSendMessage(id, data, dataLen, flags) ); // Delay so that when we are transmitting contents of FIFO all at once, // CANKing can receive it correctly without overflowing its buffer. id = 0xafff; while( id-- ); } while(1); }
void main(void) { /************************* * Variable Declarations * *************************/ BYTE radio_sw[2], drs_over_sw[2], fan_over_sw[2], fuel_map_sw[2], paddle_l_sw[2], paddle_r_sw[2]; BYTE ADLmsg[8]; BYTE cycleStates[2], intensity; unsigned int bounceTimer[2]; unsigned int CAN_tmr; /********************* * Oscillator Set-Up * *********************/ #ifdef INTERNAL // OSCTUNE OSCTUNEbits.INTSRC = 0; // Internal Oscillator Low-Frequency Source Select (1 for 31.25 kHz from 16MHz/512 or 0 for internal 31kHz) OSCTUNEbits.PLLEN = 1; // Frequency Multiplier PLL Select (1 to enable) OSCTUNEbits.TUN5 = 0; // Fast RC Oscillator Frequency Tuning (seems to be 2's comp encoding) OSCTUNEbits.TUN4 = 0; // 011111 = max OSCTUNEbits.TUN3 = 0; // ... 000001 OSCTUNEbits.TUN2 = 0; // 000000 = center (running at calibrated frequency) OSCTUNEbits.TUN1 = 0; // 111111 ... OSCTUNEbits.TUN0 = 0; // 100000 // OSCCCON OSCCONbits.IDLEN = 1; // Idle Enable Bit (1 to enter idle mode after SLEEP instruction else sleep mode is entered) OSCCONbits.IRCF2 = 1; // Internal Oscillator Frequency Select Bits OSCCONbits.IRCF1 = 1; // When using HF, settings are: OSCCONbits.IRCF0 = 1; // 111 - 16 MHz, 110 - 8MHz (default), 101 - 4MHz, 100 - 2 MHz, 011 - 1 MHz OSCCONbits.SCS1 = 0; OSCCONbits.SCS0 = 0; // OSCCON2 OSCCON2bits.MFIOSEL = 0; while(!OSCCONbits.HFIOFS); // wait for stable clock #else // OSCTUNE OSCTUNEbits.INTSRC = 0; // Internal Oscillator Low-Frequency Source Select (1 for 31.25 kHz from 16MHz/512 or 0 for internal 31kHz) OSCTUNEbits.PLLEN = 1; // Frequency Multiplier PLL Select (1 to enable) // OSCCCON OSCCONbits.SCS1 = 0; // select configuration chosen oscillator OSCCONbits.SCS0 = 0; // SCS = 00 // OSCCON2 OSCCON2bits.MFIOSEL = 0; while(!OSCCONbits.OSTS); // wait for stable external clock #endif /********************* * Peripherals Setup * *********************/ // turn on and configure the A/D converter module OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_4_TAD, ADC_CH0 & ADC_INT_OFF, ADC_REF_VDD_VDD & ADC_REF_VDD_VSS & ADC_NEG_CH0); ANCON0 = 0b00100111; // AN0 - 2 and AN5 are analog ANCON1 = 0x00; // rest are digital TRISAbits.TRISA0 = INPUT; TRISAbits.TRISA1 = INPUT; TRISAbits.TRISA2 = INPUT; TRISAbits.TRISA5 = INPUT; // turn on and configure the TIMER1 oscillator OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_128); WriteTimer0(0x82); // load timer register millis = 0; // clear milliseconds count INTCONbits.TMR0IE = 1; // turn on timer0 interupts // SPI setup SSPSTATbits.CKE = 1; // SPI Clock Select, 1 = transmit on active to idle SSPCON1bits.CKP = 0; // Clock Polarity Select, 0 = low level is idle state SSPCON1bits.SSPM = 0b1010; // Clk Frequecy (Note: FOSC = 64MHz) SSPCON1bits.SSPEN = 1; // SPI Enable, 1 enables // SPI pin I/O setup TRISCbits.TRISC3 = OUTPUT; // SCK TRISCbits.TRISC5 = OUTPUT; // SDO TRISDbits.TRISD3 = OUTPUT; // CS CS = 1; // driver set up intensity = 0x0F; driver_write(DISP_MODE, NORMAL); // leave test mode driver_write(SHUTDOWN, SHUTDOWN_OFF); // leave shutdown mode driver_write(INTENSITY, intensity); // set brightness to highest driver_write(SCAN, FULL_SCAN); // Set scan to all digits driver_write(DECODE, NO_DECODE); // Decoding disabled // set displays to display zero write_gear(0); write_num(0, 2, LEFT); write_num(0, 2, RIGHT); // intialize states cycleStates[LEFT] = CYCLE_L; cycleStates[RIGHT] = CYCLE_R; holdText[LEFT] = holdText[RIGHT] = TRUE; refreshTime[LEFT] = refreshTime[RIGHT] = holdTimer[LEFT] = holdTimer[RIGHT] = blinkTimer[LEFT] = blinkTimer[RIGHT] = millis; displayStates[LEFT] = OIL_T; displayStates[RIGHT] = ENGINE_T; ECANInitialize(); // setup ECAN // interrupts setup INTCONbits.GIE = 1; // Global Interrupt Enable (1 enables) INTCONbits.PEIE = 1; // Peripheral Interrupt Enable (1 enables) RCONbits.IPEN = 0; // Interrupt Priority Enable (1 enables) TRISCbits.TRISC6 = OUTPUT; // programmable termination TERM_LAT = FALSE; while(1) { // check for change in button state if(cycleStates[LEFT] != CYCLE_L & millis - bounceTimer[LEFT] > BOUNCE_TIME) { // save new state cycleStates[LEFT] = CYCLE_L; bounceTimer[LEFT] = millis; // only change display if button is low if(!cycleStates[LEFT]) { if(++displayStates[LEFT] == NUM_CHAN) displayStates[LEFT] = 0; // put the appropriate text on the displays and // get the current time for timing logic updateText(LEFT, displayStates); holdText[LEFT] = TRUE; blinkTimer[LEFT] = holdTimer[LEFT] = millis; } } if(cycleStates[RIGHT] != CYCLE_R & millis - bounceTimer[RIGHT] > BOUNCE_TIME) { cycleStates[RIGHT] = CYCLE_R; bounceTimer[RIGHT] = millis; if(!cycleStates[RIGHT]) { if(++displayStates[RIGHT] == NUM_CHAN) displayStates[RIGHT] = 0; updateText(RIGHT, displayStates); holdText[RIGHT] = TRUE; blinkTimer[RIGHT] = holdTimer[RIGHT] = millis; } } // update left and right displays with text or numerical data updateDisp(LEFT); updateDisp(RIGHT); write_gear(gear); // radio button if(!RADIO) { radio_sw[0] = 0x13; radio_sw[1] = 0x88; } else *(int *)radio_sw = 0; #if 0 // paddle switches if(PADDLE_L) { paddle_l_sw[0] = 0x13; paddle_l_sw[1] = 0x88; } else *(int *)paddle_l_sw = 0; if(PADDLE_R) { paddle_r_sw[0] = 0x13; paddle_r_sw[1] = 0x88; } else *(int *)paddle_r_sw = 0; #endif // DRS override switch if(DRS_OVER) { drs_over_sw[0] = 0x13; drs_over_sw[1] = 0x88; } else *(int *)drs_over_sw = 0; // fan override switch if(FAN_OVER) { fan_over_sw[0] = 0x13; fan_over_sw[1] = 0x88; } else *(int *)fan_over_sw = 0; // fuel map switch if(FUEL_MAP) { fuel_map_sw[0] = 0x13; fuel_map_sw[1] = 0x88; } else *(int *)fuel_map_sw = 0; if(millis - CAN_tmr > CAN_PER) { CAN_tmr = millis; // send out the first three sampled switches ADLmsg[0] = 0x00; ADLmsg[1] = 0x00; ADLmsg[ADL1] = radio_sw[0]; ADLmsg[ADL1 + 1] = radio_sw[1]; ADLmsg[ADL2] = fan_over_sw[0]; ADLmsg[ADL2 + 1] = fan_over_sw[1]; ADLmsg[ADL3] = fuel_map_sw[0]; ADLmsg[ADL3 + 1] = fuel_map_sw[1]; ECANSendMessage(ADLid, ADLmsg, 8, ECAN_TX_STD_FRAME | ECAN_TX_NO_RTR_FRAME | ECAN_TX_PRIORITY_1); // send out first three rotary encoders ADLmsg[0] = 0x01; ADLmsg[1] = 0x00; ADLsample(ADLmsg, ADL4, LAUNCH_ROT); ADLsample(ADLmsg, ADL5, TRAC_ROT); ADLsample(ADLmsg, ADL6, DRS_ROT); ECANSendMessage(ADLid, ADLmsg, 8, ECAN_TX_STD_FRAME | ECAN_TX_NO_RTR_FRAME | ECAN_TX_PRIORITY_1); } } // end main loop return; }
//if there was a bad reading then store the error and shut down the car. void failure(unsigned char type, unsigned char address, unsigned int intVal, unsigned char charVal) { unsigned int i=0; unsigned char action = BALANCEOFF; unsigned char send_data[4]; memcpy_reduced(&(send_data[1]), &intVal); send_data[0] = address; send_data[3] = charVal; //send the message that the car is going to shut down and why while(!ECANSendMessage(MASK_MASTER_SHUTDOWN, send_data, 4, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); //Try to shut the CBS relay off for the module that's out of range. this should not be a problem if the relay fails to shut off. while(!ECANSendMessage(MASK_BPS_MASTER | MASK_CBS | ((unsigned int)(address << 2)), &action, 1, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); printf("Shutting Car Down\n\r"); printf("Addr = %.2x\n\r",address); printf("Volt = %u\n\r",intVal); printf("temp = %.2d\n\r",charVal); //store the error type (don't bother with type 0(not an error)) if(type==BPSERR) { writeByte(LOCATION_ERRTYPE, ((type<<6) & address)); writeByte(LOCATION_INTVAL0, send_data[1]); writeByte(LOCATION_INTVAL1, send_data[2]); writeByte(LOCATION_CHARVAL, charVal); } else if(type == CURRENTERR) { writeByte(LOCATION_ERRTYPE, (type<<6)); writeByte(LOCATION_INTVAL0, send_data[1]); writeByte(LOCATION_INTVAL1, send_data[2]); } else if(type == SHUTDOWN) { writeByte(LOCATION_ERRTYPE, (type<<6)); } //wait very short time for message to get through to LCD and telemetry for(i=0; i<1000; ++i); //shut down the car arrayrelay = RELAYOFF; mainrelay = RELAYOFF; //wait for car to shut down (yes it seems pointless until you run it on a power supply) //different PWM's for the led to let us know what type of error if(switch1 == SWITCHOFF) //switch1 casues data to continue being collected after the relay has been shut off { if(type==BPSERR){ while(1){ led1 = ~led1; Delay10KTCYx(0); } } else if(type == CURRENTERR){ while(1){ led1 = ~led1; Delay10KTCYx(0); led1 = ~led1; Delay10KTCYx(0); Delay10KTCYx(0); } } else if(type == SHUTDOWN){ while(1){led1 = LEDOFF;} } else{ while(1){ led1 = ~led1; for(i=0; i<20; ++i){Delay10KTCYx(0);} } } } return; }
void readSlaves(unsigned int *voltageArray, unsigned char *tempArray, unsigned char numModules) { int i = 0, j = 0; char messageReceived = 0; unsigned char dataReceived[8]; //maximum length that can be recieved unsigned char lengthReceived, flagsReceived; unsigned long addressReceived = 0; unsigned long sendAddress; unsigned int receiveTimeoutCounter = 0; unsigned int slaveTimeoutCounter = 0; unsigned int newVoltage = 0; unsigned char newTemp = 0; for(i=0; i<numModules; ++i) { unsigned int timeOutCounterJohn = 1000; //how long we wait for a message slaveTimeoutCounter = 0; //how many other messages we get before fail; sendAddress = (i << 2) | MASK_BPS_READING; //printf("i:%d\r\nadd:%lb\r\n", i, sendAddress); while(addressReceived != sendAddress) { receiveTimeoutCounter = 0; //ensure that the 0 transmit buffer is empty /* while((TXB0CON & 0b10000000) == 0) { for(j=0; j<100; ++j); arrayrelay=~arrayrelay; for(j=0; j<100; ++j); arrayrelay=~arrayrelay; }//*/ //send the message until it is acknowledged by something timeOutCounterJohn = 1000; while(!ECANSendMessage((MASK_BPS_MASTER | sendAddress), NULL, 0, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME) && timeOutCounterJohn) { timeOutCounterJohn --; for(j=0; j<50; ++j); //led1=~led1; for(j=0; j<50; ++j); //led1=~led1; } //check for a reply from the master acknowleging the message while( (!ECANReceiveMessage(&addressReceived, &dataReceived, &lengthReceived, &flagsReceived)) && receiveTimeoutCounter<=RECEIVETIMEOUT && timeOutCounterJohn) { timeOutCounterJohn--; // ++receiveTimeoutCounter; for(j=0; j<100; ++j); //led1=~led1; // printf("\tRXcnt: %u\r\n", receiveTimeoutCounter);//need this here for timing } //printf("RXadd:%lb\r\n", addressReceived); //* ++slaveTimeoutCounter; if(slaveTimeoutCounter >= SLAVETIMEOUT) {printf("Slave Timeout Error\r\n");failure(BPSERR, i, 0x00, 0x00);}//*/ } //check and ensure that three byte has been recieved if(lengthReceived == 3) { //retrieve and store the values for voltage and temperature memcpy_reduced(&newVoltage, dataReceived); newTemp = dataReceived[2]; //store the new values into their arrays voltageArray[i] = newVoltage; tempArray[i] = newTemp; //print out the values GLOBALINTERRUPTS = INTERRUPTDISABLE; printf("V[%.2d]=%u\n\r",i, newVoltage); printf("T[%.2d]=%.2d\n\r",i, newTemp); GLOBALINTERRUPTS = INTERRUPTENABLE; //if it is under voltage over voltage or over temperature then shut the car off if((newVoltage < CUTOFF_VOLTAGE_LOW) || (newVoltage > CUTOFF_VOLTAGE_HIGH) || (newTemp > CUTOFF_TEMP_HIGH)) { failure(BPSERR, i, newVoltage, newTemp); } } else {printf("Message Corruption Error\r\n");failure(BPSERR, i, 0x00, 0x00);} //if there was an interrupt, check the current now. if(glob_interrupt && switch5 == SWITCHOFF) //switch5 disables current reading { glob_current=checkcurrent(); printf("BC=%ld\n\r",glob_current); while(!ECANSendMessage((MASK_BPS_MASTER|MASK_BPS_READING), &glob_current, 4, ECAN_TX_STD_FRAME | ECAN_TX_PRIORITY_0 | ECAN_TX_NO_RTR_FRAME)); glob_interrupt = 0; } } return; }