code to convert ADC value to hex?

MrChips

Joined Oct 2, 2009
30,824
I haven't done the code for these yet, so can't really show them. It's a task I need to prove that I can do, but i'm not sure and understand how to do it.
I am not asking you to show code. What I am asking for is the big picture.
Draw a picture of what is connected to what, physically.

Without seeing the big picture we are going to be playing the game of 101 Q & A.
 

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
well, after hours of experimenting and trials
I've managed to get my voltage to show up in puTTy. However, my code is a bit long and I can only show the voltage.
Is there a simpler way of doing this plus I want it to say 'Voltage=*number*'. And also I want it to stay in one line instead of repeating itself. as shown here : https://imgur.com/a/wA5x2va

Here's my code.
Code:
char number[7];


void realVoltage_usart ()
{

number[0] = '0';
number[1] = '.';
number[2] = '0';
number[3] = '0';
number[4] = '0';
number[5] = 'v';
number[6] = ' ';

unsigned int ActVolt;



ActVolt = ADC_convert()*1000;




while (ActVolt > 1000)
{
ActVolt -= 1000;
number[0]++;
}
send_usart(number[0]);
send_usart(number[1]);
while (ActVolt > 100)
{
ActVolt -= 100;
number[2]++;
}
send_usart(number[2]);
while (ActVolt > 10)
{
ActVolt -= 10;
number[3]++;
}
send_usart(number[3]);
while (ActVolt > 1)
{
ActVolt -= 1;
number[4]++;
}
send_usart(number[4]);
send_usart(number[5]);
send_usart(number[6]);


}
Where my ADC conversion is
Code:
float ADC_convert(void)
{
unsigned short ADC_DATA;
  float Voltage;
    ADC_DATA=read_adc();
    Voltage= (ADC_DATA*(3.3/4096));
    return Voltage;
}
considering, my voltages fluctuate a lot, is there a way to average the numbers and get the mean?
 

MrSoftware

Joined Oct 29, 2013
2,202
Use something like sprintf() to convert your float to a string, then send the string to the uart. For example:

Code:
    char mystr[128] = { 0 };
    float myfloat = 123.456;
    sprintf(mystr, "%f", myfloat);
    printf("Number: %s\n", mystr); // send to uart instead of printf here
If your ADC values are jumping all over, put a scope on your power leads and check if it's clean. If there is ripple or noise on your power, that can affect the ADC readings. Additionally you can take multiple samples. Just put a little loop to read your ADC a few times with a pause in-between, add them up and divide by the number of readings. That will give you an average. Play with the number of readings and delay it to suit your needs. Also check the spec for your ADC, some are configurable to oversample automatically if you enable the option.

To get it to type overitself on the same line, you're going to have to use a combination of things. Your terminal will have to be set to NOT automatically line-feed, then send the \r character to rewind the carriage to the start of the line (terminology from the old typewriter days). Sending \n will give you a new line.
 
Last edited:

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
Use something like sprintf() to convert your float to a string, then send the string to the uart. For example:

Code:
    char mystr[128] = { 0 };
    [code]float myfloat = 123.456;
sprintf(mystr, "%f", myfloat);
printf("Number: %s\n", mystr); // send to uart instead of printf here
[/code]

If your ADC values are jumping all over, put a scope on your power leads and check if it's clean. If there is ripple or noise on your power, that can affect the ADC readings. Additionally you can take multiple samples. Just put a little loop to read your ADC a few times with a pause in-between, add them up and divide by the number of readings. That will give you an average. Play with the number of readings and delay it to suit your needs. Also check the spec for your ADC, some are configurable to oversample automatically if you enable the option.

To get it to type overitself on the same line, you're going to have to use a combination of things. Your terminal will have to be set to NOT automatically line-feed, then send the \r character to rewind the carriage to the start of the line (terminology from the old typewriter days). Sending \n will give you a new line.
I'll give it a go. Thank you! Mind explaining what line 2 of the code means?
Code:
float myfloat = 123.456;
not too sure how to do the average but ill see what i can do.
 

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
any idea how to fix this?

https://imgur.com/a/A8FDhH8


This is my send_usart code
Code:
void send_usart(unsigned char d)
{
    while(!(USART_MODULE->SR&USART_SR_TC));        //wait for transmission complete
    USART_MODULE->DR=d;        //write byte to usart data register
}
 
Last edited:

MrSoftware

Joined Oct 29, 2013
2,202
Line 2 is just creating a float variable and putting some value in it. It just takes the place of your "Voltage" variable.

Your error is because your send_usart doesn't take that many parameters. Just put everything you want to display on the terminal in your sprintf(), then sending the resulting string. Use your memory watch to watch the memory where your string variable lives to see what's happening there. I'll leave that as an exercise for you.

The average is easy, just do this:

Code:
int iNumReadings = 5;
int iDelayBetweenReadingsMicroSec = 10;
float avgReading = 0.0;
for(int i = iNumReadings; i > 0; i--)
{
  avgReading += ADC_convert();
  delayMicroseconds(iDelayBetweenReadingsMicroSec );
}
avgReading /= iNumReadings;
 

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
I also have a progression bar on the second line of my LCD above my Voltage. Is it possible to just do the same thing to get it showing up?
Code:
void CustomChar (float q)   //analogue signal. (q is adcvalue)
{
float divider = 255;    //3.3V represented by 16 character spaces (4096/16) (12bits)
int sum = q/divider;     

cmdLCD(LCD_LINE2);  //setting cursor location
  
for(int i = 0; i< 16 ; i++) //to get complete progress bar, have to account for all 16 memory locations, for= loops again.
if(i<=sum)                                  
{
putLCD(0xFF); //transfer character code to memory and increments the cursor by 1
}
else putLCD(' '); //otherwise, put space.
}
 
Last edited:

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
I've tried your code as shown here :
Code:
void realVoltage_usart()
{
char mystr[128] = { 0 };
    float Voltage = 123.456;
    sprintf(mystr, "Volts=%.3f\n", Voltage);
    send_usart((unsigned char) mystr); // send to uart instead of printf here}
}
https://imgur.com/a/U8n5N0r this is what i get in terminal
 

Thread Starter

HappyC4mper

Joined Oct 13, 2017
71
Did you initialize the USART correctly?
Yes, as using my old code works :
Code:
char number[7];
void realVoltage_usart ()
{
number[0] = '0';
number[1] = '.';
number[2] = '0';
number[3] = '0';
number[4] = '0';
number[5] = 'v';
number[6] = ' ';
unsigned int ActVolt;
ActVolt = ADC_convert()*1000;
while (ActVolt > 1000)
{
ActVolt -= 1000;
number[0]++;
}
send_usart(number[0]);
send_usart(number[1]);
while (ActVolt > 100)
{
ActVolt -= 100;
number[2]++;
}
send_usart(number[2]);
while (ActVolt > 10)
{
ActVolt -= 10;
number[3]++;
}
send_usart(number[3]);
while (ActVolt > 1)
{
ActVolt -= 1;
number[4]++;
}
send_usart(number[4]);
send_usart(number[5]);
send_usart(number[6]);
}
 

MrSoftware

Joined Oct 29, 2013
2,202
Look carefully at your code until you understand what it's doing. mystr holds the address of the first byte of a string (character array), yet you're casting it as a unsigned char and passing it to your send_suart(), which is expecting a single byte, most likely an ASCII character. Do some quick reading on strings (character arrays) in C and see if you can figure it out.
 

402DF855

Joined Feb 9, 2013
271
First, check the logic of your while loops. Hint: what if the voltage is exactly 1.0?

Second, a useful averaging technique is an IIR (infinite impulse response) filter.

C:
void myfunc(float voltage)
{
    static bool init = false;
    static float useval = 0.0;
    const float gain = 0.5; // adjust this as necessary
    if (!init) {
        init = true;
        useval = voltage;
    } else {
        useval = useval*gain + voltage*(1-gain);
    }
    // print useval as desired
}
The init step is optional; with sufficient update rate the filtered value will converge on the desired result. Play with the gain factor. For really noisy signals I'd increase the gain. I've used 0.99 or more in some cases.
 
Top