approach allows to send the full 12-bit ADC via Uart

Thread Starter

Kittu20

Joined Oct 12, 2022
434
Hello forum members,

Suppose I'm working on an embedded system project where I need to measure and display a voltage range of 0 to 12 V DC on a serial terminal. I'm using a 12-bit ADC for voltage measurement, and my UART is configured for 8N1 at a 9600 baud rate, meaning it can only send one byte of ADC data at a time.

This formula will give the voltage in the 0-12 V DC range based on the received byte.

Code:
voltage = (received_byte * 12.0) / 255.0
I'm facing difficulties in figuring out how to send full 12-bit ADC value via UART.
Any suggestions on how to accomplish this without using sprintf and string.h library?"
 

MrChips

Joined Oct 2, 2009
29,798
There are a number of solutions to your problem.

1) You can convert 12-bit binary to BCD text. Hence 0000-4095 can be sent as four text characters.
2) You can convert 12-bit binary to hexadecimal characters. Hence 0000-4095 becomes 000-FFF, three hexadecimal characters.
3) You can send two bytes of 8-bit binary values. This allows you to send a 16-bit binary value. You choose the order of your bytes, Big-endian vs Little-endian.

If you want to ensure that the bytes are received in the correct order, you can send 6 bits at a time. This leaves two unused bits which can be used to tag the order of the bits. For example, 01 = low order, 10 = high order, 00 and 11 = error in data.
 

Papabravo

Joined Feb 24, 2006
20,584
You can also send three bytes with 4 significant bits in each byte. That will allow all of the characters you send to come from the set of printable characters. This can be an advantage in debugging.
 
Last edited:

Ian Rogers

Joined Dec 12, 2012
1,133
Any suggestions on how to accomplish this without using sprintf and string.h library?"
Any reason why not? I use text whenever I can.. The basics behind sprintf() is atoi() or atol() smaller footprint but will do the same.
 

Ian0

Joined Aug 7, 2020
8,935
9600 baud will send one character every 1.04ms. If the signal does not change significantly in 20ms, then send the top 8 bits, and then add the lowest four to the next sample. (Feed forward error correction).
Then filter the received data with a cutoff frequency of <50Hz.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
434
3) You can send two bytes of 8-bit binary values. This allows you to send a 16-bit binary value. You choose the order of your bytes, Big-endian vs Little-endian.
Thanks! The approach used here splits the 12-bit ADC value into two parts for UART transmission:

  1. The most significant 8 bits (MSB) are sent in the first byte.
  2. The least significant 4 bits (LSB) are sent in the second byte, with a shift.

On the receiving end, these two bytes are combined to reconstruct the original 12-bit ADC value. This method allows the complete ADC value to be transmitted in two 8-bit UART transmissions while maintaining bit order.
 

MrChips

Joined Oct 2, 2009
29,798
Thanks! The approach used here splits the 12-bit ADC value into two parts for UART transmission:

  1. The most significant 8 bits (MSB) are sent in the first byte.
  2. The least significant 4 bits (LSB) are sent in the second byte, with a shift.

On the receiving end, these two bytes are combined to reconstruct the original 12-bit ADC value. This method allows the complete ADC value to be transmitted in two 8-bit UART transmissions while maintaining bit order.
How does that maintain bit order?
If one byte is 1 and the next byte is 15, how do you know which is low and which is high?
 

Thread Starter

Kittu20

Joined Oct 12, 2022
434
Any reason why not? I use text whenever I can.. The basics behind sprintf() is atoi() or atol() smaller footprint but will do the same.
I don't have any specific reason just wanted to know how it can be done without library like you mentioned.

9600 baud will send one character every 1.04ms.
I assume 9600 just for example. I would always choose highest speed
 

Ian0

Joined Aug 7, 2020
8,935
I assume 9600 just for example. I would always choose highest speed
9600 might be the highest speed, if you wanted to send it over a long distance!
For 115200 baud you could deal with a signal that doesn't change much in 175us.
At a guess, FFEC will probably have the lowest software overhead, and you don't have to decide what to do if you receive a high byte without its associated low byte, or vice versa.
 
Top