Stand aiurea pe internet si cautand proiecte cu arduino am dat peste unul pe instructables, cu testare de acumulatori ni-cd 1,2v, si am inceput sa ma uit cum este facut, schema, cod etc. Am inceput sa fac si eu montajul si am vazut ca in cod poti modifica tensiunile de maxim si minim pentru acumulator. Si ce am zis eu, hmm hai sa bagam minim 2.5v si maxim 4.30, si ce credeti chiar a functionat, putea citit un acumulator li-ion si sa il descarce. Dar na, eu mereu sa fac modificari am mai vrut sa adaug un acumulator pe langa cei 3, am incercat sa ridic textul mai sus sa mai scot din cuvinte si facusem jos spatiu pentru inca un semn de baterie...si aici m-am oprit :)). Oricum i-am dat de capat cu ajutorul dl Nicu si am mai adaugat si referinta cu TL431. Cam atat, numai bine !
http://nicuflorica.blogspot.ro/
https://www.youtube.com/watch?v=96MvGp2XzuU
////////////////////////////////////////////////////////////////
// Tester capacitate acumulatori li-ion by TrAx & Nicu 09.2016
// Preluat si modificat de la http://www.instructables.com/id/Rechargeable-Battery-Capacity-Tester/
// Modificat pentru 4 acumulatori li-ion + referinta stabila TL431 4,5v
// PCD8544 library
// Feb 8, 2011 - B. Hobbs
///////////////////////////////////////////////////////////////
#include // library of functions for Nokia LCD (http://code.google.com/p/pcd8544/)
#define LCD_TEXT_WIDTH 14 // Width of text line for Nokia LCD
#define LCD_LINE1 0
#define LCD_LINE2 1
#define LCD_LINE3 2
#define LCD_LINE4 3
#define LCD_LINE5 4
#define LCD_LINE6 5
#define NUM_LINES_ON_LCD 6
#define MAX_BATTERIES 4
#define LOAD_RESISTANCE 5.8 //load resistance in ohms
#define START_BEEP 5000 // frequency in Hz
#define DONE_BEEP 1800
#define SPKR_PIN 8 // The pin used for the SPEAKER
#define LED_PIN 13 // The pin used for the LED
#define LCD_WIDTH 84 // The dimensions of the Nokia LCD(in pixels)...
#define LCD_HEIGHT 48
#define BAT_WIDTH 18 // Width of battery icon in pixels
#define BAT_HEIGHT 1 // Height of battery Icon (1 line = 8 pixels)
#define BATTERY_ICON_HORIZ 34 // Horizontal position of battery icon (in pixels)
#define MAH_HORIZ_POSITION 60 // Horizontal position of mAh display
// Bitmaps for battery icons, Full, Empty, and Battery with an X (no battery)
static const byte batteryEmptyIcon[] ={ 0x1c, 0x14, 0x77,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x7f};
static const byte batteryFullIcon[] = { 0x1c, 0x14, 0x77,0x7f,0x7f,0x7f,
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f};
static const byte noBatteryIcon [] = { 0x1C, 0x14, 0x77, 0x41, 0x41,0x41,
0x41,0x63,0x77,0x5D,0x5D,0x77,0x63,0x41,0x41,0x41,0x41,0x7f};
///////// Battery voltage limits //////////////////////////////////////////
// The following constants define the expected voltages for detecting the
// battery and the minimum voltage at which the discharge test is complete.
// *Lithium Ion cells have a fully charged no-load voltage of 3.6 to 3.7 volts
// and cause too much power dissapation in the load resistor, so
// they will not be tested
// *NiCads have a fully charged no-load voltage of 1.2 to 1.35 volts
// *NiMH batteries have a fully charged no-load voltage of 1.4 to 1.45 volts
// Since the NiCad and NiMH batteries are similar (and difficult to
// reliably autodetect) they are handled identically in this program.
////////////////////////////////////////////////////////////////////////////
#define MAX_VOLTAGE 4290 // Max Voltage used for detection (in mV)
#define MIN_VOLTAGE 2500 // Min Voltage for load removal (in mV)
static PCD8544 lcd;
enum {NOT_INSTALLED, DETECTING_TYPE, OVER_VOLTAGE, TEST_IN_PROGRESS, DONE}; // battery status values
struct batteryStruct
{
unsigned long charge; // Total microamp hours for this battery
byte battStatus; // set this to DONE when this cell's test is complete
byte batteryVoltagePin; // Analog sensor pin (0-5) for reading battery voltage
byte fetVoltagePin; // Analog sensor pin (0-5) to read voltage across FET
byte dischargeControlPin; // Output Pin that controlls the load for this battery
unsigned int lowerThreshold; // voltage at which discharge is complete (mV)
unsigned long PrevTime; // Previous time reading (in milliseconds)
unsigned int numSamplesAboveMin; // number of good voltage readings (to determine battery installed)
unsigned int numSamplesBelowMin; // number of samples read below minimum (to determine battery discharged)
}
battery[MAX_BATTERIES];
static const byte progressIndicator[] = "-\0|/";
static const byte backslashNokia[] = //define backslach LCD character for Nokia5110 (PCD8544)
{
B0000010,
B0000100,
B0001000,
B0010000,
B0100000
};
//Prototypes for utility functions
void printRightJustifiedUint(unsigned int n, unsigned short numDigits);
void ClearDisplayLine(int line); // function to clear specified line of LCD display
unsigned int getBatteryVoltage(unsigned int batteryNum);
unsigned int getFetVoltage(unsigned int batteryNum);
void printVoltage(unsigned int n);
//-------------------------------------------
float referinta = 4500.; // in mV
void setup()
{
analogReference(EXTERNAL); // use AREF for reference voltage
unsigned int batteryNum;
unsigned int battVoltage;
Serial.begin(9600); // Initialize serial port
pinMode(SPKR_PIN, OUTPUT); //Set output mode for pin used for spkr
lcd.begin(LCD_WIDTH, LCD_HEIGHT);// set up the LCD's dimensions in pixels
// Register the backslash character as a special character
// since the standard library doesn't have one
lcd.createChar(0, backslashNokia);
tone(SPKR_PIN, START_BEEP,50); // short beep
battery[0].dischargeControlPin = 12; // setup the corresponding pins
battery[0].fetVoltagePin = 0; // for each battery according to
battery[0].batteryVoltagePin = 1; // schematic wiring diagram.
battery[1].dischargeControlPin = 11;
battery[1].fetVoltagePin = 2;
battery[1].batteryVoltagePin = 3;
battery[2].dischargeControlPin = 10;
battery[2].fetVoltagePin = 4;
battery[2].batteryVoltagePin = 5;
battery[3].dischargeControlPin = 9;
battery[3].fetVoltagePin = 6;
battery[3].batteryVoltagePin = 7;
battery[0].battStatus = DETECTING_TYPE; // initialize status of each battery
battery[1].battStatus = DETECTING_TYPE;
battery[2].battStatus = DETECTING_TYPE;
battery[3].battStatus = DETECTING_TYPE;
battery[0].numSamplesAboveMin = 0;
battery[1].numSamplesAboveMin = 0;
battery[2].numSamplesAboveMin = 0;
battery[3].numSamplesAboveMin = 0;
battery[0].numSamplesBelowMin = 0;
battery[1].numSamplesBelowMin = 0;
battery[2].numSamplesBelowMin = 0;
battery[3].numSamplesBelowMin = 0;
// Set the three FET control pins for output
pinMode(battery[0].dischargeControlPin, OUTPUT);
pinMode(battery[1].dischargeControlPin, OUTPUT);
pinMode(battery[2].dischargeControlPin, OUTPUT);
pinMode(battery[3].dischargeControlPin, OUTPUT);
lcd.setCursor(0, LCD_LINE1);// First Character, First line
lcd.print(" Test "); // Print a message to the LCD.
lcd.setCursor(0, LCD_LINE2);
lcd.print(" Capacitate ");
lcd.setCursor(0, LCD_LINE3);
lcd.print(" Li-Ion ");
lcd.setCursor(0, LCD_LINE4);
lcd.print(" Creat de ");
lcd.setCursor(0, LCD_LINE5);
lcd.print(" TrAx Palicaru");
delay(3000);
lcd.clear(); // clear the display
lcd.print(" Descarcare");
lcd.setCursor(0, LCD_LINE2);// set cursor to 3rd line
lcd.print(" Volti mAh");
}
void loop()
{
static unsigned int i = 0 ;
static unsigned int line , p, batteryNum, width1;
static unsigned long duration, currentTime;
static unsigned int battVoltage,fetVoltage, loadCurrent;
static boolean done = false;
static unsigned int beepCounter = 0;
if (!done)
{
lcd.setCursor(LCD_WIDTH-5, LCD_LINE1); // end of line 1
lcd.write(progressIndicator[i % (sizeof(progressIndicator)-1)]);
lcd.home();
lcd.write(progressIndicator[i++ % (sizeof(progressIndicator)-1)]);
for (batteryNum= 0 ; batteryNum < MAX_BATTERIES ; batteryNum++)
{
battVoltage = getBatteryVoltage(batteryNum);
fetVoltage = getFetVoltage(batteryNum);
// Calculate the display line number for this battery
line = batteryNum + LCD_LINE3; // first battery displayed on line4
if ( battery[batteryNum].battStatus == TEST_IN_PROGRESS)
{
ClearDisplayLine(line);
printVoltage(battVoltage);
lcd.setCursor(BATTERY_ICON_HORIZ , line); // indent to horiz pixel location for battery icon
width1 = 3 + (i % (sizeof(batteryEmptyIcon)-3)) ; //start at offset of 3 pixels
// Display the left half of the Battery Icon (Empty), at calculated width
lcd.drawBitmap(batteryEmptyIcon, width1, 1); // Battery Empty icon (partial) one line tall
// Display the remainder of the Battery Icon (Full)
lcd.drawBitmap(&batteryFullIcon[width1], sizeof(batteryFullIcon) - width1, 1);
// Calculate the time duration between the last reading (in milliseconds)
currentTime = millis();
duration = (currentTime - battery[batteryNum].PrevTime);
battery[batteryNum].PrevTime = currentTime;
// Current through resistor is voltage across the resistor divided by load restistance
// Since the voltage is in millivolts, the current will be in milliamps
loadCurrent = (battVoltage - fetVoltage) / LOAD_RESISTANCE;
// milliAmpHours = current (in milliAmps) * duration (in Hours)
// Must divide by (60*60*1000) to convert duration in micro seconds to hours
// But doing this now would cause a loss of precision, so
// divide by 3600 which will result in microamp hours to be summed.
// Divide by 1000 when milliamp hours are desired for display
battery[batteryNum].charge += (loadCurrent * duration) / 3600;
Serial.print("Bat");
Serial.print(batteryNum+1);
Serial.print(" V=");
Serial.print(battVoltage);
Serial.print(" duration ");
Serial.print(duration);
Serial.print("ms load=");
Serial.print(loadCurrent );
Serial.print("mA mAh=");
Serial.println(battery[batteryNum].charge/1000);
lcd.setCursor(MAH_HORIZ_POSITION, line); // indent to pixel location for mAh
printRightJustifiedUint(battery[batteryNum].charge/1000,4);
// Has the battery voltage dropped below the minimum?
// Must have several battery voltage samples below minimum
// in a row, before declaring 'done'
if (battVoltage < battery[batteryNum].lowerThreshold)
{
Serial.print("Batt");
Serial.print(batteryNum);
Serial.print(" Below threshold: ");
Serial.println(battVoltage);
if ( battery[batteryNum].numSamplesBelowMin < 3 )
{
battery[batteryNum].numSamplesBelowMin++;
}
else
{
// This testing on this battery is complete, set status to DONE
// Turn off the discharge load and update the display
battery[batteryNum].battStatus = DONE;
digitalWrite(battery[batteryNum].dischargeControlPin, LOW); // turn off the load
ClearDisplayLine(line);
// Display the Empty Battery Icon
lcd.setCursor(BATTERY_ICON_HORIZ , line); // indent to horiz pixel location for battery icon
lcd.drawBitmap(batteryEmptyIcon, sizeof(batteryEmptyIcon), 1);
lcd.setCursor(MAH_HORIZ_POSITION, line); // indent to pixel location for mAh
printRightJustifiedUint(battery[batteryNum].charge/1000,4);
tone(SPKR_PIN, DONE_BEEP,50); // short beep
// Check to see if ALL installed batteries are in the DONE state.
done = checkAllDone();
}
}
else
{
// reset counter since this reading was good.
battery[batteryNum].numSamplesBelowMin = 0;
}
}
else if (battery[batteryNum].battStatus == DONE)
{
// don't update this line of the display
}
else if (battery[batteryNum].battStatus == NOT_INSTALLED)
{
ClearDisplayLine(line);
lcd.setCursor(BATTERY_ICON_HORIZ , line); // indent to horiz pixel location for battery icon
lcd.drawBitmap(noBatteryIcon, sizeof(noBatteryIcon), 1);
if (battVoltage >= MIN_VOLTAGE)
{
// This condition indicates that a battery has
// been installed, change status to Detecting
battery[batteryNum].battStatus = DETECTING_TYPE;
}
}
else if (battery[batteryNum].battStatus == OVER_VOLTAGE )
{
lcd.setCursor(0, line);
lcd.print(" OVER VOLTAGE ");
battery[batteryNum].battStatus = DETECTING_TYPE;
}
else if (battery[batteryNum].battStatus == DETECTING_TYPE)
{
lcd.setCursor(0, line);
lcd.print(" Detecting... ");
detectBatteryType(batteryNum, battVoltage );
}
else // undefined battery status
{
// should never get here
lcd.setCursor(0, line);
lcd.print("???");
}
}
}
else
{
// we're done - all batteries are discharged
if (beepCounter < 3 )
{
lcd.setCursor(0, LCD_LINE1);// First Character, First line
lcd.print(" Test Complet ");
lcd.setInverse(beepCounter % 2); // Invert the display
tone(SPKR_PIN, DONE_BEEP,200); // done beep
beepCounter++;
}
// continue to update battery voltage
for (batteryNum= 0 ; batteryNum < MAX_BATTERIES ; batteryNum++)
{
battVoltage = getBatteryVoltage(batteryNum);
line = batteryNum + LCD_LINE3; // first battery displayed on line4
if (battery[batteryNum].battStatus == DONE)
{
// set cursor at beginning of line but don't erase battery icon
// or the result mAh
lcd.setCursor(0 , line);
printVoltage(battVoltage);
}
else
{
ClearDisplayLine(line);
lcd.setCursor(BATTERY_ICON_HORIZ , line); // indent to horiz pixel location for battery icon
lcd.drawBitmap(noBatteryIcon, sizeof(noBatteryIcon), 1);
}
}
}
delay(1000); // wait one second, then get next set of samples
} //end of main loop
//////////////////////////////////////////////////////////////////////////////////
// detectBatteryType() Detects the battery type and sets up the appropriate
// status and thresholds
//////////////////////////////////////////////////////////////////////////////////
void detectBatteryType(unsigned int batteryNum, unsigned int battVoltage)
{
if (battery[batteryNum].numSamplesAboveMin > 3)
{
if (battVoltage > MAX_VOLTAGE )
{
battery[batteryNum].battStatus = OVER_VOLTAGE;
}
else if (battVoltage > MIN_VOLTAGE)
{
// Battery Type identified as: li-ion
// Initialize variables and start discharge
battery[batteryNum].lowerThreshold = MIN_VOLTAGE;
battery[batteryNum].battStatus = TEST_IN_PROGRESS;
battery[batteryNum].charge = 0;
battery[batteryNum].PrevTime = millis();
digitalWrite(battery[batteryNum].dischargeControlPin, HIGH); // turn on the FET
}
else
{
battery[batteryNum].numSamplesAboveMin = 0;
}
}
else // not enough good samples yet
{
if (battVoltage > MIN_VOLTAGE)
{
battery[batteryNum].numSamplesAboveMin++;
battery[batteryNum].numSamplesBelowMin = 0;
}
else
{
battery[batteryNum].numSamplesBelowMin++;
battery[batteryNum].numSamplesAboveMin = 0;
}
}
if (battery[batteryNum].numSamplesBelowMin > 3)
{
battery[batteryNum].battStatus = NOT_INSTALLED;
}
}
//////////////////////////////////////////////////////////////////////////////////
// checkAllDone() checks to see if ALL installed batteries are in the DONE state.
// return true if all tests are complete.
//////////////////////////////////////////////////////////////////////////////////
boolean checkAllDone()
{
unsigned int batteryNum;
unsigned int count=0;
for (batteryNum= 0 ; batteryNum < MAX_BATTERIES ; batteryNum++)
{
if( battery[batteryNum].battStatus == TEST_IN_PROGRESS)
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////
// printRightJustifiedUint() prints unsigned integer, right justified
// on the LCD with the specified number of digits (up to 5)
// supressing leading zeros. Prints asterisks if the number is too
// big to be displayed.
//////////////////////////////////////////////////////////////////////////////////
void printRightJustifiedUint(unsigned int n, unsigned short numDigits)
{
const unsigned int powersOfTen[]={1,10,100,1000,10000};
boolean overflow = false, supressZero = true;
unsigned int digit, d;
for (d = numDigits ; d > 0 ; d--)
{
if (overflow || numDigits > 5)
{
lcd.print("*");
}
else
{
// pow() function doesn't work as expected - use array powersOfTen[]
digit = n / powersOfTen[d-1];
n = n % (powersOfTen[d-1]);
if (digit == 0 && supressZero && d > 1)
lcd.print(" ");
else if (digit <= 9)
{
lcd.print(digit);
supressZero = false;
}
else
{
overflow = true;
lcd.print("*");
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////
// printVoltage() prints unsigned integer (millivolts), as a voltage with
// decimal point on the LCD from 0.000 to 9.999 volts
// Prints asterisks if the number is too big to be displayed.
//////////////////////////////////////////////////////////////////////////////////
void printVoltage(unsigned int n)
{
const unsigned int powersOfTen[]={1,10,100,1000,10000}, numDigits = 4;
boolean overflow = false, supressZero = true;
unsigned int digit, d;
for (d = numDigits ; d > 0 ; d--)
{
if (overflow)
{
lcd.print("*");
}
else
{
// pow() function doesn't work as expected - use array powersOfTen[]
digit = n / powersOfTen[d-1];
n = n % (powersOfTen[d-1]);
if (digit <= 9)
{
lcd.print(digit);
if (d == numDigits)
lcd.print(".");
}
else
{
overflow = true;
lcd.print("*");
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////
// ClearDisplayLine() utility function to clear one full line of the display
//////////////////////////////////////////////////////////////////////////////////
void ClearDisplayLine(int line)
{
unsigned int i;
lcd.setCursor(0, line); // put cursor on first char of specified line
lcd.clearLine();
lcd.home();
}
//////////////////////////////////////////////////////////////////////////////////
// Read analog input for specified battery and maps into a voltage (in millivolts)
//////////////////////////////////////////////////////////////////////////////////
unsigned int getBatteryVoltage(unsigned int batteryNum)
{
//return analogRead(battery[batteryNum].batteryVoltagePin), *4.887;
return map(analogRead(battery[batteryNum].batteryVoltagePin), 0,1023,0,referinta);
}
//////////////////////////////////////////////////////////////////////////////////
// Read analog input for specified battery's FET and maps into a voltage (in millivolts)
//////////////////////////////////////////////////////////////////////////////////
unsigned int getFetVoltage(unsigned int batteryNum)
{
//return analogRead(battery[batteryNum].fetVoltagePin)*4.887;
return map(analogRead(battery[batteryNum].fetVoltagePin), 0,1023,0,referinta);
}
proiectul este super , il fac si eu . Sa fii iubit aline
RăspundețiȘtergereMultsumesc foarte mult.
RăspundețiȘtergereAcest comentariu a fost eliminat de autor.
RăspundețiȘtergere