# SLA Charger/Backup System

#### R!f@@

Joined Apr 2, 2009
9,740
I would like to continue from this thread onwards.
One, Two and Three

I am attaching the Schema for reference.

Aim: The PIC monitors the PSU, Charger Voltage, Charging current and Float charging mode. Senses AC failure and PSU + charger fault conditions.
Displays everything in a 16x2 LCD in 4 bit mode. Audible alarm is also there just to annoy me if I forgot to check since this charger is mounted a bit high.

@JohnInTX
The Buzzer is at RC6. RC2 is Enable pin of LCD.
I will swap them if you want me to.

The Problem I had was that the LCD is getting jumbled as I add more messages.
I figured it was due to all blocking codes of the buzzer and LCD like you said.

As of now the beeper is working. From the scope images you can see.

The Project is about the SLA charger I built.
I can do the ADC reading and displaying stuff. I have done that before. Crude but works. It gets messed up with too many messages. I cannot figure out why and nobody here had an answer before.

Since you are here I knew you will have an answer and so I thought why not start it.
The aim of the code is to monitor the charger.
Measure voltages from 5 different ADC inputs. Display them and act on it accordingly. Nothing more. It drives the Charging circuit, ON, OFF and alarm stuff with 16x2 4 bit LCD display.

All I need for now it to display Messages in LCD using interrupt. It must be possible but I cannot get my head around that part.
Can we use TMR0 for LCD messages and leave TMR2 for buzzer as it is ?

PS. Originally the target was '876 but that did not have an int osc. So switched to '886. It was PIN compatible

#### Attachments

• 75.1 KB Views: 13
Last edited:

#### Picbuster

Joined Dec 2, 2013
1,025
I don't know how your program is constructed.
In main you go once a time round to read, average and display content.
next step as you said is send data, under interrupt, to display.
But here is some care needed some compilers do not like an interrupt into an interrupt.
like
if ( int serial){
output_serial(serial_byte; // this goes wrong without any code attention
}

#### R!f@@

Joined Apr 2, 2009
9,740
@Picbuster
Wouldn't it be better to update the LCD in 100ms intervals via interrupt. Read ADC, do the conversion and update LCD Data register in Main.

@JohnInTX
As you said before that I do not need reload TMR2 I tried as below.
Commented out TMR += TMR2reload and the buzzer is at 10KHz. I can see from the scope.
I need to reload TMR2 to TMR2reload value to get the buzzer at 3.3KHz.

Am I missing something here ?

#### Picbuster

Joined Dec 2, 2013
1,025
@Picbuster
Wouldn't it be better to update the LCD in 100ms intervals via interrupt. Read ADC, do the conversion and update LCD Data register in Main.

@JohnInTX
As you said before that I do not need reload TMR2 I tried as below.
Commented out TMR += TMR2reload and the buzzer is at 10KHz. I can see from the scope.
I need to reload TMR2 to TMR2reload value to get the buzzer at 3.3KHz.

Am I missing something here ?
Conversion in interrupt and display in main is the best way. But again I do not have your code.
Displays don't need, in a normal case, updates faster than 0,5 sec. I use 1 sec.

#### R!f@@

Joined Apr 2, 2009
9,740
We'll see. I do not have a complete working code, just the buzzer part is working

#### JohnInTX

Joined Jun 26, 2012
4,357
@R!f@@
Ahhh.. I see. Not Easy7. Thanks for the skiz, I'll take a look at it.
I don't see any reason that this can't be done with what you have drawn. As Picbuster says, display in main. The ADC conversion can be done via interrupt but I usually just start a conversion in an ADC task and leave. Next time the task runs, the ADC is likely done. Read it and start conversion again. This makes for lots of readings. I average them for a smooth converted value.
A display update interval of 100ms is probably more than you need. 500ms-1 sec is probably plenty. The values don't change that fast in a charger.
I'll take a look at your code..

EDIT: Have you laid out PC boards for this or is it in proto stage? If still a proto, we can make things better with some pin relocations. If already on a PCB, we can go from there.
EDIT: Do you want the backlight to be dimmable (PWM?) or just switchable on/off?
EDIT: Are you going to use a debugger that uses the ICSP lines or just reserve them for programming? (I'd use the debugger if you have it available).I'm working up a better pinout for you if you can move pins... It takes advantage of both hardware PWMs and will make the rest of your code much easier..

Last edited:

#### R!f@@

Joined Apr 2, 2009
9,740
Ahhh.. I see. Not Easy7. Thanks for the skiz, I'll take a look at it.
What's Easy7 ?
Are you referring to the EasyPIC7 I have ?

I don't see any reason that this can't be done with what you have drawn. As Picbuster says, display in main. The ADC conversion can be done via interrupt but I usually just start a conversion in an ADC task and leave. Next time the task runs, the ADC is likely done. Read it and start conversion again. This makes for lots of readings. I average them for a smooth converted value.
A display update interval of 100ms is probably more than you need. 500ms-1 sec is probably plenty. The values don't change that fast in a charger.
I'll take a look at your code..
Fair enough. I will go with the advice. You guys know better about these stuff

EDIT: Have you laid out PC boards for this or is it in proto stage? If still a proto, we can make things better with some pin relocations. If already on a PCB, we can go from there.
PCB is already made and the components are in, as you can see from the pictures. Even though a proto, making PCB's is not easy for me yet.
It will be easy for me if you can go with what I have already made.

EDIT: Do you want the backlight to be dimmable (PWM?) or just switchable on/off?
Just ON/OFF not dimmable. No need for that

EDIT: Are you going to use a debugger that uses the ICSP lines or just reserve them for programming? (I'd use the debugger if you have it available).
PCB is made to use ICSP only. Nothing else is connected.

I'm working up a better pinout for you if you can move pins...
What do you have in mind. It won't harm to lay out what you think. Might be better for the next version. A better one may be.

Last edited:

#### JohnInTX

Joined Jun 26, 2012
4,357
OK, I'll chew on that for awhile..
You will use MikroC's LCD routines I assume and they won't be compatible with the software PWM we have since you can't mix shadowed (our PWM) and non-shadowed (MikroC libraries) constructs on the same port. No worries. Just have to think on it a bit...

#### R!f@@

Joined Apr 2, 2009
9,740
I do not need to use MikroC's routines if I can do what I want without it
It's not compatible. I checked. The Buzzer does not work if I put a message routine in the main.

Me think this is new to you too...!

#### JohnInTX

Joined Jun 26, 2012
4,357
I do not need to use MikroC's routines if I can do what I want without it
It's not compatible. I checked. The Buzzer does not work if I put a message routine in the main.

Me think this is new to you too...!
Its not news but I didn't know the context until now. Thinking...

#### Picbuster

Joined Dec 2, 2013
1,025
OK, I'll chew on that for awhile..
You will use MikroC's LCD routines I assume and they won't be compatible with the software PWM we have since you can't mix shadowed (our PWM) and non-shadowed (MikroC libraries) constructs on the same port. No worries. Just have to think on it a bit...
your lcd driver for the 16 x2 in 4 bit mode. ( rename to lcd.c)
I am to lazy to map the data and control lines to your hw but file will explain it self.

#### Attachments

• 2.3 KB Views: 4

#### MMcLaren

Joined Feb 14, 2010
851
PCB is already made and the components are in, as you can see from the pictures.
What pictures, please? Are they buried in one of the three other threads?

I get confused trying to figure out which particular problem you're actually working on at any given moment (lol).

#### R!f@@

Joined Apr 2, 2009
9,740
@Picbuster
Thanks ... I will check it.

@MMcLaren
Where have you been ?
Sorry the pictures were buried in the other threads. Different questions on one project. That is why I decided to put them in one.
I believe I posted a question especially to you MMClaren in the Led strip project. I believe John wanted your opinion on a issue I ran into.
Not tht is a priority.
Need to get this project done as soon as possible.

I like to learn to fix this issue. It will solve a previous problem I had with an earlier project (which is on hold) too

#### R!f@@

Joined Apr 2, 2009
9,740
your lcd driver for the 16 x2 in 4 bit mode. ( rename to lcd.c)
I am to lazy to map the data and control lines to your hw but file will explain it self.
So how does this actually work.
I see it uses delays. If it does, that is what I wanna avoid

#### Picbuster

Joined Dec 2, 2013
1,025
Delays the display needs some time to handle the data see spec sheet.
Some displays are faster please use delays as indicated by supplier.
The program is simple and easy to understand but here is how to use it.
I use it with 4 X 20 and 2 x 20 displays and 1 x 16 and 2 x 16
The delay can't be the problem if you handle this in main

do an include lcd.h with content
end lcd.h

lcd_init(); // at start-up

lcd_clear(); // when needed

lcd_goto(DR1); // goto line/ position
lcd_puts("this is written @ DR1"); // print the line

two lines display uses DR1 and DR2 ( note: they are not sequential)
DR1= 64+10 start at position 10 at second line.
the positions for a 4 line display are
#define DR1 0
#define DR2 64
#define DR3 20
#define DR4 84

#### R!f@@

Joined Apr 2, 2009
9,740
LCD_DATA ???
Is it for I2C ?

My Code

C:
// ****** LCD Configuration ************
sbit LCD_RS at RC0_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D4 at RC2_bit;
sbit LCD_D5 at RC3_bit;
sbit LCD_D6 at RC4_bit;
sbit LCD_D7 at RC5_bit;
sbit LCD_RS_Direction at TRISC0_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D4_Direction at TRISC2_bit;
sbit LCD_D5_Direction at TRISC3_bit;
sbit LCD_D6_Direction at TRISC4_bit;
sbit LCD_D7_Direction at TRISC5_bit;
// End of LCD Connections.

#### MMcLaren

Joined Feb 14, 2010
851
I believe I posted a question especially to you MMClaren in the Led strip project. I believe John wanted your opinion on a issue I ran into.
I recall you guys were wondering which rotary encoder I had used but I had already stated it was a Bourns PEC11 series (lol)...
Need to get this project done as soon as possible.

I like to learn to fix this issue. It will solve a previous problem I had with an earlier project (which is on hold) too
Well, I agree with JohnInTx and Picbuster that it's time to ditch the MikroC LCD library routines. The LCD functions Picbuster posted are similar to the ones I use. Ask him to post a simple usage example... oops! I see he already has...

Last edited:

#### R!f@@

Joined Apr 2, 2009
9,740
The encoder issue,we could discuss later on that thread if you up for it.

For this project any example will help. Please post if you don't mind
Is Picbuster routine for serial I2C

#### R!f@@

Joined Apr 2, 2009
9,740
@MMcLaren I bumped that thread so you can check it out

#### MMcLaren

Joined Feb 14, 2010
851
Ok, here's an example... It's actually a project from Raj Bhatt that was written in MikroC Pro that I converted to BoostC for someone. It includes actual LCD and ADC functions instead of the MikroC library functions... I know you've had difficulties with BoostC's handling of bits so I'm not sure this will be much help. BoostC also allows "function overloading" which explains why a couple functions have the same name. I don't know if MikroC or XC8 support "function overloading". Anyway, good luck on your project...

Code:
  /******************************************************************
*                                                                *
*  Project: Raj Voltmeter                                        *
*   Source: Raj_Voltmeter.c                                      *
*   Author: Mike McLaren, K8LH                                   *
*     Date: 03-Aug-12                                            *
*  Revised: 03-Aug-12                                            *
*                                                                *
*  16F688 + HD44780 2x16 LCD 0-20V Voltmeter Experiment based    *
*  on a project from Rajendra Bhatt's blog (embedded-lab.com).   *
*                                                                *
*                                                                *
*      IDE: MPLAB 8.84 (tabs = 4)                                *
*     Lang: Sourceboost BoostC v7.05, Lite/Free version          *
*                                                                *
******************************************************************/

#include <system.h>

#pragma DATA _CONFIG, _WDT_OFF & _INTOSCIO

#pragma CLOCK_FREQ 8000000   // 8-MHz INTOSC

/******************************************************************
*  function prototypes                                           *
******************************************************************/
/******************************************************************
*  variables                                                     *
******************************************************************/

/******************************************************************
*  constants                                                     *
******************************************************************/

#define line1 0x80           // lcd ddram address for line 1
#define line2 0xC0           // lcd ddram address for line 2

#define lcd_d4 portc.0       // RC0
#define lcd_d5 portc.1       // RC1
#define lcd_d6 portc.2       // RC2
#define lcd_d7 portc.3       // RC3
#define lcd_rs portc.4       // RC4
#define lcd_e portc.5        // RC5

/******************************************************************
*  low level drivers & functions                                 *
******************************************************************/

void PutNyb(char work)       // write nibble
{ lcd_d4 = work.4;           //
lcd_d5 = work.5;           //
lcd_d6 = work.6;           //
lcd_d7 = work.7;           //
lcd_e = 1; lcd_e = 0;      // strobe 'E' pin
delay_us(160);             //
}                            //

void PutLCD(char work)       // write byte (two nibbles)
{ PutNyb(work);              // write hi nibble
asm swapf  _work,F         // swap nibbles
PutNyb(work);              // write lo nibble
}                            //

void PutCMD(char pdata)      // lcd command (RS=0)
{ lcd_rs = 0; PutLCD(pdata); //
}                            //

void PutDAT(char pdata)      // lcd data (RS=1)
{ lcd_rs = 1; PutLCD(pdata); //
}                            //

void PutDAT(char *pdata)     // lcd data (RS=1) strings
{ while(*pdata)              //
PutDAT(*pdata++);        //
}                            //

/*                                                                *
*  HD44780 "initialize by instruction" procedure for 4-bit mode  *
*                                                                */
void lcdinit()               //
{ delay_ms(100);             //
lcd_rs = 0;                // RS=0 (command)
PutNyb(0x30); delay_ms(4); // step 1 (required 4-ms delay)
PutNyb(0x30);              // step 2 (built-in 160-us delay)
PutNyb(0x30);              // step 3 (built-in 160-us delay)
PutNyb(0x20);              // step 4 (built-in 160-us delay)
/*                                                                *
*  now in 4-bit interface mode and can write full 8-bit bytes    *
*                                                                */
PutCMD(0x28);              // 4-bit, 2-lines, 5x7 font
PutCMD(0x0C);              // display on, currsor & blink off
PutCMD(0x06);              // cursor inc, shift off
PutCMD(0x01);              // clear display
delay_ms(2);               // required delay
}                            //

int getadc(char channel)     // channel, 0..7
{ int result;                //
adcon0.CHS0 = channel.0;   // select channel
delay_us(20);              // acquisition delay
adcon0.GO_DONE = 1;        // start conversion
while(adcon0.GO_DONE);     // wait for conversion complete
return result;             // 0..1023
}

/******************************************************************
*  main setup                                                    *
******************************************************************/

void main()                  //
{
ansel = 0b00000100;        // RA2/AN2 analog, others digital
adcon1 = 0b01010000;       // Fosc/16 conversion clock
cmcon0 = 0x07;             // disable comparators
osccon = 0b01110000;       // INTOSC = 8-MHz
while(osccon.HTS == 0);    // wait until osc stable
trisa = 0b00001100;        // RA2(AN2) & RA3(MCLR) inputs
trisc = 0b00000000;        // portc all outputs
lcdinit();                 // init LCD in 4-bit interface mode
PutDAT("DVM Project");     //

/******************************************************************
*  main loop                                                     *
******************************************************************/

while(1)                   //
input *= 2;              // scale to volts * 100
input += 5;              // rounding (to 1/10th volt)
PutCMD(line2+5);         // line 2 tab 6
PutDAT((input/1000) | '0');    // 'tens' digit
PutDAT((input/100)%10 | '0');  // 'ones' digit
PutDAT('.');                   // '.'
PutDAT((input/10)%10 | '0');   // 'tenths' digit
delay_ms(500);           // 500 msec update intervals
}                          // loop forever
}                            // end main()

Last edited: