📄 main.c
字号:
set_bit( ADCSRA, ADSC ); // initiate A/D conversion
++ucCounter;
return;
}
if ( ucCounter == 1 || ucCounter == 9 || ucCounter == 17 )
uiAccum = 0;
// Get the ADC result
if ( test_bit( ADCSRA, ADSC ) ) // should not happen
return;
uiAdc = (uint16_t) ADCL;
uiAdc += ( (uint16_t) ADCH << 8 );
if ( ucDiscard ) // discard sample requested
{
ucDiscard = 0;
set_bit( ADCSRA, ADSC ); // initiate another A/D conversion
return;
}
uiAccum += uiAdc;
if ( ucCounter == 8 || ucCounter == 16 || ucCounter == 24 )
uiAdc = uiAccum / 8; // get the average
if ( ucCounter == 8 )
{
// Process result for ADC0
uiVoltHigh_ADC = uiAdc;
// Set up for ADC1 now
ADMUX = 0b01000001; // ref=AVcc; input=ADC1; right-adjust
ucDiscard = 1; // discard the next sample
++ucCounter;
set_bit( ADCSRA, ADSC ); // initiate A/D conversion
return;
}
if ( ucCounter == 16 )
{
// Process result for ADC1
uiVoltLow_ADC = uiAdc;
// Set up for ADC2 now
//ADMUX = 0b01000010; // ref=AVcc; input=ADC2; right-adjust
ADMUX = 0b11000010; // ref=1.1V; input=ADC2; right-adjust
ucDiscard = 1; // discard the next sample
++ucCounter;
set_bit( ADCSRA, ADSC ); // initiate A/D conversion
return;
}
if ( ucCounter == 24 )
{
// Process result for ADC2
uiTemp_ADC = uiAdc;
// Set up for ADC0 now
ADMUX = 0b01000000; // ref=AVcc; input=ADC0; right-adjust
ucDiscard = 1; // discard the next sample
ucCounter = 0;
}
++ucCounter;
set_bit( ADCSRA, ADSC ); // initiate A/D conversion
}
/*---------------------------------------------------------------------
displayReadings() - information displayed on LCD row 1
Displays the various measurments on row one of the LCD, i.e.
xxxxMa y.yyV zzC
where xxxx is the charge current, y.yy is the cell voltage, and
zz is the temperature.
---------------------------------------------------------------------*/
static void displayReadings()
{
uint8_t uc, ucCol, cBuf[8];
uint16_t uiNr;
int16_t iTmp;
// Calculate and display the current across Rsense
cli();
uiNr = uiVoltHigh_ADC;
sei();
uiVoltHigh_MV = adc_to_mv( uiNr, 5000 ) * 2;
cli();
uiNr = uiVoltLow_ADC;
sei();
uiVoltLow_MV = adc_to_mv( uiNr, 5000 ) * 2;
uiCurrent_mA = ( ( uiVoltHigh_MV - uiVoltLow_MV ) * 10 ) / RESISTOR_TENTHS_OHMS;
utoa( uiCurrent_mA, cBuf, 10 );
lcd_gotoxy( 0, 0 ); // line 1 column 0
lcd_puts( cBuf );
lcd_puts( "mA" );
ucCol = strlen( cBuf ) + 2; // clear to col. 7
for ( uc=ucCol; uc<7; ++uc )
lcd_puts( " " );
// Calculate and display the cell voltage, which is 1/2 of ADC1
uiNr = uiVoltLow_MV / 2;
utoa( uiNr, cBuf, 10 );
cBuf[4] = '\0';
cBuf[3] = cBuf[2];
cBuf[2] = cBuf[1];
cBuf[1] = '.';
lcd_gotoxy( 7, 0 ); // line 1 column 7
lcd_puts( cBuf );
lcd_puts( "V " );
if ( test_bit( ucFlags, FASTCHARGE_ON ) )
if ( uiNr > uiHighestCellVoltage )
uiHighestCellVoltage = uiNr; // save the highest cell voltage
// Calculate and display the temperature
cli();
uiNr = uiTemp_ADC;
sei();
uiTemp_MV = adc_to_mv( uiNr, 1100 );
iTmp = mv_to_temp( uiTemp_MV ); // get temperature in tenthes degrees C
// Check the temperature for spurious readings.
if ( iTempCtenths )
{
if ( iTmp < ( iTempCtenths + 50 ) && iTmp > ( iTempCtenths - 50 ) )
iTempCtenths = iTmp;
}
else
iTempCtenths = iTmp; // 1st time only
iTmp = iTempCtenths / 10; // display whole degrees only
(void) itoa( iTmp, cBuf, 10 );
lcd_gotoxy( 13, 0 ); // line 1 column 13
lcd_puts( cBuf );
lcd_puts( "C" );
}
/*---------------------------------------------------------------------
displayCharge() - information displayed on LCD row 2
Compute the charge amount and display on the LCD. Using the timer1
interrupt, the charge current was added to ulChgCtr every 10
seconds, and the number of samples counted in uiReadings (there
are 360 samples per hour).
To get the total charge, divide the charge counter by 360. To get
the minutes under charge, divide the samples by 6.
---------------------------------------------------------------------*/
static void displayCharge()
{
uint16_t uiMinutes, uiChg;
uint8_t uc, ucCol, cBuf[8];
uiChg = (uint16_t) ( ulChgCtr / 360L );
if ( uiChg > 9999 ) uiChg = 9999;
utoa( uiChg, cBuf, 10 );
lcd_gotoxy( 0, 1 ); // line 2 column 0
lcd_puts( cBuf );
lcd_puts( " mAH" );
ucCol = strlen( cBuf ) + 4; // clear to col. 9
for ( uc=ucCol; uc<9; ++uc )
lcd_puts( " " );
uiMinutes = uiReadings / 6; // minutes under charge
if ( uiMinutes > 999 ) uiMinutes = 999;
utoa( uiMinutes, cBuf, 10 );
lcd_gotoxy( 9, 1 ); // line 2 column 10
lcd_puts( cBuf );
lcd_puts( " Min" );
ucCol = strlen( cBuf ) + 13; // clear to col. 16
for ( uc=ucCol; uc<16; ++uc )
lcd_puts( " " );
}
/*---------------------------------------------------------------------
build_host_msg()
Builds the message sent to the host in cTxBuffer and sets the
length in ucTxBytes.
---------------------------------------------------------------------*/
static void build_host_msg()
{
uint8_t ucN;
int8_t *ptr, cBuf[8];
uint16_t uiChg, uiMinutes, uiNr;
ptr = cTxBuffer;
// Temperature
*ptr = 'T';
++ptr;
*ptr = '=';
++ptr;
ucTxBytes = 2;
ucN = formatTemp( iTempCtenths, cBuf );
strcpy( ptr, cBuf );
ucTxBytes += ucN;
ptr += ucN;
*ptr = ' ';
++ptr;
++ucTxBytes;
// Cell voltage
strcpy( ptr, "CV=" );
ucTxBytes += 3;
ptr += 3;
uiNr = uiVoltLow_MV / 2;
utoa( uiNr, cBuf, 10 );
cBuf[4] = '\0';
cBuf[3] = cBuf[2];
cBuf[2] = cBuf[1];
cBuf[1] = '.';
strcpy( ptr, cBuf );
ucN = (uint8_t) strlen( ptr );
ucTxBytes += ucN;
ptr += ucN;
*ptr = ' ';
++ptr;
++ucTxBytes;
// Current
strcpy( ptr, "I=" );
ucTxBytes += 2;
ptr += 2;
utoa( uiCurrent_mA, ptr, 10 );
ucN = (uint8_t) strlen( ptr );
ucTxBytes += ucN;
ptr += ucN;
*ptr = ' ';
++ptr;
++ucTxBytes;
// Charge
strcpy( ptr, "CH=" );
ucTxBytes += 3;
ptr += 3;
uiChg = (uint16_t) ( ulChgCtr / 360L );
utoa( uiChg, ptr, 10 );
ucN = (uint8_t) strlen( ptr );
ucTxBytes += ucN;
ptr += ucN;
*ptr = ' ';
++ptr;
++ucTxBytes;
// Time
strcpy( ptr, "TM=" );
ucTxBytes += 3;
ptr += 3;
uiMinutes = uiReadings / 6; // minutes under charge
utoa( uiMinutes, ptr, 10 );
ucN = (uint8_t) strlen( ptr );
ucTxBytes += ucN;
ptr += ucN;
*ptr = '\r';
++ptr;
*ptr = '\n';
++ptr;
ucTxBytes += 2;
}
/*---------------------------------------------------------------------
state_analysis()
Here's where the state of the charger is determined. There are 3
states:
1. No cells in holder
2. Fast Charging
3. Trickle charging (fast charge complete)
Initially cell detection is done. No cells are indicated by
lighting the red LED. When cells are detected, fast charge state
is entered, and the yellow LED is lit. When the temperature
reaches the limit, fast charge is terminated and the state remains
fixed in trickle charge until the "zero" buton is pressed or power
is cycled. During trickle charge no LEDs are lit.
---------------------------------------------------------------------*/
static void state_analysis()
{
uint16_t uiNr;
static uint8_t ucTempCtr=0;
// If the cell voltage exceeds the threshold, there's no cells in
// the holder
uiNr = MAX_CELL_MV * 2; // two cells
if ( uiVoltLow_MV >= uiNr )
{
set_bit( RED_LED_PORT, RED_LED_PIN ); // red LED on
clear_bit( YELLOW_LED_PORT, YELLOW_LED_PIN ); // yellow LED off
clear_bit( RELAY_PORT, RELAY_PIN ); // relay off
if ( test_bit( ucFlags, FASTCHARGE_ON ) )
{
// Cells probably removed
clear_bit( ucFlags, FASTCHARGE_ON );
if ( test_bit( ucFlags, ENABLE_STATS ) )
{
strcpy( cTxBuffer, "Fast Charge ended - voltage\r\n" );
ucTxBytes = (uint8_t) strlen( cTxBuffer );
UDR0 = cTxBuffer[0];
ucTxIndex = 1;
--ucTxBytes;
set_bit( UCSR0B, UDRIE0 ); // enable Tx interrupts
}
}
return;
}
// If the state is fast charge complete, do nothing until
// the user presses the zero button
if ( test_bit( ucFlags, FASTCHARGE_COMPLETE ) )
return;
if ( test_bit( ucFlags, FASTCHARGE_ON ) )
{
// Test the temperature for charge completion
if ( iTempCtenths >= MAX_TEMPERATURE )
{
// Look for several consecutive readings over 1/2 minute
if ( ucTempCtr > 2 )
{
clear_bit( RELAY_PORT, RELAY_PIN ); // relay off
clear_bit( RED_LED_PORT, RED_LED_PIN ); // red LED off
clear_bit( YELLOW_LED_PORT, YELLOW_LED_PIN ); // yellow LED off
clear_bit( ucFlags, FASTCHARGE_ON );
set_bit( ucFlags, FASTCHARGE_COMPLETE );
uiBeepMs = 500;
if ( test_bit( ucFlags, ENABLE_STATS ) )
{
strcpy( cTxBuffer, "Fast Charge ended - temperature\r\n" );
ucTxBytes = (uint8_t) strlen( cTxBuffer );
UDR0 = cTxBuffer[0];
ucTxIndex = 1;
--ucTxBytes;
set_bit( UCSR0B, UDRIE0 ); // enable Tx interrupts
}
}
else
++ucTempCtr;
}
else
ucTempCtr = 0;
if ( uiTenSecCtr >= MAX_10SECS )
{
// Maximum time on fast charge reached
clear_bit( RELAY_PORT, RELAY_PIN ); // relay off
clear_bit( RED_LED_PORT, RED_LED_PIN ); // red LED off
clear_bit( YELLOW_LED_PORT, YELLOW_LED_PIN ); // yellow LED off
clear_bit( ucFlags, FASTCHARGE_ON );
set_bit( ucFlags, FASTCHARGE_COMPLETE );
uiBeepMs = 500;
if ( test_bit( ucFlags, ENABLE_STATS ) )
{
strcpy( cTxBuffer, "Fast Charge ended - time\r\n" );
ucTxBytes = (uint8_t) strlen( cTxBuffer );
UDR0 = cTxBuffer[0];
ucTxIndex = 1;
--ucTxBytes;
set_bit( UCSR0B, UDRIE0 ); // enable Tx interrupts
}
}
return;
}
// Since there are cells inserted and we never fast
// charged, let's fast charge now
set_bit( YELLOW_LED_PORT, YELLOW_LED_PIN ); // yellow LED on
clear_bit( RED_LED_PORT, RED_LED_PIN ); // red LED off
set_bit( RELAY_PORT, RELAY_PIN ); // relay on
set_bit( ucFlags, FASTCHARGE_ON );
ucTempCtr = 0;
uiTenSecCtr = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -