Custom version for NXP cup car
Fork of FRDM-TFC by
Revision 9:0c6d78c56091, committed 2017-06-01
- Comitter:
- Clarkk
- Date:
- Thu Jun 01 13:16:37 2017 +0000
- Parent:
- 8:24430a0d7fd8
- Commit message:
- Few changes
Changed in this revision
TFC.cpp | Show annotated file Show diff for this revision Revisions of this file |
TFC.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 24430a0d7fd8 -r 0c6d78c56091 TFC.cpp --- a/TFC.cpp Thu Feb 11 14:58:08 2016 +0000 +++ b/TFC.cpp Thu Jun 01 13:16:37 2017 +0000 @@ -4,8 +4,8 @@ #define FTM1_CLK_PRESCALE 6// Prescale Selector value - see comments in Status Control (SC) section for more details #define SERVO_DEFAULT_PERIOD (float)(.020) // Desired Frequency of PWM Signal - Here 50Hz => 20ms period // use these to dial in servo steering to your particular servo -#define SERVO_MIN_PULSE_WIDTH_DEFAULT (float)(.00095) // The number here should be be *pulse width* in seconds to move servo to its left limit -#define SERVO_MAX_PULSE_WIDTH_DEFAULT (float)(.00160) // The number here should be be *pulse width* in seconds to move servo to its left limit +#define SERVO_MIN_PULSE_WIDTH_DEFAULT (float)(.0005) // The number here should be be *pulse width* in seconds to move servo to its left limit +#define SERVO_MAX_PULSE_WIDTH_DEFAULT (float)(.00150) // The number here should be be *pulse width* in seconds to move servo to its left limit #define FTM0_CLOCK (SystemCoreClock/2) @@ -24,13 +24,16 @@ #define ADC_STATE_CAPTURE_POT_1 2 #define ADC_STATE_CAPTURE_BATTERY_LEVEL 3 #define ADC_STATE_CAPTURE_LINE_SCAN 4 - +#define ADC_STATE_CAPTURE_MOTOR_A_CURRENT 5 +#define ADC_STATE_CAPTURE_MOTOR_B_CURRENT 6 #define TFC_POT_0_ADC_CHANNEL 13 #define TFC_POT_1_ADC_CHANNEL 12 #define TFC_BAT_SENSE_CHANNEL 4 #define TFC_LINESCAN0_ADC_CHANNEL 6 #define TFC_LINESCAN1_ADC_CHANNEL 7 +#define TFC_IFB_MOTA_ADC_CHANNEL 7 +#define TFC_IFB_MOTB_ADC_CHANNEL 3 #define ADC0_irq_no 57 @@ -214,14 +217,6 @@ #define PGAG_32 0x05 #define PGAG_64 0x06 - -#define ADC_STATE_INIT 0 -#define ADC_STATE_CAPTURE_POT_0 1 -#define ADC_STATE_CAPTURE_POT_1 2 -#define ADC_STATE_CAPTURE_BATTERY_LEVEL 3 -#define ADC_STATE_CAPTURE_LINE_SCAN 4 - - /////////// The above values fit into the structure below to select ADC/PGA /////////// configuration desired: @@ -241,7 +236,6 @@ #define CAL_BLK_NUMREC 18 typedef struct adc_cal { - uint16_t OFS; uint16_t PG; uint16_t MG; @@ -343,13 +337,22 @@ volatile uint16_t * TFC_LineScanImage1; volatile uint8_t TFC_LineScanImageReady; +volatile uint8_t ConvertionTasks; volatile uint16_t PotADC_Value[2]; volatile uint16_t BatSenseADC_Value; volatile uint16_t CurrentADC_State; +volatile uint16_t MotACurrentADC_Value; +volatile uint16_t MotBCurrentADC_Value; volatile uint8_t CurrentLineScanPixel; volatile uint8_t CurrentLineScanChannel; volatile uint32_t TFC_ServoTicker; +volatile uint8_t TFC_Pot0Ready; +volatile uint8_t TFC_Pot1Ready; +volatile uint8_t TFC_BatteryVoltageReady; +volatile uint8_t TFC_MotorCurrentReady; + +FunctionPointer TFC_ConvertionReadyCallback; void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle); void TFC_InitLineScanCamera(); @@ -383,9 +386,7 @@ void TFC_GPIO_Init() { - //enable Clocks to all ports - SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK; //Setup Pins as GPIO @@ -396,7 +397,6 @@ PORTC->PCR[13] = PORT_PCR_MUX(1); PORTC->PCR[17] = PORT_PCR_MUX(1); - //Ports for DIP Switches PORTE->PCR[2] = PORT_PCR_MUX(1); PORTE->PCR[3] = PORT_PCR_MUX(1); @@ -409,7 +409,6 @@ PORTB->PCR[10] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; PORTB->PCR[11] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; - //Setup the output pins PTE->PDDR = TFC_HBRIDGE_EN_LOC; PTB->PDDR = TFC_BAT_LED0_LOC | TFC_BAT_LED1_LOC | TFC_BAT_LED2_LOC | TFC_BAT_LED3_LOC; @@ -468,26 +467,17 @@ //Dump the queued values to the timer channels TPM1->CONTROLS[0].CnV = QueuedServo0Val; TPM1->CONTROLS[1].CnV = QueuedServo1Val; - + + //TFC_StartDataAcquisition(); - //Prime the next ADC capture cycle - TAOS_SI_HIGH; - //Prime the ADC pump and start capturing POT 0 - CurrentADC_State = ADC_STATE_CAPTURE_POT_0; - - ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux - ADC0->SC1[0] = TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; //Start the State machine at POT0 - - //Flag that a new cervo cycle will start + //Flag that a new servo cycle will start if (TFC_ServoTicker < 0xffffffff)//if servo tick less than max value, count up... TFC_ServoTicker++; } - void TFC_InitServos(float PulseWidthMin, float PulseWidthMax, float ServoPeriod) { - SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; _ServoPeriod = ServoPeriod; @@ -766,6 +756,109 @@ } +void TFC_StopCameraExposure() +{ + TAOS_SI_HIGH; +} + +void TFC_StartADC_Pot0() +{ + // start capturing POT 0 + CurrentADC_State = ADC_STATE_CAPTURE_POT_0; + + ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux + ADC0->SC1[0] = TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; //Start the State machine at POT0 +} + +void TFC_StartADC_Pot1() +{ + CurrentADC_State = ADC_STATE_CAPTURE_POT_1; + ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux + ADC0->SC1[0] = TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK; +} + +void TFC_StartADC_Battery() +{ + CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL; + ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux + ADC0->SC1[0] = TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK; +} + +void TFC_StartADC_MotACurrent() +{ + CurrentADC_State = ADC_STATE_CAPTURE_MOTOR_A_CURRENT; + ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux + ADC0->SC1[0] = TFC_IFB_MOTA_ADC_CHANNEL| ADC_SC1_AIEN_MASK; +} + +void TFC_StartADC_MotBCurrent() +{ + CurrentADC_State = ADC_STATE_CAPTURE_MOTOR_B_CURRENT; + //ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux + ADC0->SC1[0] = TFC_IFB_MOTB_ADC_CHANNEL| ADC_SC1_AIEN_MASK; +} + +void TFC_StartADC_LineScan() +{ + uint8_t i; + CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN; + + //Prime the next ADC capture cycle + TAOS_SI_HIGH; + for(i = 0; i<50; i++) { // 50 counts is ~120ns + } + TAOS_CLK_HIGH; + for(i = 0; i<50; i++) { + } + TAOS_SI_LOW; + + CurrentLineScanPixel = 0; + CurrentLineScanChannel = 0; + ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux + ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; +} + +void TFC_StartNextConvertion() +{ + if(ConvertionTasks&ADC_MASK_CAPTURE_POT_0) + { + TFC_StartADC_Pot0(); + ConvertionTasks ^= ADC_MASK_CAPTURE_POT_0; + return; + } + if(ConvertionTasks & ADC_MASK_CAPTURE_POT_1) + { + TFC_StartADC_Pot1(); + ConvertionTasks ^= ADC_MASK_CAPTURE_POT_1; + return; + } + if(ConvertionTasks & ADC_MASK_CAPTURE_BATTERY_LEVEL) + { + TFC_StartADC_Battery(); + ConvertionTasks ^= ADC_MASK_CAPTURE_BATTERY_LEVEL; + return; + } + if(ConvertionTasks & ADC_MASK_CAPTURE_MOTOR_CURRENT) + { + TFC_StartADC_MotACurrent(); + ConvertionTasks ^= ADC_MASK_CAPTURE_MOTOR_CURRENT; + return; + } + if(ConvertionTasks & ADC_MASK_CAPTURE_LINE_SCAN) + { + TFC_StartADC_LineScan(); + ConvertionTasks ^= ADC_MASK_CAPTURE_LINE_SCAN; + return; + } + CurrentADC_State = ADC_STATE_INIT; +} + +void TFC_StartDataAcquisition(uint8_t mask) +{ + ConvertionTasks = mask; + TFC_StartNextConvertion(); +} + extern "C" void ADC0_IRQHandler() { uint8_t Junk; @@ -776,54 +869,56 @@ break; case ADC_STATE_CAPTURE_POT_0: - PotADC_Value[0] = ADC0->R[0]; - ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux - ADC0->SC1[0] = TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK; - CurrentADC_State = ADC_STATE_CAPTURE_POT_1; - + TFC_StartNextConvertion(); + TFC_Pot0Ready++; break; case ADC_STATE_CAPTURE_POT_1: - PotADC_Value[1] = ADC0->R[0]; - ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux - ADC0->SC1[0] = TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK; - CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL; - + TFC_StartNextConvertion(); + TFC_Pot1Ready++; break; case ADC_STATE_CAPTURE_BATTERY_LEVEL: - BatSenseADC_Value = ADC0->R[0]; - - //Now we will start the sequence for the Linescan camera - - TAOS_CLK_HIGH; - - for(Junk = 0; Junk<50; Junk++) { - } + TFC_StartNextConvertion(); + TFC_BatteryVoltageReady++; + TFC_ConvertionReadyCallback.call(); + break; - TAOS_SI_LOW; - + case ADC_STATE_CAPTURE_MOTOR_A_CURRENT: + MotACurrentADC_Value = ADC0->R[0]; + TFC_StartADC_MotBCurrent(); + break; - CurrentLineScanPixel = 0; - CurrentLineScanChannel = 0; - CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN; - ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux - ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; - + case ADC_STATE_CAPTURE_MOTOR_B_CURRENT: + MotBCurrentADC_Value = ADC0->R[0]; + TFC_StartNextConvertion(); + TFC_MotorCurrentReady++; + TFC_ConvertionReadyCallback.call(); break; case ADC_STATE_CAPTURE_LINE_SCAN: - - if(CurrentLineScanPixel<128) { - if(CurrentLineScanChannel == 0) { + if(CurrentLineScanPixel<128) + { + LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0]; + ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; + CurrentLineScanPixel++; + + TAOS_CLK_LOW; + for(Junk = 0; Junk<50; Junk++) { + } + TAOS_CLK_HIGH; + + /* if(CurrentLineScanChannel == 0) // Pixel of camera 0 has been converted + { LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0]; ADC0->SC1[0] = TFC_LINESCAN1_ADC_CHANNEL | ADC_SC1_AIEN_MASK; CurrentLineScanChannel = 1; - - } else { + } + else // Pixel of camera 1 has been converted + { LineScanImage1WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0]; ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; CurrentLineScanChannel = 0; @@ -833,45 +928,40 @@ for(Junk = 0; Junk<50; Junk++) { } TAOS_CLK_HIGH; - - } - - } else { + }*/ + } + else + { // done with the capture sequence. we can wait for the PIT0 IRQ to restart - TAOS_CLK_HIGH; - for(Junk = 0; Junk<50; Junk++) { } - TAOS_CLK_LOW; - CurrentADC_State = ADC_STATE_INIT; + TFC_StartNextConvertion(); //swap the buffer - if(LineScanWorkingBuffer == 0) { LineScanWorkingBuffer = 1; LineScanImage0WorkingBuffer = &LineScanImage0Buffer[1][0]; - LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0]; + //LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0]; TFC_LineScanImage0 = &LineScanImage0Buffer[0][0]; - TFC_LineScanImage1 = &LineScanImage1Buffer[0][0]; + //TFC_LineScanImage1 = &LineScanImage1Buffer[0][0]; } else { LineScanWorkingBuffer = 0; LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0]; - LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0]; + //LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0]; TFC_LineScanImage0 = &LineScanImage0Buffer[1][0]; - TFC_LineScanImage1 = &LineScanImage1Buffer[1][0]; + //TFC_LineScanImage1 = &LineScanImage1Buffer[1][0]; } TFC_LineScanImageReady++; + TFC_ConvertionReadyCallback.call(); } - break; } - } void TFC_InitLineScanCamera() @@ -899,10 +989,6 @@ TFC_LineScanImage1 = &LineScanImage1Buffer[1][0]; } - - - - /** Initialized TPM0 to be used for generating PWM signals for the the dual drive motors. This method is called in the TFC constructor with a default value of 4000.0Hz * * @param SwitchingFrequency PWM Switching Frequency in floating point format. Pick something between 1000 and 9000. Maybe you can modulate it and make a tune. @@ -970,11 +1056,31 @@ else if(MotorB<-1.0) MotorB = -1.0; - TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0)); +/* TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0)); TPM0->CONTROLS[3].CnV = TPM0->CONTROLS[2].CnV; TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorB + 1.0)/2.0)); - TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV; + TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV;*/ + if(MotorA >= 0) + { + TPM0->CONTROLS[2].CnV = 0xffff; // recirculation by high side to have current measurement + TPM0->CONTROLS[3].CnV = (uint16_t) ((float)TPM0->MOD * (float)MotorA); // channel is inverted + } + else + { + TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)(1.0 + MotorA)); + TPM0->CONTROLS[3].CnV = 0; // recirculation by high side to have current measurement (channel is inverted) + } + if(MotorB >= 0) + { + TPM0->CONTROLS[0].CnV = 0xffff; // recirculation by high side to have current measurement + TPM0->CONTROLS[1].CnV = (uint16_t) ((float)TPM0->MOD * (float)MotorB); // channel is inverted + } + else + { + TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)(1.0 + MotorB)); + TPM0->CONTROLS[1].CnV = 0; // recirculation by high side to have current measurement (channel is inverted) + } } //Pot Reading is Scaled to return a value of -1.0 to 1.0 @@ -986,11 +1092,35 @@ return ((float)PotADC_Value[1]/-((float)ADC_MAX_CODE/2.0))+1.0; } +uint16_t TFC_ReadBatteryVoltageRaw() +{ + return BatSenseADC_Value; +} + +uint16_t TFC_ReadMotACurrentRaw() +{ + return MotACurrentADC_Value; +} + +uint16_t TFC_ReadMotBCurrentRaw() +{ + return MotBCurrentADC_Value; +} + float TFC_ReadBatteryVoltage() { - return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0); + return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 18.81);// * ((47000.0+10000.0)/10000.0*3.3) } +float TFC_ReadMotACurrent() +{ + return (((float)MotACurrentADC_Value/(float)(ADC_MAX_CODE)) * 5.625);// * 3.3 / 220 * 375 +} + +float TFC_ReadMotBCurrent() +{ + return (((float)MotBCurrentADC_Value/(float)(ADC_MAX_CODE)) * 5.625);// * 3.3 / 220 * 375 +} void TFC_SetBatteryLED_Level(uint8_t BattLevel) {
diff -r 24430a0d7fd8 -r 0c6d78c56091 TFC.h --- a/TFC.h Thu Feb 11 14:58:08 2016 +0000 +++ b/TFC.h Thu Jun 01 13:16:37 2017 +0000 @@ -85,6 +85,12 @@ #define TAOS_SI_HIGH PTD->PSOR = (1<<7) #define TAOS_SI_LOW PTD->PCOR = (1<<7) +#define ADC_MASK_CAPTURE_POT_0 1 +#define ADC_MASK_CAPTURE_POT_1 2 +#define ADC_MASK_CAPTURE_BATTERY_LEVEL 4 +#define ADC_MASK_CAPTURE_MOTOR_CURRENT 8 +#define ADC_MASK_CAPTURE_LINE_SCAN 16 +#define ADC_MASK_CAPTURE_ALL 31 /** @@ -211,13 +217,29 @@ */ float TFC_ReadPot(uint8_t Channel); + +uint16_t TFC_ReadBatteryVoltageRaw(); +uint16_t TFC_ReadMotACurrentRaw(); +uint16_t TFC_ReadMotBCurrentRaw(); + + /** Gets the current battery voltage * * @returns Battery voltage in floating point form. */ float TFC_ReadBatteryVoltage(); +/** Gets motor A current +* +* @returns Current value in amps in floating point form. +*/ +float TFC_ReadMotACurrent(); +/** Gets motor B current +* +* @returns Current value in amps in floating point form. +*/ +float TFC_ReadMotBCurrent(); /** Sets the Battery level indiciate * @@ -226,6 +248,16 @@ */ void TFC_SetBatteryLED_Level(uint8_t BattLevel); +/** Stop camera exposure +* +*/ +void TFC_StopCameraExposure(); + +/** Start ADC convertion of all analog inputs +* +* @param mask The mask of convertions to perform +*/ +void TFC_StartDataAcquisition(uint8_t mask); /** Pointer to two channels of line scan camera data. Each channel is 128 points of uint8_t's. Note that the underlying implementation is ping-pong buffer These pointers will point to the *inactive buffer. @@ -241,10 +273,12 @@ */ extern volatile uint8_t TFC_LineScanImageReady; - +extern volatile uint8_t TFC_Pot0Ready; +extern volatile uint8_t TFC_Pot1Ready; +extern volatile uint8_t TFC_BatteryVoltageReady; +extern volatile uint8_t TFC_MotorCurrentReady; - - +extern FunctionPointer TFC_ConvertionReadyCallback; /** @} */