16F684 based lithium ion cell charger

Status
Not open for further replies.
I'm trying to make a li ion battery charger using a PIC because the one I recently bought from Ebay looks like a simple SMPS with no protection or anything.

Anyway the problem I am having is I'm trying to get the PIC to read the voltage from an ADC and turn on a LED (eventually a transistor) to supply current to the cell and switch it off when the voltage reaches 4.0V but I can't see why it's not working - probably something small (syntax, register not setup properly, etc.) All that happens is D1 is on all the time and I can't tell if the ADC part is working or not.

Code:
/*

Main.Single.Cell.Charger.c

Created by: Jules Lewarne
Date: 17/09/2010

*/

#include <htc.h>

  //CONFIGURATION BASED ON 16F684.h and pic.h and CONFIG reg pg 94

  __CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & MCLRDIS & PWRTDIS & WDTDIS & INTIO);

  //  FCMDIS:     Disabled Fail-safe clock monitor because we don't use an ext osc
  //  IESODIS:    Internal/External Switch over is disabled (we aren't using an ext osc)
  //  BORDIS:     Brown Out detection disabled
  //  UNPROTECT:  Disable Program Code Protection
  //  MCLRDIS:    Disables pin 4 on chip from being able to clear memory externally
  //  PWRTDIS:    Allows for a min time before PIC works
  //  WDTDIS:     Disable Watchdog timer
  //  INTIO:      RA4 and RA5 are I/O instead of CLKOUT


//Define Variables

int i,j;
int dlay = 100;
int CellVoltage = 0;
int Current = 0;
int ADCState = 0;


void init(void) 
{
	CMCON0 = 0x07;	//Comparators off. Digital I/O
	PORTA = 0x00;	//Clear PORTA 
	//PORTC = 0x00;	//Clear PORTC
	TRISA = 0b00001111;	//Set PORTA all as outputs
	//TRISC = 0x00;	//Set RC0 and RC1 as outputs, rest to Output

	//ADC Initialize
	ANSEL = 0x01;	//Set AN0 as analogue input
	ADCON0 = 0x01;	//Turn on ADC channel 0
					//Bit 7 - Left Justified
					//Bit 6 - Use Vdd as ref.
					//Bit 4:2 - Channel 0
					//Bit 1 - Do Not Start
					//Bit 0 - Turn on ADC
	ADCON1 = 0x10;	//Select the clock Fosc/8

}


void cellvolt(void)	
{
	switch (ADCState)	//ADC State Machine
					{
					case 0:			//Finished, Start next sample
						GODONE = 1;
						ADCState++;
						break;
					case 1:			//Wait for ADC to complete
						if (!GODONE)
							ADCState++;
						break;
					case 2:			//Save sample value in "CellVoltage"
						CellVoltage = ADRESH;
			
						ADCState = 0;
					
						break;
								
					}
				
}


void main(void) 
{ 
	INTCON = 0;
	init();
        while(1) 
        {
			PORTA = 0b00100000;
			for (i = 0; i < dlay; i++)
			{
				for (j = 0; j < 160; j++) {};
			}
			
				
				cellvolt();	//Read CellVoltage

				if (CellVoltage < 128) //check ADC count is less than 128
					PORTA = 0x00; //switch on D0

				else
					PORTA = 0x10; //switch off D0 when threshold reached
				
						for (i = 0; i < dlay; i++)
					{
						for (j = 0; j < 160; j++) {};
					}
			
        }
}

It's been a couple of months since I was last tinkering with PICs and I was struggling with the basics then.

FYI, I'm using a PICKIT1 and MPLAB 8.53 if that makes a difference.

Jules
 
I thought that was what the switch / state machine was doing. I tried removing the ADC part and just get it to flash the LED on and off but can't even do that. Can someone suggest a simple LED flasher code?

Jules
 
Are you using the pickit1 demo board if so try this
Code:
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
  & UNPROTECT & BORDIS & IESODIS & FCMDIS);


int i, j;
int ADCState = 0;               //  Keep Track of ADC Operation
int ADCValue = 0;
int Dlay = 63;                  //  LED Time on Delay Variable
const char PORTAValue[8] = {0b010000, 0b100000, 0b010000, 0b000100, 
                            0b100000, 0b000100, 0b000100, 0b000010};
const char TRISAValue[8] = {0b001111, 0b001111, 0b101011, 0b101011, 
                            0b011011, 0b011011, 0b111001, 0b111001};
const char NOTPORTA[8] = {0, 0, 0, 0, 0, 0, 0, 0};

main()
{

    PORTA = 0;
    CMCON0 = 7;                 //  Turn off Comparators
    ANSEL = 1;                  //  Just RA0 is an Analog Input

    ADCON0 = 0b00000001;        //  Turn on the ADC
                                //   Bit 7 - Left Justified Sample
                                //   Bit 6 - Use VDD
                                //   Bit 4:2 - Channel 0
                                //   Bit 1 - Do not Start
                                //   Bit 0 - Turn on ADC
    ADCON1 = 0b00010000;        //  Selemct the Clock as Fosc/8

    while(1 == 1)               //  Loop Forever
    {
        for (i = 0; i < 8; i++ )
        {                       //  Loop through Each of the 8 LEDS
            for (j = 0; j < Dlay; j++);  //  Display "On" Delay Loop
            if ((ADCValue & (1 << i)) == 0)
                PORTA = NOTPORTA[i];
            else
                PORTA = PORTAValue[i];
            TRISA = TRISAValue[i];
        }  //  rof
        switch (ADCState)       //  ADC State Machine
        {
            case 0:             //  Finished, Start Next Sample
                GODONE = 1;
                ADCState++;
                break;
            case 1:             //  Wait for ADC to complete
                if (!GODONE)
                    ADCState++; //  Sample Finished
                break;
            case 2:             //  Save Sample Value in "ADCValue" 
                ADCValue = ADRESH;
                ADCState = 0;
                break;
        }  // hctiws
    }  //  elihw
}  //  End
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…