This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

float variable to UART

Other Parts Discussed in Thread: MSP430G2553

Hello! I'm currently working on IAR and  Launchpad with MSP430G2553 microcontroller. The task is to read analog value from potentiometer, calculate type float variable, holding respective voltage value and transmit it to PC (using RealTerm) via UART module. Difficulties start, when i need to send that 4 bytes. I think that problem is defining union for float variable, but because of my lack of knowledge in deeper programming, if can't figure out how to make it work. Code is pretty straight forward - Timer interrupt occurs every 1sec, where ADC10 reads value from pot (with Vcc as V+ref), calculate voltage and send to PC. 

I would appreciate help from more experienced members.

Interrupt code below:

// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
  P1OUT ^= RED;								//Toggle RED led
  ADC10CTL0 |= ENC + ADC10SC;				//Enable conversion and start conversion. ADC10IFG=1 so conversion is loaded to ADC10MEM
  ADC_val = ADC10MEM;						//Assigns the value held in ADC10MEM to the float variable called ADC_val
  
  ADC_voltage = (3.55 * ADC_val)/1023.0;	//Calculation to represent ADC voltage. V+REF = Vcc = 3.55V. 
  volatile union							//Create union 
  {
    float ADC_voltage;
    struct 
    {
      char dataArray[4];
    } TXdata;
  };   
  UCA0TXBUF = TXdata.dataArray[0];		//Load float variable 1st byte into transmit buffer
  while  (!(IFG2&UCA0TXIFG));    			//Wait little bit for value to be sent
  
  UCA0TXBUF = TXdata.dataArray[1];		//Load float variable 2nd byte into transmit buffer
  while  (!(IFG2&UCA0TXIFG));    			//Wait little bit for value to be sent
  
  UCA0TXBUF = TXdata.dataArray[2];		//Load float variable 3rd byte into transmit buffer
  while  (!(IFG2&UCA0TXIFG));    			//Wait little bit for value to be sent
  
  UCA0TXBUF = TXdata.dataArray[3];		//Load float variable 4th byte into transmit buffer
  while  (!(IFG2&UCA0TXIFG));    			//Wait little bit for value to be sent
}

Values in terminal also isn't what would be expected: 

  • Must it be float?

    By the way: You should move the calculation and the transmission out of the ISR. If the timer interrupt fires, start a conversion and when the conversion ready interrupt fires, set a flag that is checked in the main for doing the calculation and start the transfer.

    And you have to wait for the conversion to be ready. You read the result directly after starting the conversion. When using the conversion ready interrupt, you will not have this problem. Or read the busy bit if you prefer polling.

  • Are there some suggestions how to send calculated variable without losing fractional part?

    Ok, i will remove as much as i can out of ISR. 

  • Floating point operations in addition with conversion to ASCII on such a small processor isn't the best idea. Your code size will reach the processor's flash size quite fast.

    If you only work with integers, you will produce less code size.

    For a voltage (as example) you can use the floating point value of 1.234V, but you could also write 1234mV, which is integer only. If you need more precision, go down to µV.

    You can convert the value to anything else on the PC that receives the data. It has much more processing power and memory than the small MSP430G2553.

    Dennis

  • Hi!

    Allright i used calculation for voltage like below, but i still didn't get values as expected:

    ADC_voltage = (3550 * ADC_val)/1023;	//Calculation to represent ADC voltage

    Variable ADC_voltage then must be type long to hold big enough number. Watching from PC i can only interpret data as mV, because i don't have possiblity to write program on PC for serial data viewing.

  • One of the values used in your calculation must be from 32 bit type, so the calculation is done with 32 bit.

    You can declare ADC_val as 32 bit, for example.

  • Thank You, using Your suggestion, i have managed to get voltage like 3550 mV on serial terminal, code snippet below.  I guess that is one alternative and easier than using float type data. But if i would need like all 4 bytes of variable ADC_voltage, how to use union not copy-paste principle to write in TX buffer? 

      ADC_val = ADC10MEM;		//Assigns the value held in ADC10MEM to the unsigned long variable called ADC_val
      
      ADC_voltage = (3550 * ADC_val)/1023;	//Calculation to represent ADC voltage
      
      ADC_voltage_1stBYTE = ADC_voltage;	  //Get ADC's voltages type long first byte
      ADC_voltage_2ndBYTE = ADC_voltage >> 8; //Get ADC's voltages type long second byte
     
      UCA0TXBUF = ADC_voltage_1stBYTE;	//Send LSB first	
      while  (!(IFG2&UCA0TXIFG));    	//Wait little bit for value to be sent	
      UCA0TXBUF = ADC_voltage_2ndBYTE;	//Send 2nd byte
      while  (!(IFG2&UCA0TXIFG));    	//Wait little bit for value to be sent

**Attention** This is a public forum