EmbeddedRelated.com
Code Snippets

PID (Floating Point)

March 5, 2013 Coded in C
/*! \details This structure holds the data to run a
 * floating point PID loop.
 */
typedef struct{
	float max /*! \brief Max manipulated value */;
	float min /*! \brief Miniumum manipulated value */;
	float e /*! \brief Error value */;
	float i /*! \brief Integrator value */;
	float kp /*! \brief Proportional constant */;
	float ki /*! \brief Integrator constant */;
	float kd /*! \brief Differential constant */;
} pid_f_t;

/*! \details This function initializes the data in a PID structure.
 *
 */
void pid_init_f(pid_f_t * ptr /*! A pointer to the PID data structure */,
		float min /*! The manipulated variable's minimum value */,
		float max /*! The manipulated variable's maximum value */){
	memset(ptr, 0, sizeof(pid_f_t));
	ptr->min = min;
	ptr->max = max;
}

/*! \details This function updates the value of the manipulated variable (MV)
 * based on the current state of the PID loop.
 */
float pid_update_f(float sp /*! The set point */,
		float pv /*! The process variable */,
		pid_f_t * ptr /*! A pointer to the PID constants */){
	float temp;
	float e;
	float p;
	float manp;
	float tmpi;
	//get the error from the last call
	e = ptr->e;
	//calculate the new error (set point - present value)
	ptr->e = sp - pv;
	//use a temp variable for the integrator
	tmpi = ptr->i + ptr->e;
	//update the manipulated process variable
	manp = ptr->kp * ptr->e + ptr->ki * tmpi + ptr->kd * (ptr->e - e);
	//the integrator is only updated if the manipulated process is within range
	//otherwise the system will likely become unstable
	if ( (manp < ptr->max) && (manp > ptr->min) ){
		ptr->i = tmpi;
	} else if ( manp > ptr->max ){
		manp = ptr->max;
	} else if ( manp < ptr->min ){
		manp = ptr->min;
	}
	return manp;
}

base64 Encoding

March 1, 20132 comments Coded in C
#include <string.h>
#include <stdint.h>

//This is a helper function to convert a six-bit value to base64
char base64_encode_six(uint8_t six_bit_value){
	uint8_t x;
	char c;
	x = six_bit_value & ~0xC0; //remove top two bits (should be zero anyway)
	if( x < 26 ){
		c = 'A' + x;
	} else if ( x < 52 ){
		c = 'a' + (x - 26);
	} else if( x < 62 ){
		c = '0' + (x - 52);
	} else if( x == 62 ){
		c = '+';
	} else if (x == 63 ){
		c = '/';
	} else {
		printf("ERROR IN BASE 64\n");
		c = 'A';
	}
	return c;
}

//This is the function for encoding in base64
void base64_encode(char * dest, const char * src){
	int bits;
	int i;
	int j;
	int k;
	int len;
	uint8_t six_bits[4];
	len = strlen(src);

	k = 0;
	//We need to encode three bytes at a time in to four encoded bytes
	for(i=0; i < len; i+=3){
		//First the thress bytes are broken down into six-bit sections
		six_bits[0] = (src[i] >> 2) & 0x3F; 
		six_bits[1] = ((src[i] << 4) & 0x30) + ((src[i+1]>>4) & 0x0F);
		six_bits[2] = ((src[i+1] << 2) & 0x3C) + ((src[i+2]>>6) & 0x03);
		six_bits[3] = src[i+2] & 0x3F;
		//now we use the helper function to convert from six-bits to base64
		for(j=0; j < 4; j++){
			dest[k+j] = base64_encode_six(six_bits[j]);
		}
		k+=4;
	}

	//at the end, we add = if the input is not divisible by 3
	if( (len % 3) == 1 ){
		//two equals at end
		dest[k-2] = '=';
		dest[k-1] = '=';
	} else if ( (len %3 ) == 2 ){
		dest[k-1] = '=';
	}

	//finally, zero terminate the output string
	dest[k] = 0;
}

Exponential Moving Average

February 13, 20133 comments Coded in C
//This macros defines an alpha value between 0 and 1
#define DSP_EMA_I32_ALPHA(x) ( (uint16_t)(x * 65535) )
 
int32_t dsp_ema_i32(int32_t in, int32_t average, uint16_t alpha){
  int64_t tmp0; //calcs must be done in 64-bit math to avoid overflow
  tmp0 = (int64_t)in * (alpha) + (int64_t)average * (65536 - alpha);
  return (int32_t)((tmp0 + 32768) / 65536); //scale back to 32-bit (with rounding)
}

//here is a function that uses the averaging code
int32_t my_avg_func(void){
     static int32_t average = 0;
     int32_t adc_value;    
     adc_value = read_the_adc_value();
     average = dsp_ema_i32(adc_value, average, DSP_EMA_I32_ALPHA(0.1));
     return average;
}