McMajan Library Pack  v 2.00
Improve your Arduino !
Ss_Analogico.cpp
Go to the documentation of this file.
1 #include "Ss_Analogico.h"
2 
3 
4 //==============================================================================
5 /** \brief Inizialize McMajanLibrary analogic section
6  */
8 {
9 #if defined ARDUINO_ARCH_AVR
10  ADCSRA &= ~Mc_PS_128; //Set up the ADC: remove bits set by Arduino library
11  ADCSRA |= Mc_DEFAULT_AVR_ADC_PRESCALER; // set our own prescaler to SCR_XX
12 #else
13  analogReadResolution(12);
14 #endif
15 }
16 
17 
18 //==============================================================================
19 /** \brief Calcolate internal parameters to give you values in original units as Ampere, Volt, etc and not only a raw value.
20  * \param sensore is the pointer to the sensor
21  */
23 {
24  sensore->sensorunit=(((int)(1<<Mc_ADC_extended_bits))*(float)sensore->sensor_voltage_range/(float)Mc_ArduinoVoltageRange);
25  sensore->sensor_step=((float)sensore->sensor_range/(float)sensore->sensorunit); // questo moltiplicato per la "lettura grezza" ti fornisce il valore "fisico"
26 }
27 //==============================================================================
28 /** \brief This function is useful if you need to do a "manual calibration" of the sensor
29  * \param sensore is the sensor pointer you want to calibrate
30  * \param value is the manual calibration of the sensor
31  */
32 void Mc_SetSensorStep(struct Mc_AnalogSensor* sensore,float value)
33 {
34  sensore->sensor_step=value/(1<<Mc_ADC_bit_extension);
35 }
36 //==============================================================================
37 /** \brief This function sample an analogic input and return the averange value
38  * \param localpin is the input pin of Arduino
39  * \param campioni is the number of samples you want to do.
40  * \return this function return the averange value of the samples.
41  */
42 float Mc_SampleAnalogAvg(int localpin,uint16_t campioni)
43 {
44  float valore=Mc_OversampledAnalogRead(localpin);
45  for(int i=0;i<campioni;i++) valore=(valore+Mc_OversampledAnalogRead(localpin))/2;
46  return(valore);
47 
48 }
49 
50 //==============================================================================
51 /** \brief This function return the kalman filtered value of samples on an analogic pin.
52  * Note: the voltage of input pin must be stable. This function is useful to read the right value removing the background noise.
53  * \param localpin is the input pin of Arduino
54  * \param campioni is the number of samples you want to do.
55  * \return this function return the kalman filtered value of the samples.
56  */
57 
58 float Mc_KalmanAnalogAvg(int localpin,uint16_t campioni)
59 {
60  campioni=(campioni>>1);
61  kalman_state K1,K2;
62  float valore=Mc_OversampledAnalogRead(localpin);
63  K1=kalman_init(2,50, valore, valore); //0.1 -4
64  for(uint8_t i=0;i<campioni;i++) kalman_update(&K1,Mc_OversampledAnalogRead(localpin));
65 
66  K2=kalman_init(1,80, K1.value, K1.value); //0.1 -4
67  for(uint8_t i=0;i<campioni;i++) kalman_update(&K2,Mc_OversampledAnalogRead(localpin));
68 
69  return(K2.value);
70 
71 }
72 //==============================================================================
73 /** \brief This function sample an analogic input using oversample algorithm
74  * \param pin is the input pin of Arduino
75  * \return this function return the reded value
76  */
77 inline double Mc_OversampledAnalogRead(int pin)
78 { // al posto di overbit ci metto Mc_ADC_bit_extension
79  unsigned int val=0;
80  unsigned int misureoversample=pow(4,Mc_ADC_bit_extension);
81  for(unsigned char z=0;z<misureoversample;z++) val+=analogRead(pin);
82 
83  return(val>>Mc_ADC_bit_extension); //2^n
84 }
85 //==============================================================================
86 /** \brief This function initialize a Kalman filter
87  * \param q process noise covariance
88  * \param r measurement noise covariance
89  * \param p estimation error covariance
90  * \param value initial value
91  * \return initialized kalman filter.
92  */
93 kalman_state kalman_init(double q, double r, double p, double intial_value)
94 {
95  kalman_state result;
96  result.q = q;
97  result.r = r;
98  result.p = p;
99  result.value = intial_value;
100 
101  return result;
102 }
103 //==============================================================================
104 /** \brief This function updates a Kalman filter
105  * \param state is the actual kalman filter pointer
106  * \param measurement is the new value you want to filter
107  * \return this funtion DON'T retrun nothing because the original filter is modificated
108  */
109 
110 void kalman_update(kalman_state* state, double measurement)
111 {
112  //prediction update
113  state->p = state->p + state->q;
114 
115  //measurement update
116  if((state->p + state->r)!=0) state->k = state->p / (state->p + state->r);
117  else state->k = state->p / 0.00001;
118  state->value = state->value + state->k * (measurement - state->value);
119  state->p = (1 - state->k) * state->p;
120 }
121 //==============================================================================
122 /** \brief Test analogic line
123  *
124  * This function samples an analogic input to read lower, higher , mean and, rms values. inoltre - althought you can see the number of samples and the kalmann filtered value. This last value is useful to test
125  * lines wich signal is stable (or may be it).
126  * \param pin is the analogic pin you want to test
127  * \param num is the number of "grid waves" you want to sample (default 450 if you don't specify values).
128  * \return this funtion return a Mc_AnalogLine structure.
129  */
130 struct Mc_AnalogLine CheckAnalogLine(int pin,uint16_t num)
131 {
132  struct Mc_AnalogLine Local;
133 
134  kalman_state KK;
135 
136  unsigned long LocalTime=0;
137  float value=0;
138  double sum_radice=0;
139 
140  Local.min=Mc_High_ADC_Value;
141  Local.max=-Mc_High_ADC_Value;
142 
143  double timelen=(double)num*1/Mc_voltage_freq*1000*1000; //0.02sec...è la lunghezza in microsecondi dell'onda completa.
144 
145  Local.mean=Mc_SampleAnalogAvg(pin,1);
146 
147  KK=kalman_init(1,80, Local.mean, Local.mean);
148 
149 
150  Local.counter=0;
151  LocalTime=micros();
152  while(micros()-LocalTime<timelen)
153  {
154 
155  value=(Mc_SampleAnalogAvg(pin,1)); // corrente
156 
157  kalman_update(&KK,value);
158  if(value<Local.min) Local.min=value;
159  if(value>Local.max) Local.max=value;
160  Local.mean=(Local.mean+value)/2;
161 
162 
163  sum_radice+=(value*value);
164  Local.counter++;
165  }
166 
167  Local.rms=sqrt(sum_radice/Local.counter);
168  Local.klm=KK.value;
169 
170 
171 
172  return(Local);
173 
174 }
void Mc_Analog_Inist()
Inizialize McMajanLibrary analogic section.
Definition: Ss_Analogico.cpp:7
float Mc_SampleAnalogAvg(int, uint16_t)
This function sample an analogic input and return the averange value.
void Mc_CalculateSensorStep(struct Mc_AnalogSensor *)
Calcolate internal parameters to give you values in original units as Ampere, Volt, etc and not only a raw value.
#define Mc_ArduinoVoltageRange
Definition: Ss_Global.h:31
void kalman_update(kalman_state *, double)
This function updates a Kalman filter.
#define Mc_High_ADC_Value
Definition: Ss_Global.h:37
kalman_state kalman_init(double, double, double, double)
This function initialize a Kalman filter.
int sensor_voltage_range
Definition: Ss_Analogico.h:37
double Mc_OversampledAnalogRead(int)
This function sample an analogic input using oversample algorithm.
double value
Definition: Ss_Analogico.h:47
void Mc_SetSensorStep(struct Mc_AnalogSensor *, float)
This function is useful if you need to do a "manual calibration" of the sensor.
#define Mc_ADC_extended_bits
Definition: Ss_Global.h:36
float Mc_KalmanAnalogAvg(int, uint16_t)
This function return the kalman filtered value of samples on an analogic pin. Note: the voltage of in...