Not sure what I am doing wrong. But I am not reading the internal temperature correctly.
I am using the 2.5V internal reference and the ADC value I get is 1374.
Looking at the Device Descriptors and
adc_ref15_30_temp 2051
adc_ref15_85_temp 2435
adc_ref20_30_temp 1547
adc_ref20_85_temp 1837
adc_ref25_30_temp 1230
adc_ref25_85_temp 1458
At first glance the measurement seems wrong because it is between 30 and 85 degrees. That can not be right because it feels cool to the touch. So I would guess it is closer to 23-25C.
Doing the math
Temp = (ADC - CAL_ADC_T30) * (((85 - 30) / (CAL_ADC_T85 - CAL_ADC_T30)) + 30
Temp = (1374 - 1230) * (((55 / (1458 - 1230)) + 30 = 64.73 degrees C.
That cannot be right. I would be very hot to touch.
My first thought was the internal reference was wrong, or not set up correctly. But I am measuring the 3.3V with the same reference using the built-in voltage divider (Channel 11) and it works as expected.
I am reading a sequence off ADC values with one start one time. I am reading , Channels 0, 1, 2, 3, 4, 5 6, 10, and 11. Channels 0-6 use the external reference (3.3V) and 10 and 11 use the internal 2.5V reference. Channels 2, 3, 4, and 11 seem to be working perfectly. Channels 0 and 1, are current measurements and I have not started testing the,, and channels 5 and 6 are temperature sensors which I have not calibrated. And that leaves 10 which I thought would be easy to test with no messing with the HW.
I read the ADC every millisecond. I accumulate 8 samples, then flag a routine to process the ADC values outside the interrupt.
So the ADC interrupt reads the data and moves it to a results array.
The Timer A0 interrupts every millisecond, takes the data from the results array and adds it to an accumulator array, and starts the next ADC sequence. A counter is incremented.
When the counter reaches 8 the accumulator values are moved to new locations, the accumulators and counter to 8 are cleared, and a flag to indicate data is ready is set.
Seems to be O.K. Except for the value received. Any ideas what I am doing wrong?
static const ADC12_A_configureMemoryParam cCH_I = {ADC12_A_MEMORY_0, ADC12_A_INPUT_A0, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cDCH_I ={ADC12_A_MEMORY_1, ADC12_A_INPUT_A1, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cCH_M2 = {ADC12_A_MEMORY_2, ADC12_A_INPUT_A2, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cCH_M1 = {ADC12_A_MEMORY_3, ADC12_A_INPUT_A3, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cPK_M = {ADC12_A_MEMORY_4, ADC12_A_INPUT_A4, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cTS_4 = {ADC12_A_MEMORY_5, ADC12_A_INPUT_A5, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cTS_5 = {ADC12_A_MEMORY_6, ADC12_A_INPUT_A6, ADC12_A_VREFPOS_AVCC, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cTS_Ch = {ADC12_A_MEMORY_7, ADC12_A_INPUT_TEMPSENSOR, // 10 ADC12_A_VREFPOS_INT, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cV3_3 = {ADC12_A_MEMORY_8, ADC12_A_INPUT_BATTERYMONITOR, //11 ADC12_A_VREFPOS_INT, ADC12_A_VREFNEG_AVSS, ADC12_A_ENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cTS_Sleep = {ADC12_A_MEMORY_10, ADC12_A_INPUT_TEMPSENSOR, ADC12_A_VREFPOS_INT, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; static const ADC12_A_configureMemoryParam cV_cal = {ADC12_A_MEMORY_11, ADC12_A_INPUT_BATTERYMONITOR, // 11 ADC12_A_VREFPOS_INT, ADC12_A_VREFNEG_AVSS, ADC12_A_NOTENDOFSEQUENCE}; void ADC_Configuration(void) { // initialize data ADC_Data[0] = 0; ADC_Data[1] = 0; ADC_Data[2] = 0; ADC_Data[3] = 0; ADC_Data[4] = 0; ADC_Data[5] = 0; ADC_Data[6] = 0; ADC_Data[7] = 0; ADC_Data[8] = 0; ADC_Data_Counter = 0; // Make sure HW is set right P6SEL = 0x7F; // Enable A/D channel inputs ADC12_A_disableConversions(ADC12_A_BASE,true); ADC12_A_disable(ADC12_A_BASE); // Disable while we configure it. // Initialize the reference to 2.5V Ref_setReferenceVoltage(REF_BASE, REF_VREF2_5V); // Enable chip temperature sensor Ref_enableTempSensor(REF_BASE); REFCTL0 |= 1; // Force it on to see if it is different. //Initialize the ADC12_A Module /* * Base Address of ADC12_A Module * Use internal ADC12_A bit as sample/hold signal to start conversion * USE MCLK as clock source * Use default clock divider of 1 */ ADC12_A_init(ADC12_A_BASE, ADC12_A_SAMPLEHOLDSOURCE_SC, ADC12_A_CLOCKSOURCE_ADC12OSC, ADC12_A_CLOCKDIVIDER_1); // 12-bits ADC12_A_setResolution(ADC12_A_BASE,ADC12_A_RESOLUTION_12BIT); /* * Base Address of ADC12_A Module * For memory buffers 0-7 sample/hold for 768 clock cycles * For memory buffers 8-15 sample/hold for 4 clock cycles (default) * Disable Multiple Sampling * Right now I am thinking we will measure everything including the chip * temperature and the 3.3V rail to see how it changes during operation. * * Note: ADC12_A may have a minimum sample rate of 30us or 100us. * This example uses a sample time of ~154us to ensure it works. * 256 cycles (51.2us) or 512 cycles (100.4us) may be used, but * resulting readings may be less accurate. * * Sampling time is > (Rs + 1800 Ohms) * ln(2^(n+1) * 25 pF + 800 ns * * For Charge_mon1 and Charge_mon2 and pack+mon that means 2.005 uS. with maximum * 5.4 MHz 4 clocks are .74 us too small, or 8 clocks is 1.48 us too small, * 16 is 2.96 us which is enough. * So we could do 337 samples in 1 ms. * 32 is 5.9 us which is about 168 in 1 us. * 64 is 11us which is about 84 in 1us best case 0r worst case at 4.2 MHz * is 15.23 us which is about 65 samples in 1 ms. It gives us lots of margin * for the data to settle and for the ADC to complete the operations in plenty * of time for the 1 ms timer interrupt to process it. */ ADC12_A_setupSamplingTimer(ADC12_A_BASE, ADC12_A_CYCLEHOLD_64_CYCLES, // Low 0-7 Memory ADC12_A_CYCLEHOLD_64_CYCLES, // high 8-15 Memory ADC12_A_MULTIPLESAMPLESENABLE); // O.K. ADC12_A_enableReferenceBurst(ADC12_A_BASE); //Configure Memory Buffer /* * Base Addres of ADC12_A Module * Configure memory buffer 0 * Map temp sensor to memory buffer 0 * Vref+ = Vref+ (int) 2.5V * Vref- = AVss * Memory buffer 0 is not the end of a sequence */ ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_I); // 0x00 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cDCH_I); // 0x01 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_M2); // 0x02 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_M1); // 0x03 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cPK_M); // 0x04 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_4); // 0x05 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_5); // 0x06 ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_Ch); // 0x1A ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cV3_3); // 0x9B // This interrupt is used by SLEEP State Do not want it active in this mode ADC12_A_disableInterrupt(ADC12_A_BASE, ADC12IFG10); ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG8); ADC12_A_enableInterrupt(ADC12_A_BASE, ADC12IE8); ADC12_A_enable(ADC12_A_BASE); ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_0,ADC12_A_SEQOFCHANNELS); } #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) { uint16_t temp = ADC12IV; add_trace_buf(105); __no_operation(); switch(__even_in_range(ADC12IV,34)) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC overflow case 4: break; // Vector 4: ADC timing overflow //case 6: break; // Vector 6: ADC12IFG0 case 6: //Vector 6: ADC12IFG0 //Move results, IFG is cleared //temperature_sensor_ADC = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_0); //Exit active CPU //__bic_SR_register_on_exit(LPM3_bits); break; case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: // Vector 12: ADC12IFG3 not used? results[0] = ADC12MEM0; // Move results, IFG is cleared results[1] = ADC12MEM1; // Move results, IFG is cleared results[2] = ADC12MEM2; // Move results, IFG is cleared results[3] = ADC12MEM3; // Move results, IFG is cleared break; // LPM0_EXIT; // Exit active CPU, SET BREAKPOINT HERE case 14: break; // Vector 14: ADC12IFG4 case 16: // Vector 16: ADC12IFG5 // Not used? results[0] = ADC12MEM0; // Move results, IFG is cleared results[1] = ADC12MEM1; // Move results, IFG is cleared results[2] = ADC12MEM2; // Move results, IFG is cleared results[3] = ADC12MEM3; // Move results, IFG is cleared results[4] = ADC12MEM4; // Move results, IFG is cleared results[5] = ADC12MEM5; // Move results, IFG is cleared // P1OUT ^= BIT2; case 18: // Vector 18: ADC12IFG6 Not used? results[0] = ADC12MEM0; // Move results, IFG is cleared results[1] = ADC12MEM1; // Move results, IFG is cleared results[2] = ADC12MEM2; // Move results, IFG is cleared results[3] = ADC12MEM3; // Move results, IFG is cleared results[4] = ADC12MEM4; // Move results, IFG is cleared results[5] = ADC12MEM5; // Move results, IFG is cleared results[6] = ADC12MEM6; // Move results, IFG is cleared LED1_Off; break; case 20: break; // Vector 20: ADC12IFG7 case 22: // Vector 22: ADC12IFG8 // this is cirrent interrupt for all states but Sleep. adc_data_ready = true; // for checking ADC_interrupt_counter++; // for debugging results[0] = ADC12MEM0; // Move results, IFG is cleared results[1] = ADC12MEM1; // Move results, IFG is cleared results[2] = ADC12MEM2; // Move results, IFG is cleared results[3] = ADC12MEM3; // Move results, IFG is cleared results[4] = ADC12MEM4; // Move results, IFG is cleared results[5] = ADC12MEM5; // Move results, IFG is cleared results[6] = ADC12MEM6; // Move results, IFG is cleared results[7] = ADC12MEM7; // Move results, IFG is cleared results[8] = ADC12MEM8; // Move results, IFG is cleared break; case 24: break; // Vector 24: ADC12IFG9 case 26: // Vector 26: ADC12IFG10 // This is interrupt for Sleep State add_trace_buf(99); temperature_sensor_ADC = ADC12MEM10; // we do this only in sleep mode. We have not gotten to LPM3 mode // when this interrupt fires. break; case 28: // Vector 28: ADC12IFG11 add_trace_buf(98); // Used in calibration of V3_3. { uint16_t x; // to fix compiler warning about order of volatile evaluation x = ADC12MEM10; AVcc_ADC[AVcc_ADC_count] = x; } AVcc_ADC_count++; break; case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } } // Since Timer A0 and the ADC interrupt are so closely tied together I will // put them in the same file. Normally they would be separate //------------------------------------------------------------------------------ // This interrupt executes every millisecond. // Timer A0 interrupt service routine #pragma vector=TIMER0_A0_VECTOR __interrupt void TIMER0_A0_ISR(void) { //add_trace_buf(101); LED1_ON; ADC_Data[0] += results[0]; // Move results, IFG is cleared ADC_Data[1] += results[1]; // Move results, IFG is cleared ADC_Data[2] += results[2]; // Move results, IFG is cleared ADC_Data[3] += results[3]; // Move results, IFG is cleared ADC_Data[4] += results[4]; // Move results, IFG is cleared ADC_Data[5] += results[5]; // Move results, IFG is cleared ADC_Data[6] += results[6]; // Move results, IFG is cleared ADC_Data[7] += results[7]; // Move results, IFG is cleared ADC_Data[8] += results[8]; // Move results, IFG is cleared // When ADC12SC triggers a sequence, successive sequences can be triggered by // the ADC12SC bit. The ADC12SC must be cleared by software after each sequence // to trigger another sequence. When any other trigger source is used, ADC12ENC // must be toggled between each sequence. // Do we need to turn off and on? Or do we just need to bring ADC12SC low? ADC12CTL0 &= ~ADC12MSC; // Turn off ADC12 ADC12CTL0 |= ADC12MSC; // Turn on ADC12 ADC12CTL0 &= ~ADC12SC; ADC12CTL0 |= ADC12SC; // Start convn - software trigger Conversion time 580uS Timer_interrupt_counter++; // For Debugging to see if we ever lose sequence. ADC_Data_Counter++; if (adc_data_ready == false) data_not_ready_error_count++; // Should never happen. For debugging adc_data_ready = false; if(ADC_Data_Counter == 8) // Averages 8 reads { adc_chg_current8 = ADC_Data[0]; // Start integrating a version that uses all the bits. adc_dsch_current8 = ADC_Data[1]; adc_charge_mon28 = ADC_Data[2]; adc_charge_mon18 = ADC_Data[3]; adc_packv8 = ADC_Data[4]; adc_ts48 = ADC_Data[5]; adc_ts58 = ADC_Data[6]; adc_tschip8 = ADC_Data[7]; adc_v3_38 = ADC_Data[8]; adc_new_data_available = true; ADC_Data_Counter = 0; ADC_Data[0] = 0; ADC_Data[1] = 0; ADC_Data[2] = 0; ADC_Data[3] = 0; ADC_Data[4] = 0; ADC_Data[5] = 0; ADC_Data[6] = 0; ADC_Data[7] = 0; ADC_Data[8] = 0; ADC_Sample_Counter++; } // Other timing functions based on 1 ms. if(Time_mS_counter != 0) Time_mS_counter--; // used for 1ms delay function if(bq34_CE_Read_ENABLE > 0) bq34_CE_Read_ENABLE--; // used at power up and coming out of sleep if(bq769x_Read_ENABLE > 0) bq769x_Read_ENABLE--; // used at power up and coming out of sleep if(System_Ready > 0) System_Ready--; // used at power up and coming out of sleep if(Time_to_Read_Data_Counter_mS != 0) Time_to_Read_Data_Counter_mS--; else { Time_to_Read_Data_Counter_mS = 333; { si.Ready_Flags.TTRD = true; //Time_to_Read_Data = TRUE; LPM3_EXIT; } } LED1_Off;// 100us } void init_REF_calvalues(void) { TLV_getInfo(TLV_TAG_REFCAL, 0, &bREFCAL_bytes, (uint16_t **)&pREFCAL); } // Put Ref in known state void Ref_Init(void) { // Must do this before setting up the ADC. ADC12_A_disable(ADC12_A_BASE); ADC12_A_disable(ADC12_A_BASE); ADC12_A_clearInterrupt(ADC12_A_BASE,0xFF); //DAC12_A_disable(ADC12_A_BASE,DAC12_A_SUBMODULE_1); Ref_disableReferenceVoltage(REF_BASE); while (Ref_isRefGenBusy(REF_BASE)); Ref_setReferenceVoltage(REF_BASE,REF_VREF2_5V); Ref_disableTempSensor(REF_BASE); Ref_disableReferenceVoltageOutput(REF_BASE); Ref_disableReferenceVoltage(REF_BASE); }