#include <cstdio>
#include <cstdint>
#include <cmath>

/*
  Examples for dealing with ADCs & DACs, including how to work with
  voltages and how to adjust readings to account for offset and gain
  errors.
*/

/*
  Examples for converting between code points and voltage.
  Code points are the integer readings from an ADC or the integer
  output register for a DAC. For example, if you have a 10-bit DAC,
  then the code points are from 0 to 1023.
*/


#define RESOLUTION_8_BIT 256
#define RESOLUTION_10_BIT 1024
#define RESOLUTION_12_BIT 4096
#define RESOLUTION_14_BIT 16384
#define RESOLUTION_16_BIT 65536


/*
  Convert a code point to a voltage.
  
  This is useful for ADCs - if you know the range of the ADC's
  measurements you can use this to determine which voltage
  an analogRead() result corresponds to.
*/
float code_points_to_volts(uint32_t code_point, uint32_t resolution = RESOLUTION_12_BIT, float min_voltage = 0.0f, float max_voltage = 3.3f) {
  float voltage_range = max_voltage - min_voltage;
  float normalized_value = (float)(code_point) / (float)(resolution - 1);
  return min_voltage + (voltage_range * normalized_value);
}


/*
  Convert a voltage to a code point.
  
  This is useful for DACs - if you want to output a specific
  voltage, then you can use this to determine which code point
  to pass to analogWrite()
*/
uint32_t volts_to_code_points(float volts, uint32_t resolution = RESOLUTION_12_BIT, float min_voltage = 0.0f, float max_voltage = 3.3f) {
  float voltage_range = max_voltage - min_voltage;
  float normalized_value = (volts - min_voltage) / voltage_range;
  uint32_t code_points = ceil(normalized_value * (resolution - 1));
}


/*
  Demonstration of the conversion functions
*/
void demonstrate_coversions() {
  printf("\nConversion demonstration:\n\n");
  printf("Code points -> Volts:\n");
  float volts = code_points_to_volts(2048);
  printf("2048 : 4096 :: %0.2f V : 3.3 V\n", volts);
  volts = code_points_to_volts(256, RESOLUTION_10_BIT, 1.0f, 2.0f);
  printf("256 : 1024 :: %0.2f V : 1.0 V to 2.0 V\n", volts);
  
  printf("Volts -> Code points:\n");
  uint32_t code_points = volts_to_code_points(1.65f);
  printf("%u : 4096 :: 1.65 V : 3.3 V\n", code_points);
  code_points = volts_to_code_points(1.25f, RESOLUTION_10_BIT, 1.0f, 2.0f);
  printf("%u : 1024 :: 1.25 V : 1.0 V to 2.0 V\n", code_points);
}


/*
  Helpers for determining and correcting gain and offset
  errors.
*/


/*
  Determines the gain and offset error using two measurements.
  
  For example, if you were using this for a DAC, you would pick
  two output voltages to measure - one near the bottom of the range,
  one near the top. Use the volts_to_code_points() function to set
  the DAC output's value. Measure the *actual* voltage for both
  of the expected values. You would use those values here to get
  the gain and offset errors.
*/
void calculate_gain_and_offset_error(float low_measured, float high_measured, float low_expected, float high_expected, float& gain_error, float& offset_error) {
  gain_error = (high_measured - low_measured) / (high_expected - low_expected);
  offset_error = (low_measured * (1.0f / gain_error)) - low_expected;
}

/*
  Use the gain and offset error to correct a value.
*/
float apply_error_correction(float value, float gain_error, float offset_error) {
  return (value * (1.0f / gain_error)) - offset_error;
}


/*
  Demonstration of the conversion error functions.
*/
void demonstrate_error_correction() {
  printf("\nGain & offset error demonstration:\n\n");
  
  float low_expected = 1.0;
  float high_expected = 3.0;
  printf("Expected values: %0.2f and %0.2f\n\n", low_expected, high_expected);
  
  /* Measurements are the same as expected, there should be no
     errors measured. */
  float low_measured = 1.0;
  float high_measured = 3.0;
  float gain_error;
  float offset_error;
  calculate_gain_and_offset_error(
    low_measured, high_measured,
    low_expected, high_expected,
    gain_error, offset_error);
  printf("Actual values: %0.2f and %0.2f: gain error: %0.4f, offset error: %0.2f\n", low_measured, high_measured, gain_error, offset_error);
  
  /* The high-side measurment is more than it should be, which
     indicates that the gain error is above one. */
  high_measured = 3.5;
  calculate_gain_and_offset_error(
    low_measured, high_measured,
    low_expected, high_expected,
    gain_error, offset_error);
  printf("Actual values: %0.2f and %0.2f: gain error: %0.4f, offset error: %0.2f\n", low_measured, high_measured, gain_error, offset_error);
  
  /* The high-side measurment is less than it should be, which
     indicates that the gain error is below one. */
  high_measured = 2.5;
  calculate_gain_and_offset_error(
    low_measured, high_measured,
    low_expected, high_expected,
    gain_error, offset_error);
  printf("Actual values: %0.2f and %0.2f: gain error: %0.4f, offset error: %0.2f\n", low_measured, high_measured, gain_error, offset_error);

  /* Both readings are slightly more than they should be (by
     the same amount) which indicates there is a positive
     offset error, but no gain error. */
  low_measured = 2;
  high_measured = 4;
  calculate_gain_and_offset_error(
    low_measured, high_measured,
    low_expected, high_expected,
    gain_error, offset_error);
  printf("Actual values: %0.2f and %0.2f: gain error: %0.4f, offset error: %0.2f\n", low_measured, high_measured, gain_error, offset_error);

    /* Both readings are slightly less than they should be (by
     the same amount) which indicates there is a negative
     offset error, but no gain error. */
    low_measured = 0;
    high_measured = 2;
    calculate_gain_and_offset_error(
      low_measured, high_measured,
      low_expected, high_expected,
      gain_error, offset_error);
    printf("Actual values: %0.2f and %0.2f: gain error: %0.4f, offset error: %0.2f\n", low_measured, high_measured, gain_error, offset_error);
    

  printf("\nError correction demonstration:\n\n");
  printf("Expected values: 1.0 and 3.0\n");

  low_measured = 1.1;
  high_measured = 2.95;
  printf("Actual values: %0.2f and %0.2f\n", low_measured, high_measured);
  
  calculate_gain_and_offset_error(
      low_measured, high_measured,
      low_expected, high_expected,
      gain_error, offset_error);
  printf("Gain error: %0.4f, offset error: %0.2f\n\n", gain_error, offset_error);
  
  for(float v = low_expected; v <= high_expected; v += 0.1) {
    printf("Unadjusted: %0.2f, adjusted: %0.2f\n", v, apply_error_correction(v, gain_error, offset_error));
  }
}


/*
  This main function is just here to demonstrate these functions,
  you wouldn't include this in your Arduino sketch.
*/

int main() {
  demonstrate_coversions();
  demonstrate_error_correction();
  return 0;
} 
by

C++ Online Compiler

Write, Run & Share C++ code online using OneCompiler's C++ online compiler for free. It's one of the robust, feature-rich online compilers for C++ language, running on the latest version 17. Getting started with the OneCompiler's C++ compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as C++ and start coding!

Read inputs from stdin

OneCompiler's C++ online compiler supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample program which takes name as input and print your name with hello.

#include <iostream>
#include <string>
using namespace std;

int main() 
{
    string name;
    cout << "Enter name:";
    getline (cin, name);
    cout << "Hello " << name;
    return 0;
}

About C++

C++ is a widely used middle-level programming language.

  • Supports different platforms like Windows, various Linux flavours, MacOS etc
  • C++ supports OOPS concepts like Inheritance, Polymorphism, Encapsulation and Abstraction.
  • Case-sensitive
  • C++ is a compiler based language
  • C++ supports structured programming language
  • C++ provides alot of inbuilt functions and also supports dynamic memory allocation.
  • Like C, C++ also allows you to play with memory using Pointers.

Syntax help

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition If-Else is used.

if(conditional-expression) {
   //code
}
else {
   //code
}

You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.

2. Switch:

Switch is an alternative to If-Else-If ladder.

switch(conditional-expression){    
case value1:    
 // code    
 break;  // optional  
case value2:    
 // code    
 break;  // optional  
......    
    
default:     
 code to be executed when all the above cases are not matched;    
} 

3. For:

For loop is used to iterate a set of statements based on a condition.

for(Initialization; Condition; Increment/decrement){  
  //code  
} 

4. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while (condition) {  
// code 
}  

5. Do-While:

Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.

do {  
 // code 
} while (condition); 

Functions

Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity. Function gets run only when it is called.

How to declare a Function:

return_type function_name(parameters);

How to call a Function:

function_name (parameters)

How to define a Function:

return_type function_name(parameters) {  
 // code
}