Arduino power supply : Completed schematics + pics + code
Update : There is an updated version with better current limiting + better software here
Here is the ~ correct schematic
Some pictures (i know it's ugly)
The finished box (outside)
Internals
And the source code (sorry, can't attach it)
/**
* Simple power supply monitored by arduino
* - We have an INA219 monitoring voltage and current
* - Basic relay (with protection diode) disconnecting output when active
* - Nokia 5110 screen printing out voltage and amps
*
* Gettings the current limit is a bit tricky as it is done in anolog world through a resistor
*/
#include <Wire.h>
#include <Adafruit_INA219.h> // You will need to download this library
#include "U8glib.h"
U8GLIB_PCD8544 u8g(12, 11, 9, 10, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
Adafruit_INA219 sensor219; // Declare and instance of INA219
float currentBias=300./1000.; // to correct current bias
bool connected=false; // is the relay disconnecting voltage ? false => connected
int relayPin = 5; // D6 : L
int buttonPin = 4; // choose the input pin (for a pushbutton)
int bounce=0;
#define ANTIBOUNCE 2
#define NEXT_CYCLE() delay(250)
//#define VERBOSE 1
//#define TESTMODE
/**
*
*
*
*/
void setup(void)
{
pinMode(relayPin, OUTPUT); // declare relay as output
pinMode(buttonPin, INPUT_PULLUP); // declare pushbutton as input
// D3 is PWM for fan
pinMode(3, OUTPUT); // D3
TCCR2A = _BV(COM2A1)| _BV(WGM21) | _BV(WGM20)| _BV(COM2B1) ;
//TCCR2B = _BV(CS22);
//OCR2A = 180;
OCR2B = 120;
Serial.begin(9600);
Serial.print("Start");
#ifndef TESTMODE
Serial.print("Sensor initialization\n");
sensor219.begin();
Serial.print("Screen initialization\n");
u8g.setColorIndex(1); // pixel on
u8g.setFont(u8g_font_gdr14);
u8g.setContrast(105); //105
u8g.drawStr(1, 15, "** booting **");
#endif
setRelayState(false);
Serial.print("Setup done\n");
}
/**
* Small function to turn a float to a string
* It automatically scale i.e. 0.5 becomes 500 m
*
*/
void float2str(char *s,float f,const char *unit)
{
float scale=1;
const char *ext=" ";
if(f<1.1)
{
f=f*1000.;
sprintf(s,"%04dm%s",(int)f,unit);
return;
}
int zleft=(int)(f);
float g=f-(float)(zleft);
int right=(int)(g*10.);
sprintf(s,"%02d",zleft);
s[2]='.';
s+=3;
sprintf(s,"%01d",right);
s+=1;
sprintf(s,"%s%s",ext,unit);
}
/**
* drive relay
* If state is on; the relay disconnects the output
* if state if off, output is connected to power supply
*/
void setRelayState(bool state)
{
if(state)
digitalWrite(relayPin, HIGH);
else
digitalWrite(relayPin, LOW);
}
/**
* Check for button press
a high enough value of NEXT_CYLE should get ride of the bumps on the button (> ~ 20 ms)
*/
bool buttonPressed()
{
if(bounce)
{
bounce--;
return false;
}
int r=digitalRead(buttonPin);
if(!r)
{
Serial.print("Press\n");
bounce=ANTIBOUNCE;
return true;
}
return false;
}
/**
*
*/
void loop(void)
{
float busVoltage = 0;
float current = 0; // Measure in milli amps
float power = 0;
char stA[10];
char stV[10];
#ifndef TESTMODE
busVoltage = sensor219.getBusVoltage_V();
current = sensor219.getCurrent_mA()+currentBias;
power = busVoltage * (current/1000); // Calculate the Power
float currentInMa=current+currentBias;
if(busVoltage>30.) // cannot read
{
u8g.drawStr(1, 15, "** ERROR **");
NEXT_CYCLE();
return;
}
if(currentInMa<1.) // Accuracy of INA219, below 1mA it's meaningless
{
strcpy(stA,"<1.0mA");
}else
{
long int c=(int)currentInMa*1000.;
c>>=3;
c<<=3;
//currentInMa=((float)c)/1000.;
float2str(stA,((float)(c))/1000000.,"A");
}
if(!connected)
{
strcpy(stA,"-- DISC --");
}
float2str(stV,busVoltage,"V");
#ifdef VERBOSE
Serial.print(stV);
Serial.print(stA);
Serial.print("-----------------\n");
#endif
u8g.firstPage();
do
{
u8g.drawStr(1, 15, stV);
u8g.drawStr(1, 32, stA);
}
while(u8g.nextPage());
#endif
if(buttonPressed()) // button pressed
{
connected=!connected;
setRelayState(connected); // when relay is high, the output is disconnected
}
NEXT_CYCLE();
}
// EOF
Comments
Post a Comment