Hello!!
1. I have problems.
I don't understand why measurement was influenced on temperature in this ENERGIA example source(Cap Touch Raw)
So, I want to measure capacitance without temperature.
-------------------------------------------------------------------------------------------------------------------------------------
#include <CapTouch.h>
#define PROXIMITY_SENSOR P2_0
#define MIDDLE_LED P1_0
/* Create a CapTouch instance for the proximity sensor */
CapTouch proximity = CapTouch(PROXIMITY_SENSOR, TOUCH_PROXIMITY);
uint16_t measured, base;
/* Delta can be negative */
int16_t delta;
uint8_t state;
void setup() {
/* Use middle LED as proximity indicator */
pinMode(MIDDLE_LED, OUTPUT);
/* Set the proximity threshold to 100 to increase range */
proximity.setThreshold(100);
Serial.begin(9600);
}
void loop() {
state = proximity.isTouched();
digitalWrite(MIDDLE_LED, state);
measured = proximity.getMeasured();
base = proximity.getBaseline();
delta = proximity.getDelta();
Serial.print("State: ");
Serial.print(state);
Serial.print("\tBase: ");
Serial.print(base);
Serial.print("\tMeasured: ");
Serial.print(measured);
Serial.print("\tDelta: ");
Serial.println(delta);
}
-----------------------------------------------------------------------------------------------------------------------------------------------
2. And Following source is that edited CCS example source. This isn't influenced on temperature.
What's different?
-----------------------------------------------------------------------------------------------------------------------------------------------
#include <msp430.h>
#include <stdio.h>
/* Define User Configuration values */
/*----------------------------------*/
/* Defines WDT SMCLK interval for sensor measurements*/
#define WDT_meas_setting (DIV_SMCLK_512)
/* Defines WDT ACLK interval for delay between measurement cycles*/
#define WDT_delay_setting (DIV_ACLK_512)
/*Set to ~ half the max delta expected*/
/* Definitions for use with the WDT settings*/
#define DIV_ACLK_512 (WDT_ADLY_16) // ACLK/512 --Auxiliary Clock(see basic clock module)
#define DIV_SMCLK_512 (WDT_MDLY_0_5) // SMCLK/512 --Sub-System Master (Clock See Basic Clock Module)
#define LED_1 (0x01) // P1.0 LED output
#define LED_2 (0x40) // P1.6 LED output
// Global variables for sensing
unsigned int base_cnt, meas_cnt; //set int base_cnt,int meas_cnt
char buffer[32]; //set char buffer
long temp; //set long IntDegF
long IntDegC; //set long IntDegC
volatile unsigned int timer_count=0;
/* System Routines*/
void measure_count(void); // Measures each capacitive sensor
void pulse_LED(void); // LED gradient routine
void init_uart(void);
void init_timer();
void init_adc();
void start_conversion();
/* Main Function*/
int main(void)
{
unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz (Basic Clock System Control 1)
DCOCTL = CALDCO_1MHZ; // DCOCTL Calibration Data for 1MHz
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO (Basic Clock System Control 3)
IE1 |= WDTIE; // enable IE1 to WDT interrupt
P2SEL = 0x00; // port2 selection, No XTAL
P1DIR = LED_1 + LED_2; // P1.0 & P1.6 = LEDs (Port 1 Direction)
P1OUT = 0x00; // Port 1 output set 0
__bis_SR_register(GIE); // set GIE Register, Enable interrupts
measure_count(); // Establish baseline capacitance
base_cnt = meas_cnt; // count start?
for(i=30; i>0; i--) // Repeat and avg base measurement
{
measure_count(); // count start,
base_cnt = (meas_cnt+base_cnt)/2;
}
/* Main loop starts here*/
while (1)
{
measure_count(); // Measure all sensors
/* Delay to next sample, sample more slowly if no keys are pressed*/
WDTCTL = WDT_delay_setting; // WDT, ACLK, interval timer
/* Handle baseline measurment for a base C increase*/
// if no keys are touched
base_cnt = base_cnt - 1; // Adjust baseline down, should be
// slow to accomodate for genuine
pulse_LED(); // changes in sensor C
init_uart();
init_timer();
init_adc();
// enable interrupts and put the CPU to sleep
_bis_SR_register(GIE+LPM0_bits); //set GIE
}
} // End Main
/* Measure count result (capacitance) of each sensor*/
/* Routine setup for four sensors, not dependent on NUM_SEN value!*/
void measure_count(void)
{
TA0CTL = TASSEL_3+MC_2; // TACLK, cont mode
TA0CCTL1 = CM_3+CCIS_2+CAP; // Pos&Neg,GND,Cap
/*Configure Ports for relaxation oscillator*/
/*The P2SEL2 register allows Timer_A to receive it's clock from a GPIO*/
/*See the Application Information section of the device datasheet for info*/
P2DIR &= ~ BIT5; // P2.5 is the input used here
P2SEL &= ~ BIT5;
P2SEL2 |= BIT5;
/*Setup Gate Timer*/
WDTCTL = WDT_meas_setting; // WDT, ACLK, interval timer
TA0CTL |= TACLR; // Clear Timer_A TAR
__bis_SR_register(LPM0_bits+GIE); // Wait for WDT interrupt
TA0CCTL1 ^= CCIS0; // Create SW capture of CCR1
meas_cnt = TACCR1; // Save result
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P2SEL2 &= ~BIT5;
__delay_cycles(100000);
}
void pulse_LED(void)
{
P1OUT ^= LED_1 + LED_2;
}
void init_uart(void){
P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2 = TXD
P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2 = TXD
UCA0CTL1|=UCSSEL_2; // SMCLK
UCA0BR0 = 104; // see baud rate divider above
UCA0BR1 = 0;
UCA0MCTL = UCBRS0; // modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // ** initialize USCI state machine **
IE2 |= UCA0TXIE; // Enable USCI_A0 TX interrupt
}
void init_timer() {
TA0CTL |= TACLR; // reset timer
TA0CTL = TASSEL_2 // SMCLK
+ID_0 // input divider = 1
+MC_2; // continuous mode, interrupt disabled
TA0CCTL0 = OUTMOD_2 // compare mode
+CCIE // interrupt enabled
+CCIFG;
}
void init_adc(){
// :NOTE: On-board heat sensor is used.
ADC10CTL1 = INCH_10 // temperature sensor input to ADC
+SHS_0 // use ADC10SC bit to trigger sampling
+ADC10DIV_3 // clock divider = 4
+ADC10SSEL_3 // clock source = SMCLK
+CONSEQ_0; // single channel, single conversion
ADC10DTC1 = 1; // one block per transfer
ADC10CTL0 = SREF_1 // reference voltages are Vss and Vcc
+ADC10SHT_3 // 64 ADC10 clocks for sample and hold time (slowest)
+REFON // reference generator on
+ADC10ON // turn on ADC10
+ENC; // enable (but not yet start) conversions
}
void start_conversion()
{
if ((ADC10CTL1 & ADC10BUSY) == 0){ // if not already converting
P1OUT ^= 0x40;
ADC10CTL0 |= ADC10SC;
//ADC10SA = (unsigned) & latest_adc_result;
temp = ADC10MEM;
IntDegC = ((270664L*temp)-181698560L)>>16;
//IntDegC = ((temp - 673) * 4225) / 1024;
}
}
/* Watchdog Timer interrupt service routine*/
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
TA0CCTL1 ^= CCIS0; // Create SW capture of CCR1
// IE2 |= UCA0TXIE;
__bic_SR_register_on_exit(LPM3_bits); // Exit LPM3 on reti
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer0_A0(void) {
//timer_count++;
//if (timer_count > 32) {
//timer_count = 0;
start_conversion();
//IE2 |= UCA0TXIE;
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void){
P1OUT |= 0x01;
unsigned int i = 0; // iterator pointers
sprintf(buffer,"count :" "%d, %d \n\r", (unsigned int)(meas_cnt), (long)(IntDegC/10));
while(buffer[i] != '\0'){
while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = buffer[i++];
__delay_cycles(10);
}
buffer[i++] ^=0;
P1OUT &= ~0x01;
IE2 &= ~UCA0TXIFG;
}
---------------------------------------------------------------------------------------------------------------------------------------
3. Especially, what is difference in this source of bold
One is edited CCS file and the other is .cpp file linked on ENERGIA example.
Both are measuring capacitance but, CCS is stable and ENERGIA is unstable and influence on temperature.
-------------------------------------------------------------------------------------------------------------------------------------------
#include <msp430.h>
#include <stdio.h>
/* Define User Configuration values */
/*----------------------------------*/
/* Defines WDT SMCLK interval for sensor measurements*/
#define WDT_meas_setting (DIV_SMCLK_512)
/* Defines WDT ACLK interval for delay between measurement cycles*/
#define WDT_delay_setting (DIV_ACLK_512)
/*Set to ~ half the max delta expected*/
/* Definitions for use with the WDT settings*/
#define DIV_ACLK_512 (WDT_ADLY_16) // ACLK/512 --Auxiliary Clock(see basic clock module)
#define DIV_SMCLK_512 (WDT_MDLY_0_5) // SMCLK/512 --Sub-System Master (Clock See Basic Clock Module)
#define LED_1 (0x01) // P1.0 LED output
#define LED_2 (0x40) // P1.6 LED output
// Global variables for sensing
unsigned int base_cnt, meas_cnt; //set int base_cnt,int meas_cnt
char buffer[32]; //set char buffer
long temp; //set long IntDegF
long IntDegC; //set long IntDegC
volatile unsigned int timer_count=0;
/* System Routines*/
void measure_count(void); // Measures each capacitive sensor
void pulse_LED(void); // LED gradient routine
void init_uart(void);
void init_timer();
void init_adc();
void start_conversion();
/* Main Function*/
int main(void)
{
unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz (Basic Clock System Control 1)
DCOCTL = CALDCO_1MHZ; // DCOCTL Calibration Data for 1MHz
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO (Basic Clock System Control 3)
IE1 |= WDTIE; // enable IE1 to WDT interrupt
P2SEL = 0x00; // port2 selection, No XTAL
P1DIR = LED_1 + LED_2; // P1.0 & P1.6 = LEDs (Port 1 Direction)
P1OUT = 0x00; // Port 1 output set 0
__bis_SR_register(GIE); // set GIE Register, Enable interrupts
measure_count(); // Establish baseline capacitance
base_cnt = meas_cnt; // count start?
for(i=30; i>0; i--) // Repeat and avg base measurement
{
measure_count(); // count start,
base_cnt = (meas_cnt+base_cnt)/2;
}
/* Main loop starts here*/
while (1)
{
measure_count(); // Measure all sensors
/* Delay to next sample, sample more slowly if no keys are pressed*/
WDTCTL = WDT_delay_setting; // WDT, ACLK, interval timer
/* Handle baseline measurment for a base C increase*/
// if no keys are touched
base_cnt = base_cnt - 1; // Adjust baseline down, should be
// slow to accomodate for genuine
pulse_LED(); // changes in sensor C
init_uart();
init_timer();
init_adc();
// enable interrupts and put the CPU to sleep
_bis_SR_register(GIE+LPM0_bits); //set GIE
}
} // End Main
/* Measure count result (capacitance) of each sensor*/
/* Routine setup for four sensors, not dependent on NUM_SEN value!*/
void measure_count(void)
{
TA0CTL = TASSEL_3+MC_2; // TACLK, cont mode
TA0CCTL1 = CM_3+CCIS_2+CAP; // Pos&Neg,GND,Cap
/*Configure Ports for relaxation oscillator*/
/*The P2SEL2 register allows Timer_A to receive it's clock from a GPIO*/
/*See the Application Information section of the device datasheet for info*/
P2DIR &= ~ BIT5; // P2.5 is the input used here
P2SEL &= ~ BIT5;
P2SEL2 |= BIT5;
/*Setup Gate Timer*/
WDTCTL = WDT_meas_setting; // WDT, ACLK, interval timer
TA0CTL |= TACLR; // Clear Timer_A TAR
__bis_SR_register(LPM0_bits+GIE); // Wait for WDT interrupt
TA0CCTL1 ^= CCIS0; // Create SW capture of CCR1
meas_cnt = TACCR1; // Save result
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P2SEL2 &= ~BIT5;
__delay_cycles(100000);
}
void pulse_LED(void)
{
P1OUT ^= LED_1 + LED_2;
}
void init_uart(void){
P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2 = TXD
P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2 = TXD
UCA0CTL1|=UCSSEL_2; // SMCLK
UCA0BR0 = 104; // see baud rate divider above
UCA0BR1 = 0;
UCA0MCTL = UCBRS0; // modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // ** initialize USCI state machine **
IE2 |= UCA0TXIE; // Enable USCI_A0 TX interrupt
}
void init_timer() {
TA0CTL |= TACLR; // reset timer
TA0CTL = TASSEL_2 // SMCLK
+ID_0 // input divider = 1
+MC_2; // continuous mode, interrupt disabled
TA0CCTL0 = OUTMOD_2 // compare mode
+CCIE // interrupt enabled
+CCIFG;
}
void init_adc(){
// :NOTE: On-board heat sensor is used.
ADC10CTL1 = INCH_10 // temperature sensor input to ADC
+SHS_0 // use ADC10SC bit to trigger sampling
+ADC10DIV_3 // clock divider = 4
+ADC10SSEL_3 // clock source = SMCLK
+CONSEQ_0; // single channel, single conversion
ADC10DTC1 = 1; // one block per transfer
ADC10CTL0 = SREF_1 // reference voltages are Vss and Vcc
+ADC10SHT_3 // 64 ADC10 clocks for sample and hold time (slowest)
+REFON // reference generator on
+ADC10ON // turn on ADC10
+ENC; // enable (but not yet start) conversions
}
void start_conversion()
{
if ((ADC10CTL1 & ADC10BUSY) == 0){ // if not already converting
P1OUT ^= 0x40;
ADC10CTL0 |= ADC10SC;
//ADC10SA = (unsigned) & latest_adc_result;
temp = ADC10MEM;
IntDegC = ((270664L*temp)-181698560L)>>16;
//IntDegC = ((temp - 673) * 4225) / 1024;
}
}
/* Watchdog Timer interrupt service routine*/
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
TA0CCTL1 ^= CCIS0; // Create SW capture of CCR1
// IE2 |= UCA0TXIE;
__bic_SR_register_on_exit(LPM3_bits); // Exit LPM3 on reti
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer0_A0(void) {
//timer_count++;
//if (timer_count > 32) {
//timer_count = 0;
start_conversion();
//IE2 |= UCA0TXIE;
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void){
P1OUT |= 0x01;
unsigned int i = 0; // iterator pointers
sprintf(buffer,"count :" "%d, %d \n\r", (unsigned int)(meas_cnt), (long)(IntDegC/10));
while(buffer[i] != '\0'){
while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = buffer[i++];
__delay_cycles(10);
}
buffer[i++] ^=0;
P1OUT &= ~0x01;
IE2 &= ~UCA0TXIFG;
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------
#include "Energia.h"
#include "CapTouch.h"
CapTouch::CapTouch(uint8_t pin, uint8_t sensorType)
{
/* Find out if the pin is on a port we know of */
uint8_t port = digitalPinToPort(pin);
/* Not a port we know of */
if (port == NOT_A_PORT) return;
/* Get the port function select 2 register address */
sel2 = portSel2Register(port);
/* If there is no sel2 register then this port does not have PIN OSC */
if (sel2 == NOT_A_PORT) return;
/* Get the bit mask for this pin */
bit = digitalPinToBitMask(pin);
/* Get the port function select register address */
sel = portSelRegister(port);
type = sensorType;
/* Set initial threshold */
threshold = 250;
}
void CapTouch::setThreshold(uint16_t sensorThreshold)
{
threshold = sensorThreshold;
}
void CapTouch::setBaseLine() {
/* Set initial base line */
base = measure();
base = (base + measure()) / 2;
base = (base + measure()) / 2;
base = (base + measure()) / 2;
}
uint16_t CapTouch::getBaseline()
{
if(base == 0)
setBaseLine();
return base;
}
uint16_t CapTouch::getMeasured()
{
return measured;
}
int16_t CapTouch::getDelta()
{
return delta;
}
uint8_t CapTouch::isTouched() {
if(base == 0)
setBaseLine();
measured = measure();
delta = base - measured;
if(delta < 0) {
base = (base / 2) + (measured / 2);
}
if(delta < (int16_t) threshold) {
base--;
return 0;
}
return 1;
}
uint16_t CapTouch::measure()
{
uint8_t SelSave, Sel2Save;
uint16_t WDTCTLSave;
uint16_t TA0CTLSave, TA0CCTL1Save, TA0CCR1Save;
uint16_t delta_count;
int16_t ret_val;
/* TODO:
* The following delay is a work around for the CapTouch code
* not behaving when following a Serial.print call */
delay(1);
/* Save context */
WDTCTLSave = WDTCTL;
WDTCTLSave &= 0x00FF;
WDTCTLSave |= WDTPW;
TA0CTLSave = TA0CTL;
TA0CCTL1Save = TA0CCTL1;
TA0CCR1Save = TA0CCR1;
SelSave = *sel;
Sel2Save = *sel2;
/* Set bit in pin function select register to select PIN OSC */
*sel2 |= bit;
*sel &= bit;
/* TA0 in continous mode and clock source as INCLK.
* INCLK comes from the PIN OSC cricuit. See PIN OSC clock tree
* in section "Pin Oscillator" of Users Guide.
* Pins without external load show typical oscillation frequencies of 1 MHz to 3 MHz. */
TA0CTL = TASSEL_3 + MC_2;
/* Capture mode, capture on rising and falling edge, input as GND
* Later on we will XOR with CCIS0 to induce a s/w capture. */
TA0CCTL1 = CM_3 + CCIS_2 + CAP;
/* Enable Watchdog interrupt */
IE1 |= WDTIE;
/* Interval mode + ACLK + /512 for hires and /64 for lowres */
if(type == TOUCH_PROXIMITY) {
BCSCTL1 |= DIVA_1;
WDTCTL = (WDTPW + WDTTMSEL + GATE_WDT_ACLK + WDT_GATE_512);
} else {
WDTCTL = (WDTPW + WDTTMSEL + GATE_WDT_ACLK + WDT_GATE_64);
}
/* Clear Timer_A TAR */
TA0CTL |= TACLR;
/* Wait for WDT interrupt in LPM3 and global interrupts enables */
if(type == TOUCH_PROXIMITY) {
__bis_status_register(LPM0_bits + GIE);
BCSCTL1 &= ~DIVA_1;
} else {
__bis_status_register(LPM3_bits + GIE);
}
/* Capture initiated by Software .
* Worse case count = min PIN OSC Freq / ACLK / WDT gate time
* = for hires -> 1 MHz / (12 KHz / 512) = 42666
* = for regular -> 1 MHz / (12 KHz / 64 ) = 5333
* In this configuration a hires measurement takes ~43 ms and a lowres measurement takes ~5 ms */
TA0CCTL1 ^= CCIS0;
measured = TA0CCR1;
/* Stop watchdog timer */
WDTCTL = WDTPW + WDTHOLD;
/* Restore context */
*sel = SelSave;
*sel2 = Sel2Save;
WDTCTL = WDTCTLSave;
TA0CTL = TA0CTLSave;
TA0CCTL1 = TA0CCTL1Save;
TA0CCR1 = TA0CCR1Save;
return measured;
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------