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);
}