Sunday, 29 January 2017

ATMEGA328P BASED HEART BEAT MONITOR PROJECT

ATMEGA328P BASED HEART BEAT PROJECT 

PROJECT DESCRIPTION:

Heart rate, body temperature and blood pressure monitoring are very important parameters of human body. Doctors use various kind of medical apparatus like thermometer for checking fever or body temperature, BP monitor for blood pressure measurement and heart rate monitor for heart rate measurement. 

 Here we have used a heartbeat sensor module which senses the heartbeat by the pulse in ear, Heart rate ear clip kit contain a ear clip and a receiver module. The heart rate measure kit can be used to monitor heart rate of patient and athlete. The result can be displayed on a screen via the serial port and can be saved for analysis. The entire system has a high sensitivity, low power consumption and is very portable.

This simple project will allow you to visualize your heart rate result  through a  Bluetooth connection with an  android moblie phone using hc-06  Bluetooth module

COMPONENT:

  1. Atmega328p
  2. Heart rate ear clip
  3. LCD 16X 2
  4. Bluetooth module
 
 
Here is the code:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(5,6,7,8,9,10);

#include <SoftwareSerial.h>// import the serial library

SoftwareSerial Genotronex(12, 11); // RX, TX
int ledpin=13; // led on D13 will show blink on / off
int BluetoothData; // the data given from Computer

#define LED 4 //indicator, Grove - LED is connected with D4 of Arduino
boolean led_state = LOW;//state of LED, each time an external interrupt
                //will change the state of LED
unsigned char counter;
unsigned long temp[21];
unsigned long sub;
bool data_effect=true;
unsigned int heart_rate;//the measurement result of heart rate

const int max_heartpluse_duty = 2000;//you can change it follow your system's request.
            //2000 meams 2 seconds. System return error
            //if the duty overtrip 2 second.
void setup()
{
    Genotronex.begin(9600);
  Genotronex.println(" HEART RATE MONITORING PROJECT ");
  delay (500);
  Genotronex.println(" BLUETOOTH DEVICE CONNECTED... "); 
  pinMode(ledpin,OUTPUT);
 delay (1000); // delay for lcd to boot up
    // initialize LCD and set up the number of columns and rows:
  lcd.begin(16, 2);
  delay (1000);
 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   HEART RATE   ");
  lcd.setCursor(0,1);
  lcd.print("    MONITOR     ");
  delay (2500);
   Genotronex.println(" HEART RATE MONITORING PROJECT ");

  pinMode(LED, OUTPUT);
  Serial.begin(9600);
  arrayInit();
    lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   HEART RATE   ");
  lcd.setCursor(0,1);
  lcd.print(" TEST BEGIN.... ");
 
   Genotronex.println(" SCANNING PULSE BEGIN..... ");

  delay (2500);
  attachInterrupt(0, interrupt, RISING);//set interrupt 0,digital port 2



}
void loop()
{
  digitalWrite(LED, led_state);//Update the state of the indicator
}
/*Function: calculate the heart rate*/
void sum()
{
 if(data_effect)
    {
      heart_rate=1200000/(temp[20]-temp[0]);//60*20*1000/20_total_time
          lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Heartrate_is: ");
    lcd.print(heart_rate);
   Genotronex.println(" YOUR HEART_RATE IS: ");
   Genotronex.println(heart_rate);

   delay (1000);
    }
   data_effect=1;//sign bit
}
/*Function: Interrupt service routine.Get the sigal from the external interrupt*/
void interrupt()
{
    temp[counter]=millis();
  Serial.println(counter,DEC);    Serial.println(temp[counter]);
    digitalWrite(13, HIGH);
        lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" SCANNING ......");
      lcd.setCursor(0,1);
    lcd.print("Heartrate_is: ");
    lcd.print(heart_rate);
  delay (50);
 digitalWrite(13, LOW );
    switch(counter)
  {

   case 0:
      sub=temp[counter]-temp[20];
      Serial.println(sub);
      break;
    default:
      sub=temp[counter]-temp[counter-1];
      Serial.println(sub);
      break;
  }
    if(sub>max_heartpluse_duty)//set 2 seconds as max heart pluse duty
  {
    data_effect=0;//sign bit
    counter=0;
       Genotronex.println(" HEART BEAT SENSOR IS NOT WELL CONNECTED.. ");
    lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   HEART RATE   ");
  lcd.setCursor(0,1);
  lcd.print("  READS  ERROR  ");
  delay (2500);
arrayInit();
  }
    if (counter==20&&data_effect)
    {
    counter=0;
    sum();
    }
    else if(counter!=20&&data_effect)
    counter++;
    else
    {
    counter=0;
    data_effect=1;
    }
   
}
/*Function: Initialization for the array(temp)*/
void arrayInit()
{
  for(unsigned char i=0;i < 20;i ++)
  {
    temp[i]=0;
  }
  temp[20]=millis();
}
 
You can contact engrable.ea@gmail.com for the circuit diagram and other details about the heart beat monitor system

Sunday, 22 January 2017

DSP30F2010 PURE SINE WAVE INVERTER

DSP30F2010 PURE SINE WAVE INVERTER

  1. Full bridge configuration based on power MOSFET or IGBT
  2. DSP based intelligent control
  3. LCD based display for user-friendly display of parameters and status
  4. Protection against 440V mains input
  5. Protection against reverse polarity
  6. Dynamic short circuit protection with fold-back current limiting.
  7. Protections against all possible errors like battery low, over load, heavy load, short circuit etc.
  8. Early warning for battery low and overload conditions. System continue normally if the error is corrected.
  9. Cutoff and auto restart with permanent cut after 5 consecutive cutoff.
  10. Pure sine wave output resulting in silent operation of motor and fans. Safe to all kind of loads.
  11. Protection against accidental output feedback disconnection.

TECHNICAL SPECIFICATIONS: 

VOLTAGE LIMITS (UPS MODE) :

    Mains A.C. Lower Voltage Limit :180+ 5V Lower Recovery Voltage : 190+ 5V

    Mains A.C. Higher Voltage Limit : 255+ 5V Higher Recovery Voltage : 245+ 5V.

Important hardware parts:

 Microchip Dspic30f2010 (28 DIP) micro-controller

LM324 (Op-amp for ADC measurement (AC Voltage ,Current etc)).

LM311 (for short circuit protection).

FAN7392 (for MOSFET gate driving)’

MOSFET IRF3205, P90NF03l or any N channel MOSFET for H bridge arrangement.

Resistor and Capacitor of different value.

Software Component
MPLAB IDE (proposed project used v.8.91 ,you can use MPLABX also)
Compiler c30 or x16.
PICKit2 or PICKit 3.
 

  VOLTAGE LIMITS (INVERTER MODE) :

    Mains A.C. Lower Voltage Limit :110+ 5V Lower Recovery Voltage :120+ 5V
    Mains A.C. Higher Voltage Limit : 275+ 5V Higher Recovery Voltage : 265+ 5V
    Output Voltage in Inverter Mode : 210V+5%


 Output Frequency :
   Main Output Frequency : Same as Input Inverter, Output Frequency : 50.0+0.3Hz

CHARGER:
   DSP controlled CC/CV Charger with Soft Start

TECHNOLOGY :
    Processor: DSP
    Conversion: Full H bridge
    Switching: 20 Khz Modulation
    Charging: Dynamic five stage charger to decrease charging time and increase battery life

PROTECTIONS:
Battery voltage
Inverter output voltage
Percentage of load
Mains voltage
Changer on/off
Solar charging /mains charging
Inverter standby on/off
UPS mode / inverter mode
Phase input output reverse : whether mains is connected to inverter output
Neutral and phase reverse : whether neutral and phase is connected reverse
Overload
Short circuit
Overload trip
Heavy load trip
Short circuit trip 

  1. If 440V is applied to the AC input, it will not fail. It will indicate high voltage cut-off and restart when voltage is normal.
  2. If AC mains is given to the inverter output, it will not fail. It will indicate phase input output reverse and continue to work after it is rectified.
  3. It has fold-back current limiting for short circuit and heavy loads. At short circuit or heavy loads, current limiting action will take place instead of tripping which will lead to more reliability.
  4. LCD display for indicating various status of the system like inverter voltage, mains voltage, battery voltage, % of load, overload/short circuit status, battery low status, charger status etc.
  5. LCD based Menu driven setup of various parameters like battery full charge voltage, battery low voltage, load condition, Inverter output voltage, charging current etc.
  6. Protections against: Overload, short circuit, battery deep discharge, battery over charge, mains over voltage, reverse connection of phase in – phase out, reverse connection of phase and neutral of mains input. In all these error conditions will be shown in the LCD display.
  7. Priority solar charging facility: When solar charger is connected mains charger will be in stand-by and priority will be for solar charger.















The 10-bit Analog-to-Digital Converter (ADC) allows conversion of an analog input signal to a 10-bit digital number. This module is based on a Successive Approximation Register (SAR) architecture. It has Six Channel 10-bit Analog-to-Digital Converter. The output of the sample and hold is the input into the converter which generates the result.
The A/D module has six 16-bit registers
  1. A/D Control Register 1 (ADCON1)
  2.  A/D Control Register 2 (ADCON2)
  3.  A/D Control Register 3 (ADCON3)
  4.  A/D Input Select Register (ADCHS)
  5.  A/D Port Configuration Register (ADPCFG)
  6.  A/D Input Scan Selection Register (ADCSSL)



 

 



This is another version of the DSPic sine wave Power Inverter System with the following features :

  1. Isolated sensing of Mains to ensure that even if Phase-Neutral connection is reversed at the input side there will not be any electric shock on the PCB or battery terminals.
  2. Cycle-Cycle current Limiting to enhanced protection method for the short circuit / heavy load condition.
  3. it can use TLP250, IR2110 or low cost driver with discrete components.
  4. LED/LCD display which will display all the parameters of the system and indicates any error during the functioning of the power inverter. The LCD will displays  
  • Battery voltage
  • Inverter output voltage
  • Mains voltage
  • Changer on/off and Solar charging /mains charging
  • Heavy : if load is above 300%
  • Short circuit, etc.




The circuit with differential amplifier using LM324 op-amp. It is used to measure AC voltage and current as an isolated input and output sensor.


Call or whatsapp: +2348037909203. (Nigeria)
email: abledesigns@yahoo.com

 SAMPLE SOURCE CODE FOR THE ABOVE CIRCUIT USING DSPIC30F2010.

PURE SINE INVERTER WITH CHARGER



//////////////////////////////////////////////////////////////////////
#include <p30f2010.h>
#include <libpic30.h>

_FOSC(CSW_ON_FSCM_OFF & XT_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_ON & BORV_42 & RST_PWMPIN & PWMxH_ACT_HI & PWMxL_ACT_HI);
_FGS (CODE_PROT_ON)
 

#define buzzer    LATEbits.LATE4
#define change    LATDbits.LATD1
#define stbyinv 1
#define upsmode 2
#define invmode 3
#define modekey 4
#define upkey   5
#define downkey 6
#define stbyups 7
#define fanheat 700

///////////////////////////////////////////////////////////////////////////////////////////
 const signed int sine_table[91]={0,174,348,523,697,871,1045,1218,1391,1564,1736,1908,2079,2249,2419,2588,2756,2923,3090,
                  3255,3420,3583,3746,3907,4067,4226,4383,4539,4694,4848,5000,5150,5299,5446,
                  5591,5735,5877,6018,6156,6293,6427,6560,6691,6819,6946,7071,7193,7313,7431,7547,7660,7771,
                  7880,7986,8090,8191,8290,8386,8480,8571,8660,8746,8829,8910,8987,9063,9135,9205,9271,9335,
                  9396,9455,9510,9563,9612,9659,9702,9743,9781,9616,9848,9876,9902,9925,9945,9961,9975,9986,
                  9993,10000,10000};

signed int factory[17]={3,12,0,350,220,250,400,180,400,180,141,104,102,117,50,10};
signed int setting[17];
char arr[4];

struct
{
unsigned int batt_full:1;
unsigned int frstdisp:1;
unsigned int setup:1;
unsigned int gravity:1;
unsigned int onflag:1;
unsigned int vcorrect:1;
unsigned int chrcorrect:1;
unsigned int chon:1;
unsigned int swon:1;
unsigned int nofeed:1;
unsigned int shorttrip:1;
unsigned int zincfail:1;
unsigned int mainsok:1;
unsigned int lbwarn:1;
unsigned int olwarn:1;
unsigned int olcut:1;
unsigned int lbcut:1;
unsigned int fault:1;
unsigned int hiload:1;
unsigned int msgrtn:1;
unsigned int chrmsgrtn:1;
unsigned int firston:1;
unsigned int fan_error:1;
unsigned int over_battery:1;
unsigned int ntc_fail:1;
}flags;

unsigned int chshoot;
unsigned int chshootdly=0;
unsigned int flicker=0;
int *adjust;
char *ptr;
int adj;
int *value;
unsigned int chadj;
unsigned int champs1;
signed int duty_cycle_1;
signed int p=0,flag=1,rising=1;

signed int pr=0,kflag=1,rising1=1;
unsigned int amplitude=0;

unsigned int pb,qb,cth,ctl;
//////////////////////////////



///////////////////////////////
unsigned int battery_full;
unsigned int setdly;
unsigned int menudelay;
unsigned int lcdtmr;
unsigned int lcdtmr1;
unsigned int counter;
unsigned int resumedelay;
unsigned int buzzcount;
unsigned int buzzdelay;
unsigned int buzzoftme;
unsigned int buzzontme;
unsigned int peakfail;
unsigned int oldelay;
unsigned int tripdly;
unsigned int rounds;
unsigned int chrdly;
unsigned int slowdly;
unsigned int fbdly;
unsigned int ctfaildly;
unsigned int deadshortdly;
unsigned int lbdly;
unsigned int acdly;
unsigned int keydly;
unsigned int msgrtndly;
unsigned int gravitydly;
unsigned int fltdly;
unsigned int blinkdly;
unsigned int startdly;
////////////////////////////////
unsigned long endtimer;
unsigned long controlavg;
unsigned long mainsavg;
unsigned long outavg;
unsigned long wattsavg;
unsigned long batavg;
unsigned long keyavg;
unsigned long heatavg;
unsigned int  modeavg;
/////////////////////////////////
unsigned int indummy;
unsigned int outdummy;
unsigned int ctdummy;
unsigned int keys;
unsigned int ntcvalue;
unsigned int batts;
unsigned int batrecharge;
//////////////////////////////////
unsigned int total_loaddisp;
unsigned int loaddisp;
unsigned int acoutdisp;
unsigned int mainsdisp;
unsigned int battdisp;
unsigned int battvolts;
unsigned int batrestart;
unsigned int loadpercent;
unsigned int champs;
unsigned int chdisp;
unsigned int mainsvolt;
unsigned int acout;
unsigned int keyvalue;
unsigned int key;
unsigned int heat;
unsigned int post;
unsigned int err;
unsigned int cherr;
unsigned int prect;
unsigned int initcount;
int yaxis;
///////////////////////////////////
signed int   upspeak;
signed int   acpeak;
signed int   ctpeak;
signed int   batclb;
signed int   mainsclb;
unsigned int chrclb;
unsigned int loadclb;
unsigned int pdctemp;
////////////////////////////////////

unsigned int deadshort;
unsigned int controlvolt;
unsigned int setvout;
unsigned int setchramp;
unsigned int setoverload;
unsigned int setupshi;
unsigned int setupslo;
unsigned int setinvhi;
unsigned int setinvlo;
unsigned int setbatful;
unsigned int setbatwrn;
unsigned int setbatlo;
unsigned int setbatres;
unsigned int defaults;
unsigned int setmaxwatts;

/////////////////////////////////////

unsigned int x,y,u;
unsigned long Ax,bx,Wt;
unsigned int aclo;
unsigned int achi;
unsigned int zinc;

/////////////////////////////////////
void InitADC1();
extern void Eeprom_WriteWord(unsigned short  pushAddressOffset, unsigned short value);
extern unsigned short Eeprom_ReadWord(unsigned short  pushAddressOffset);
void delay_ms(unsigned int gs);
void delay_us(unsigned int gs);

///////////////////////////////////////////////
const char str0[17]= "SYSTEM SETTINGS" ;
const char str20[17]=" BATTERY :    V" ;

//const char str24[17]="SWITCH IS ON ";
const char str25[17]="MAINS INPUT:   V";
const char str26[17]=" OUTPUT :   V   ";
const char str27[17]=" LOAD :    %    ";
//////////////////////////////////////////
const char str29[17]="SORRY BATT. LOW" ;
const char str30[17]="WAS OVERLOADED " ;
const char str31[17]="SHORT CCT FAULT" ;
const char str32[17]="  LOW BATTERY"   ;
const char str33[17]=" OVER LOADING"   ;
const char str34[17]="  NO OUTPUT "    ;
const char str35[17]="TRIP:SYNC FAULT ";
const char str36[17]="CHRGING.CUR:    ";
const char str38[17]="ABLE INVERTER";

//const char str40[17]="   FAULT";
const char str41[17]="  CHECK OUPUT   ";
const char str42[17]=" CHK FET/FORMER ";
const char str43[17]="  SYSTEM IS OFF ";
const char str44[17]="! REDUCE LOAD   ";
const char str45[17]="CONNECT CHARGER ";
const char str46[17]=" AUTO START ON  ";
const char str47[17]=" CHARGING MODE  ";
const char str48[17]="BATTERIES ERROR ";
const char str49[17]="REDUCE BATTERIES";
const char str50[17]="BATTERY IS FULL ";
const char str51[17]="CHGING COMPLETE ";
//const char str52[17]="LOAD:   WATT";
const char str53[17]="TEMPERATURE HIGH";
const char str54[17]="  CHECK FAN"     ;
const char str55[17]="HEAT SENSOR ERR" ;
const char str56[17]="   CHECK NTC    ";
const char str58[17]="  COMPLETE"      ;

#include "lcdsoft.h"
#include "functions.h"
void clear_flag();
void trip(int s);
int getvalue(int ch);
void chargeron();
void chroff();
void invon();
void invoff();
void stabilise();
void Modulate();
void find_key();
int findpeak(int ct);
void mains_stat_check();
void find_mainsvolt();
void find_batvolt();
void find_champs();
void find_upsvolt();
void find_load();
void  overload_check();
void lobat_check();
void chr_stabilize();
////////////////////////////////////
void feed_buzz(int a,int b,int c)
     {
     buzzdelay=0;
     buzzoftme=b;
     buzzontme=a;
     buzzcount=c;
     }
//////////////////////////////////////////////////////
void __attribute__((__interrupt__,no_auto_psv)) _FLTAInterrupt(void)
    {


_FLTAIF = 0;
    }
//////////////////////////////////////////////////////////
void __attribute__((__interrupt__, __auto_psv__)) _T1Interrupt(void)
   {
    _T1IF = 0;   // Clear interrupt flag
     if(PORTEbits.RE8==0)
     {
     fltdly++;
     if(fltdly>3000)
     {
      flags.olcut=1;
     __asm__ volatile ("reset");
     }
     }
    counter++;
    acpeak=getvalue(0);        //4.4 us
    indummy=acpeak;
    acpeak=indummy-508;
    if(acpeak<0)
    {
    acpeak=508-indummy;
    if(!flags.onflag)
    {
    rising=0;
    flag=0;
    }
    }
   
    mainsavg+=acpeak;

    if(flags.setup)
     {
OVDCON=   0X0000;
change=0;
buzzer=0;
     }

     if(!flags.setup)
    {
    if((indummy<600)&&(indummy>400)&&(flags.swon))
    {
    if(peakfail<150)
    {
    peakfail++;
    }
    if(peakfail==149)
    {
    if(flags.vcorrect)
    {
    invon(150);
    }
    }
    }
    else
    {
    peakfail=0;
    }

    if(flags.onflag)
    {
    Modulate();                         //4.4 us ///MODULATE SINE PWM OVER 50 HZ/////////////
    upspeak=getvalue(1);                //4.4 us
    outdummy=upspeak;              
    upspeak=outdummy-508;
    if(upspeak<0)
    upspeak=508-outdummy;
    outavg+=upspeak;
    if(upspeak<150)
     {
     fbdly++;
     if(fbdly>30000)                  // IF NO FEED BACK DETECTED///////////////
     {
     flags.fault=1;                  // TRIP: FB FAULT
     trip(5);
     }
     }
    else
    fbdly=0;
      }
    else
    {
    rising=1;
    flag=1;
    loadpercent=0;
    acout=0;
    }

    ctpeak=getvalue(2);

    if(flags.onflag)
    {
    if((ctpeak>750)||(ctpeak<250))
    {
    deadshortdly++;                  //OUTPUT DEAD SHORT TRIP//////////SHORT CKT FAULT
    if(deadshortdly>1500)
    {
    deadshort=1;
    OVDCON=   0X0000;
    trip(1);
    }
    }
    }

else
        {

        if(flags.chon==1)
        {
        if((ctpeak<508)||(ctpeak>512))
        ctfaildly=0;
        else
        {
        ctfaildly++;
        if(ctfaildly>10000)  // IF CT FEEDBACK FAIL, CHARGER OFF!
        {
        chroff();
        }
        }
        }
        }



    if(ctpeak>506)
    {
    pb=ctpeak-506;
    if(cth<pb)
    cth=pb;
    } 
    if(ctpeak<506)
    {
    qb=506-ctpeak;
    if(ctl<qb)
    ctl=qb;
    } 
    wattsavg+=cth+ctl;
    ctl=cth=0;
       heat=getvalue(3);    // GET NTC VALUE FOR FAN FUNCTION                      
     }       
   
                     
    batavg+=getvalue(5);   

lcdtmr1++;
    lcdtmr++;
if(counter==359)//////////////////////   20 milli sec checking sequence /////////////////
     {
     mainsvolt=__builtin_divud(mainsavg,288)+mainsclb;    //2.2 microseconds
  mainsavg=0;
   if(mainsvolt<90)
     {
     mainsvolt=0;
     mainsdisp=0;
     }
   else
     {
     if((indummy>180)&&(indummy<900))
     {
     if(mainsdisp==0)
     {
     mainsdisp=mainsvolt-80;
    
     }
     if(mainsdisp<mainsvolt-2)
     {
     mainsdisp++;
     }
     if(mainsdisp>mainsvolt+2)
     {
     mainsdisp--;
     }
     }
     }


     find_batvolt();  //get battery voltage


     keyavg+=getvalue(4);    // get switch status 
     keydly++;
     if(keydly==10)
     find_key();

     if(!flags.setup)
     {
     mains_stat_check(); // mains voltage status checking
     if(flags.onflag==1)
     {
     acout=__builtin_divud(outavg,285);
     outavg=0;  
     if(acoutdisp<acout-2)
     acoutdisp++;
     if(acoutdisp>acout+2)
     acoutdisp--;

     find_load();
     overload_check();
     lobat_check();
     }
     }
    
     wattsavg=0;

      if(buzzcount>0)
      {
      buzzdelay++;
      if(buzzdelay<=buzzontme)
      buzzer=1;
      else
      {
      buzzer=0;
      if(buzzdelay>=buzzoftme)
      {
      buzzdelay=0;
      buzzcount--;
      fltdly=0;
      }
      }
      }
      else
      {
      FLTACON=0x0001;
      IEC2bits.FLTAIE = 1;
      if(rounds>0)
      {
      if((!flags.onflag)&&(flags.swon)&&(rounds<4))
      {
      if(mainsvolt<110)
      {
      clear_flag();
      invon(0);
      }
      }
      }
      if(rounds==4)
      change=0;
      }
   
     if(!flags.setup)
    {
    if(flicker==0)
    {
    if((resumedelay==200)||(flags.mainsok==1))
    {
    LCD_DB6=1;
    if(flags.swon==1)
    {
    blinkdly++;
    if(blinkdly<30)
    LCD_DB7=1;
    else
    LCD_DB7=0;
    if(blinkdly>60)
    blinkdly=0;
    }
    else
    LCD_DB7=0;
    }
    else
   {
   LCD_DB6=0;
   if(flags.onflag==1)
   LCD_DB7=1;
   else
   LCD_DB7=0;
   }
   }


if((key==modekey)&&(flags.setup==0))
{
menudelay++;
if(menudelay>124)
flags.setup=1;
}
else
menudelay=0;
}

if(flags.setup==1)
{
setdly++;
if(setdly>3000)
__asm__ volatile ("reset");
}

  counter=0;

   }
   cherr=mainsvolt;
   }

//////////////////////////////////////
void init_PWM()
    {
    PTCON=    0XE003;
    PTMR =    0x0000;
    PTPER = PDC1=PDC2=  1230; //20 khz pwm
    SEVTCMP = 0x0000;
    PWMCON1 = 0x0033;
    PWMCON2 = 0x0000;
    DTCON1=   0X0059;      // 3.5 us dead band delay
    FLTACON = 0x0000;
    OVDCON=   0X0000;
    PTCONbits.PTEN = 1;
    IEC2bits.PWMIE = 0;        // disable PWM interrupts
   
    T1CON = 0XE000;        
    TMR1 = 0;           
    PR1 = 1355;         //20 khz timer
   _T1IF = 0;         
   _T1IE = 1;        //  enable timer interrupts
    }
/////////////////////////////////////////////////
void memread()
{
int x;
for(x=0;x<16;x++)
{
setting[x]=Eeprom_ReadWord(x);
}
}
//////////////////////////////////////////////////////////
void memwrite()
{

int x;
for(x=0;x<16;x++)
{
if(flags.setup==0)
Eeprom_WriteWord(x,factory[x]);
else
Eeprom_WriteWord(x,setting[x]);
}
}
//////////////////////////////////////////////
/*
void modedisp()
{
if(flags.msgrtn)
return;
if((key==upsmode)||(key==stbyups))
{
//printmes(str22,100,1);         //"\fU.P.S MODE ON";
if(key==upsmode)
{
aclo=setupslo;
achi=setupshi;
}
}
}
//if((key==invmode)||(key==stbyinv));      
                                        //"\fINVERTER MODE ON";
}*/
//////////////////////////////////////////////////////
/*void swdisp()
{
if(flags.msgrtn)
return;


if((key==stbyinv)||(key==stbyups))              //"\fSBY SWITCH OFF";
{

aclo=setinvlo;
achi=setinvhi;
}

}
*/


//                         MAIN ROUTINE                             
//*****************************************************************************/
int main()
{
TRISF=0X0000;
TRISE=0X010F;
TRISD=0X0000;
TRISC=0X0000;
TRISB=0XFFFF;
OVDCON=0X0000;
PWMCON1 = 0x0000;
PTCONbits.PTEN = 0;
buzzer=0;
lcd_init();
InitADC1();
init_PWM();
keyvalue=getvalue(4);
     if(((keyvalue>660)&&(keyvalue<680))||((keyvalue>560)&&(keyvalue<575)))
     {
     flags.swon=1;
     flags.firston=1;
     }

prect=getvalue(2);

flags.frstdisp=0;

defaults=Eeprom_ReadWord(14);
if(defaults!=50)
{
memwrite();
}

while(1)
{
while(PORTEbits.RE7==0)
{
 flags.msgrtn=0;
printmes(str31,100,1);     // SHORT CKT FAULT
printmes(str41,100,2);     // check output
if(flags.swon==0)
__asm__ volatile ("reset");
}

while(flags.nofeed==1)
{
 flags.msgrtn=0;
printmes(str34,100,1);     // NO FEED BACK
printmes(str42,100,2);     // CHK FET/FORMER
if(flags.swon==0)
__asm__ volatile ("reset");

while(flags.lbcut==1)
{
  flags.msgrtn=0;
printmes(str29,100,1);        //" TRIP:LOW-BATTERY ";
printmes(str43,100,2);        //SYSTEM IS OFF; 
if((flags.swon==0)||(resumedelay>175))
__asm__ volatile ("reset");
}


while((flags.olcut==1)||(flags.olwarn))
{
  flags.msgrtn=0;
printmes(str30,100,1);        //" TRIP:OVER-LOAD ";
printmes(str44,100,2);         // PLS REDUCE LOAD
if((flags.swon==0)||(resumedelay>175))
__asm__ volatile ("reset");
}

while(flags.olwarn)
{
  flags.msgrtn=0;
//printmes(str33,100,1);        //" WARN:OVER-LOAD ";
printmes(str44,100,2);        // PLS REDUCE LOAD
if(flags.swon==0)
__asm__ volatile ("reset");
}

while(flags.lbwarn==1)
{
  flags.msgrtn=0;
feed_buzz(2,50,25);
printmes(str32,100,1);        //"WARN:LOW-BATTERY";
printmes(str45,100,2);        //CONNECT CHARGER
printmes(str20,1,2);          //battery
if(flags.swon==0)
__asm__ volatile ("reset");

}
if(!flags.onflag==1)
{
//printmes(str59,100,1);       //"\fTITLE NAME
printmes(str38,100,1);       //"\fTITLE NAME
printmes(str43,100,2);     //   //"\system is off:";
printmes(str20,1,1);         // 0/0/"\fBATTERY V:";

}


if(mainsvolt>aclo+10)
{
    printmes(str25,2,2);     //   //"\fMAINS VOLT:";
}  

while(flags.chon==1)
{
if(champs==0)
goto outmes;
printmes(str36,3,1);          //"AC CHARGR:";
printmes(str20,1,2);         // 0/0/"\fBATTERY V:";
printmes(str25,2,2);        //"\fMAINS VOLT:"

if((change==0)&&(flags.swon==1))
{
printmes(str25,2,2);        //"\fMAINS VOLT:"
}
if((battvolts>=setbatful)&&(champs<=40))
{
 printmes(str50,100,1);      // battery is full
// printmes(str51,100,2);      //charging complete

}
}
outmes:


if((key==upsmode)||(key==invmode))
{
if(flags.onflag==1)
{
lcd_init();
printmes(str26,0,1);        //"\fINVERTER V:";
printmes(str27,4,2);        //"\fTOTAL LOAD:";;
printmes(str20,1,1);         // 0/0/"\fBATTERY V:"

//printmes(str25,2,2);     //   //"\fMAINS VOLT:";
//printmes(str52,4,2);        //"\fTOTAL WATT:";
}
}
/*else
{
//modedisp();
//swdisp();
printmes(str25,2,2);        //"\fMAINS VOLT:";
}
*/

if(heat<=fanheat-65)
{
feed_buzz(20,48,25);
printmes(str53,100,1);
printmes(str54,100,2);
if(flags.swon==1)
__asm__ volatile ("reset");
}

if(heat>=fanheat+320)
{
feed_buzz(2,48,25);
printmes(str55,100,1);
printmes(str56,100,2);
if(flags.swon==1)
__asm__ volatile ("reset");
}

if(battvolts>155)
{
printmes(str48,100,1);         ///over battery
printmes(str49,100,2);
}


if(menudelay>=125)
{
flags.setup=1;
menudelay=0;
printmes(str0,100,1);           //"\fCALIBRATION MENU";
while(key==modekey);
while(1)
{
if(key==modekey)
{
setchramp=setting[5]/10;
loadclb=setting[3];
functions();
memwrite();
flags.setup=0;
__asm__ volatile ("reset");
}
}

}

}


}

//main
///////////////////////////////////////////////////////////////////////////////////////
void InitADC1()
{
    ADPCFG = 0;       // Lowest 6 PORTB pins are analog inputs
    ADCON1 = 0;          // Manually clear SAMP to end sampling, start conversion
    ADCON2 = 0;          // Voltage reference from AVDD and AVSS
    ADCON3 = 0x0003;     // Manual Sample, ADCS=5 -> Tad = 3*Tcy
    ADCON1bits.ADON = 1; // Turn ADC ON
}

//////////////////////////////////////////
void delay_ms(unsigned int gs)
{
  while(gs--)
{
__delay32(55000);

}

}
///////////////////////////////////////////////////////////
void delay_us(unsigned int gs)
{
 while(gs--)
 __delay32(3000);
}
int getvalue(int ch)
{
ADCON1bits.DONE=0;
ADCHS = ch;        
ADCON1bits.SAMP = 1;     
__delay32(50);             
ADCON1bits.SAMP = 0;     
while (!ADCON1bits.DONE);
return ADCBUF0;

//////////////////////////////////
void clear_flag()
     {
     flags.olwarn=0;
     flags.lbwarn=0;
     flags.olcut=0;
     flags.lbcut=0;
     flags.nofeed=0;
     flags.zincfail=0;
     }
////////////////////////////////////
void trip(int s)
     {
     invoff();
     clear_flag();
     if(s==1)
     flags.olcut=1;
     if(s==2)
     flags.lbcut=1;
     if(s==4)
     flags.zincfail=1;
     if(s==5)
    flags.nofeed=1;
  if(s>2)
   {
    feed_buzz(8,48,25);
    flags.fault=1;
    rounds=0;
     }
     else
   {
     rounds++;
    feed_buzz(8,48,25);
    }
     flags.msgrtn=1;
     }
/////////////////////////////////////
void chargeron()
     {
     if(heat>=fanheat+300)
     return;
     if(heat<=fanheat-60)
     return;
     if(flags.onflag)
     return;
     chdisp=0;
     if(battvolts<90)
     return;
     if(battvolts>155)
     return;
     if(flags.chon==1)
     return;
     if(mainsvolt<150)
     return;
     if(chrdly<500)
     chrdly++;
     if(chrdly==499)
     {
     if(flags.gravity==1)
     {
     if(battvolts>batrestart)
     {
     chrdly=0;
     return;
     }
     gravitydly++;
     if(gravitydly<20)
     {
     chrdly=0;
     return;
     }
     gravitydly=0;
     }
     flags.gravity=0;
     PTCON=    0XE002;
     PTPER = 615;
     PWMCON1 = 0x0330;
     OVDCON=0X0A05;
     DTCON1=0X0000;
     PDC1=PDC2=0;
     flags.chon=1;
     chrdly=0;
   
     endtimer=0;
     }
     }
///////////////////////////////////////
void chroff()
    {
    OVDCON = 0x0000;
    PWMCON1 = 0x0033;
    DTCON1=0X0030;
    PTPER = 1230;
    PDC1=PDC2=0;
    flags.chon=0;
    champs=0;
    chrdly=0;
    }
/////////////////////////////////////////////////
void chr_stabilize()
     {
int kdly;

     if(flags.onflag)
     return;

     if(mainsvolt>cherr+5)
     {
     chroff();
     return;
     }

     if((battvolts>155)||(battvolts<90))
     {
     chroff();
     return;
     }

     if(mainsvolt<150)
     {
     chroff();
     return;
     }


//////////////////////////////////////////////////////////////
    if(battvolts>setbatful+1)
    {
    flags.chrcorrect=1;
     if(champs>35)
    {
    PDC1--;
    PDC2--;
    }
    }

 if(champs<30)
kdly=0;
else
kdly=4;




 if(battvolts<=setbatful)
     {
    if(flags.chrcorrect==0)
     {
     slowdly++;
     if(slowdly<kdly)
     return;
     slowdly=0;
     }

        if(champs<setchramp)
     {
     if(PDC1<900)
     {
     PDC1++;
     PDC2++;
     if(flags.chrcorrect==0)
     {
     if((champs<35)&&(champs>25))
     flags.frstdisp=1;
     }
     }
     }
    if(champs>setchramp)
       {
    flags.chrcorrect=1;
    if(PDC1>1)
    {
    PDC1--;
    PDC2--;
    }
    }

    }

    }
//void batt_full()
//{
  //  if((battvolts>=setbatful+1)&&(champs<=40))
    //  flags.batt_full=1; 
//}
////////////////////////////////////////////////
void find_champs()
     {
  
     x=__builtin_divud(wattsavg,359);             //1.03 microseconds
     Ax=__builtin_muluu(x,mainsdisp);
     bx=__builtin_divsd(Ax,battvolts);
     Ax=__builtin_muluu(bx,1000);
     bx=__builtin_divsd(Ax,450-chrclb);
     champs=bx;

   
if(flags.chrcorrect==1)
{
chshootdly++;
if(chshootdly==20)
{
 if(setchramp>chshoot)
setchramp--;
chshootdly=0;
}
}

     if(champs<10)

     {
     champs=0;
     chdisp=0;
     }
    
     if((battvolts<setbatful+2)&&(champs>35))
     {
     if(chdisp<champs-1)
     chdisp++;
     if(chdisp>champs+1)
     chdisp--;
     endtimer=0;
     }
     if((battvolts>=setbatful+2)&&(champs<35))
     {
     endtimer++;
     if(endtimer>100)
     {
     if(chdisp>12)
     chdisp--;
     else
     {
     flags.gravity=1;
     chroff();
     }
     endtimer=0;
     }
     }


    if(chdisp>chshoot)
    chdisp=chshoot;




     pb=qb=ctl=cth=0;
     }


//////////////////////////////////////
void invon(int k)
   {
   if(heat>=fanheat+300)
   return;
   if(heat<=fanheat-60)
   return;
   if(battvolts>155)
   return;    
   if(flags.olcut==1)
   return;
   if(flags.lbcut==1)
   return;
   if(flags.fault==1)
   return;
   if(flags.setup)
   return;
   if(flags.onflag)
   return;

   OVDCON = 0x0000;
   flags.onflag=1;
   flags.chon=0;  
   IEC2bits.FLTAIE = 0;
   FLTACON=0x0000;
   ctfaildly=0;
   fbdly=0;
   lbdly=0;
   oldelay=0;
   deadshortdly=0;
   chrdly=0;
   champs=0;
   ctfaildly=0;
   loadpercent=0;
   resumedelay=0;
   deadshort=0;
   flags.gravity=0;
   if(flag==0)
   p=90;
   else
   p=0;
   amplitude=k;
   buzzontme=51;
   buzzcount=1;
   buzzdelay=0;
   controlavg=u=0;
   change=1;
   PWMCON1 = 0x0033;
   DTCON1=0X0059;
   PTPER = 1230;
   OVDCON = 0x0F0f;
   }
////////////////////////////////////
  void invoff()
   {
  if(flags.onflag==0)
  return;
   flags.onflag=0;
   OVDCON = 0x0000;
   buzzer=0;
   flags.vcorrect=0;
   counter=0;
   }
//////////////////////////////////////////////////
void stabilise()
{
controlvolt=__builtin_divud(controlavg,90);
controlvolt+=43;
if(controlvolt<setvout)
{
err=setvout-controlvolt;
if(flags.vcorrect)
amplitude+=err;
else
amplitude++;
}
else
{
flags.vcorrect=1;
}

if(controlvolt>setvout)
{
err=controlvolt-setvout;
if(flags.vcorrect)
amplitude-=err;
}
controlavg=0;
}
///////////////////////////////////////

void Modulate()
{
if(flags.onflag==0)
return;

if(rising==1)
{
p++;
if((mainsvolt<50)&&(flags.mainsok==0))
{
if(p==45)
{
if(flag==1)
{
if(outdummy<200)
{
trip(4);// flags.zincfail=1;
}
}
}
}
u++;
controlavg+=upspeak;
}

if(p==91)
{
rising=0;
p=90;
u=0;
stabilise();



  if(resumedelay==200)
    {
    if((indummy<400))
    {
    IEC2bits.FLTAIE = 0;
    FLTACON=0x0000;
    flags.mainsok=1;
    change=0;
  __delay32(50000);
    flags.onflag=0;
    OVDCON = 0x0000;
    feed_buzz(10,50,3);
    peakfail=0;
    resumedelay=0;
    }
    }


    }
if(rising==0)
{
p--;
u++;
controlavg+=upspeak;
}
if(p<0)
{
rising=1;
p=0;
u=0;
stabilise();

if(flag==1)
{
flag=0;
}
else
{
flag=1;
}
}
duty_cycle_1=sine_table[p];
duty_cycle_1=((long)duty_cycle_1*amplitude)>>11;
if(duty_cycle_1>1230)
{
duty_cycle_1=1230;
}
if(duty_cycle_1<=0)
{
duty_cycle_1=0;
}
if(flag==1)
{
PDC1=1230+duty_cycle_1;
PDC2=1230-duty_cycle_1;
}
if(flag==0)
{
PDC1=1230-duty_cycle_1;
PDC2=1230+duty_cycle_1;
}
}
////////////////////////////////////////
void find_key()
     {
     keyvalue=__builtin_divsd(keyavg,10);
     keyavg=0;
     keydly=0;

     if(keyvalue>750)
     {
     key=7;//stbyups;

     if(keyvalue>850)
     {
     key=1;//stbymode;
     }
     if(flags.swon==1)
     {
     flags.swon=0;
    if((!flags.chon)&&(!flags.setup))
    __asm__ volatile ("reset");
     }
     flags.firston=1;
     peakfail=0;
     aclo=setinvlo;
     achi=setinvhi;
     return;
     }
 


     if((keyvalue>510)&&(keyvalue<530))
     {
     key=4;//modekey
     setdly=0;
     return;
     }


    if(flags.setup)
     {
     if((keyvalue>680)&&(keyvalue<705))
     {
     key=6;//downkey
     setdly=0;
     return;
     }

     if((keyvalue>590)&&(keyvalue<610))
     {
     key=5;//upkey
     setdly=0;
     return;
     }
     }

     if((keyvalue>660)&&(keyvalue<700))
     {
     if(flags.swon==0)
     {
     flags.swon=1;
     if(resumedelay==0)
     invon(0);
     }
     aclo=setinvlo;
     achi=setinvhi;
     key=3;//invmode
     return;
     }

     if((keyvalue>560)&&(keyvalue<575))
     {
     if(flags.swon==0)
     {
     flags.swon=1;
     if(resumedelay==0)
     invon(0);
     }
     aclo=setupslo;
     achi=setupshi;
     key=2;//upsmode;
     return;
     }
     }

//////////////////////////////////////////////////
void mains_stat_check()
    {
if(flags.fault==1)
   return;
    if((mainsvolt>aclo+10)&&(mainsvolt<achi-10))
    {
    if(resumedelay<200)
    resumedelay++;
    if(resumedelay==199)
    {
     clear_flag();
     rounds=0;
     setchramp=setting[5]+40;
    }

 if((key==3)||(key==2))
    {
    if(flags.firston==1)
    {
    flags.vcorrect=1;
    flags.firston=0;
    }
    }



      if(!flags.onflag)
      {
      if(resumedelay==200)
      {
      change=0;



      if(flags.chon==0)
      {
      slowdly=0;
      chargeron();
      flags.chrcorrect=0;
      }
      else
      {
      find_champs();
      chr_stabilize();
      }
    



      }
      }
      }
 
else
    {
 if((mainsvolt<aclo)||(mainsvolt>achi))
    {
    if(flags.chon)
    chroff();
    flags.mainsok=0;
    resumedelay=0;
    if(flags.firston==0)
    {
    if((key==3)||(key==2))
    {
    startdly++;
    if(startdly>10)
    {
    invon(150);
    startdly=0;
    }
    }
    else
   startdly=0;
    }
    }
    }
    }
/////////////////////////////////////////////////
void find_batvolt()
     {
     battvolts=__builtin_divsd(batavg,366);   ///1.307 microseconds
   __asm__ volatile ("mov   _battvolts, w3");
   __asm__ volatile ("mov     #0xffff, w1");
   __asm__ volatile ("mul.uu  w3,w1,w2");
   __asm__ volatile ("mov   w3,_battvolts");
     battvolts+=batclb+17;
     batavg=0;
     if(battdisp<battvolts)
     battdisp++;
     if(battdisp>battvolts)
     battdisp--;

 if(battvolts>=setbatful+1)
     battdisp=setbatful+1;

     }

////////////////////////////////////////////////

////////////////////////////////////////////////
void find_load()
     {
     x=__builtin_divud(wattsavg,loadclb);             //1.03 microseconds
     Ax=__builtin_muluu(x,125);
     bx=__builtin_divud(Ax,100);  //2.25 microseconds
     x=bx ;                    
     loadpercent=x;               // 1.2 microseconds
     if(loadpercent<10)
     {
     loadpercent=0;
     loaddisp=0;
     }
     if(loaddisp<loadpercent)
     loaddisp++;
     if(loaddisp>loadpercent)
     loaddisp--;
     }
/////////////////////////////////////////////////
void  overload_check()
     {
     if(flags.fault==1)
     return;
     if(loadpercent>=100)
     {
     oldelay++;

     if(loadpercent>110)
     tripdly=20;
     else if(loadpercent>105)
     tripdly=40;
     else
     tripdly=60;


if(tripdly==60)
{
if(oldelay>tripdly)
   {
 if(!flags.lbwarn)
     {
     if(!flags.olwarn)
     {
     flags.olwarn=1;
     if(!flags.lbwarn)
     flags.msgrtn=1;
     feed_buzz(10,50,7800);
     }
 }
}
}
     else
     {
     if(oldelay>tripdly)
     {
     if(!flags.olcut)
     {
     trip(1);
     }
     }
     }
     }
     else
     {
     if(flags.olwarn)
     {
     buzzer=0;
     buzzcount=0;
     flags.olwarn=0;
   flags.msgrtn=0;
     }
     oldelay=0;
     }



     }

/////////////////////////////////////////////////
void lobat_check()
     {
    if(flags.fault==1)
     return;
    if(flags.onflag==0)
     return;
   if(battvolts<setbatwrn)
     {
     lbdly++;
    if(lbdly>150)
     {
     if(!flags.lbwarn)
     {
     flags.olwarn=0;
     flags.lbwarn=1;
     flags.msgrtn=1;
     }
   if(battvolts<setbatlo)
     {
     trip(2);
     }
     }
     }
else
     lbdly=0;
     if(battvolts>setbatwrn)
     {
     if(flags.lbwarn)
     {
     flags.lbwarn=0;
     }
     }
     }

//////////////////////////////////////////////////////////////////////////////





There is no preset, the parameters such as battery low, charging current, inverter output voltage, load etc can be set by scrolling up and down keys and press enter. The Inverter/UPS selection switch, micro switch or ordinary switch selectable. 20KHz operating frequency while inverter and charging, absolutely no sound. Pure sine wave output


Specification
  • Battery Input voltage : 12V DC – 96V DC
  • Mains Input voltage : 1110V or 230V AC, 50Hz.
  • Mains input range : 0V – 440V, 45Hz-65Hz
  • AC Output (Inverter) : 230V +/- 3%, 50Hz
  • Inverter topology : Bridge type center aligned switching. MOSFET or IGBT based.
  • Inverter output power : 200VA - 10000VA
  • Battery charging : Constant current SMPS charging with full charge cutoff
  • Charging current : Settable up to 30A
  • Charger working range : 120V – 270V AC Mains input With mains or generator 




For more detail or to purchase the Hex file: 
Call or whatsapp: +2348037909203. (Nigeria)
email: abledesigns@yahoo.com
 If you have any question, feel free to comment on this post.