⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 avr chargeer source code
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -