websterling 12 Posted June 3, 2012 Share Posted June 3, 2012 I'm trying to develop my current project entirely in Energia. Since Energia is still in development, I'm breaking the code down into chunks and making sure that things work as expected. The following code gets 3 values from the ADC (TEMPSENSOR and 2 analog inputs), divides each value by 4, and writes the resulting values out to the Serial Monitor. I can vary the voltage to the analog inputs with a potentiometer. This is using 0101E0006 on a 2553 on a Rev. 1.4 Launchpad with the crystal installed. #include #define CO_IN A4 //P1.4 #define RH_IN A5 //P1.5 uint32_t co_volts; uint32_t rh_volts; uint32_t temp_raw; uint8_t co_value; uint8_t rh_value; uint8_t temp; TimerSerial mySerial; void setup(){ mySerial.begin(); } void loop(){ analogReference(INTERNAL1V5); delay(100); //the delays are to make sure the references and the adc have settled temp_raw = analogRead(TEMPSENSOR); delay(100); temp = temp_raw/4; analogReference(INTERNAL2V5); delay(100); co_volts = analogRead(CO_IN); delay(100); co_value = co_volts/4; rh_volts = analogRead(RH_IN); delay(100); rh_value = rh_volts/4; mySerial.print("T: "); mySerial.print(temp, DEC); mySerial.print("\t"); mySerial.print("C: "); mySerial.print(co_value, DEC); mySerial.print("\t"); mySerial.print("R: "); mySerial.println(rh_value, DEC); } I can see the outputs vary as the pots are rotated. The output in the Serial Monitor is of the form- T: 244 C: 189 R: 0 The problem is that the output values are shifted. The printed value for T is actually the value for R; the value for C is actually T; and R is actually C. The code is fairly simple and I can't see anything wrong with it. Is there something I have overlooked/gotten wrong, or have I stumbled into another bug? Thanks, George Quote Link to post Share on other sites
websterling 12 Posted June 4, 2012 Author Share Posted June 4, 2012 Some additional information in case anyone is interested. If I change the code so that each analog Read() is called 2 times- for example: temp_raw = analogRead(TEMPSENSOR); delay(1000); temp_raw = analogRead(TEMPSENSOR); delay(1000); temp = temp_raw/4; The output is in the order expected. I edited the title of this thread to make it more indicative of what the problem is. Quote Link to post Share on other sites
Rickta59 589 Posted June 4, 2012 Share Posted June 4, 2012 I took a look at this problem and I'm seeing the same results as you. I tried changing the analogRead code so that instead of sleeping and waiting for the ADC interrupt, it just sits in a busy while loop. That seems to fix it. Sitting in a busy loop isn't a very power friendly solution though. If you want the gory details here is a patch: diff --git a/hardware/msp430/cores/msp430/wiring_analog.c b/hardware/msp430/cores/msp430/wiring_analog.cindex 1bb2539..0543aa9 100644--- a/hardware/msp430/cores/msp430/wiring_analog.c+++ b/hardware/msp430/cores/msp430/wiring_analog.c@@ -179,14 +179,22 @@ uint16_t analogRead(uint8_t pin) if(pin > 7 && pin != 10) // ADC on pin? return 0; ADC10CTL0 &= ~ENC; // disable ADC+#if 0 ADC10CTL0 = analog_reference + // set analog reference- ADC10ON + ADC10SHT_3 + ADC10IE; // turn ADC ON; sample + hold @ 64 bluehash and websterling 2 Quote Link to post Share on other sites
Rickta59 589 Posted June 4, 2012 Share Posted June 4, 2012 After conferring with Robert he thinks and I concur that the problem is probably that the watchdog isr is kicking off between the time the ADC capture starts and before it has completed. The watchdog timer reenables the CPU which causes the analogRead code to continue execution when it really isn't ready. The code below seems to work and is somewhat more power friendly. It uses a combination of sleeping and checking the ADC busy bit. uint16_t analogRead(uint8_t pin) { // make sure we have an ADC#if defined(__MSP430_HAS_ADC10__) // 0000 A0 // 0001 A1 // 0010 A2 // 0011 A3 // 0100 A4 // 0101 A5 // 0110 A6 // 0111 A7 // 1010 Internal temperature sensor //TODO: Only int. temp. sensor requires Tsample > 30us. // The below ADC configuration applies this rule to all channels right now. // ADC10CLK = 5MHz / 5 = 1Mhz // Tsample = S&H / ADC10CLK = 64 / 1 MHz = 64 us // Tconver = 13 / ADC10CLK = 13 / 1 MHz = 13 us // Total time per sample = Tconvert + Tsample = 64 + 13 = 67 us = ~15k samples / sec if (pin > 7 && pin != 10) // ADC on pin? return 0; ADC10CTL0 &= ~ENC; // disable ADC ADC10CTL0 = analog_reference | // set analog reference ADC10ON | ADC10SHT_3 | ADC10IE; // turn ADC ON; sample + hold @ 64 oscarl1718 and websterling 2 Quote Link to post Share on other sites
websterling 12 Posted June 4, 2012 Author Share Posted June 4, 2012 Thanks, rick! I patched wiring_analog.c and my code runs as expected. I wish I had the experience to go into the internals of Energia and contribute by fixing these things, but I don't. But I guess that he who finds bugs (and reports them) also contributes. Thanks, again, George Quote Link to post Share on other sites
Rickta59 589 Posted June 4, 2012 Share Posted June 4, 2012 I think it is just as important to find a bug as to fix it. Thanks for your efforts and keep it up! -rick Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.