Created
February 9, 2017 20:33
-
-
Save anonymous/c47f3ab42c39678716136837f08872ae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include <wiring_private.h> | |
// included for access to cbi(), sbi() macros, and TCCR1B register definitions | |
// Nov, 2011 - commented out wiring_private.h and copied the macros here | |
#ifndef cbi | |
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | |
#endif | |
#ifndef sbi | |
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | |
#endif | |
#include <avr\wdt.h> | |
// access to watchdog timer macros | |
unsigned int power_level = 0; | |
// The target regulated voltage, default power level 0V (output will be input voltage +/-1V) | |
// Do not change this definition (change the SetVoltage(v) assignment in setup, below) | |
unsigned int SetVoltage(double voltage); | |
// Calculate the desired analog input reading, for a given voltage | |
signed int duty = 0; // used in the main program loop | |
// it's assigned to the analog output, to control the output voltage. | |
// the relationship between duty cycle and voltage depends on output load and input voltage. | |
// since neither the load or input are assumed, the program estimates/seeks | |
// the correct duty cycle by sensing the output voltage and making small adjustments. | |
// A greater duty cycle makes a greater voltage. | |
void setup() { | |
// I use pin 13 to indicate power, with an LED. (like the older revisions had built-in) | |
// For my rev.c arduino, I put an LED between pin 13 and GND (outputs only source 20mA). | |
pinMode(13,OUTPUT); | |
digitalWrite(13,HIGH); | |
// The following code increases the PWM frequency | |
// This might have an effect on delay(n) and millis() functions. | |
// The ideal frequency depends on the inductor, but it'll only be important if you need alot more power. | |
// My earlier tests indicated 20-300KHz are usable (depending on the inductor). | |
// (If 1KHz is used, the inductor will make a buzzing sound.) | |
#if defined(__AVR_ATmega168__) | |
// 62.5KHz PWM for the ATMega168 -> only on Arduino pins 9 and 10 | |
// set prescaler to 1 | |
// (sbi means "set bit register", cbi means "clear bit register") | |
cbi(TCCR1B, CS12); | |
cbi(TCCR1B, CS11); | |
sbi(TCCR1B, CS10); | |
// set fast PWM | |
cbi(TCCR1B, WGM13); | |
sbi(TCCR1B, WGM12); | |
// with fast PWM, the frequency is (CLK/256*prescaler) = 16MHz/256 = 62.5KHz | |
// with slow PWM, it is half that speed (31KHz) | |
#else | |
// 22KHz for the ATMega8 (this is a low frequency, so fewer inductors might work with it) | |
TCCR2 = ((TCCR2 & ~0x07) | 0x01); | |
TCCR1B = ((TCCR1B & ~0x07) | 0x01); | |
#endif | |
// enable the watchdog timer (a failsafe reset: if the program freezes, the voltage booster will shut off) | |
// the Arduino will reset if this timer isn't cleared in less than 400ms. | |
wdt_enable(400); | |
// set the voltage you want the program to maintain (any decimal value greater than your input voltage) | |
power_level = SetVoltage(9); | |
// Do not exceed 24V without taking special precautions. | |
// Do not exceed 60V with the circuit/schematic provided with this software. (75V or more will damage the arduino) | |
// Do not exceed 250mW (aka 1/4W, aka quarter watt) of power. (MAX: 5V 50mA, 9V 28mA, 12V 21mA, 24V 10mA, 48V 5mA) | |
} | |
void loop() { | |
unsigned int measure = analogRead(0); | |
wdt_reset(); // watchdog timer reset (see above) | |
if (measure>power_level+18) { | |
// "panic" if the measured voltage is more than 1V above where it should be, | |
// cut power by 50% to respond quickly. | |
duty=duty/2; | |
} else if (measure>power_level) { | |
// decrease duty cycle to compensate for smaller load | |
duty=max(0,duty-1); | |
} else if (measure<power_level) { | |
// increase duty cycle to compensate for larger load | |
duty=min(191,duty+1); | |
// Without the 191 limit, it can cause regulation to fail at high loads or high voltages. | |
// Only modify this limit if you're using an improved version of the schematic I've given. | |
} else { | |
return; | |
} | |
analogWrite(10,duty); | |
// If you have HF noise problems, you might want to add a small microseconds delay here to see if it helps. | |
// Delays can make voltage regulation worse, by reacting slower to changes in the output load. | |
// If you have regulation problems, make sure your output filter capacitor is at least 0.1uF. | |
// As your circuit's load changes, the capacitor will slow down output fluctuations. | |
} | |
// Calculate the desired analog input reading, for a given voltage | |
unsigned int SetVoltage(double voltage) { | |
if (voltage>60) { | |
return 0; // do not exceed 60V | |
} | |
// This function converts the voltage value (0 to 5V reading; 0 to 60V actual), into a value for an analog input (from 0 to 1024) | |
// If your resistor voltage divider is not perfectly 15:1 you'll need to change the formula below | |
// with ideal resistors and a perfect 5V Analog Reference voltage (AREF), an analog input value of 13.65 would be 1V | |
return (voltage*12.8); | |
// ideal ADC value, per volt = voltage*(1024/5)/(15/1) = 13.65 | |
// the real value for my circuit = voltage*(204.8)/(16.5) = 12.41 | |
// 16.5 was my measured resistor voltage divier ratio. | |
// I increased my calculated 12.41 constant to 12.8, by trial and error, in order to get closer to the target voltage | |
// My results were +/-0.2V, at a 0.1mA (100Kohm) load when powered by the Arduino. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment