EmbeddedRelated.com
The 2024 Embedded Online Conference

Olympic Averaging

Douglas Butler March 29, 20132 comments Coded in C
int16 adcval,sum,max,min;
int8 i;
#define samples 10

max=0;
min=0xFFFF;    //Set max and min to the limits of the range.

for (i=0;i<samples;i++){
    adcval=read_adc();
    if (adcval>max) max=adcval;    //Update max and min on the fly.
    if (adcval<min) min=adcval;
    sum+=adcval;    //Generate sum of all samples.
    }
sum-=max;    //Remove the maximum, and minimum values
sum-=min;    //as likely outliers.

return(sum/(samples-2)); //Average the remaining total.
     //If samples = 10 then the division becomes sum<<3

I2C driver

March 29, 2013 Coded in C for the Atmel AT89
/*
File: I2C_drive.h
*/

#ifndef __I2C_H
#define __I2C_H

#include <AT89X51.H>
#include <INTRINS.H>

typedef unsigned char ubyte;

/*
****************************************************
*       I2C Bus Configuration
*
****************************************************
*/

#define sda P1_0
#define scl P1_1
#define HOLD _nop_(); _nop_(); _nop_()

void send_stop();
void master(ubyte);
void send_byte(ubyte);
void send_data(ubyte, ubyte, ubyte, ubyte *);
ubyte recv_byte(ubyte);
void recv_data(ubyte, ubyte, ubyte, ubyte *);

#endif
----------------------------------------------------------

/*
File: I2C_drive.c
*/

#include "I2C_drive.h"

bit i2c_busy, no_ack, bus_fault;

ubyte bdata a;

sbit LSB=a ^ 0;
sbit MSB=a ^ 7;

/*
************************************
*       Sending Stop Condition
************************************
*/

void send_stop()
{
	sda = 0;
	scl = 1;
	HOLD;
	sda = 1;
	i2c_busy = 0;
}

/*
************************************
*      I2C Start Condition
*
*     NOTE: need to use it.
************************************
*/

void master(ubyte slave_addr)
{
	i2c_busy = 1;
	no_ack = 0;
	bus_fault = 0;
	if(!scl||!sda)
		bus_fault = 1;
	else
	{
		sda = 0;
		HOLD;
		scl = 0;
		HOLD;
		send_byte(slave_addr);
	}
}

/*
************************************
*     Sending a byte on I2C Bus
************************************
*/

void send_byte(ubyte i2c_data)
{
	ubyte i;
	a=i2c_data;
	for(i=0;i<8;i++)
	{
		scl=0;
		HOLD;
		sda=MSB;
		a<<=1;
		_nop_();
		scl=1;
		HOLD;
		scl=0;
	}
	sda = 1;
	scl = 1;
	HOLD;
	if(!sda)
	{
		scl = 0;
		HOLD;
	}
	else
	{
		no_ack = 1;
		scl = 0;
		HOLD;
	}
}

/*
****************************************************
*       Sending data on I2C bus
*
*   Usage:
*         send_data(0xD0,0x10, 0x20, send_buffer)
*
*         0XD0: Slave address, Must me with write bit
*         0x10: Starting address, or sub-address
*         0x20: number of bytes to send
*         send_buffer: adress of the buffer pointer
*
*****************************************************
*/

void send_data(ubyte slave_add, ubyte sub_add, ubyte bytes, ubyte *data_in)
{
	master(slave_add);
	send_byte(sub_add);
	if(no_ack)
		send_stop();
	else
	{
		for(bytes;bytes>0;bytes--)
		{
			send_byte(*data_in++);
			if(no_ack)
				break;
		}
		send_stop();
	}
}

/*
*********************************************
*      Recieve a single byte from I2C Bus
*
*    Note: if you are going to recieve
*          a single byte then the passing
*          argument should be 1.
*
*********************************************
*/

ubyte recv_byte(ubyte cnt)
{
	ubyte i,rcv_data;
	for(i=0;i<8;i++)
	{
		sda=1;
		scl=1;
		HOLD;
		LSB=sda;
		if(i<7)
			a<<=1;
		HOLD;
		scl=0;
		HOLD;
	}
	if(cnt==1)
		sda = 1;
	else
		sda = 0;
	scl =1;
	HOLD;
	scl = 0;
	sda = 1;
	HOLD;
	rcv_data = a;
	return rcv_data;
}

/*
****************************************************
*       Recieving bulk data on I2C bus
*
*   Usage:
*         recv_data(0xD0,0x10, 0x20, send_buffer)
*
*         0XD0: Slave address, Must me with write bit
*         0x10: Starting address, or sub-address
*         0x20: number of bytes to recieve
*         send_buffer: adress of the recieve buffer
*                      pointer
*
*****************************************************
*/

void recv_data(ubyte slave_add, ubyte sub_add, ubyte byte_cnt, ubyte *recv_buf)
{
	ubyte i;
	scl = sda = 1;
	master(slave_add);
	send_byte(sub_add);
	slave_add+=1;
	scl = sda = 1;
	master(slave_add);
	if(no_ack)
	{
		send_stop();
		goto exit;
	}
	for(i=0;i<byte_cnt;i++)
		recv_buf[i]=recv_byte(byte_cnt-i);
	send_stop();
exit:;
}

Complex serial port driver with feedback acceptance.

March 29, 20131 comment Coded in C for the TI MSP430
/*
Developed By: Dinesh SB
E-Mail: dinesh.badkas0809@gmail.com
*/

#include "msp430.h"

#define initialDelay 50000

unsigned int k,ADC12temp = 0,PotTemp = 0;;
unsigned char AdcDec[4],PotDec[4];;
volatile unsigned int i,j,m = 0,n = 0;
unsigned char IMUTemp = 0;
unsigned char IMURazorBuffer[35];

void IMU_Buffering(void);
void FSR_Read(void);
void Switch_Position_Read(void);
void Battery_Monitoring(void);
void Pot_Read(void);
void PC_UART_Transmit(unsigned char);
void Bluetooth_UART_Transmit(unsigned char);
void delayGen(unsigned int tcount);
void startTB(unsigned int,unsigned int,unsigned int);
void StartVibration(unsigned int);

unsigned char tmp;
static unsigned int module = 0;
unsigned int delay = 0, tone = 0;
static unsigned int cmdRcvd =0;
static unsigned int delayFinished =0;
static unsigned int multiDigitDelay = 0;
static unsigned int previousDelayDigit =0;
static unsigned int digitCnt = 0;
static unsigned int digit3Rcvd = 0;
static unsigned int pDetected = 0;
static unsigned int eDetected = 0;
static unsigned int time;

static unsigned int vModule = 0;
unsigned int vDelay = 0;
static unsigned int VCmdRcvd =0;
static unsigned int VDigitCnt =0;
static unsigned int VMultiDigitDelay = 0;
static unsigned int VPreviousDelayDigit =0;
static unsigned int iDetected = 0;
static unsigned int bDetected = 0;

static unsigned int UART_Select = 0;

/*******************************************************************************

 * Function :		Board_Init

 * Description: 	This function initializes GPIOs

 * Input parameters :   None

 * Output parameters :  None

*******************************************************************************/
void Board_Init(void)
{
  //P8DIR |= BIT0;                            //P8.0 LED 1
  //P8OUT &= ~BIT0;                           //LED 1 OFF

  P7DIR |= BIT3;                            //P7.3 LED 2
  P7OUT &= BIT3;                            //LED 2 off

  P1DIR = 0x3F;                             //P1.6,7 AS input 
  P1REN = 0xC0;                             //enable pullup/down reg.
  P1OUT = 0xC0;                             //select pull-up reg.

  P2DIR = 0x00;                             //P2.0-7 as input
  P2REN = 0xFF;                             //enable pullup/down reg.
  P2OUT = 0xFF;                             //select pull-up reg.

  P6DIR |= BIT6;                            //AMP_SD pin as O/P
  P6OUT &= ~BIT6;                           //SHUTDOWN disabled

  P4SEL |= BIT4;                            //select TB4
  P4DIR |= BIT4;                            //To take PWM @ pin configure that pin HIGH

  P3DIR |= BIT0;                            //LED_BATMON on P3.0
  P3OUT &= ~BIT0;                           //LED_BATMON OFF

  P7DIR |= BIT5;                            //P7.5 configued as output
  P7OUT &= ~BIT5;                           //P7.5 made 0 to sink current

  P4DIR |= BIT6;                            //vibration motor
  P4OUT &= ~BIT6;
  
  P6SEL |= BIT7;                            //select A7_____Vout_FSR pin 
  P7SEL |= BIT4;                            //select A12____VBat_Mon.
  P6SEL |= BIT5;                            //select A5_____POT

  P10DIR &= ~BIT1;                          //mechanical switch detection; P10.1
  P10REN |= BIT1;                           //enable register
  P10OUT |= BIT1;                           //select pull-up register
}

/*******************************************************************************

 * Function :		ADC12_Init

 * Description: 	This function initializes ADC12 peripheral

 * Input parameters :   None

 * Output parameters :  None

*******************************************************************************/
void ADC12_Init(void)
{
  ADC12CTL0 &= ~ADC12ENC;                                                                     //DISABLE ADC12 FOR CONFIGURATION
  P5SEL |= BIT0;                                                                              // select P5.0 for Veref+.
  ADC12CTL0 = ADC12SHT0_8 + ADC12ON + ADC12MSC;
  ADC12MCTL0 = ADC12SREF_2 | ADC12INCH_7;                                                     //FSR__A7
  ADC12MCTL1 = ADC12SREF_2 | ADC12INCH_12;                                                    //BAT-MON.__A12
  ADC12MCTL2 = ADC12EOS | ADC12SREF_2 | ADC12INCH_5;                                          //POT__A5
  ADC12CTL1 = ADC12CSTARTADD_0|ADC12SHS_0|ADC12SHP|ADC12DIV_0|ADC12SSEL_0|ADC12CONSEQ_1;      //ADC12CONSEQ_1 = SEQUENCE OF CHANNELS. .... 

  for (k = 0x4600; k; k--);                                                                   // Delay approx. = 368 ms for needed ref start-up.
  ADC12CTL0 |= ADC12ENC;                                                                      //ENABLE ADC12 for working
}

/*******************************************************************************

 * Function :		PC_UART_Init

 * Description: 	This function initializes USCI_A0; connected to PC

 * Input parameters :   None

 * Output parameters :  None

*******************************************************************************/
void PC_UART_Init(void)                       //USB-serial UART
{
  P3SEL |= BIT4 | BIT5;                       //USCI_A0 ... RXD TXD SELECT 
  UCA0CTL0 &= 0x00;                           //USCYNC = 0 ....... for UART mode.
  UCA0CTL1 |= UCSWRST;                     
  UCA0CTL1 |= UCSSEL_2;                       //select SMCLK = 1 MHz
  UCA0BR0 = 0x09;                             //115200 baud rate..
  UCA0BR1 = 0x00;
  UCA0MCTL = 0x00;
  UCA0CTL1 &= ~UCSWRST;                       //Initialize USCI state machine**
  //UCA0IE |= UCRXIE;                         //Enable USCI_A0 RX interrupt
}

/*******************************************************************************

 * Function :		IMU_UART_Init

 * Description: 	This function initializes USCI_A1; connected to IMU Razor
                        Sensor Board.

 * Input parameters :   None

 * Output parameters :  None

*******************************************************************************/
void IMU_UART_Init(void)                      //IMU UART
{
  P5SEL |= BIT6 | BIT7;
  UCA1CTL0 &= 0x00;
  UCA1CTL1 |= UCSWRST;                     
  UCA1CTL1 |= UCSSEL_2;
  UCA1BR0 = 0x12;                             //57600 baud rate..
  UCA1BR1 = 0x00;
  UCA1MCTL = 0x00;
  UCA1CTL1 &= ~UCSWRST;
}

/*******************************************************************************
 
 * Function :		Bluetooth_UART_Init
 
 * Description: 	This function initializes USCI_A2; connected to 
                        Bluetooth module.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void Bluetooth_UART_Init(void)                //bluethooth UART
{
  P9SEL |= BIT4 | BIT5;            
  UCA2CTL0 &= 0x00;
  UCA2CTL1 |= UCSWRST;                     
  UCA2CTL1 |= UCSSEL_2;                  
  UCA2BR0 = 0x09;                             //115200 baud rate..
  UCA2BR1 = 0x00;
  UCA2MCTL = 0x00;
  UCA2CTL1 &= ~UCSWRST;
  //UCA2IE |= UCRXIE;
}

void main(void)
{
  volatile unsigned int loop_var;

  WDTCTL = WDTPW + WDTHOLD;                                 //WDT made off

  for(loop_var = 0;loop_var < initialDelay;loop_var++);    //approx. 1 sec.
  for(loop_var = 0;loop_var < initialDelay;loop_var++);    //approx. 1 sec.
  for(loop_var = 0;loop_var < initialDelay;loop_var++);    //approx. 1 sec.
  
/*
  do                                                        //for to stabilize the oscillator
  {
    UCSCTL7 &= ~(XT1LFOFFG + DCOFFG);                       //clear XT1, DCO fault flags
    SFRIFG1 &= ~OFIFG;                                      //clear oscillator fault flag.
    for(loop_var = 0x47FF;loop_var > 0;loop_var--);         //delay approx. = 368 ms
  }while((SFRIFG1 & OFIFG));                                //loop till crystal oscillator stabilizes.
*/
  Board_Init();
  ADC12_Init();
  IMU_UART_Init();
  PC_UART_Init();
  Bluetooth_UART_Init();

  __bis_SR_register(GIE);                                   //set Global Interrupt Enable
  //for (k = 0x4600; k; k--);                               //delay to initialize IMU sensor board  

while(1)
{
  if(0x02 & P10IN)                        //P10.1 = 1 ---- for bluetooth
  {
    UART_Select = 1;
    UCA0IE &= ~UCRXIE;
    UCA2IE |= UCRXIE;
  }
  else                                    //P10.1 = 0 ---- for PC
  {
    UART_Select = 0;
    UCA0IE |= UCRXIE;
    UCA2IE &= ~UCRXIE;
  }

  switch(UART_Select)
  {
  case 0:                                       //PC UART selected

          IMU_Buffering();
          n = 0;
          while(IMURazorBuffer[n] != '\r')
          {
            PC_UART_Transmit(IMURazorBuffer[n]);
            n++;
          }

          PC_UART_Transmit(';');
          PC_UART_Transmit('F');
          PC_UART_Transmit('S');
          PC_UART_Transmit('R');
          PC_UART_Transmit(':');

          FSR_Read();
          for(i=0;i<4;i++)                            //FSR decimal transmit
          {
            PC_UART_Transmit(AdcDec[3-i]);
          }

          PC_UART_Transmit(';');
          PC_UART_Transmit('P');
          PC_UART_Transmit('O');
          PC_UART_Transmit('T');
          PC_UART_Transmit(':');
          Pot_Read();
          for(i=0;i<4;i++)                            //POT decimal transmit
          {
            PC_UART_Transmit(PotDec[3-i]);
          }

          PC_UART_Transmit(';');
          PC_UART_Transmit('S');
          PC_UART_Transmit('W');
          PC_UART_Transmit('I');
          PC_UART_Transmit('T');
          PC_UART_Transmit('C');
          PC_UART_Transmit('H');
          PC_UART_Transmit('E');
          PC_UART_Transmit('S');
          PC_UART_Transmit(':');

          Switch_Position_Read();
          PC_UART_Transmit(';');

          Battery_Monitoring();
          PC_UART_Transmit('\n');
          PC_UART_Transmit('\r');

   break;

  case 1:                                        //Bluetooth UART selected

          IMU_Buffering();
          n = 0;
          while(IMURazorBuffer[n] != '\r')
          {
            Bluetooth_UART_Transmit(IMURazorBuffer[n]);
            n++;
          }

          Bluetooth_UART_Transmit(';');
          Bluetooth_UART_Transmit('F');
          Bluetooth_UART_Transmit('S');
          Bluetooth_UART_Transmit('R');
          Bluetooth_UART_Transmit(':');

          FSR_Read();
          for(i=0;i<4;i++)                           //FSR decimal transmit
          {
            Bluetooth_UART_Transmit(AdcDec[3-i]);
          }

           Bluetooth_UART_Transmit(';');
           Bluetooth_UART_Transmit('P');
           Bluetooth_UART_Transmit('O');
           Bluetooth_UART_Transmit('T');
           Bluetooth_UART_Transmit(':');
           Pot_Read();
           for(i=0;i<4;i++)                          //POT decimal transmit
           {
              Bluetooth_UART_Transmit(PotDec[3-i]);
           }

           Bluetooth_UART_Transmit(';');
           Bluetooth_UART_Transmit('S');
           Bluetooth_UART_Transmit('W');
           Bluetooth_UART_Transmit('I');
           Bluetooth_UART_Transmit('T');
           Bluetooth_UART_Transmit('C');
           Bluetooth_UART_Transmit('H');
           Bluetooth_UART_Transmit('E');
           Bluetooth_UART_Transmit('S');
           Bluetooth_UART_Transmit(':');

           Switch_Position_Read();
           Bluetooth_UART_Transmit(';');

           Battery_Monitoring();
           Bluetooth_UART_Transmit('\n');
           Bluetooth_UART_Transmit('\r');
  break;

  default:
    break;
}//switch

}//while(1)

}//main

/*******************************************************************************
 
 * Function :		PC_UART_Transmit
 
 * Description: 	This function transmits data to USCI_A0.
 
 * Input parameters :   unsigned char PC_Transmit_char
  					
 * Output parameters :  None
  					
*******************************************************************************/
void PC_UART_Transmit(unsigned char PC_Transmit_char)
{
  while (!(UCA0IFG&UCTXIFG));                           //wait for TxBuf to become empty
  UCA0TXBUF = PC_Transmit_char;
}

/*******************************************************************************
 
 * Function :		Bluetooth_UART_Transmit
 
 * Description: 	This function transmits data to USCI_A2.
 
 * Input parameters :   unsigned char BL_Transmit_char
  					
 * Output parameters :  None
  					
*******************************************************************************/
void Bluetooth_UART_Transmit(unsigned char BL_Transmit_char)
{
  while (!(UCA2IFG&UCTXIFG));                          //wait for TxBuf to become empty
  UCA2TXBUF = BL_Transmit_char;
}

/*******************************************************************************
 
 * Function :		Pot_Read
 
 * Description: 	This function converts pot`s digitalized value 
                        to decimal.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void Pot_Read(void)
{
  PotTemp = ADC12MEM2;                      //collect digitalized O/P of POT

  for(i=0;i<4;i++)                          //convert to Decimal
  {
    PotDec[i]=(PotTemp%10) + 0x30;          //for HEX->ASCII conversion
    PotTemp = PotTemp/10;                   //for HEX->Decimal conversion
  }
}

/*******************************************************************************
 
 * Function :		IMU_Buffering
 
 * Description: 	This function does the buffering of packets coming from 
                        IMU Razor Sensor Board.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void IMU_Buffering(void)
{
  //P8OUT |= BIT0;              //LED on
  m = 0;
  IMUTemp = 'd';               //for safety purpose
  while(1)
	{
          
            while(IMUTemp != '!')                           //wait till '!' to be received
            {
              if(UCA1IFG&UCRXIFG)
	      {IMUTemp = UCA1RXBUF;}
            }
            
			do                                  //collect a complete packet of IMU Razor. 
			{   
		          IMURazorBuffer[m] = IMUTemp;
                          while(!(UCA1IFG&UCRXIFG));
		          IMUTemp = UCA1RXBUF;
                          m++;
			}while((IMUTemp != '!'));
                        IMURazorBuffer[m] = '\0';
          
			break;
	}
  
  //P8OUT &= ~BIT0;       //LED off
}

/*******************************************************************************
 
 * Function :		FSR_Read
 
 * Description: 	This function converts FSR`s digitalized value 
                        to decimal.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void FSR_Read(void)
{
  ADC12CTL0 |= ADC12SC;                     //start conversion for 3 channels - A7 & A12 & A5
  ADC12temp = 0;         
  while(ADC12CTL1 & ADC12BUSY);             //wait till conversion ends

  ADC12temp = ADC12MEM0;                    //collect converted O/P of FSR

  for(i=0;i<4;i++)                          //convert to Decimal
  {
  AdcDec[i]=(ADC12temp%10) + 0x30;          //for HEX->ASCII conversion
  ADC12temp = ADC12temp/10;                 //for HEX->Decimal conversion
  }
}

/*******************************************************************************
 
 * Function :		Battery_Monitoring
 
 * Description: 	This function checks the battery voltage.
                        Assume Battery deferres @ 2.75V
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void Battery_Monitoring(void)
{
  if(ADC12MEM1 <= 0x11D)                    //considering Vbat_min.= 2.75V
  {
     P3OUT |= BIT0;                         //LED_BATMON ON
     if(UART_Select == 0)
     PC_UART_Transmit('1');
     else
     Bluetooth_UART_Transmit('1');
  }
  else
  {
    P3OUT &= ~BIT0;                        //LED_BATMON OFF
    if(UART_Select == 0)
    PC_UART_Transmit('0');
    else
    Bluetooth_UART_Transmit('0');
  }
}

/*******************************************************************************
 
 * Function :		Switch_Position_Read
 
 * Description: 	This function sends the status of all switches of 
                        the switch board.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
void Switch_Position_Read(void)
{
    if(!(0x40 & P1IN))                        //SW2-P1.6
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x80 & P1IN))                      //SW3-P1.7
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x01 & P2IN))                      //SW4-P2.0
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x02 & P2IN))                      //LEFT-P2.1
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x04 & P2IN))                      //RIGHT-P2.2
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');                  
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x08 & P2IN))                      //SELECT-P2.3
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x10 & P2IN))                      //UP-P2.4
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x20 & P2IN))                      //DOWN-P2.5
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
     {
       if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }

    if(!(0x80 & P2IN))                      //SW6-P2.7
    {
      if(UART_Select == 0)
      PC_UART_Transmit('1');
      else
      Bluetooth_UART_Transmit('1');
    }
      else
      {
        if(UART_Select == 0)
        PC_UART_Transmit('0');
        else
        Bluetooth_UART_Transmit('0');
      }
}

/*******************************************************************************
 
 * Function :		startTB
 
 * Description: 	This function starts the TIMER_B & speaker 
                        on speaker sound request.
 
 * Input parameters :   unsigned int count0,unsigned int count1,unsigned int delayTime
  					
 * Output parameters :  None
  					
*******************************************************************************/
void startTB(unsigned int count0,unsigned int count1,unsigned int delayTime)
{
  TBCCR0 = count0;                            // PWM Period
  TBCCTL4 = OUTMOD_7;                         // CCR4 reset/set
  TBCCR4 = count1;                            // CCR4 PWM duty cycle	
  TBCTL = TBSSEL_2 + MC_1;                    // SMCLK, upmode
  delayGen(delayTime);
}

/*******************************************************************************
 
 * Function :		delayGen
 
 * Description: 	This function starts the TIMER_A1 on speaker sound request.
 
 * Input parameters :   unsigned int tcount
  					
 * Output parameters :  None
  					
*******************************************************************************/
void delayGen(unsigned int tcount)
{
  //P8OUT ^= BIT0;
  TA1CCR0 = tcount;                         //Timer_A1 compare count
  TA1CCTL0 |= CCIE;                         //enable Timer_A1 Interrupt
  TA1CTL = TASSEL_1 + ID_3 + MC_2;          //Select ACLK, divider 8, Continuous mode
}

/*******************************************************************************
 
 * Function :		TIMER1_A0_ISR
 
 * Description: 	This ISR function stops the TIMER_A1.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
  //P7OUT ^= BIT3;
  TA1CCTL0 &= ~CCIE;                          //clear Timer_A1 interrupt flag
  TA1CTL |= TACLR;                            //clears all counts of Timer_A1
  TA1CTL &= MC_0;                             //Stop Timer_A1
  TBCTL |= TBCLR;                             //clears all counts of Timer_B
  TBCTL &= MC_0;                              //Stop Timer_B
  module = 0;                                 
  digitCnt = 0;
  digit3Rcvd = 0;
  pDetected = 0;
  eDetected = 0;                              //clear all static global flags for safety purpose
}

/*******************************************************************************
 
 * Function :		StartVibration
 
 * Description: 	This function starts the Vibration motor & TIMER_A0
                        on vibration motor request.
 
 * Input parameters :   unsigned int tcount
  					
 * Output parameters :  None
  					
*******************************************************************************/
void StartVibration(unsigned int vtime)
{
  volatile unsigned int x,y;
  
  P4OUT |= BIT6;                                //start vibration motor
  //P7OUT &= ~BIT3;

  TA0CCR0 = (vtime*4);                          //Initialize Timer_A0 compare count 
  TA0CCTL0 |= CCIE;                             //Enable Timer_A0 interrupt flag 
  TA0CTL = TASSEL_1 + ID_3 + MC_2;              //Select ACLK, divider 8, Continuous mode
}

/*******************************************************************************
 
 * Function :		TIMER0_A0_ISR
 
 * Description: 	This ISR function stops the TIMER_A0.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
  //P7OUT ^= BIT3;
  P4OUT &= ~BIT6;                           //turn off vibration motor.
  TA0CCTL0 &= ~CCIE;                        //clear Timer_A0 interrupt flag
  TA0CTL |= TACLR;                          //clear Timer_A0
  TA0CTL &= MC_0;                           //stop Timer_A0
  vModule = 0;                            
  iDetected = 0;
  bDetected = 0;                            //clear all static global flags for safety purpose
}

/*******************************************************************************
 
 * Function :		USCI_A0_ISR
 
 * Description: 	ISR function of USCI_A0.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
{
  switch(__even_in_range(UCA0IV,4))
  {
  case 0:break;                             // Vector 0 - no interrupt
  case 2:                                   // Vector 2 - RXIFG
    
    tmp = UCA0RXBUF;
    while (!(UCA0IFG&UCTXIFG));
    UCA0TXBUF = tmp;

    if((tmp == 's')/* | (tmp == 'S')*/)
    {
      module = 1;
      cmdRcvd = 0;
      delay = 0;
      previousDelayDigit = 0;
      delayFinished = 0;
      multiDigitDelay = 0;
      tone = 0;
      digitCnt = 0;
      digit3Rcvd = 0;
      pDetected = 0;
      eDetected = 0;
      break;
    }
    if((tmp == 'v') /*|(tmp == 'V')*/)
    {
      vModule = 1;
      VCmdRcvd = 0;
      vDelay = 0;
      VPreviousDelayDigit = 0;
      VMultiDigitDelay = 0;
      VDigitCnt = 0;
      iDetected = 0;
      bDetected = 0;
      break;
    }
       if(module == 1 )                             
       {
	  if((cmdRcvd != 1) &  (tmp == 'p') & (pDetected != 1) & (tmp != ','))
          {
            pDetected = 1;
	  //break;
	  }
	  if((cmdRcvd != 1) &  (tmp == 'e') & (pDetected == 1) & (eDetected != 1) & (tmp != ','))
          {
            eDetected = 1;
	  //break;
	  }
	  
          if((cmdRcvd != 1) & (tmp == ',') & (digit3Rcvd != 1) & (pDetected == 1) & (eDetected == 1))
          {
	    cmdRcvd = 1;
	    //break;
	  }
           	  
          if((cmdRcvd == 1) & (digitCnt <= 3) & (tmp >= '0') & (tmp <= '9') & (digit3Rcvd != 1) & (pDetected == 1) & (eDetected == 1))
          {
          digitCnt++;
	  delay = tmp - '0'; 
          if(digitCnt == 1)
          {
            multiDigitDelay = delay * 100;
            previousDelayDigit = multiDigitDelay;
          }
          if(digitCnt == 2)
          {
            multiDigitDelay = previousDelayDigit + (delay * 10);
            previousDelayDigit = multiDigitDelay;
          }
          if(digitCnt == 3)
          {
            multiDigitDelay = previousDelayDigit + delay;
            digit3Rcvd = 1;
          }
	  //break;
	  }
          
	  if((cmdRcvd == 1) & (digit3Rcvd == 1) & (tmp== ',') & (delayFinished != 1) & (pDetected == 1) & (eDetected == 1))
          {
            delayFinished = 1;
	    //break;		  		
	  }
            	  
	  if((delayFinished == 1) & (tmp >= '1') & (tmp <= '3') & (pDetected == 1) & (eDetected == 1))
          {
	    tone = tmp;
          
            time = multiDigitDelay * 4;              //delay is in msec. if you want delay in sec. make "time = delay * 4000;"
            TA1CTL |= TACLR;
            TBCTL |= TBCLR;
            if(tone == '1')
            {
              startTB(1023,256,time);
              //break;
            }
            if(tone == '2')
            {
              startTB(332,167,time);
              //break;
            }
            if(tone == '3')
            {
              startTB(255,64,time);
              //break;
            }
          }
      }

      if( vModule == 1)
      {
	if( (VCmdRcvd != 1) &  (tmp =='i') & (iDetected != 1)  & (tmp != ','))
        {
          iDetected = 1;
	  break;
	}
	if( (VCmdRcvd != 1) &  (tmp =='b') & (iDetected == 1)  & (bDetected != 1) & (tmp != ','))
        {
          bDetected = 1;
	  break;
	}
        
	if( (VCmdRcvd != 1) & (tmp == ',') & (iDetected == 1)  & (bDetected == 1))
        {
	  VCmdRcvd = 1;
	  break;
	}
	if((VCmdRcvd == 1) & (VDigitCnt <= 3 ) & (iDetected == 1)  & (bDetected == 1))
          {
          VDigitCnt++;
	  vDelay = tmp - '0'; 
          if(VDigitCnt == 1)
          {
            VMultiDigitDelay = vDelay * 100;
            VPreviousDelayDigit = VMultiDigitDelay;
          }
          if(VDigitCnt == 2)
          {
            VMultiDigitDelay = VPreviousDelayDigit + (vDelay * 10);
            VPreviousDelayDigit = VMultiDigitDelay;
          }
          if(VDigitCnt == 3)
          {
            VMultiDigitDelay = VPreviousDelayDigit + vDelay;
            {StartVibration(VMultiDigitDelay);}
          }
	  break;
	  }

      }
    break;
  case 4:

    break;                             // Vector 4 - TXIFG
  default: break;  
  }

}

/*******************************************************************************
 
 * Function :		USCI_A2_ISR
 
 * Description: 	ISR function of USCI_A2.
 
 * Input parameters :   None
  					
 * Output parameters :  None
  					
*******************************************************************************/
#pragma vector = USCI_A2_VECTOR
__interrupt void USCI_A2_ISR (void)
{
  switch(__even_in_range(UCA2IV,4))
  {
  case 0:break;                             // Vector 0 - no interrupt
  case 2:                                   // Vector 2 - RXIFG
    
    tmp = UCA2RXBUF;
    while (!(UCA2IFG&UCTXIFG));
    UCA2TXBUF = tmp;

    if((tmp == 's') /*| (tmp == 'S')*/)
    {
      module = 1;
      cmdRcvd = 0;
      delay = 0;
      previousDelayDigit = 0;
      delayFinished = 0;
      multiDigitDelay = 0;
      tone = 0;
      digitCnt = 0;
      digit3Rcvd = 0;
      pDetected = 0;
      eDetected = 0;
      break;
    }
    if((tmp == 'v') /*|(tmp == 'V')*/)
    {
      vModule = 1;
      VCmdRcvd = 0;
      vDelay = 0;
      VPreviousDelayDigit = 0;
      VMultiDigitDelay = 0;
      VDigitCnt = 0;
      iDetected = 0;
      bDetected = 0;
      break;
    }
       if(module == 1 )
       {
	  if((cmdRcvd != 1) &  (tmp == 'p') & (pDetected != 1) & (tmp != ','))
          {
            pDetected = 1;
	  //break;
	  }
	  if((cmdRcvd != 1) &  (tmp == 'e') & (pDetected == 1) & (eDetected != 1) & (tmp != ','))
          {
            eDetected = 1;
	  //break;
	  }
	  
          if((cmdRcvd != 1) & (tmp == ',') & (digit3Rcvd != 1) & (pDetected == 1) & (eDetected == 1))
          {
	    cmdRcvd = 1;
	    //break;
	  }
           	  
          if((cmdRcvd == 1) & (digitCnt <= 3) & (tmp >= '0') & (tmp <= '9') & (digit3Rcvd != 1) & (pDetected == 1) & (eDetected == 1))
          {
          digitCnt++;
	  delay = tmp - '0'; 
          if(digitCnt == 1)
          {
            multiDigitDelay = delay * 100;
            previousDelayDigit = multiDigitDelay;
          }
          if(digitCnt == 2)
          {
            multiDigitDelay = previousDelayDigit + (delay * 10);
            previousDelayDigit = multiDigitDelay;
          }
          if(digitCnt == 3)
          {
            multiDigitDelay = previousDelayDigit + delay;
            digit3Rcvd = 1;
          }
	  //break;
	  }
          
	  if((cmdRcvd == 1) & (digit3Rcvd == 1) & (tmp== ',') & (delayFinished != 1) & (pDetected == 1) & (eDetected == 1))
          {
            delayFinished = 1;
	    //break;		  		
	  }
            	  
	  if((delayFinished == 1) & (tmp >= '1') & (tmp <= '3') & (pDetected == 1) & (eDetected == 1))
          {
	    tone = tmp;
          
            time = multiDigitDelay * 4;              //delay is in msec. if you want delay in sec. make "time = delay * 4000;"
            TA1CTL |= TACLR;
            TBCTL |= TBCLR;
            if(tone == '1')
            {
              startTB(1023,256,time);
              //break;
            }
            if(tone == '2')
            {
              startTB(332,167,time);
              //break;
            }
            if(tone == '3')
            {
              startTB(255,64,time);
              //break;
            }
          }
      }

      if( vModule == 1)
      {
	if( (VCmdRcvd != 1) &  (tmp =='i') & (iDetected != 1)  & (tmp != ','))
        {
          iDetected = 1;
	  break;
	}
	if( (VCmdRcvd != 1) &  (tmp =='b') & (iDetected == 1)  & (bDetected != 1) & (tmp != ','))
        {
          bDetected = 1;
	  break;
	}
        
	if( (VCmdRcvd != 1) & (tmp == ',') & (iDetected == 1)  & (bDetected == 1))
        {
	  VCmdRcvd = 1;
	  break;
	}
	if((VCmdRcvd == 1) & (VDigitCnt <= 3 ) & (iDetected == 1)  & (bDetected == 1))
          {
          VDigitCnt++;
	  vDelay = tmp - '0'; 
          if(VDigitCnt == 1)
          {
            VMultiDigitDelay = vDelay * 100;
            VPreviousDelayDigit = VMultiDigitDelay;
          }
          if(VDigitCnt == 2)
          {
            VMultiDigitDelay = VPreviousDelayDigit + (vDelay * 10);
            VPreviousDelayDigit = VMultiDigitDelay;
          }
          if(VDigitCnt == 3)
          {
            VMultiDigitDelay = VPreviousDelayDigit + vDelay;
            {StartVibration(VMultiDigitDelay);}
          }
	  break;
	  }

      }
    break;
  case 4:

    break;                             // Vector 4 - TXIFG
  default: break;  
  }

}

bitbang (software) SPI implementation

Fabien Le Mentec March 28, 2013 Coded in C for the atmega328p
#include <stdint.h>
#include <avr/io.h>

/* default pins */
#define SOFTSPI_CLK_DDR DDRD
#define SOFTSPI_CLK_PORT PORTD
#define SOFTSPI_CLK_MASK (1 << 3)
#define SOFTSPI_MOSI_DDR DDRD
#define SOFTSPI_MOSI_PORT PORTD
#define SOFTSPI_MOSI_MASK (1 << 4)

#ifndef SOFTSPI_DONT_USE_MISO
#define SOFTSPI_DONT_USE_MISO 0
#endif

#if (SOFTSPI_DONT_USE_MISO == 0)
#define SOFTSPI_MISO_DDR DDRD
#define SOFTSPI_MISO_PIN PIND
#define SOFTSPI_MISO_MASK (1 << 5)
#endif

static void softspi_setup_master(void)
{
  SOFTSPI_CLK_DDR |= SOFTSPI_CLK_MASK;
  SOFTSPI_MOSI_DDR |= SOFTSPI_MOSI_MASK;

#if (SOFTSPI_DONT_USE_MISO == 0)
  SOFTSPI_MISO_DDR |= SOFTSPI_MISO_MASK;
#endif
}

static inline void softspi_clk_low(void)
{
  SOFTSPI_CLK_PORT &= ~SOFTSPI_CLK_MASK;
}

static inline void softspi_clk_high(void)
{
  SOFTSPI_CLK_PORT |= SOFTSPI_CLK_MASK;
}

static inline void softspi_mosi_low(void)
{
  SOFTSPI_MOSI_PORT &= ~SOFTSPI_MOSI_MASK;
}

static inline void softspi_mosi_high(void)
{
  SOFTSPI_MOSI_PORT |= SOFTSPI_MOSI_MASK;
}

static inline void softspi_write_bit(uint8_t x, uint8_t m)
{
  /* dac7554 samples at clock falling edge */

  /* 5 insns per bit */

  softspi_clk_high();
  if (x & m) softspi_mosi_high(); else softspi_mosi_low();
  softspi_clk_low();
}

static void softspi_write_uint8(uint8_t x)
{
  /* transmit msb first, sample at clock falling edge */

  softspi_write_bit(x, (1 << 7));
  softspi_write_bit(x, (1 << 6));
  softspi_write_bit(x, (1 << 5));
  softspi_write_bit(x, (1 << 4));
  softspi_write_bit(x, (1 << 3));
  softspi_write_bit(x, (1 << 2));
  softspi_write_bit(x, (1 << 1));
  softspi_write_bit(x, (1 << 0));
}

static inline void softspi_write_uint16(uint16_t x)
{
  softspi_write_uint8((uint8_t)(x >> 8));
  softspi_write_uint8((uint8_t)(x & 0xff));
}

#if (SOFTSPI_DONT_USE_MISO == 0)

static inline void softspi_read_bit(uint8_t* x, uint8_t i)
{
  /* read at falling edge */

  softspi_clk_high();
#if 0
/* no need, atmega328p clock below 50mhz */
/* softspi_wait_clk(); */
#endif
  softspi_clk_low();

  if (SOFTSPI_MISO_PIN & SOFTSPI_MISO_MASK) *x |= 1 << i;
}

static uint8_t softspi_read_uint8(void)
{
  /* receive msb first, sample at clock falling edge */

  /* must be initialized to 0 */
  uint8_t x = 0;

  softspi_read_bit(&x, 7);
  softspi_read_bit(&x, 6);
  softspi_read_bit(&x, 5);
  softspi_read_bit(&x, 4);
  softspi_read_bit(&x, 3);
  softspi_read_bit(&x, 2);
  softspi_read_bit(&x, 1);
  softspi_read_bit(&x, 0);

  return x;
}

static inline uint16_t softspi_read_uint16(void)
{
  /* msB ordering */
  const uint8_t x = softspi_read_uint8();
  return ((uint16_t)x << 8) | (uint16_t)softspi_read_uint8();
}

#endif /* SOFTSPI_DONT_USE_MISO == 0 */

Finite State Machine Template

Gabriel Rivas March 28, 20131 comment Coded in C
/*********************************************************************
Finiste State Machine design example

FSM based embedded software design has several advantages:
1. You can translate the systems' requirements into FSM diagramas or
state transition tables.
2. From the FSM diagram or state transition table you can validate if the design
is right or wrong before actually start coding.
3. It makes the code easier to understand
4. You can have traceability from the requirements document to the
code
5. Determinism; you can now exactly what the system is doing at any time
6. Hmmm I don't know, they just look good in C! 

In this code Example it is shown how to implement the following FSM
state transition table into C code. You can use this as a template by 
replacing inputs and outputs sets, set of states by your actual application 
values.

I hope this helps.

Current State	INPUT_0	INPUT_1	INPUT_2	INPUT_3	Next State	OUTPUT_0
DETECT_IN0	    0	    X	    X	    X	    DETECT_IN1	0
	            1	    X	    X	    X	    DETECT_IN0	0
DETECT_IN1	    X	    0	    X	    X	    DETECT_IN2	0
	            X	    1	    X	    X	    DETECT_IN1	0
DETECT_IN2	    X	    X	    0	    X	    DETECT_IN3	0
	            X	    X	    1	    X	    DETECT_IN2	0
DETECT_IN3	    X	    X	    X	    0	    SET_OUTPUT	0
	            X       X	    X	    1	    DETECT_IN3	0
SET_OUTPUT	    X	    X	    X	    X	    DETECT_IN0	1
	            X	    X	    X	    X	    DETECT_IN0	1
 *
 ********************************************************************/
 
#include <stdio.h>

/*Inputs and outputs sets
You can give meaningful names to the IO ports of your microcontroller,
and that will make the code easier to understand and make it consistent
with a FSM diagram or state transition table
*/
#define INPUT_0  PTA0
#define INPUT_1  PTA1
#define INPUT_2  PTA2
#define INPUT_3  PTA3
#define OUTPUT_0 PTB0

/*
The inputs have pull-ups resistors so we can define a condition
to identify when an input has been selected, in this case an
input is selected when its value is 0
*/
#define SELECTED 0x00

/*Set of states
It is more convenient to give meaningful names to the states
and it's better when you can map them to a finite state machine
diagram or state transition table.
*/
typedef enum { DETECT_IN0 = 0x00, 
               DETECT_IN1, 
               DETECT_IN2, 
               DETECT_IN3, 
	       SET_OUTPUT} SM_STATES;

/*We need a state variable to store the next state value as well
and we have to assign an initial state to it
*/
unsigned char state = DETECT_IN0;

int ctr_ms = 500;  /*This finite state machine executes every 500 ms*/

/*wait function*/
static unsigned char wait_ms(void);

void main(void) {
    for(;;) {
        if(wait_ms()) {  /*The state machine is synch to a timer*/
            switch(state) {
                case DETECT_IN0:
                    OUTPUT_0 = 0;
                    if(INPUT_0 == SELECTED) {   
                        state = DETECT_IN1;					
                    }
                    break;
                case DETECT_IN1:
                    if(INPUT_1 == SELECTED) {   
                        state = DETECT_IN2;					
                    }
                    break;		
                case DETECT_IN2:
                    if(INPUT_2 == SELECTED) {   
                        state = DETECT_IN3;					
                    }
                    break;	
                case DETECT_IN3:
                    if(INPUT_3 == SELECTED) {   
                        state = SET_OUTPUT;					
                    }
                    break;	
                case SET_OUTPUT:
                    OUTPUT_0 = 1;
		    state = DETECT_IN0;	
                    break;					
                default:
                /*None of the above*/
                break;                
            }
	}
    } /* loop forever */
  /* please make sure that you never leave main */
}

unsigned char wait_ms(void) {
    unsigned char ctr_flag;
    
    ctr_flag = 0;

	/*Test for timer overflow flag*/
    if(TPM_Get_OVFlag() == 1) {     
        if (ctr_ms == 0) {
            ctr_flag = 1;
         } else {
            ctr_ms--;  
         }
         TPM_Clr_OVFlag();          
     }
     return ctr_flag; 
}

SHT11 humidity sensor library (sensirion manufacture)

March 25, 20131 comment Coded in C
/*********** begin of library header file sht11.h ***************/

#ifndef _SHTXX_H
#define _SHTXX_H

#include <inttypes.h>

#define HUMIDITY_BYTE    0x05
#define TEMPERATURE_BYTE 0x03

//State machine states

#define SHT_DATA_WAIT_INITIAL_STATE     0
#define SHT_DATA_WAIT_TIMEOUT_STATE     1

#define SHT_PROC_RESET_COND_STATE       0   
#define SHT_PROC_START_COND_STATE       1
#define SHT_PROC_SEND_STATE             2
#define SHT_PROC_WAIT_STATE             3
#define SHT_PROC_RETURN_STATE           4

#define SHT_RH_READ_TEMPERATURE_STATE   0
#define SHT_RH_READ_HUMIDITY_STATE      1
#define SHT_RH_CONVERT_RH_STATE         2

#include <sht_low_level_drv.h>

void shtxx_init(void);

int shtxx_proc(uint8_t sht_param,uint16_t *ret_value);

int shtxx_get_temp(uint16_t *ret_temperature);
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity );

#endif /* _SHTXX_H */

/*********** begin of library source file sht11.c ***************/
#include "sht11.h"

void shtxx_init( void )
{
    shtxx_set_db();
    shtxx_set_cb();
}

void shtxx_wait( void ) //SHT_WAIT should be tuned acording to MCU clock
{
    volatile int wait_cnt;
    for ( wait_cnt = 0; wait_cnt < SHT_WAIT;wait_cnt )
    {
        wait_cnt++;
    }
}

void shtxx_reset_condition( void )
{
    uint8_t i;
    shtxx_set_db();
    shtxx_set_out_data_dir();
    for ( i = 0;i < 12;i++ )
    {
        if ( i % 2 == 0 )
            shtxx_set_cb();
        else
            shtxx_clr_cb();
        shtxx_wait();
    }
}

void shtxx_start_condition( void )
{
    shtxx_set_db();
    shtxx_set_out_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_clr_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_set_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();

}

int shtxx_send_byte( uint8_t sht_data2send )
{
    uint8_t i = 0;
    while ( i <= 7 )
    {
        if ( ( ( sht_data2send << i++ ) & 0x80 ) == 0x80 )
            shtxx_set_db();
        else
            shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();

    }
    shtxx_set_in_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    if ( shtxx_get_db() == 0 )
        return 1;

    else
        return -1;
}

int shtxx_data_wait( sht_ticks_t sht_timeout )
{
    static uint8_t sht_wait_state;
    static sht_ticks_t sht_previous_ticks;

    switch ( sht_wait_state )
    {
    case SHT_DATA_WAIT_INITIAL_STATE:
        sht_previous_ticks = sht_msec_ticks;
        sht_wait_state = SHT_DATA_WAIT_TIMEOUT_STATE;
        shtxx_set_in_data_dir();
        shtxx_clr_cb();

    case SHT_DATA_WAIT_TIMEOUT_STATE:
        if ( shtxx_get_db() == 0 )
        {
            sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
            return 1;
        }
        else
        {
            if ( ( sht_msec_ticks - sht_previous_ticks ) > sht_timeout )
            {
                sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
                return -1;
            }
            else
                return 0;
        }
    }
}

uint8_t sht_read_byte( uint8_t sht_ack )
{
    shtxx_set_in_data_dir();
    uint8_t temp_rx_buff = 0;
    int8_t i = 7;
    while ( i >= 0 )
    {
        shtxx_wait();
        shtxx_set_cb();
        temp_rx_buff |= ( ( shtxx_get_db() & 0x01 ) << i );
        i--;
        shtxx_wait();
        shtxx_clr_cb();

    }

    if ( sht_ack == 1 )
    {
        shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();
        shtxx_set_in_data_dir();

    }
    return temp_rx_buff;
}

int shtxx_proc( uint8_t sht_param, uint16_t *ret_value )
{

    static uint8_t sht_proc_state = 0;
    int8_t	wait_status;

    switch ( sht_proc_state )
    {
    case SHT_PROC_RESET_COND_STATE:
        shtxx_reset_condition();
    case SHT_PROC_START_COND_STATE:
        shtxx_start_condition();
    case SHT_PROC_SEND_STATE:
        shtxx_send_byte( sht_param );
    case SHT_PROC_WAIT_STATE:
        wait_status = shtxx_data_wait( 300 );
        if ( wait_status == -1 )
        {
            sht_proc_state = SHT_PROC_RESET_COND_STATE;
            return -1;

        }
        if ( wait_status == 0 )
        {
            sht_proc_state = SHT_PROC_WAIT_STATE;
            return 0;
        }
        else
            sht_proc_state = SHT_PROC_RETURN_STATE;
    case SHT_PROC_RETURN_STATE:
        *ret_value = ( ( uint16_t ) sht_read_byte( 1 ) << 8 );
        shtxx_wait();
        *ret_value += sht_read_byte( 0 );
        sht_proc_state = SHT_PROC_START_COND_STATE;
        return 1;

    }
}

int shtxx_get_temp( uint16_t *ret_temperature )
{
    static uint16_t tmp_temp;
    if ( shtxx_proc( TEMPERATURE_BYTE, &tmp_temp ) == 1 )
    {
        *ret_temperature = tmp_temp - 3965;
        return 1;
    }
    else
        return 0;
}

int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity )
{

    static uint8_t sht_humidity_state;
    static uint16_t sht_humidity_raw;
    static uint16_t sht_temp_C;

    static float RH_linear;
    static float RH_compensated;

    switch ( sht_humidity_state )
    {
    case SHT_RH_READ_TEMPERATURE_STATE:
        if ( shtxx_get_temp( &sht_temp_C ) )
            sht_humidity_state = SHT_RH_READ_HUMIDITY_STATE;
        break;
    case SHT_RH_READ_HUMIDITY_STATE:
        if ( shtxx_proc( HUMIDITY_BYTE, &sht_humidity_raw ) )
            sht_humidity_state = SHT_RH_CONVERT_RH_STATE;
        break;
    case SHT_RH_CONVERT_RH_STATE:
        RH_linear = ( float ) ( ( 0.0405 * ( float ) sht_humidity_raw ) - ( 0.0000028 * ( float ) sht_humidity_raw * ( float ) sht_humidity_raw ) - 4 );
        RH_compensated = ( float ) ( ( ( ( ( ( float ) sht_temp_C ) / 100 ) - 25 ) * ( 0.01 + ( 0.00008 * ( float ) sht_humidity_raw ) ) ) + RH_linear );
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
        *ret_temperature = sht_temp_C;
        *ret_humidity = ( ( int16_t ) ( RH_compensated * 100 ) );
        return 1;
    default:
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
    }
	return 0;
}

/*** sample low-level functions (platform dependent) sht_low_level_drv.h ***/

#ifndef _SHT_LOW_LEVEL_DRV_H
#define _SHT_LOW_LEVEL_DRV_H

#include <types.h>
#include <system_def.h> /* for concrete HW,  SHT_PORT, SHT_DATA_BIT must be defined*/

#define SHT_MAX_CLK		100000
#define SHT_WAIT		(CCLK/SHT_MAX_CLK) /* CCLK is MCU clock */
#define sht_ticks_t		uint32_t
#define sht_msec_ticks		sys_timer_ticks /* this variable should be defined in BSP and incremented each ms (usually in some timer interrupt routine) */

static inline void shtxx_set_db(void)
{
	
	SET_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_clr_db(void)
{
	CLR_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_set_cb(void)
{
	SET_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline void shtxx_clr_cb(void)
{
	CLR_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline uint8_t shtxx_get_db(void)
{
	return(	GET_IN_PIN(SHT_PORT,SHT_DATA_BIT) );	
}

static inline void shtxx_set_in_data_dir(void)
{
	IO0DIR &=~(SHT_DATA_BIT);
}

static inline void shtxx_set_out_data_dir(void)
{
	IO0DIR |= SHT_DATA_BIT ;
}

#endif /* _SHT_LOW_LEVEL_DRV_H */

/********************* sample usage in main program ************************/

//..............
int16_t temperature, humidity;

while(1) //main loop of the user program
{
    if (shtxx_get_temp_RH( &temperature, &humidity )
    {
        //do something
    }
    //do other operations
    //.....................      
}

Interface matrix Keypad

March 25, 2013 Coded in C for the Microchip PIC16
/Keypad connection: 

#define col0 PIN_B3
#define col1 PIN_B2
#define col2 PIN_B1
#define col3 PIN_B0
#define row0 PIN_B7
#define row1 PIN_B6
#define row2 PIN_B5
#define row3 PIN_B4

#define num_col 4

// Keypad layout:
char const KEYS[4][4] = {{1,2,3,13},
                         {4,5,6,14},
                         {7,8,9,15},
                         {11,10,12,16}};

void init_keypad()
{
	output_high(row0);
	output_high(row1);
	output_high(row2);
	output_high(row3);
	output_low(col0);
	output_low(col1);
	output_low(col2);
	output_low(col3);	
}

short int ALL_ROWS (void)
{
   if (input (row0) & input (row1) & input (row2) & input (row3))
      return (0);
   else
      return (1);
}

//Will return a key value if pressed or 0 if not 

int8 get_key()
{
int8 row,col=0;
	do	
	{
		switch (col)
		{
			case 0   :
				output_low(col0);
				output_high(col1);
				output_high(col2);
				output_high(col3);
				break;
			case 1   :
				output_high(col0);
				output_low(col1);
				output_high(col2);
				output_high(col3);
				break;
			case 2   : 
				output_high(col0);
				output_high(col1);
				output_low(col2);
				output_high(col3);
				break;
			case 3   : 
				output_high(col0);
				output_high(col1);
				output_high(col2);
				output_low(col3);
				break;                    
		}
		
		if(!input (row0))
			row=1;
		else if(!input (row1))
			row=2;
		else if(!input (row2))
			row=3;
		else if(!input (row3))
			row=4;
		else
			row=0;
		col++;
	}while(!row && col<num_col);	
	if(row)
        return KEYS[row-1][col-1];
    else
        return 0;		
}
//function waits until any key is pressed and released.
int8 get_key_released()
{
int8 _key_temp ;
    do
    {
        _key_temp=get_key();
    }while(!_key_temp);
    init_keypad();
    do
    {
        while(ALL_ROWS());
        delay_ms(50);
    }
    while(ALL_ROWS());
return _key_temp;
}

I2C driver using bit bang

Sathyanarayana Hadadi March 24, 20138 comments Coded in C
typedef struct 
{
  unsigned int PIN0:1;
  unsigned int PIN1:1;
  unsigned int PIN2:1;
  unsigned int PIN3:1;
  unsigned int PIN4:1;
  unsigned int PIN5:1;
  unsigned int PIN6:1;
  unsigned int PIN7:1;
} PORT;

/* TODO: Example address shown, but the proper address */
#define PORT0 *(volatile PORT *)0x1234

/* Define the port used for I2C data and clk as shown above to access them pin wise */
#define I2C_DATA PORT0.PIN0
#define I2C_CLK  PORT0.PIN1

#define HIGH 1
#define LOW  0

/* I2C Start - bit bang */
void I2C_START(void)
{
    /* I2C Start condition, data line goes low when clock is high */
    I2C_DATA = HIGH;
    I2C_CLK = HIGH;
    I2C_DATA = LOW;
    I2C_CLK = LOW;
}

/* I2C Stop - bit bang */
void I2C_STOP (void)
{
    /* I2C Stop condition, clock goes high when data is low */
    I2C_CLK = LOW;
    I2C_DATA = LOW;
    I2C_CLK = HIGH;
    I2C_DATA = HIGH;
}

/* I2C Write - bit bang */
void I2C_WRITE(unsigned char data)
{
	unsigned char outBits;
	unsigned char inBit;
	
 	/* 8 bits */
	for(outBits = 0; outBits < 8; outBits++) 
	{
	    if(data & 0x80)
		    I2C_DATA = 1;
		else
		    I2C_DATA = 0;
      	data  <<= 1;
		/* Generate clock for 8 data bits */
		SCLK = HIGH;
		SCLK = LOW;					
	}
	
	/* Generate clock for ACK */
	I2C_CLK = HIGH;
        /* Wait for clock to go high, clock stretching */
        while(I2C_CLK);
        /* Clock high, valid ACK */
	inBit = I2C_DATA;
	I2C_CLK = LOW;					
}

unsigned char I2C_READ (void)
{
	unsigned char inData, inBits;

	inData = 0x00;
	/* 8 bits */
	for(inBits = 0; inBits < 8; inBits++)
	{
		inData <<= 1;
		I2C_CLK = HIGH;
      	inData |= I2C_DATA;
		I2C_CLK = LOW;					
	}

   return inData;
}

/* Examble for writing to I2C Slave */
void writeI2CSlave (unsigned char data)	
{
    /* Start */
  	I2C_START();
	/* Slave address */
   	I2C_WRITE(0xAA)
	/* Slave control byte */
   	I2C_WRITE(0xBB);
	/* Slave data */
   	I2C_WRITE(data);
	/* Stop */
   	I2C_STOP();
}

/* Examble for reading from I2C Slave */
unsigned char readI2CSlave(unsigned char data)
{
   	unsigned char inData;

	/* Start */
  	I2C_START(); 
	/* Slave address */
   	I2C_WRITE(0xAA);
	/* Slave control byte */
   	I2C_WRITE(data);
	/* Stop */
   	I2C_STOP();
	
	/* Start */
   	I2C_START();
	/* Slave address + read */
   	I2C_WRITE(0xAA | 1);
	/* Read */
	inData = I2C_READ();

   	return inData;                 
}

Simple serial and timer ISR state machine

March 23, 2013 Coded in C for the Atmel AT89
/*
    k164_js.c
    
    Purpose:    New firmware for the k164 dtmf decoder board and
                the AT89C2051-24PC The source code was compiled with sdcc.

    URLs:
        http://www.digikey.com/product-detail/en/AT89C2051-24PU/AT89C2051-24PU-ND/1118880
        http://www.electronics123.com/kits-and-modules/Telephone-Call-Logger-Kit-16k.html
        http://www.kitsrus.com/pdf/k164.pdf

    Compile:    sdcc k164_js.c ; packihx k164_js.ihx > k164_js.hex
    Simulate:   s51 k164_js.hex

    Copyright (C) 2009 Nu Tech Software Solutions, Inc.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.

    AUTHOR: Sean Mathews <coder at f34r.com> 1/27/2009

*/

#include <at89x051.h>

#define STATUS_LED  P3_5
#define HOOK_LED    P3_4
#define LOOP_STATUS P3_3
#define STD_STATUS  P3_7
#define MODE_SWITCH P1_5

/* UART parameters                                            */
#define CpuClk        20275200              // 20.2752 MHz clock chip on the k164 board
#define Baudrate      9600                  // UART - 9600,N,8,1 baud used by current firmware
#define Timer1ReloadValue (256-(2*CpuClk/32/12/Baudrate))

#define F34R_MODE   0

char szVERSION[] = "V1.0";

/*
To determine the value that must be placed in TH1 to generate a given baud rate, we may use the following equation (assuming PCON.7 is clear).
      TH1 = 256 - ((Crystal / 384) / Baud) 
If PCON.7 is set then the baud rate is effectively doubled, thus the equation becomes:
      TH1 = 256 - ((Crystal / 192) / Baud)      

  make this next macro work and we wont hvae to hard code the values ... 
 */
#define InterruptRate 10000    // how oftin to hit our interrupt per second
#define Timer0H           0xBE //(char)((0xFF00 & (65536 - (InterruptRate / 12 * 1000))) >> 8)
#define Timer0L           0x00 //(char)(0x00FF & (65536 - (InterruptRate / 12 * 1000)))

/* prototypes                                                 */
void hw_init();
char getchar( void );
void myputchar( char c );
void doevents();
void myputs(char *);
void itoa(int value, char* string, int radix);
void uitoa(unsigned int value, char* string, int radix);
void send_version(void);
void send_hello(void);
void send_help(void);

#define UNKNOWN  0x01
#define OFFHOOK  0x02
#define ONHOOK   0x03
#define VERSION  0x04
#define EGGS     0x05
#define RESET    0x06
#define SEND_HELP 0x07

char hook_state;
char input_state;

int notdone=1;

#define ON       0x02
#define OFF      0x03
char std_state;

static char state_machine_active=0;

/* plug all of the other interrupt vectors                    */
#ifdef SDCC
void mydummyISR (void) interrupt 12 _naked {
}
#endif

/* Serial interrupt to track incoming key strokes             */
void serial_isr(void) interrupt 4 {
        if (RI != 0)
        {
          RI = 0;
          
          if(SBUF == '?')
            hook_state = UNKNOWN;
          if(SBUF == 'V' || SBUF == 'v')
            input_state = VERSION;
          if(SBUF == 'R' || SBUF == 'r')
            input_state = RESET;
          if(SBUF == '!')
            input_state = EGGS;
          if(SBUF == 'H' || SBUF == 'h')
            input_state = SEND_HELP;
          
        }
        return;
}

/*-------------------------------------------------------------------------
 integer to string conversion

 Written by:   Bela Torok, 1999 in the public domain
               bela.torok@kssg.ch
 usage:

 uitoa(unsigned int value, char* string, int radix)
 itoa(int value, char* string, int radix)

 value  ->  Number to be converted
 string ->  Result
 radix  ->  Base of value (e.g.: 2 for binary, 10 for decimal, 16 for hex)
---------------------------------------------------------------------------*/

#define NUMBER_OF_DIGITS 16   /* space for NUMBER_OF_DIGITS + '\0' */

void uitoa(unsigned int value, char* string, int radix)
{
unsigned char index, i;

  index = NUMBER_OF_DIGITS;
  i = 0;

  do {
    string[--index] = '0' + (value % radix);
    if ( string[index] > '9') string[index] += 'A' - ':';   /* continue with A, B,.. */
    value /= radix;
  } while (value != 0);

  do {
    string[i++] = string[index++];
  } while ( index < NUMBER_OF_DIGITS );

  string[i] = 0; /* string terminator */
}

void itoa(int value, char* string, int radix)
{
  if (value < 0 && radix == 10) {
    *string++ = '-';
    uitoa(-value, string, radix);
  }
  else {
    uitoa(value, string, radix);
  }
}

/* setup UART                                                 */
void hw_init() {

        LOOP_STATUS = 1; //set our loop status pin to an input
        STD_STATUS  = 1; //set our std status pin to an input
        MODE_SWITCH = 1; //set the "ECHO" switch input on the K164 board to input 

        EA = 0; // disable all interrupts
                  
        PCON |= 0x80;  // SMOD = 1 double speed clock for our baud rate interrupt

        TH1 = TL1 = Timer1ReloadValue;   // timer 1 mode 1 reload value 9600 baud as calculated in our macro

        TMOD &= 0x0f;    /* Set timer 1 */ 
        TMOD |= 0x20;    /* Set timer 1 as Gate=0 Timer, mode 2 */ 

        TR1 = 1;        // turn on serial timer Timer 1

        SCON = 0x40;    // init port as 8-bit UART with variable baudrate 
        SCON |= 0x10;   // Enabling serial reception
//      SCON |= 0x02;   // Setting TI bit 
        ES = 1;         // Enable Serial Interrupt */

        /* Timer 0 setup */
        TMOD &= 0xf0;    /* Set timer 0 */ 
        TMOD |= 0x01;    /* Set timer 0 16 bit timer  */ 

        /* configure generic timer 0 reset value */        
        TH0 = Timer0H;
        TL0 = Timer0L;  // reload with 35711 for 1Hz
    
        TR0 = 1;        // turn on timer 0
        ET0 = 1;        // Enable timer 0 interrupt 
        

        RI  = 0;
        TI  = 1;

        EA  = 1; // enable all interrupts

}

/* setup FIRMWARE                                              */
void fw_init() {

        /* initialize our state machine to ON HOOK */
        hook_state = UNKNOWN;
        input_state = UNKNOWN;
        std_state = UNKNOWN;

        /* Turn off our LED's we just started */
        HOOK_LED = 0;
        STATUS_LED = 0;

}

/* read a character from UART                                 */
char getchar( void ) { 
        while(!RI);
        RI = 0;
        return(SBUF);
}

/* send a character to UART port                              */
void myputchar( char c ) { 
        while(!TI);
        TI =0;
        SBUF = c;
}

void myputs(char *sz) {
   while(*sz) myputchar(*sz++);
} 

/* Timer 0 interrupt the state machines main interrupt */
void timer_isr(void) interrupt 1 {
        static int suppressfirst=1;
        static int x=0;
        static int counter=0;
        char buffer[17];
        /* configure generic timer 0 reset value */
        TH0 = Timer0H;
        TL0 = Timer0L;
        
        /* every 1 second do our event routine */        
        if(x++>50) {
                x=0;
                doevents();
        }

        /* we need to control this or we will be trying to send out serial data from two threads */
        if(state_machine_active) {

                if( input_state == VERSION ) {
                        send_version();
                        input_state = UNKNOWN;
                }
                if( input_state == SEND_HELP ) {
                        send_help();
                        input_state = UNKNOWN;
                }
                if( input_state == EGGS ) {
                        myputs("! Jack Edin 1961-2012 rip - Logic Unlimited !\r\n");
                        myputs("! Sean Mathews - NuTech.com   !\r\n");
                        input_state = UNKNOWN;
                }
                if( input_state == RESET ) {
                        notdone=0;
                        input_state = UNKNOWN;
                }

                /* check state of the hook line it seems to be inverted */
                if(!LOOP_STATUS) {
                        HOOK_LED = 1; /* ON  NPN Transistor base*/
                          if( hook_state != OFFHOOK ) {
                                counter++;
                                if(counter>10) { // 100ms
                                        hook_state = OFFHOOK;
                                        if(!suppressfirst) {
                                           myputs("OFFHOOK\r\n");
                                        } else {
                                           suppressfirst=0;
                                        }
                                }
                          }

                } else {
                        HOOK_LED = 0; /* OFF NPN Transistor base*/
                        counter=0;
                        if( hook_state != ONHOOK ) {
                                hook_state = ONHOOK;
                                if(!suppressfirst) {
                                   myputs("ONHOOK\r\n");                                   
                                } else {
                                   suppressfirst=0;
                                }
                        }
                }

                /* check state of the STD pin on the MT8870CE chip      */
                if(STD_STATUS) {
                        if( std_state != ON ) {
                                std_state = ON;
                                if(MODE_SWITCH==F34R_MODE) {
                                        myputs("TONE ");
                                }

                                switch(P1 & 0x0f) {
                                        case  10:
                                                buffer[0]='0';
                                                buffer[1]=0;
                                                break;
                                        case  11:
                                                buffer[0]='*';
                                                buffer[1]=0;
                                                break;
                                        case  12:
                                                buffer[0]='#';
                                                buffer[1]=0;
                                                break;
                                        default:
                                                itoa(P1 & 0x0f,buffer,10);
                                                break;
                                }
                                myputs(buffer);
                                if(MODE_SWITCH==F34R_MODE) {
                                        myputs("\r\n");
                                }
                        }
                } else {
                        if( std_state != OFF ) {
                                std_state = OFF;
                        }
                }
        }
} 

/* Event routine for periodic processing                      */
void doevents() {
  static char flipflop=0;
  /* one second event handler. Future use...*/

 
 
 /* flash the status led every 1 second */
 if(MODE_SWITCH!=F34R_MODE) {   
 
   STATUS_LED = !STATUS_LED;   
   
 } else {
 
        flipflop = !flipflop;
 
        if(flipflop) 
           STATUS_LED = !STATUS_LED;   
 }
                 
}

/* MAIN                                                       */
void main(void) {
        notdone=1;
        /* first setup our states and any other startup code so 
          when our hardware calls our routines they are ready */
        fw_init();

        /* ok now setup our hardware and start the interrupts */
        hw_init();

        /* tell the world we are up and running */
        send_hello();

        /* let the state machine go */
        state_machine_active=1;

        /* ... */
        while (notdone) { }

        // disable all interrupts
        EA = 0; 
        // jump to 0
        ((void (code *)(void)) 0) ();
}

void send_hello() {
        myputs("\r\n! K164mh Telephone DTMF Decoder ");
        myputs(szVERSION);
        myputs(" written for my good friend Jack Edin 1961-2012 rip!\r\n");
}

void send_version() {
        myputs(szVERSION);
        myputs("\r\n");
}

void send_help() {
 myputs("\r\n! Every line that starts with a ! is considered informational\r\n!and is not part of any call logging.\r\n");
 myputs("! The state messages are ONHOOK [%1], OFFHOOK, TONE %1\r\n");
 myputs("! The tones can also be on the ONHOOK line if the device is in inbound calls mode\r\n");
 myputs("! K164mh commands: \r\n!    ? = Information\r\n!    V = Version\r\n!    R = Reset\r\n!    H = This info\r\n");        
}

PID Control

March 23, 20131 comment Coded in C
// PID Control program by Bill Keenan, Melbourne

// Throttle PID loop stuff
#define Umin -1022
#define Umax 1022

#define Kp  0.5	//
#define Ki 0.005 //
#define Kd 1.25 	//
float U0 = 0;
float integ;  	// integration part of PID-loop must be saved 
float ep;		// previous error used for differential error (e - ep) 
 

/*****************************************************************************/
float prop, junk, der;      //  
//	junk, U0, Umax, Umin, Kp, Ki, err. 
int throttle_pidloop(int realpos) // PID-loop calc 
                          // integ - integral part of controller 
                          // ep - preceding control error 
                          // realpos - throttle position feedback 
// Besides this function uses global variables such as:
//                    Kp,Ki,Kd,U0 - constants of controller;
//                    accel_use - setpoint
//                    Umin,Umax - range of the output control signal 
{
int output;
float error;		// actual control error 

error = (float)(accel_use - realpos); // calculation of actual error 

der = ((error - ep) * Kd);
prop = error * Kp;  // calculation of proportional part 
if(prop > 1022)
	{
	prop = 1022;
	}
if(prop < -1022)
	{
	prop = -1022;
	}
junk = error * Ki;	// calculation of integral part 
integ = integ + junk;	 

if ((int)integ > Umax) 
	{
	integ = (float)Umax;
	}
else if ((int)integ < Umin) 
	{
	integ = (float)Umin;
	}

output = (int)(prop + integ + der); 

if (output > Umax) 
	{
	output = Umax;          
	}
 else if (output < Umin) 
 	{
	output = Umin;
	}
ep = error;                          		// new error 
return(output);        // return the object controlling magnitude 
}

The 2024 Embedded Online Conference