# Programming the Programmable Hotwire Regulated Driver drop-in for [email protected]



## Alan B (May 15, 2009)

This is the Advanced User's Programming thread for the* Programmable Hotwire Regulated Driver drop-in for [email protected] *Here we will develop the Advanced User Programming Documentation and answer questions, take suggestions, etc. related to Users Programming the Regulator.
*

Table of Contents

*1. Introduction (this posting)
2. FAQ
3. Advanced Programming Manual
4. Source Code
5. Configuration Program Manual
6. reserved
7. discussion begins*


Related Threads

Discussion Thread:
*https://www.candlepowerforums.com/threads/231656*

Order Thread:
*https://www.candlepowerforums.com/threads/231886*

Review by LuxLuthor:*
http://www.candlepowerforums.com/vb/...d.php?t=230519
*
Feeler Thread:*
http://www.candlepowerforums.com/vb/...d.php?t=218506

*Design Collaboration Part I*:
http://www.candlepowerforums.com/vb/...d.php?t=186291

*Design Collaboration Part II*:
http://www.candlepowerforums.com/vb/...d.php?t=209098

*Design Collaboration Part III*:
http://www.candlepowerforums.com/vb/...d.php?t=220475


----------



## Alan B (May 15, 2009)

*Programming FAQ* (in development)


*Why would a user want to "Program" this Regulator?*

The parameters and features such as regulated bulb voltages, battery cutoff and many more are controlled by making settings in the software and loading this changed software into the Regulator.

*What are the Configurable Parameters?*

examples (the following list is not complete):

maximum bulb voltage
minimum bulb voltage
battery chemistry
number of cells
voltage range
battery voltage protection
number of clicks to enable/disable lock out
temperature of overtemperature shutdown
and many more.. (see sourcecode for all settings)

*Do I need to have "programming" experience to program the Regulator?*

Not really. The changes do not require understanding programming. The process involves making straightforward changes to a file and following a process to build the code and load it into the chip. The new Graphical Configuration program makes this even easier.

*What about the New Graphical Configuration Program*

This new Graphical program makes it easier than ever to reprogram your regulator. Click on a few things and configure, compile and load your regulator. See the instructions in post #5 of this thread.

*What does it take to Program the Regulator?*

I am using AVR Studio and WinAVR software tools. Both are free. An AVR ISP programmer is required, such as the recommended AVR USB ISP2. The programming connector is used both for the programmer and for the pushbutton switch. A convenient extender board with a testing pushbutton mounted on it is available to reach down into the flashlight and program the regulator in place.

The new configuraiton program requires much less. WinAVR, Python and the program.

*Does the Regulator need to be Removed for Programming?*

No. It remains in the flashlight during programming.

*Can the Regulator be Programmed without Batteries installed?*

Not as easily. The Programmer does not normally power the CPU, so the flashlight batteries need to be installed and powering the CPU for normal programming. Some programmers do have an option to power the CPU during programming, but this is not as convenient for testing. For testing the batteries and a suitable test bulb should be installed.

*Is a special Test Bulb required?*

If an error in programming or calibration is made the full battery voltage may be presented to the bulb. Testing with a bulb (or resistive load) that can take the full battery voltage is prudent but not required. I often use dummy cells to reduce the battery voltage such that the bulb can handle it an do initial testing that way. The software needs to be reconfigured so the low battery shutdown does not prevent testing. When things are working well the battery and software can be reconfigured and the bulb removed for final voltage calibration verification. Then the bulb can be reinstalled for final test.

*Can the Regulator be damaged by Programming?*

The microprocessor chip is rated for thousands of programming cycles and reports indicate that it will go many times that. So wearing out the chip is not likely. The microprocessor controls the FET directly and some types of incorrect programs may cause more heat in the FET. This could in some circumstances lead to damage to the FET. The greatest danger to the FET is in increasing the drive frequency which increases FET heating. As long as the FET is driven at the designed 250 hz or lower the losses in the FET are very low.

*Can the Bulb or Batteries be damaged by the Program?*

If the battery voltage is higher than the voltage the bulb can stand and full voltage is applied to the bulb, or the current is started too abruptly the bulb may fail. Incorrect software can cause this. If the battery overdischarge protection is incorrectly configured or disabled the battery may be overdischarged and damaged. So yes, the software can damage the battery or bulb, if it is incorrect.

*What is Calibration and why is it required?*

The Analog to Digital converter (ADC) on the CPU chip is used to measure the battery voltage which is required to regulate accurately. Resistors are used to set the voltage sensitivity of this ADC. The precision of the resistors and the voltage reference inside the ADC are good but not perfect. Calibration is about adjusting for the "reality" of these components so the CPU can get accurate readings of the voltage.

*How is Calibration performed?*

There are a number of different techniques to accomplish calibration. The simplest one developed so far is to load a program into the CPU that is roughly calibrated based on the marked value of the resistors. Then the regulator is set to put out a fixed known voltage. The actual voltage is measured, either with an AC+DC RMS meter, or by measuring both the battery voltage and the average bulb DC voltage with a regular meter. These value(s) are put into the software and the calibration coefficients are calculated by the program. The CPU is reloaded with this calibrated version of the software and the calibration checked by measuring the output again.

*What is the Programming Process like?*

Remove the rubber pushbutton cover on the flashlight. Pull out the pushbutton. Plug in the programming extender. Plug in the programmer. Plug the USB into the computer. Fire up AVR Studio. Select the program file.

Make any changes to voltages, UI features, etc by changing the values in the text file with the editor. Save the file. Compile the code and check the compiler messages for errors. Open the programming window and program the cpu chip. Check the programmer messages for errors. Test the light with the pushbutton on the adapter. Repeat this section till desired results are obtained.

To return the flashlight to normal, remove the programming adapter, plug in the standard control pushbutton and replace the rubber cover.

*What happens to the bulb when programming?*

The bulb stays off when programming. The pin used for the bulb is not involved and programming resets the CPU so the output goes off. If the light was on when programming started it would go off before programming starts. After programming the CPU is reset again, so the light will be in the rebooted state, which is off.

*What about software development with Linux or the Mac?*

It is possible to program this from Linux or the Mac, but I'm not working with them at this time. The Gnu C Compiler works on most platforms, but AVR Studio from Atmel is Windoze based. It is not necessary to use AVR Studio as editing can be done with other editors, and makefiles used to manage the compile/link phase. Loading via the ISP is supported by programs such as AVRDude that are platform portable. Effort is required to set this up, but it is all possible.

*What is the Software Licensing?*

This software is released under the GNU license. For further info see the sourcecode.


_Send questions and comments to_:


----------



## Alan B (May 15, 2009)

*Advanced Programming Manual* (in development)

This posting is for using AVR Studio for programming. This has been superceded by the programming GUI, jump down to post #5 for details on that method of regulator programming.

*Required Equipment*

0. Regulator and Programming Adapter in a flashlight with batteries and bulb
1. AVR ISP MkII USB Programmer and USB Cable
2. WinAVR Gcc development tools for AVR (free from http://sourceforge.net/project/showfiles.php?group_id=68108)
3. Atmel AVR Studio 4 development environment (free from http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725)
4. Source Code (from post #4 of this thread)
5. Windows PC running XP or later
6. DC Multimeter

*Hardware Installation*

Install Regulator in Flashlight (see Regulator Manual)
Install AVR ISP MkII in computer (see AVR ISP Documentation, use the cd provided)

*Software Installation and Preparations*

Download theWinAVR and AVR Studio 4 software (URLs above)
Install WinAVR
Install AVR Studio 4
Upgrade the AVR ISP MkII

*Configuring the Regulator Program the First Time*

These instructions are draft, more detail is needed...

*Create the Software Project*
- Open AVR Studio 4
- Select Project/Create new Project
- Select Project Type: AVR GCC
- Fill in Project Name: hwreg
- Insure the Create Initial File box is checked
- The initial file name will be the same as the project name
- Navigate Location to directory where you want the project to be
- Click Finish to create the new project

*Copy the source code into the file*
- Selecting the first line of the code in post #4, 
- scrolling to the end of the code, 
- holding down shift and selecting the last line (the whole text should select). 
- Then type Control-C to copy the code
- Go to the source editor window in Studio and click in the empty window. 
- Type Control-V to paste the source into the file.
- Click Save or type Control-S

*Configure the Project*
- Select Project/Configuration Options
- Active configuration should be default
- Output file name should be hwreg.elf
- Output directory should be default\
- Select device: attiny45
- Leave Frequency blank
- Optimization should be -Os
- The four boxes to the right of the device should be checked
- Click OK
- Click Project/Save Project

*Configure the AVR ISP MkII Programmer*
- Connect the AVR ISP MkII Programmer
- Open the Programming software
- On the first tab, Configure the ISP Clock rate to 250khz
- Configure the CPU type to ATTiny45
- Close the Programmer
- Close AVR Studio 4

*Preparing the flashlight for Programming*
- Remove the flashlight batteries
- Remove the Rubber switch cover from the flashlight
- Remove the switch using the switch removal tool or a loop of insulated wire
- Install the Programming Adapter
- Connect the ISP programmer to the Programming Adapter
- Connect the ISP programmer to the computer via the USB cable
- Reinstall the flashlight batteries

*Compiling and loading the program to the Regulator*

- Make any changes needed to source code file
- Save (File/Save or Control-S)
- Compile the program with Build/Build or F7
- Review the messages in the Build window for errors and warnings
- If anything needs fixing return to the Make any Changes step above
- Bring up Programmer with Tools/Program AVR/Auto Connect or the AVR button
On the Main Tab (the first time, does not need to be done each time)
- insure ATTiny45 is selected
- insure ISP Mode is selected
- under Settings select 250 khz (may need to be lower the first time)
- click "Read Signature" to verify the connection to the target board
On the Program Tab; in the ELF sub-window,
- select the input ELF file (the first time only, will remember it)
- click the Program button to program the chip!!!!!
- review the messages
-- if there are errors reducing the ISP frequency may help (the first time on a new unprogrammed chip)
-- make sure the CPU type is the same in both the project build and in the programmer settings, they are separate 

*Installing and Calibrating* (the section above needs to be merged into this section)

Open AVR Studio (the previous project should open)
Make changes to the file as needed
Save the file
Compile
Check the Error Messages. There are a number of warning INFO and NOTE statements, those do not indicate a problem. Most any other warning or error needs to be addressed before continuing.
Open the Programmer
Program the chip. If there are errors while programming the chip try reducing the clock rate and reprogramming. If that does not fix it check the CPU type to make sure it matches.
Close the Programming Software
Test the Program
If necessary back up to "make changes ..." and repeat

*Returning the Flashlight and Regulator to Operational Configuration*

Remove the flashlight batteries
Remove the Programming Adapter from the flashlight
Install the Pushbutton Control Switch
Install the Rubber Switch Cover
Reinstall the flashlight batteries
Retest the light


*Appendix A - Using Other Programmers*

Many other programmers can be used in place of the recommended AVR ISP MkII. This model is recommended due to the low cost and convenience - the software is already present in the AVR Studio Development software. Other programmers may require revised procedures to program the regulator. Some that have been used successfully:

Atmel STK500 Development and Programmer board
Atmel Dragon Development and Debugging board
USBtinyISP http://ladyada.net/make/usbtinyisp/index.html
...more...


*Appendix B - Modifications to Programmers*

Adding target power capability to the AVR ISP MkII
http://www.ehow.com/how_4998924_provide-v-power-target-board.html

_Send Corrections, Comments and Suggestions to_


----------



## Alan B (May 15, 2009)

This source code is for the prototype and contains programs FP1 through FP9. The first article uses a later version that has multiple voltage ranges and battery chemistry selection (program FP10). The version containing FP10 is not quite ready for release yet.


```
/* Hotwire Regulator 0.95 (c) 10/2008 Alan K Biocca */

/* Voltage regulator for high power incandescent flashlights
 * using PWM driving a FET
 *
 * website http://www.akbeng.com/w/HotWireReg
 *
 *-------------------------------------------------------------------------*
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
 *-------------------------------------------------------------------------*
 */

/* Hardware Config (ATTiny25/45/85)
 *
 * see schematic
 *
 * The SPI programming plug takes either the programming cable or
 *   dongle with pushbutton.
 *
 * BP0/MOSI enable ref out to capacitor for filtering and SPI
 * BP1/MISO drive opto input low to enable battery v sampler and SPI (optional)
 * BP2/SCK control pushbutton switch to ground and SPI
 * BP3/OC1Bnot drive high with PWM to enable bulb current
 * PB4/ADC2 battery/bulb voltage sample input divider
 * PB5/!RST SPI programming
 */

/* Voltage Divider Resistor Values
 *
 * R1, R2 and R3 determine the voltage range of the regulator. R3
 * should be 10K to maintain the impedance of the circuit to Atmel
 * guidlines. R2, the pot, is chosen to provide a reasonable span of
 * calibration adjustment. It should be shorted, 1K or 2K, generally.
 * The pot may be omitted and the calibration done in software. R1 is
 * the resistor that determines the high voltage end of things.
 * R1 = 100K is adequate for about 30V. R1 = 47K is good for up to
 * 12V battery packs. The 100K will work for the lower voltages, but
 * the lower R value will give slightly more resolution, however it 
 * also increases the standby drain of the circuit.
 */

/* Formulae
 *
 * VbattDC^2 * Duty_cycle = VbulbRMS^2
 *
 * VbulbRMS = VbattDC * sqrt(Duty_cycle)
 *
 * Duty_cycle = VbulbRMS^2 / VbattDC^2
 *
 * VbulbMEAN = VbattDC * Duty_cycle
 *
 * VbulbRMS = sqrt(VbattDC * VbulbMEAN)
 *
 * VbulbMEAN = VbulbRMS^2 / VbattDC
 */

/* REGULATOR MAXIMUM RATINGS
 *
 * The maximum ratings depend on the hardware. The prototype hardware
 * maximum ratings are (proposed to be) 30V 15A. Maximum current will
 * depend on heatsinking if run for long periods of time. The minimum
 * voltage is 6 volts. Below 6 volts the system will shut down. Above
 * 30 volts the electronics is subject to damage.
 */

/* WARNING
 *
 * Unlike most software this program controls hardware that
 * is not completely protected against damage. Errors in the software 
 * can cause hardware damage including blowing light bulbs,
 * damaging the FET and overcurrent or overdischarging the
 * batteries of the flashlight, possibly leading to fire or
 * explosion of the batteries. Use at your own risk. Test
 * with a resistor/LED combination, or bulb that can safely
 * take the full battery voltage, and protected or safe
 * chemistry batteries or a power supply. 
 *
 * YOU HAVE BEEN WARNED.
 */

/* TESTING
 *
 * Safe testing can be performed using a low power load that 
 * can handle full battery voltage. An LED with a resistor 
 * that will limit the current is a good example. A 1K resistor
 * will limit the current to less than 30 mA at 30V. Watch the
 * polarity or use two LEDs in parallel, one with each polarity
 * to make a polarity independent test load. 
 * 
 * Measuring bulb voltage on this regulator will require a DC RMS
 * reading meter. Note that many RMS capable meters only do RMS on
 * the AC scale. This will not produce a correct reading on this PWM
 * signal. Using an averaging DC meter will produce the mean 
 * voltage, which is different from RMS. The bulb will react to
 * RMS not average voltage. A common averaging DC meter can be
 * used by doing the calculations shown below.
 *
 *
 * RMS Calculations
 *
 * VbulbRMS = sqrt(VbattDC * VbulbMEAN)        # to see what you have
 *
 * VbulbMEAN = VbulbRMS^2 / VbattDC            # to set a desired value
 */

/* Tools and Settings
 *
 * use WinAVR and AVR Studio (free software tools)
 *
 * set to ATTiny85 or ATTiny25 CPU type (depending on which you have)
 * Compiler Optimization: Os
 * Additional Library: libm.a
 */

/* Flashlight Program Calibration
 *
 * The chip's ADC needs to be calibrated for voltage. Use one of the
 * first two methods, and optionally use the RMS method after.
 *
 * 1) Rough Calibration Method
 *
 * The accuracy of this method depends on the actual values of the 
 * resistors and the on chip voltage reference. These can vary a bit
 * so this method is not recommended for a final solution. If the RMS
 * method is going to be used for fine tuning this is adequate for 
 * initial settings.
 *
 * set the desired values for battery and bulb voltage parameters
 * set the known values for R1, R2, R3, VREF and VCAL
 * compile and load the software into the chip
 *
 * 2) DC Calibration Method (not implemented yet)
 *
 * Measure the DC voltage of the power source
 * Set the measured voltage into the DC Cal Voltage parameter
 * Set the DC Calibration flag to one
 * Apply the CAL Voltage until the light comes on (approx 10 seconds)
 * The calbration flag is automatically reset and the calibration
 *   parameter automatically determined and set
 *
 * 3) RMS Meter Fine Tune Calibration Method
 *
 * This method REQUIRES an RMS+DC meter. Most standard meters measure
 * average voltage and WILL NOT WORK for this method. Even many RMS meters
 * won't handle the square wave PWM properly or only measure RMS on AC scales.
 *
 * Use either the Rough or DC Calibration methods first
 *
 * Then turn the flashlight on to the lowest level
 * adjust the potentiometer for the specified lowest voltage
 * set the control for the highest voltage (if appropriate)
 * fine tune the potentiometer for the highest voltage
 *
 * IF the adjustment range is insufficient (or there is no adjustment pot
 * in the hardware) then adjust the VCAL calibration
 * parameter value by the error percentage
 *
 *
 * 4) DC Meter and Calculator Fine Tune Calibration Method
 *
 * Using a standard averaging meter, measure the DC battery voltage
 * (VbattDC) and the average bulb voltage (VbulbMEAN). Calculate the
 * VbulbRMS from the equation shown above. Otherwise follow method (3)
 * above.
 */


/* Program Selection
 *
 * This project will have several different programs for testing
 * and flashlight operation. The software switches here select
 * which program and options will be used in creating the
 * program. Define ONE program and any options that relate
 * to that program, and then compile and load into the chip.
 * TEST CAREFULLY at low power using an LED with resistor or 
 * low power bulb that can withstand full battery voltage.
 *
 * Programs
 *
 * FP1: Toggle the FET Gate Output (very slow or 100 hz, 50% duty cycle)
 * FP2: Electronic Pushbutton Switch (on/off)
 * FP3: Always On, Fixed PWM, Soft Start
 * FP4: Pushbutton, Fixed PWM, Soft Start
 * FP5: Pushbutton, VariLevel PWM, Soft Start
 * FP6: Always On, Regulated, Calibrated, Soft Start
 * FP7: Pushbutton, Regulated, Calibrated, Soft Start
 * FP8: Test Suite for ADC, PWM, Regulation Algorithms - WARNING - BULB DANGER
 */

#define FP9            // select ONE of the programs in the suite


/***********************************************************/

#define F_CPU 8e6        // 8 mhz cpu frequency for delay timing

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <math.h>

/***********************************************************/



#ifdef FP9 // Flashlight Program Number Nine


// This is ALPHA, partially debugged

// Feature Options in this software include:
//
// VariLevel - variable level control between two values, or on/off option
// Level Memory option
// Synchronous end of PWM pulse read ADC option
// Soft Start with fast ramp option
// Pre-calculated and Dynamic calibration options
// Blast to VMAX from double-click
// Low Battery protection backoff option
// Low standby power option
// Minimum Voltage auto-off
//

// This Flashlight Regulation and Control Program has many options

// VariLevel - This monitors the pushbutton, soft-starting to the low
// voltage setting when clicked. Clicking at low will turn off. Pressing
// will ramp toward the high voltage setting, stopping when released. 
// Clicking when above the minimum value will ramp down to minimum, where
// the next click will turn off. Pressing anytime will ramp toward high.
//
// If the low and high voltage values are set to the same number the
// interface becomes click-on and click-off. Press will always turn on.
//
// If the battery voltage is too high, or too low the voltage protection
// code will turn the output. There may
// be a "moon" mode as the voltage goes low if the batteries will hold voltage
// as the load is reduced. If they recover after being off a short time
// the light will come on when clicked again, temporarily.
//
// The optional BLAST mode allows a double click from off to quickly ramp to 
// the highest voltage output.
//
// Initial Calibration is provided by entering values for the three
// resistors and the chip voltage reference that determine this. The
// pot is assumed to be in the center of rotation, it can be used to
// fine tune the output, or omitted by setting R2 to zero.
//
// The PWM is 
// computed by integrating the sign of the error calculation
// in a feedback loop. The fast start option adds additional pulsewidth
// when the error exceeds a threshold.

// Power Supply Testing - testing with this regulator with a power supply
// can lead to some problems. The peak current required may be more than
// the supply can do in a short timeframe. Using a large capacitor acros
// the supply can help this <move this above the programs>*******************


// Calibration
//
// Calibration precalculations: The C preprocessor resolves these calculations
// to integers so the runtime does not have to do floating point math.
// Most values in the chip are in ADC units.
//
// Using VCAL factor: this additional factor is multiplied by the
// VOLTStoADC coefficient. Increasing VCAL above the nominal 1.0 value
// will reduce the output RMS voltage. This factor is used to compensate
// for ADC calibration errors to get the pot in range, or calibrate units
// that do not have the pot installed. Replace this coefficient with the
// ratio of the actual to the desired RMS voltage: VCAL = measured / desired.


//=========================== User Settings ===================================


// bulb and battery settings

#define VLO 3.0        // bulb low  setting, in RMS volts
#define VHI 9.0        // bulb high setting, in RMS volts

#define VBATT 12.0  // nominal battery voltage, in volts

//#define VBATLO 9.5    // battery low voltage protection, in volts, comment out to skip



// note - instead of having an onoff flag, just set VLO = VHI
// this looks like it will work, test it!

// options for VariLevel mode

#define BLAST        // initial double click speedramp to VHI

#define LEVELMEM    // remember last and return to it


// ADC calibration factors

#define R1 47e3        // resistor, +battery to pot, ohms (47K/100K)
#define R2 0        // adjustable cal pot, adc on wiper (0 if none)
#define R3 10e3        // resistor, pot to ground, 10K recommended
#define VREF 2.56    // chip ADC reference, in volts, 2.56 typical

#define VCAL 1.0     // tuning calibration tweak factor, 1.0 nominal


// program controls and timing

#define LOOPD 4.0    // main loop delay (floating point milliseconds)
#define SHORT 50    // duration of short vs long click (in main loop cycles)
#define DEBOUNCE 3    // pushbutton debounce, (in main loop cycles)


// misc program options, comment out to disable option

//#define LOPWR            // enable low power battery saver mode

//#define VARICAL            // variable ADC calibration in eeprom, uses up/down buttons

#define FASTSTART 25    // fast soft-start (in main loop cycles)

#define SYNCADC            // read ADC at end of PWM pulse


// test options, comment out to disable option - WARNING - BULB DANGER

//#define MAXPWM 100        // maximum PWM value for bulb protection
//#define INVERT            // invert the output (LO == GATE ON) (or STK500 LED)
//#define ADCOVERRIDE 240    // override ADC on STK500 when not hooked up
//#define RAWADC            // output raw ADC readings to PWM


//========================= End of User Settings =============================


// Calibration Calculations and Convenience Macros

#define VOLTStoADC  ( (R2*0.5+R3) / (R1+R2+R3) / VREF*255.0*VCAL )

#define VLOc    ((uint8_t)(VLO * VOLTStoADC))
#define VHIc    ((uint8_t)(VHI * VOLTStoADC))
#define VBATLOc ((uint8_t)(VBATLO * VOLTStoADC))
#define VMINc   ((uint8_t)(4.0 * VOLTStoADC))        // min operating voltage

#define BUTTON (PINB & _BV(PINB2))             // button on PB2 to ground

#define ADC_START ADCSRA |= _BV(ADSC)        /* trigger an ADC conversion */
#define ADC_WAIT while (ADCSRA & _BV(ADSC)) /* await conversion complete */


// allocate nonvolatile memory consistently, grow at end only

uint16_t EEMEM EEVersion;        // version number of EE memory (unused.)
uint16_t EEMEM adcCalE;            // ADC cal factor (dynamic calibration)


// global variables

uint8_t fault = 0;                // fault period counter

int16_t pwm = 0;                // PWM control normal value 0..255
int16_t vbulb = 0;                // bulb voltage in ADC units
int16_t err;                    // feedback control error

uint16_t adc = 0;                // ADC reading
uint16_t adcsq;                    // ADC squared
uint8_t rawadc;                    // raw ADC reading

uint8_t press = 0;                // control button pressed counter
uint8_t release = 255;            // control button released counter
uint8_t ontime = 0;                // time since turning on
//uint8_t onclick = 0;            // turning-on click flag  RETIRE THIS
uint8_t uistate = 0;            // user interface state  FUTURE
uint8_t count = 0;                // main loop counter

#ifdef LEVELMEM                    // level memory
uint8_t levelMem = VLOc;
#endif
#ifdef VARICAL                  // variable calibration in eeprom
int16_t adcCal = 0;                // ADC cal factor
uint8_t cpress = 0;                // Cal button press
#endif


// interrupt handlers

ISR(INT0_vect) /**/;      // null handler for INT0 interrupt, nothing to do


// initialization and misc functions

void initADC()    // initialize and prepare ADC for battery V reading
{
    ADMUX = _BV(REFS2)+_BV(REFS1)+
            _BV(ADLAR)+_BV(MUX1);    // ADC ref 2.56V, left adjust, inp ADC2/PB4
    DIDR0 = _BV(ADC2D);                // disa binary input ADC2/PB4 power save
    ADCSRA = _BV(ADEN)+_BV(ADSC)+    // ADC ena, start convert
            _BV(ADPS2);                // clk/16 496khz 160 rdgs

    ADC_WAIT;                        // wait till done, discard first result
}

void readADC()  // read ADC result and scale
{
    ADC_WAIT;                // wait for conversion complete

    adc = ADCH;                // get left justified 8 bit result

#ifdef ADCOVERRIDE            // override ADC for testing
    adc = ADCOVERRIDE;
#endif

    rawadc = adc;            // provide raw ADC reading

#ifdef VARICAL  // variable ADC calibration in eeprom
    if (adcCal < 0)                        // adcCal in [-255..255]
    {
        adc -= (adc * -adcCal) >> 10;    // 25% plus or minus cal range
    }
    else
    {
        adc += (adc * adcCal) >> 10;
    }
#endif
}

void init()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = _BV(DDB3);                // init PB3/!OC1B as output for gate
    PORTB = _BV(PORTB2)+_BV(PORTB1)+
            _BV(PORTB0);            // ena PB0.1.2 pullups
    
    TCCR1 = _BV(CS13);                // pwm use 8 mhz ck/128 for 244 hz
    OCR1B = 255;                    // clean up first pulse
    GTCCR = _BV(PWM1B)+_BV(COM1B0);    // enable B pwm

    initADC();                        // setup ADC
}


int main()  // Program Starts Here
{
    init();

#ifdef VARICAL              // variable calibration in eeprom
    #define CALMAX (255)
    #define CALMIN (-255)
    #define CALRATE (10)    // main loop cycles per cal bit change

    cpress = 0;
    
    adcCal = eeprom_read_word(&adcCalE);        // get cal from EEMEM
    if (adcCal > CALMAX || adcCal < CALMIN)     // clamp cal to good range
        adcCal = 0;
#endif

    for (;;)        // Main Loop never exits. 
                    //   it does two primary things - 
                    //     process pushbuttons and regulation.
    {
         // read and process the pushbutton(s)

         if (BUTTON)                                  // button released
         {
            if (release < 255) ++release;
            if (release == DEBOUNCE)
            {
                if (press < SHORT)                    // short press
                {
                    if (ontime > SHORT)                // ignore the on-click
                    {
#ifdef BLAST
                        if (ontime < 3*SHORT && vbulb > 0)    // if double-click-on
                            vbulb = VHIc;            // blast to max
                        else
#endif
                        {
                             if (vbulb > VLOc)             // if above minimum
                                vbulb = VLOc;            //   step down
                            else if (vbulb == VLOc)     // if at minimum
                                vbulb = 0;                // go off
                        }
                    }
                }
               }
            if (release >= DEBOUNCE || press < DEBOUNCE) press = 0;
#ifdef LEVELMEM
            if (release == 250 && vbulb > 0) levelMem = vbulb;
#endif
          }
          else   // button pressed
          {
               if (press < 255) ++press;    // measure press duration

               if (press == DEBOUNCE && vbulb == 0) // turn on
            {
#ifdef LEVELMEM
                vbulb = levelMem;
#else
                vbulb = VLOc;            // was off, coming on
#endif
            }
            release = 0;
          }

          if (vbulb > 0 && (count & 3) == 0)     // light is on, ramp every fourth cycle
                                            // pwm can take two cycles to catch up
                                            // need better control of ramp rate here?
          {
            if (vbulb < VHIc && press > SHORT) ++vbulb; // press-ramping
          }
#ifdef VARICAL  // variable calibration in eeprom
        if (vbulb == VLOc || vbulb == VHIc)    // only at known points
        {
            if (!(PINB & _BV(PINB1)))        // if up pressed
            {
                if (++cpress > CALRATE)
                {
                    cpress = 0;
                    if (adcCal > CALMIN) --adcCal;
                }
            }
            else if (!(PINB & _BV(PINB0)))    // if down pressed
            {
                if (++cpress > CALRATE)
                {
                    cpress = 0;
                    if (adcCal < CALMAX) ++adcCal;
                }
            }
            else cpress = 0;
        }
#endif

        if (vbulb != 0)        // do RMS Voltage Regulation
        {
            if (ontime < 255) ++ontime;
            if (vbulb > VHIc) vbulb = VHIc;    // protect bulb voltage clamp

#ifdef SYNCADC    // read ADC synchronized at end of PWM pulse

            if (pwm > 0 && pwm < 255)                // sync to PWM cycle
            {
                while (PINB & _BV(PB3)) /**/;        // wait for PWM off
                while (!(PINB & _BV(PB3))) /**/;    // wait for PWM on
            }

            ADC_START;                                 // start conversion Vbatt
            readADC();                                // read result

            // get last ADC reading at end of PWM cycle

            while (pwm > 0 && pwm < 255 && PINB & _BV(PB3))    // while PWM cycle is on
            {
                readADC();                            // store previous ADC result

                ADC_START;                             // start conversion Vbatt
                ADC_WAIT;                            // wait till done
            }
#endif
            ADC_START;                             // start conversion Vbatt
            readADC();

            adcsq = (adc * adc) >> 8;            // square and scale

            // use this loaded conversion for FET drive voltage protection
            if (adc < VMINc) ++fault;                        // lo volt protection
            if (rawadc > 252 && vbulb > VLOc) vbulb = VLOc;    // hi volt protection

            // use a new unloaded conversion for battery condition
            ADC_START;                             // start conversion Vbatt
            readADC();

            err = adcsq * pwm - vbulb * vbulb;    // mean-square error
            if (err > 0) --pwm;                    // integrate error
            else ++pwm;

#ifdef FASTSTART    // fast soft-start ramp

#define NOMPWM (VHI*VHI/(VBATT*VBATT) * 255.0)    // nominal pwm
#define FASTSTEP (NOMPWM / FASTSTART)            // pwm step for fast ramp
#define FASTTHRESH ((VBATT*VBATT * FASTSTEP/255.0)*VOLTStoADC*VOLTStoADC)    // threshold above which to kick into fast ramp

            if (err < -(int16_t)(FASTTHRESH))     // if error is large
                pwm += (uint8_t)(FASTSTEP-1);    //   apply PWM kick
#endif  
        // note that fast start is going to fight with battery protection

#ifdef VBATLO
            if (adc < VBATLOc) pwm -= 5;            // low battery protect
#endif
            if (pwm < 0)                            // check for PWM fault
            {
                ++fault;
                pwm = 0;
            }
            else if (pwm > 255) pwm = 255;            // clamp PWM to valid range
        }
        else pwm = ontime = 0;

        //pwm = vbulb;            // test vbulb, bypassing regulation - WARNING - BULB AT RISK

        if (fault > 240) pwm = vbulb = ontime = fault = 0;    // fault trip
        else if (fault > 0) --fault;

#ifdef ADCTEST    // output raw adc values - WARNING - BULB AT RISK
        pwm = rawadc;
#endif

#ifdef MAXPWM
        if (pwm > MAXPWM) pwm = MAXPWM;            // safe test clamp
#endif

#ifdef INVERT
          OCR1B = pwm;        // invert output (LOW = GATE ON or for LED on STK500)
#else
        OCR1B = 255 - pwm;  // normal output PWM to FET gate (HI = ON)
#endif

        if (vbulb == 0 && release > 250)    // off and no button activity
        {
#ifdef VARICAL  // variable calibration in eeprom
            if (adcCal != eeprom_read_word(&adcCalE))    // if cal changed 
                eeprom_write_word(&adcCalE,adcCal);        // write to eeprom
#endif

#ifdef LOPWR
            // set to low power, prepare wakeup interrupt, go to sleep
            // button is on INT0 pin, use low level int, no clocks req'd
            // insure output is low. only run when PWM is off
            // disable brownout detection? (BOD not enabled)
            ADCSRA = 0;                // disable ADC to save power
            sleep_enable();            // prepare for sleep
            sei();                    // enable interrupts
            MCUCR = 0b00100000;      // int on INT0 low level, conserve power
            GIMSK = 0b01000000;      // INTO mask enable
            sleep_cpu();            // sleep, interrupt on button push

            sleep_disable();        // waking up
            cli();                    // disable interrupts
            init();                    // wake up, re-init, ADC on, etc
#endif
        }
                                    // estab loop rate
#ifdef SYNCADC
        if (pwm == 0 || pwm == 255)
            _delay_ms(LOOPD);
#else
        _delay_ms(LOOPD);            
#endif
        ++count;                    // loop counter
     }
}

#endif // FP9


//=============================================================================

#ifdef FP8  // Test Suite, Regulation, ADC, PWM Testing

// WARNING - Several of these tests are unregulated and present a risk to
// overdriving a bulb that cannot handle the full supply voltage. Keep the
// supply voltage lower than the bulb's rated voltage for bulb protection.

// Type of Control

#define PWMS        // step by PWM, choose NONE of the control algorithms (1,2,4,8,16,32,64,128,254)
//#define VOLTAGES    // step by Voltage, choose ONE of the control algorithms (0,1,2,3,4,5,6,7,8,9,10,11,12)

// Choose ONE of the following Control Algorithms. Comment the rest out.
// For the special PWMS mode, comment ALL of the control algorithms out

//#define INTEGRAL        // feedback with integrator, standard version
//#define INTEGER        // direct PWM calc using 32 bit integers
//#define FLOATINGPOINT    // direct PWM calc using floating point
//#define ADCTEST        // directly output the ADC reading as PWM - WARNING - BULB AT RISK

// The scope trigger mode limits the range of the PWM to [1,254]

#define SCOPETRIG      // leave an edge to trigger scope, comment out to skip

//#define SAFE 180    // max PWM value allowed to protect bulb, comment out to skip


// calibration factors

#define R1 47e3        // resistor, +battery to pot, ohms
#define R2 0        // adjustable cal pot, adc on wiper (0 if none)
#define R3 10e3        // resistor, pot to ground, 10K recommended
#define VREF 2.56    // chip ADC reference, in volts, 2.56 typical

#define VCAL 1.0    // additional calibration factor for tuning

// program controls and timing

#define LOOPD 4.0    // main loop delay (floating point milliseconds)

//#define INVERT            // invert the output (LO == GATE ON) (or STK500 LED)
//#define ADCOVERRIDE    200    // override ADC on STK500 when not hooked up


// This program monitors the pushbutton, cycling through integral voltage
// regulated outputs 0.0, 1.0, 2.0 through 12.0 volts and back to 0.0.
// Each press of the button advances the regulated output 1.0 volt. Note that
// if Vbatt is not greater than 12.0 volts the PWM will go to 100% duty cycle
// at the voltage settings exceeding Vbatt.
//. 
// The ADC is read at the end of the PWM cycle.
//
// The output is not soft-started except in integral feedback mode.
//
// A compile time option allows outputting the ADC reading directly as PWM.
// This allows tabulation of VbattDC versus PWM ontime in uS.
//
// Simple Calibration is provided by entering values for the three
// resistors and the chip voltage reference that determine this. The
// pot is assumed to be in the center of rotation, it can be used to
// fine tune the output with an RMS reading at the VLO or VHI levels.
//
// The Voltage is regulated by adjusting the PWM which is 
// computed directly from the equations using either integer or floating
// point math, as configured. There are several algorithms to choose from, 
// review the source code for more details.
//
// Using VCAL factor: this additional factor is multiplied by the
// VOLTStoADC coefficient. Increasing VCAL above the nominal 1.0 value
// will reduce the output RMS voltage. This factor is used to compensate
// for ADC calibration errors to get the pot in range, or calibrate units
// that do not have the pot installed. Replace this coefficient with the
// ratio of the actual to the desired RMS voltage: VCAL = measured / desired.

#define VOLTStoADC  ( (R2*0.5+R3) / (R1+R2+R3) / VREF*255.0*VCAL )

void initADC()    // initialize and prepare ADC for battery V reading
{
    ADMUX = _BV(REFS2)+_BV(REFS1)+_BV(ADLAR)+_BV(MUX1);    // adc ref 2.56V, left adjust, inp ADC2/PB4
    DIDR0 = _BV(ADC2D);            // disa binary input on ADC2/PB4
    ADCSRA = _BV(ADEN)+_BV(ADSC)+_BV(ADPS2)+_BV(ADPS1)+_BV(ADPS0);    // adc ena, start convert, clk/128 62khz
    while (ADCSRA & _BV(ADSC)) /**/;    // wait till done, discard result
}

void init()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = _BV(DDB3);                // init PB3/OC1Bnot as output for gate
    PORTB = _BV(PORTB2)+_BV(PORTB1)+
            _BV(PORTB0);            // ena PB2 pullup to observe pushbutton
    
    TCCR1 = _BV(CS13);                // pwm use 8 mhz ck/128 for 244 hz
    OCR1B = 255;                        // clean up first pulse
    GTCCR = _BV(PWM1B)+_BV(COM1B0);    // enable B pwm

    initADC();
}

#define BUTTON (PINB & _BV(PINB2)) // button PB2 to ground, use internal pullup

#define DEBOUNCE 3    // pushbutton debounce, in main loop intervals

int16_t pwm = 0;
uint16_t vbulb = 0;
uint8_t adc;
uint8_t adcsq;
uint8_t press = 0;
float level = 0.0;

int main()
{
    init();

    for (;;)
    {
         // read and debounce the pushbutton

         if (BUTTON)  // button released
         {
            if (press > 0) --press;
            if (press == DEBOUNCE) press = 0;
          }
          else   // button pressed
          {
               if (press < DEBOUNCE * 2) ++press;    // measure press duration

               if (press == DEBOUNCE) 
            {
#ifdef VOLTAGES        // switch cycles by one volt from 0 to 12
                if (level < 11.1) level += 1.0;
                else level = 0.0;

                vbulb = level * VOLTStoADC;
#endif
#ifdef PWMS            // switch cycles by PWM in 1,2,4,8,16,32,64,128,254
                pwm += pwm;
                if (pwm == 0) pwm = 1;
                if (pwm > 256) pwm = 1;
                if (pwm > 254) pwm = 254;
#endif
            }
          }

        // do RMS Voltage Regulation

        if (pwm > 0 && pwm < 255)                // sync to PWM cycle
        {
            while (PINB & _BV(PB3)) /**/;        // wait for PWM off
            while (!(PINB & _BV(PB3))) /**/;    // wait for PWM on
        }

        ADCSRA |= _BV(ADSC);                     // start conversion Vbatt
        while (ADCSRA & _BV(ADSC)) /**/;        // wait till done
        adc = ADCH;                                // read result

        // get last ADC reading at end of PWM cycle

        while (pwm > 0 && pwm < 255 && PINB & _BV(PB3))    // while PWM cycle is on
        {
            adc = ADCH;                            // store previous ADC result

            ADCSRA |= _BV(ADSC);                 // start conversion Vbatt
            while (ADCSRA & _BV(ADSC)) /**/;    // wait till done
        }

#ifdef ADCOVERRIDE
        adc = ADCOVERRIDE;                        // test only, force ADC result
#endif


#ifdef INTEGRAL
        adcsq = (adc * adc) >> 8;                    // square and scale
        if (adcsq * pwm >= vbulb * vbulb) --pwm;    // integrate error
        else ++pwm;
        if (vbulb == 0) pwm = 0;                    // insure off is off
#endif
#ifdef INTEGER
        pwm = (int32_t)(255)*(int32_t)(vbulb)*(int32_t)(vbulb)/
        ((int32_t)(adc)*(int32_t)(adc));    // direct pwm calculation
        if (vbulb == 0) pwm = 0;            // insure off is off
#endif
#ifdef FLOATINGPOINT
        pwm = 255.0*(float)(vbulb)*(float)(vbulb)/
        ((float)(adc)*(float)(adc));        // direct pwm calculation
        if (vbulb == 0) pwm = 0;            // insure off is off
#endif
        if (pwm < 0) pwm = 0;            // clamp pwm to valid range
        if (pwm > 255) pwm = 255;

#ifdef ADCTEST                            // ADC to PWM - WARNING - BULB AT RISK
        pwm = adc;
#endif

#ifdef SCOPETRIG
        if (pwm < 1) pwm = 1;            // always trigger the scope
        if (pwm > 254) pwm = 254;
#endif

#ifdef SAFE
        // 14V to 10V is 180 for testing to limit output voltage and protect bulb
        if (pwm > SAFE) pwm = SAFE;        // protection clamp for testing 
#endif

#ifdef INVERT
          OCR1B = pwm;            // invert output (LOW = GATE ON or for LED on STK500)
#else
        OCR1B = 255 - pwm;      // output pwm to FET gate (HI = ON)
#endif
        if (pwm == 0 || pwm == 255)    // sync with PWM unless there is none
            _delay_ms(LOOPD);        // estab loop rate
     }
}

#endif  // FP8

/***********************************************************/

#ifdef FP7 // Regulated, Pushbutton control with Soft Start Program

// This program has voltage regulation and soft start.

// bulb settings

#define VBULB 4.0    // bulb voltage setting, in RMS volts

// calibration factors

#define R1 47e3        // resistor, +battery to pot, ohms
#define R2 0        // adjustable cal pot, adc on wiper (0 if none)
#define R3 10e3        // resistor, pot to ground, 10K recommended
#define VREF 2.56    // chip ADC reference, in volts, 2.56 typical

#define VCAL 1.0    // additional calibration factor for tuning

// program controls and timing

#define LOOPD 4.0    // main loop delay (floating point milliseconds)

//#define INVERT            // invert the output (LO == GATE ON) (or STK500 LED)
//#define ADCOVERRIDE    200    // override ADC on STK500 when not hooked up


// This program monitors the pushbutton, turning on and off, soft starting and
// regulating the bulb voltage. ADC is unsynchronized.
//
// Simple Calibration is provided by entering values for the three
// resistors and the chip voltage reference that determine this. The
// pot is assumed to be in the center of rotation, it can be used to
// fine tune the output with an RMS reading at the VLO or VHI levels.
//
// The Voltage regulated by adjusting the PWM which is 
// computed by integrating the sign of the error calculation
// in a feedback loop.
//
// Calibration precalculations: The C preprocessor resolves these
// to integers so the runtime does not have floating point.
// Everything in the chip is in ADC units.
//
// Using VCAL factor: this additional factor is multiplied by the
// VOLTStoADC coefficient. Increasing VCAL above the nominal 1.0 value
// will reduce the output RMS voltage. This factor is used to compensate
// for ADC calibration errors to get the pot in range, or calibrate units
// that do not have the pot installed. Replace this coefficient with the
// ratio of the actual to the desired RMS voltage: VCAL = measured / desired.

#define VOLTStoADC  ( (R2*0.5+R3) / (R1+R2+R3) / VREF*255.0*VCAL )

#define VBc ((uint8_t)(VBULB * VOLTStoADC))

void initADC()    // initialize and prepare ADC for battery V reading
{
    ADMUX = _BV(REFS2)+_BV(REFS1)+_BV(ADLAR)+_BV(MUX1);    // adc ref 2.56V, left adjust, inp ADC2/PB4
    DIDR0 = _BV(ADC2D);            // disa binary input on ADC2/PB4
    ADCSRA = _BV(ADEN)+_BV(ADSC)+_BV(ADPS2)+_BV(ADPS1)+_BV(ADPS0);    // adc ena, start convert, clk/128 62khz
    while (ADCSRA & _BV(ADSC)) /**/;    // wait till done, discard result
}

void init()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = _BV(DDB3);                // init PB3/OC1Bnot as output for gate
    PORTB = _BV(PORTB2)+_BV(PORTB1)+
            _BV(PORTB0);            // ena PB2 pullup to observe pushbutton
    
    TCCR1 = _BV(CS13);                // pwm use 8 mhz ck/128 for 244 hz
    GTCCR = _BV(PWM1B)+_BV(COM1B0);    // enable B pwm
    initADC();
}

#define BUTTON (PINB & _BV(PINB2)) // button PB2 to ground, use internal pullup

#define DEBOUNCE 3    // pushbutton debounce, in main loop intervals

int16_t pwm,vbulb;
uint8_t adc;
uint8_t adcsq;
//int32_t ad,vb,pw;
//uint16_t ad,vb,pw,adsq;
uint8_t press;

int main()
{
    vbulb = pwm = press = 0;
    init();

#ifdef CKMULT
        ad = 255;                        // math check hangs on bad multiply
        if ((ad * ad) != 65025L)
        {
            for (;;) /**/;
        }
#endif

    for (;;)
    {
         // read and debounce the pushbutton

         if (BUTTON)  // button released
         {
            if (press > 0) --press;
            if (press == DEBOUNCE) press = 0;
          }
          else   // button pressed
          {
               if (press < DEBOUNCE * 2) ++press;    // measure press duration

               if (press == DEBOUNCE) 
            {
                if (vbulb == 0) vbulb = VBc;      // was off, coming on
                else vbulb = pwm = 0;            // on going off
            }
          }

        // do RMS Voltage Regulation

        ADCSRA |= _BV(ADSC);                 // start conversion battery V
        while (ADCSRA & _BV(ADSC)) /**/;    // wait till done
        adc = ADCH;                            // get ADC result

#ifdef ADCOVERRIDE
        adc = ADCOVERRIDE;                    // test only, force adc result
#endif
        //ad = adc;        // 16/32 bit test
        //vb = vbulb;
        //pw = pwm;
        //adsq = (ad * ad)>>8;
        //if (adsq * pw >= vb * vb) --pwm;    // integrate error
        //else ++pwm;

        //if (ad * ad * pw >= vb * vb * 255) --pwm;    // integrate error
        //else ++pwm;

        adcsq = (adc * adc) >> 8;        // square and scale
        if (adcsq * pwm >= vbulb * vbulb) --pwm;
        else ++pwm;

        if (adc > 250) pwm -= 2;        // overvoltage protect

        if (pwm < 0)                     // shut off
        {
            pwm = 0;
            //vbulb = 0;
        }
        if (pwm > 255) pwm = 255;        // clamp pwm to valid range

        //pwm = adc;                        // adc testing

        //if (pwm > 64) pwm = 64;            // protection clamp for testing

#ifdef INVERT
          OCR1B = pwm;            // invert output (LOW = GATE ON or for LED on STK500)
#else
        OCR1B = 255 - pwm;      // output pwm to FET gate (HI = ON)
#endif
        _delay_ms(LOOPD);            // estab loop rate
     }
}

#endif // FP7

/***********************************************************/

#ifdef FP6 // Regulated always-on with Soft Start Program

// This program has voltage regulation and soft start. It is suitable
// for a light with a mechanical switch, it will regulate whenever it
// has power.

// bulb settings

#define VBULB 4.0    // bulb voltage setting, in RMS volts

// calibration factors

#define R1 47e3        // resistor, +battery to pot, ohms
#define R2 0        // adjustable cal pot, adc on wiper (0 if none)
#define R3 10e3        // resistor, pot to ground, 10K recommended
#define VREF 2.56    // chip ADC reference, in volts, 2.56 typical

#define VCAL 1.0    // additional calibration factor for tuning

// program controls and timing

#define LOOPD 4.0    // main loop delay (floating point milliseconds)

#define INVERT        // invert the output (LO == GATE ON) (or STK500 LED)


// This program monitors the battery voltage, soft starting and
// regulating the bulb voltage. ADC is unsynchronized.
//
// Simple Calibration is provided by entering values for the three
// resistors and the chip voltage reference that determine this. The
// pot is assumed to be in the center of rotation, it can be used to
// fine tune the output with an RMS meter at the VLO or VHI levels.
//
// The Voltage regulated by adjusting the PWM which is 
// computed by integrating the sign of the error calculation
// in a feedback loop.
//
// Calibration precalculations: The C preprocessor resolves these
// to integers so the runtime does not have floating point.
// Everything in the chip is in ADC units.
//
// Using VCAL factor: this additional factor is multiplied by the
// VOLTStoADC coefficient. Increasing VCAL above the nominal 1.0 value
// will reduce the output RMS voltage. This factor is used to compensate
// for ADC calibration errors to get the pot in range, or calibrate units
// that do not have the pot installed. Replace this coefficient with the
// ratio of the actual to the desired RMS voltage: VCAL = measured / desired.

#define VOLTStoADC  ( (R2*0.5+R3) / (R1+R2+R3) / VREF*255.0*VCAL )

#define VBc ((uint8_t)(VBULB * VOLTStoADC))

int16_t pwm;
uint16_t adc,adcsq,vbulb;

void initADC()    // initialize and prepare ADC for battery V reading
{
    ADMUX = _BV(REFS2)+_BV(REFS1)+_BV(ADLAR)+_BV(MUX1);    // adc ref 2.56V, left adjust, inp ADC2/PB4
    DIDR0 = _BV(ADC2D);            // disa binary input on ADC2/PB4
    ADCSRA = _BV(ADEN)+_BV(ADSC)+_BV(ADPS2)+_BV(ADPS1)+_BV(ADPS0);    // adc ena, start convert, clk/128 62khz
    while (ADCSRA & _BV(ADSC)) /**/;    // wait till done, discard result
}

void init()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = _BV(DDB3);            // init PB3/OC1Bnot as output for gate
    PORTB = _BV(PORTB2)+_BV(PORTB1)+_BV(PORTB0);    // ena PB2 pullup to observe pushbutton action
    
    TCCR1 = _BV(CS13);            // pwm use 8 mhz ck/128 for 244 hz
    GTCCR = _BV(PWM1B)+_BV(COM1B0);    // enable B pwm
    initADC();
}

int main()
{
    pwm = 0;
    vbulb = VBc;
    init();

    for (;;)    // do RMS Voltage Regulation
    {
        ADCSRA |= _BV(ADSC);                 // start conversion battery V
        while (ADCSRA & _BV(ADSC)) /**/;    // wait till done
        adc = ADCH;                            // get ADC result

#ifdef ADCOVERRIDE
        adc = 240;             // test only, force adc result ***********
#endif
        adcsq = (adc * adc) >> 8;            // square and scale

        if (adcsq * pwm >= vbulb * vbulb) --pwm;    // integrate error
        else ++pwm;

        if (adc > 250) pwm -= 10;        // overvoltage protect

        if (pwm < 0)                     // shut off
        {
            pwm = vbulb = 0;
        }
        if (pwm > 255) pwm = 255;        // clamp pwm to valid range

#ifdef INVERT
          OCR1B = pwm;            // invert output (LOW = GATE ON or for LED on STK500)
#else
        OCR1B = 255 - pwm;      // output pwm to FET gate (HI = ON)
#endif
        _delay_ms(LOOPD);            // estab loop rate
     }
}

#endif // FP6

/***********************************************************/

#ifdef FP5 // Ramped, Pushbutton VariLevel PWM with Soft Start Test Program

#define PWM1 64  // low setting
#define PWM2 255 // high setting

// This program monitors the pushbutton, ramping the PWM up to PWM1
// when pressed. If pressed briefly it will then go off. If pressed
// and held it will ramp up towards PWM2.
//
// The PWM value is ramped in a linear fashion.
// This program does not have regulation, low 
// battery protection or low power consumption. It is intended 
// as a simple test program rather than an operational flashlight 
// program.

void init()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 8;     // init PB3 as output for gate
    PORTB = 7;     // ena pullup to observe pushbutton action
    TCCR1 = 0b00001000;  // use 8 mhz ck/128 for 244 hz pwm
    GTCCR = 0b01010000;
}

#define BUTTON (PINB & 4) // Pushbutton is on PB2 to ground

int main()
{
    uint16_t pwm;
    uint8_t press;
    pwm = press = 0;
    init();
    for (;;)
    {
         // read and debounce the pushbutton

         if (BUTTON)  // button released
         {
            if (press > 0) --press;
            if (press > 3)
            {
                if (press < 50 && pwm >= 50) // short press going off
                {
                     pwm = 0;
                }
                press = 3;
               }
          }
          else   // button pressed
          {
               if (press < 255) ++press; // measure press duration
               if (press < 3) press = 3;
               if (pwm == 0) pwm = 1;  // was off, coming on
          }

          if (pwm > 0) // light is on
          {
               if (pwm < PWM1) ++pwm;  // soft starting
               else
               {
                if (pwm < PWM2 && press > 50) ++pwm; // ramping
               }
          }

        OCR1B = 255 - pwm;  // output pwm to FET gate
          //OCR1B = pwm;    // invert output for LED on STK500
 
          _delay_ms(10.0);
     }
}
#endif // FP5     

/***********************************************************/

#ifdef FP4    // Pushbutton operated fixed PWM with Soft Start Test Program

#define PWM 16    // on PWM value [1..255]

// This program monitors the pushbutton, turning the PWM output to
// the FET on when the button is pressed, and off when pressed again.
// The PWM value is ramped up from zero to a fixed value in a linear
// fashion.

// This program does not have regulation, low 
// battery protection or low power consumption. It is intended 
// as a simple test program rather than an operational flashlight 
// program.

void delay()  // delay 5ms, (should conserve power)
{
    _delay_ms(5.0);
}

void pwm_init()
{
    TCCR1 = 0b00001000;        // use 8 mhz ck/128 for 244 hz pwm
    GTCCR = 0b01010000;
}

void pwm_on()  // ramp pwm output up to value
{
    uint16_t i;

    for (i = 1; i <= PWM; ++i)
    {
        OCR1B = 255 - i;    // gate drive inverted output, 0 is fully on
        _delay_ms(4.0);        // reduce this to speed up ramp
    }
}

void pwm_off()
{
    OCR1B = 255;            // gate driven from inverting output, 255 is off
}

#define BUTTON (PINB & 4)    // Pushbutton is on PB2 to ground

void waitForButton() // Wait for push on button PB2
{
    uint8_t i; i = 3;

    for (;;)    // wait for pushbutton release
    {
        if (BUTTON) 
        {
            if (--i == 0)
                break;
        }
        else
            i = 3;
        delay();
    }
    for (;;)
    {
        if (!BUTTON) return;
        delay();
    }
}

int main()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 8;    // init PB3 as output for gate
    PORTB = 7;    // ena pullup to observe pushbutton action
    pwm_init();
    for (;;)
    {
        pwm_off();    // set gate output low (light off)
        waitForButton();
        pwm_on();    // set gate output high (light on)
        waitForButton();
    }
}

#endif    // FP4

/***********************************************************/

#ifdef FP3    // Fixed always-on PWM with Soft Start Test Program

#define PWM 16    // on PWM value

//#define INVERT    // for gate low = on, else comment out

// The PWM value is ramped up from zero to a fixed value in a linear
// fashion. This would be good for a light with a mechanical power switch
// that needs soft start and voltage reduction via PWM.

int main()
{
    uint16_t pwm;

    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 8;    // init PB3 as output for gate
    PORTB = 7;    // ena pullups

    TCCR1 = 0b00001000;        // use 8 mhz ck/128 for 244 hz pwm
    GTCCR = 0b01010000;

    for (pwm = 0; pwm <= PWM; ++pwm)
    {
#ifdef INVERT
        OCR1B = pwm;            // gate low = on for STK500 LED
#else
        OCR1B = 255 - pwm;        // gate high = on
#endif
        _delay_ms(4);
    }
    for (;;) /**/ ;                // done, wait
}

#endif    // FP3

/***********************************************************/

#ifdef FP2    // Electronic Pushbutton Switch Program

// This program monitors the pushbutton, turning the FET fully on
// when the button is pressed, and back off when pressed again.

// This program does not have soft start, voltage regulation, low 
// battery protection or low power consumption. It is intended 
// as a simple test program rather than an operational flashlight 
// program.

// WARNING - Insure the bulb can take continuous battery voltage

void delay()  // delay 5ms, (should conserve power)
{
    _delay_ms(5.0);
}

#define BUTTON (PINB & 4)    // Pushbutton on PB2

void waitForButton() // Wait for push on button PB2
{
    uint8_t i; i = 3;

    for (;;)    // wait for pushbutton release
    {
        if (BUTTON) 
        {
            if (--i == 0)
                break;
        }
        else
            i = 3;
        delay();
    }
    for (;;)
    {
        if (BUTTON == 0) return;
        delay();
    }
}

int main()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 8;    // init PB3 as output for gate
    PORTB = 7;    // ena pullup to observe pushbutton action
    for (;;)
    {
        PORTB = 0+7;    // set gate output low (light off) and maintain pullups
        waitForButton();
        PORTB = 8+7;    // set gate output high (light on) and maintain pullups
        waitForButton();
    }
}

#endif    // FP2

/***********************************************************/

#ifdef FP1 // Test Program #1 toggles the FET Gate Output

#define SLOW    // toggle rate for FP1

// WARNING - Insure the bulb can take continuous battery voltage

// If this seems to run slow, the clock/8 fuse is probably set and
// everything will take 8 times longer. This is controlled by the
// programmer under the fuse bit window.

void delay() // if SLOW defined delay about 1 S
{
#ifdef SLOW
    _delay_ms(1000.0);      // 1 second on, 1 second off
#else
    _delay_ms(5.0);            // 100 hz
#endif
}

int main()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 9;    // init PB3 as output for gate

    for (;;)
    {
        PORTB = 9;    // set gate output high
        delay();
        PORTB = 0;    // set gate output low
        delay();
    }
}

#endif    // FP1

/***********************************************************/

#ifdef EEMEMTEST  // eeprom test

// this program initializes the second location in the eeprom to 3,
// and then blinks the led as many times as that location in the eeprom,
// and then writes the value plus one back to that location and stops
//
// when the chip is power cycled it reads the location, blinks the led
// and again writes the next value. 
//
// so the first time this runs after loading it blinks 3 times, then after
// each power cycle it adds one to the blink count.

uint8_t i,j;

uint8_t EEMEM first;        // allocate byte in eeprom uninitialized
uint8_t EEMEM test1 = 3;    // allocate byte in eeprom initialized at prog load

int main()
{
    CLKPR = 128;                    // set clock divider for 8mhz clock
    CLKPR = 0;

    DDRB = 8;                // led on the pin, lit when low

    j = eeprom_read_byte(&test1);

    for (i = 0; i < j; ++i)
    {
        PORTB = 0;            // stk500 led on
        _delay_ms(500.0);
        PORTB = 8;            // led off
        _delay_ms(500.0);
    }

    eeprom_write_byte(&test1,++i);

    for (;;) /**/ ;
}

#endif

/***********************************************************/

// test delay calibration. seems fine in sim. much slower in stk500.
// must be clock rate in chip. clock divide by 8 was fused on! fixed.

#ifdef DLY
int main()
{
    _delay_ms(10.0);
}
#endif

/***********************************************************/


// eof
```


----------



## Alan B (May 15, 2009)

*Programmable Hotwire Driver Configuration Program Manual*

Copyright 2009 by Alan K Biocca

Draft Document. More to be added here.

This document instructs in the operation and usage of the phdConfig program
for two purposes. One is to select configuration options so that they may 
be sent to the person doing the programming of the regulator. The other is
to program your own regulator.

See the READme.txt file for software installation of this program.

If you are generating a configuration for "Alan B" to program your regulator,
Run the program (described below), select your options, create a config
file, and email it to Alan via sales at akbeng dot com.

See the Regulator manual (phdRegulatorMan.txt) for information on
installation, removal and connecting up to program your own regulator.


Running phdConfig.py:

Double click on the phdConfig.py file. Two windows will open. The first
is a command window for Python.exe that will display messages as the 
program runs. The second window is the PHD Graphical Configuration program
user interface. This window is where you will enter your choices for 
the preset modes and voltages. You may use the drop down boxes on the 
menu bar at the top, or use the up/down arrow selections at the right of 
each option, and in some cases type into the boxes directly.

Position the two windows so both can be seen. The bottom section of the
Message window is the most important part of that window, so if there is
not enough room for all of both windows you can cover the top part of the
message window. Leave the scroll bar available so you can scroll through
the compiler messages when reviewing them.

You can select the amount of detail that is displayed by the Config program.
The Screen menu has selections for Minimum, Intermediate and Advanced.
These choices change the amount of detail that the interface will display.
You may want to start with "Minimum" to suppress some of the less important
displays. You may need to change this to set things like the programmer type
and port, but once done you can generally ignore that. Note that when
changing configuration files the values will be recalled from the file, so 
these not-visible fields may be changed by the selected config file.
There are also three font sizes available in this menu.


Enter the serial number of your regulator in the Config Name box, or
some other name for the files. If you have a regulator the serial number
is a good name to use, and you can add letters if you are setting up
multiple configurations for one Regulator. Note that the extension gets
added by the software, so don't include a dot or extension in the config
name. This root name will be used with a number of different extensions
for the files generated in a configuration.

Select code version 101. It really doesn't matter as version 100 is almost 
identical. The main difference is that version 101 goes directly "ON" when 
calibrating. Version 100 has to be turned on manually after loading the 
calibration code.

Select hardware version. The hardware being shipped is REV2E so use 
that. The REV2EH will be used for the high voltage version of 2E.

Select programmer type. Select port. Use "usb" for USB type programmers, 
or use the appropriate COM port for serial devices. This is only iimportant 
if you are going to actually program the chip, not if you are sending files 
to someone else.

Select bulb type. This will populate maximum voltage basic voltage, and 
minimum voltage from the database. You can over-ride these values. It will 
not change the database, but it will be saved in the config and used to program 
the regulator. Anytime the bulb is changed the fields will be over-written from
the database, so don't change bulbs after customizing individual bulb values.

Bulb filament height is a measurement from the face of the socket to the 
centerline of the filament in millimeters. It is used to approximate the height 
of the standoffs for the socket. This also depends on the reflector, and only 
a little data is entered for this function, so you can ignore it safely if you wish. 
It does not affect regulator code at all.

Select Calibration Mode as uncalibrated initially, this will be changed after
calibration measurements are completed later. This will set the calibration
factor to 0.900 to prevent the output voltage from being higher than max
during calibration.

Select cell chemistry and cell count.

Select Voltage Range Control. This will determine the position of the J1 
jumper and set the ranges in the software. The Auto setting causes the
software to pick the lowest range that exceeds the battery voltage.
The Auto Hi 3/6/12S setting will pick between those three ranges and
J1 will not be required. The Auto Lo 2/4/8S setting will pick between 
those ranges and J1 will be required. The "S" ranges will force the
range to that value. Generally you should always select an auto range.
If you want to work with J1 in or out you can use the Auto Hi or Lo
ranges to stay with the J1 configuration fixed. The "S" value refers to
4.2V per cell Lithium type chemistry, so 2S is 8.4V max. There is a little
headroom to the actual max, so it is slightly above 8.4V on the 2S
range.

The J1 jumper is a shorting jumper across the two pins inside the regulator.
You will see them in there when the regulator is removed from the flashlight.
A standard 0.1" computer type shorting jumper is placed across the two
pins to "Install J1". Placing this jumper on the pins shorts one of the 
resistors in the voltage scaling and lowers the voltage ranges slightly.
This makes the voltage measurements slightly more accurate in the 
case that 2/4/8S voltages are used, but is not required. You can just 
set the Auto Hi option and leave the jumper out.

Select the battery shutdown algorithm. This will generate a shutdown voltage
which can be over-ridden later if desired. Algorithm "C" is recommended.

Select all your interface options (Modes from the user manual).

Click on Save to save these values to the configuration file. If you are
going to send configuration values to someone for programming you
can do that now, or you can compile them first and review any errors.
Compilation requires WinAVR to be installed. The important file to save
or send is the <configname>.cfg file. You may wish to review the 
<configname>.txt file as it contains the user manual generated for 
this configuration.

Click on Compile. Review the command window to see if there are any
compile errors, and if the features match your expectations.

If there are errors, go back and fix them by selecting the appropriate
options. Report any problems to Alan B.

When there are no errors in the compile, you are ready to either send
the config file to Alan B for his programming, or you may program
your own regulator. The file to email is <configname>.cfg. There are
many other files there including the <configname>.txt manual file
that you may want to read to become familiar with how your regulator
will operate.

If you are going to program your regulator, continue on.


Programming a Regulator

Connect the regulator and programmer to the computer. Refer to the regulator
manual for details of this process. These steps require WinAVR and an AVR
ISP Programmer supported by phdConfig.py. These should already be installed,
refer to the READme.txt file for more information on installation if needed.

Click the Compile menu.

If there are any errors from the Compile (check the message window) they
must be fixed before proceeding. INFO warnings are not errors, they just 
inform about options that are selected. Warnings about unused variables
are not important and can be safely ignored.

At this point the programmer type and interface port must be correct, and 
the programmer plugged in to the computer and connected to a flashlight 
with power on the regulator.

If there are no errors from the Compile, click on Program.

Check the command window to see if there are any programming process errors.
Errors here can be from the wrong programmer selected, wrong or no drivers
for the programmer, regulator not powered or connected properly.

If there are no errors, test the light with the button on the progamming
adapter board. Once satisfied with the programming the flashlight may
be returned to normal. Instructions on this process are in the Regulator
Manual (phdRegulatorMan.txt).


Calibrating the Regulator

The components vary slightly and so for precision the regulator must be
calibrated. It should be recalibrated especially if the range changes. Initially
the Regulator is put into "calibrate" mode, measurement(s) are made of
the output, these measurements are input to the program and the program
is recompiled and reloaded into the regulator with the proper calibration
values in it.

Summary Procedure (expand later in more detail)
- Set to Uncalibrated
- Compile and Program the Regulator.
- Remove the bulb and connect wires into bulb socket holes for meter
-- Note that version HwReg version 100 requires the regulator be turned to
full on manually. Version 101 automagically goes to full output when
the regulator is in calibrate mode.
- Set regulator output to max voltage, make readings
-- using a TRUE AC+DC RMS meter read true RMS across two output pins, or
-- use a standard averaging DC DVm to read the voltage across the socket pins,
-- and also read the battery voltage
- Enter reading values into program, toggle to calibrated to update calculations
-- Insure that the Battery Voltage and Average Bulb Voltage fields are blank if
-- you are inputting True RMS values. If these fields have values they will over-
-- write the RMS input field.
- Compile and Program the Regulator.

- Optionally verify the output




Credits

This document contains some material from CPF:Starlight and has been written and
edited by Alan Biocca


----------



## Alan B (May 15, 2009)

reserved for expansion


----------



## LuxLuthor (May 19, 2009)

Very well done so far!

Edit: I'm also starting to see the value of having a dedicated website to hold all this information. I'm finding myself getting lost in which thread has what....lol!


----------



## Alan B (May 21, 2009)

When I get some time I will set up the new website. Hopefully these threads are making more sense:

For the Drop-In Regulator:
Discussion/Documentation
Ordering/Sales
Programming
and the Feeler thread now quiet

and the more general Design thread series
as well as threads for the other variants


----------



## LuxLuthor (May 21, 2009)

I noticed post #4. Is this what you are using in that proto model? I want to print it out and really look at what is in it.


----------



## Alan B (May 21, 2009)

LuxLuthor said:


> I noticed post #4. Is this what you are using in that proto model? I want to print it out and really look at what is in it.



No, that is not the current software from the first article. That is the software in the prototype that I have here. The first article software is still in work. I wanted to test putting the software into a posting. It is verrry slow to upload, so I'm not sure I want to do it that way. You might try copy/pasting it into a file and running the compiler on it to see how practical that is. We can always use files on the server instead.

The software versions are very similar, but there is a lot of new code in the first article with respect to multiple voltage ranges and battery chemistry, plus some bugfixes in the regulation code.


----------



## Starlight (May 21, 2009)

You said you were taking suggestions, so I have one for you. It would be very helpful if you showed a specific example of what values to change to set up a new bulb voltage, and a new battery voltage, for example.


----------



## Alan B (May 21, 2009)

Starlight said:


> You said you were taking suggestions, so I have one for you. It would be very helpful if you showed a specific example of what values to change to set up a new bulb voltage, and a new battery voltage, for example.



I have something along those lines in the source code, and we can extract that into the documentation as well.


----------



## LuxLuthor (May 21, 2009)

Alan, not to belabor my question, but I have the older code from your website, and have now copied what is in the above box and saved it in a text file. 

So the code in post #4 is what you are currently using in the prototype model you sent me and I returned? I know you said the most recent code is not finished, but trying to sort out which is the most up to date to become familiar with.


----------



## Alan B (May 21, 2009)

LuxLuthor said:


> Alan, not to belabor my question, but I have the older code from your website, and have now copied what is in the above box and saved it in a text file.
> 
> So the code in post #4 is what you are currently using in the prototype model you sent me and I returned? I know you said the most recent code is not finished, but trying to sort out which is the most up to date to become familiar with.



Sorry for the confusion. The code presently in post #4 contains FP9 the code in my prototype (let's call it S/N 000). The first article I sent to you (S/N 001) has the newer (FP10) code. The codes are largely identical - the new code (FP10) adds to FP9 primarily in the area of battery chemistry and multiple voltage range jumper and auto-selection. This does not change the majority of the code from FP9 but adds to it. So studying the FP9 code will be useful, and it is a lot shorter and easier to read than the FP10 code because the FP10 code has a lot of "if it is NiMH, LiCo, LiMn, LiFe, etc" type stuff that adds fluff but doesn't change the actual code much at all, it mostly sets a few constants that really run the show.

So I would recommend reading FP9 to start with. By changing the resistor values in FP9 it will work in the newer hardware, albeit at one voltage range of the three (two of the six using the jumper).

I have done a lot of cleanup on FP10 and with any luck will be able to post it sometime next week.

Perhaps the thing to do is to start taking questions on FP9 if folks want to read the code and ask. From that I may be able to improve the comments in FP10 to help answer some of the questions proactively.

FP9 runs the Vref at 2.56V. If we put in the right values for R1 and R3 we get the correct values for one jumper position (say in). Changing the R1 value to a different number will give correct operation for J1 out. If I remember correctly this will give us 4S and 6S voltage ranges which covers most uses quite well. So using FP9 on the current hardware works pretty well. What you cannot do in FP9 is specify chemistry and cell count. Instead battery conditions need to be specified directly in voltages. The FP10 code allows them to be specified either way and resolves it into the proper voltage range selection (given the position of J1).

One other very minor thing that I have not fixed in FP9 or FP10 yet either is the effect of the new shorter switch. In order to telescope the switch to the shorter length to fit properly under the rubber cover I had to ground one of the ISP pins. This is a pin we were not using, but it is pulled up in the code (the pullup resistor is enabled). This will waste a little current since it is now grounded, so one line of code needs to be changed slightly to let this line go low without current drain. This needs to be changed and tested but is low priority so not done yet. When we fix it in FP10 we can go back and fix it in FP09 as well, keeping FP9 as a viable simpler code.


----------



## LuxLuthor (Jun 6, 2009)

I might as well post about this software problem in case others are running into it. I downloaded the latest AVR Studio 4.16 from Atmel's site here. Installed it on my XP Pro (w/ SP3) system, but when I choose the AVR Studio 4 from Programs, it doesn't open. The other programs that get installed, and are listed on the Programs==>Atmel AVR Tools do open, just not the Studio. 

I uninstalled it, deleted remaining Atmel folder in Program Files, reinstalled it...same result. If I try installing 4.16 SP-1, still doesn't open.

I'm now in the process of downloading 4.13, 4.14, 4.15 on the same linked page, and plan on uninstalling 4.16 and working backwards. I get no errors when trying to launch 4.16 Studio....just nothing happens. I didn't see any obvious references to this on a Google search. I turned off my Zone Alarm Pro, and AV program--no help.

Not my idea of a fun time.


----------



## Alan B (Jun 6, 2009)

Sorry about these problems. Not sure what they are. The system logs may contain more info about what is going on.


----------



## LuxLuthor (Jun 6, 2009)

4-5 hours later....Well as is often the case, I have good news and bad news. The bad news is that no matter what version of AVR Studio I have tried to install (4.13, 14, 15, 16) with or without WinAVR installed, I cannot get it to start up as a program, despite successful installs.

I get no meaningful, repeating Windows Event Viewer logs in any of the various Events categories. This system is running XP Pro w/ SP3, Athlon 64 3500+, 1 GB RAM, and no programs that I can figure out that might conflict. So on this computer, I am unable to run the AVR Studio. It sucks, because this is my main computer that I use for almost everything. It is amazing that there are no clues given as to why the program will not start up.

The good news is an old computer I built in 2001 also running XP Pro w/ SP3, Athlon 2700, 1 GB RAM installs and runs it. I was about to take this old antique down to the basement. To show how old it is, it is using an old HP Laserjet 4L.


----------



## Alan B (Jun 7, 2009)

Sorry to hear about this software problem.

I have done some searching around the net and not found reference to this problem. AVRFreaks or Atmel may be able to help so it can probably be resolved in the longer term. It may be the newer versions are set up to handle Vista issues and are less XP compatible. Who knows. In the short term the backup machine can be used to get started if you wish. I'll have to get you a newer source file.


----------



## LuxLuthor (Jun 7, 2009)

Yeah, I can manage by using the old PC. I refuse to use VISTA, so I'm stalling until Winblows 7 comes out and likely has had its own SP1 before upgrading.

I mainly posted this in case others have run into a problem. 

I have NEVER had any other program fail to work on this main computer, and I have thrown a lot at it. Who knows, it could be a hardware conflict. Without any clues to troubleshoot with, I'm not sure how to figure it out.

I'm doing some plumbing work today, have to replace some valves and copper tubing. Old house.


----------



## Alan B (Jun 12, 2009)

Any progress here, Lux?


----------



## sylathnie (Jun 12, 2009)

As a suggestion install Microsoft Virtual PC on your XP computer and install another copy of XP inside of it. This may allow you to use your computer as you wish.


----------



## Alan B (Aug 16, 2009)

*MAJOR Progress Report

*Congratulations to *Starlight *for reprogramming his regulators! I believe he is the first non beta tester to have done so.
*

NEW GUI Configuration Program Development*

I have developed a new interactive Graphical user interface that builds the regulator software, compiles it and loads it into the chip. This is much simpler than the older technique and avoids editing files or loading AVR Studio at all.

*BSBG and Starlight* are beta testing this software and helping to develop the user documentation for it.

Thanks!!!!!

Now I will return to working on hardware (unless we find a bug).


----------



## milkyspit (Aug 16, 2009)

Alan B said:


> *MAJOR Progress Report
> 
> *Congratulations to *Starlight *for reprogramming his regulators! I believe he is the first non beta tester to have done so.
> *
> ...




Alan, the GUI interface sounds great, and should be a big help to folks not as comfortable with programming in a traditional IDE. What did you write it in?


----------



## Alan B (Aug 16, 2009)

milkyspit said:


> Alan, the GUI interface sounds great, and should be a big help to folks not as comfortable with programming in a traditional IDE. What did you write it in?



Thanks for the feedback!

Python's default GUI using the Tkinter library to "tk". Not the most fabulous GUI, but it is already installed in Python and pretty quick to build a decent program in. I rarely have time for elegant GUI programming, folks want me to do other things...


----------



## Alan B (Aug 16, 2009)

Beta testing has progressed, at least one tester has successfully programmed his regulator and calibrated it with the GUI system.

A new version has just been sent to beta with a few new features.

Here is the Change Log:

0.10 20090816 version sent to beta test

0.11 20090816 added code version support to handle multiple code version files
in the same dir, also added this ChangeLog. Code Version is NNN, started
with 099 since previous version was 0.98<something>
Moved bulb data out to a "bulbdata.csv" file.
Added Programmer Selection and Port. Select port "usb" for usb programmers.
Added support for USBtinyISP from www.adafruit.com/usbtinyisp.
Select "avrisp2" for Atmel's AVRISPmkII, and select "usbtiny" for the
www.adafruit.com programmer. Select port "usb" for both.
Restored the interface level from the configuration file.

0.12 20090816 fixed Low Bat error when inputting RMS and Battery DC Reading is
zero or blank. The Battery DC Reading must be either higher than the calibration
voltage, or it must be zero. It should be accurate or it should be left
blank.


----------



## BSBG (Aug 18, 2009)

I created config files, .

It was quite simple - we'll see how the rest of the process goes once Ihave the hardware.

This is one amazing project - who would have thought we would be programming modded Mag lights with a PC...


----------



## Alan B (Aug 18, 2009)

BSBG said:


> I created config files, .
> 
> It was quite simple - we'll see how the rest of the process goes once Ihave the hardware.
> 
> This is one amazing project - who would have thought we would be programming modded Mag lights with a PC...



I'll take a look at the config files tonite. 

Folks, this is going to work out nicely. When we release this software (very soon) the customer can run it and select the parameters for their regulator, and then send the config file back to me via email. I can use that config file to build the code for the regulator. This way the selections will be accurately communicated.

In this case all the customer needs is Python, and the config program should run on the Mac and Linux far enough to generate the config files. The compile and load code into the regulator parts will not easily work on the Mac or Linux, but these are not required to make the configuration file.


----------



## Alan B (Aug 18, 2009)

There was a new release of the beta configuration code this morning.

The new layout is improved and there were a few small bugfixes.


----------



## BSBG (Aug 19, 2009)

AVR ISP ordered from Digi-Key. Now all I need are some regulators .


----------



## Alan B (Aug 19, 2009)

Number BSBG01 is done, SN112. Need to set the socket height, but it is mounted in the sled and programmed.

The new graphical programming software worked really sweet. Lightning quick. It takes more time to hook up the plugs and wires than to program, calibrate and reprogram the regulator. Really impressive.


----------



## Alan B (Aug 20, 2009)

Here is a screenshot of the presently released graphical configuration program, phdConfig.py:

It is a bit too wide for embedding, so is now a link:

http://www.akbeng.com/flash/hwreg/PHD G-Config 03.png


----------



## BSBG (Aug 30, 2009)

OK, first attempt at programming is not going well.

Config file compiles OK.

AVR ISP has 2 green lights.

Programming fails - "did not find any device usb" :thinking:


----------



## Alan B (Aug 30, 2009)

BSBG said:


> OK, first attempt at programming is not going well.
> 
> Config file compiles OK.
> 
> ...



Sounds like the standard AVRISP USB driver problem. 

Unfortunately AVR Studio loads a driver that it uses but AVRDude cannot use. It produces exactly that error. Is that possibly what happened here?

In the READme.txt file there are instructions to change from the AVR Studio driver to the AVRDude driver, and how to tell which one is loaded.

OR you can use AVR Studio to program the chip. Not as easy or convenient, but do-able.

Sorry for the complexity.


----------



## BSBG (Aug 30, 2009)

"programming succeeded"

Thanks Alan- it was the drier. Now running an 1164 on 12 2/3A in a 2D host :thumbsup:.


----------



## Alan B (Aug 30, 2009)

BSBG said:


> "programming succeeded"
> 
> Thanks Alan- it was the driver. Now running an 1164 on 12 2/3A in a 2D host :thumbsup:.



Great! Looks like a very well regulated combo!! 40 to 60% PWM values. Very nice. I like the 2D form factor. Is that 2D bored out to take 4 aside? What is the runtime?

How do you like the pushbutton reprogramming? Now if it was only wireless...

That's another thing I should eventually do. Get the amp-hour and bulb current and do runtime estimates in the config software.


----------



## KiwiMark (Aug 30, 2009)

Alan B said:


> Now if it was only wireless...



Wow, imagine it - how cool would that be!


----------



## Alan B (Aug 30, 2009)

KiwiMark said:


> Wow, imagine it - how cool would that be!



Maybe someday. Not today. It has been on my futures list for awhile.


----------



## Alan B (Aug 30, 2009)

I just posted about the vastly improved manual auto-generation feature in the config software, and posted the new software as well as the config files and auto generated manuals from Wave 3 on the web here:

http://akbeng.com/flash/hwreg/config/

As always, feedback welcome.


----------



## KiwiMark (Aug 30, 2009)

Alan B said:


> I just posted about the vastly improved manual auto-generation feature in the config software, and posted the new software as well as the config files and auto generated manuals from Wave 3 on the web here:
> 
> http://akbeng.com/flash/hwreg/config/
> 
> As always, feedback welcome.



To run the phdConfig.py file what do we need to have installed first? I assumed python - so I downloaded the latest version (3.1.1) but it is not working right for me. Do I need an older version of Python?


----------



## Alan B (Aug 30, 2009)

KiwiMark said:


> To run the phdConfig.py file what do we need to have installed first? I assumed python - so I downloaded the latest version (3.1.1) but it is not working right for me. Do I need an older version of Python?



Instructions are in the READme.txt file. It requires Python 2.6. Sorry for the confusion. Python 3 is a major departure and lots of things don't work there yet...

NOTE that the READme.txt file has you install WinAVR and the USB programmer. Neither is required for making config files. I will redo the instructions.

All you need is Python 2.6 and the files in the zip. Double click on phdConfig.py and you are running...


----------



## BSBG (Aug 30, 2009)

Alan B said:


> Great! Looks like a very well regulated combo!! 40 to 60% PWM values. Very nice. I like the 2D form factor. Is that 2D bored out to take 4 aside? What is the runtime?
> 
> How do you like the pushbutton reprogramming? Now if it was only wireless...
> 
> That's another thing I should eventually do. Get the amp-hour and bulb current and do runtime estimates in the config software.



It is tri bored - running 3 stacks of 4 2/3A 1500 mAH Elite cells. It is essentially a direct drive 623 host running regulated . This pack is a little weak, but the 1164 at 10v is pretty impressive nonetheless. I am not sure I can fit 3 of AWs original Cs in one, but that is another option if this pack gives up on me.

The pushbutton / GUI is awesome. I will download the latest version soon. I may reprogram my Colossus for the 64458 just because I can.


Wireless eh?


----------



## Alan B (Aug 30, 2009)

NOTE that the READme.txt file has you install WinAVR and the USB programmer. Neither is required for making config files. I will redo the instructions.

All you need is Python 2.6 and the files in the zip. Double click on phdConfig.py and you are running...


----------



## LED_astray (Aug 30, 2009)

Alan B said:


> ... All you need is Python 2.6 and the files in the zip. Double click on phdConfig.py and you are running...



If anyone else is running Ubuntu Linux running the program to generate configurations is easy. (I haven't gotten further than that.) There are a couple things I discovered when I did it in 8.10 Intrepid. First python (2.5.2, an OK version) is installed by default, but TK isn't. You'll need to add "python-tk" for the program to run. I used Synaptic. Second I couldn't get the program to launch directly from the command line, however 


```
% python phdConfig.py
```
works fine. (I just tried from the File Browser and it doesn't work. It recognizes the file is a program, but it won't launch. I assume the same problem as from the command line....)

I plan to do a fresh 9.04 install and keep detailed notes while I get everything running correctly and then post an update. Unfortunately that's buried on an endless To-Do list and I'm not really a SW guy, so I'll be slow getting it all done. I will keep an eye open for questions in the meantime in case I can help.


----------



## Alan B (Aug 30, 2009)

LED_astray said:


> If anyone else is running Ubuntu Linux running the program to generate configurations is easy. (I haven't gotten further than that.) There are a couple things I discovered when I did it in 8.10 Intrepid. First python (2.5.2, an OK version) is installed by default, but TK isn't. You'll need to add "python-tk" for the program to run. I used Synaptic. Second I couldn't get the program to launch directly from the command line, however
> 
> 
> ```
> ...



Thanks for the info. I probably need to put a line in the source to fetch the interpreter at the start. Windoze doesn't require that.

I made some edits on the windows installation documentation to improve it but it is not complete and not worth a release now. Perhaps in a few days it will be. I'll probably add a Linux file and put your notes in that for a start.


----------



## Alan B (Sep 5, 2009)

Sylathnie found a bug in lockout basic that allowed multiclicks to sneak by.

Rather than add conditions to every other possible input test this quashes the click window ending variable to limit how high it can get, limiting access to the on/off function and blocking all else (when in lockout basic mode).

Here is a fix that will be in the next release (after testing, this is not verified yet):

#ifdef LOBASIC
#warning INFO - Lockout Mode Basic Flashlight Enabled
if (vbulb > VBASICc) vbulb = VBASICc; // one level allowed, but is allowed to dim during temperature/etc events
if (press == 1) clickwe = 2; // convert press to click
press = 0; // no user ramping
if (clickwe > 2): clickwe = 0; // <<<<<<< new line bugfix
#else


----------



## Alan B (Sep 9, 2009)

High Voltage parts arrived a couple days ago. Changes to the software to accomodate the higher voltage have been made but not tested. The hardware has not been assembled or tested yet either.

This should allow us to go to 12S (51 volts) with the regulator.

We are working on a beta test with Sylathnie, as I recall. Jim already did a preliminary test on the voltage regulator. This should all work okay, but it needs to be verified. Sylathnie, send me the configuration you want this programmed with.

I have to cut apart more circuit boards and am planning to make a precision jig to aid in that effort. Should have some time this weekend to work on it. I'll fold the HV test unit into the next production wave.


----------



## sylathnie (Sep 11, 2009)

Alan B said:


> if (clickwe > 2): clickwe = 0; // <<<<<<< new line bugfix



This seems to be working well. A much more elegant solution than mine certainly!

I'm trying out a new mode just for fun. (Beta Code warning!)

```
// Pulse Settings

#define PULSE        // enable pulse
#define PULSELENGTH 100    // set pulse on and off length
```


```
// Pulse variables
#ifdef PULSE
    uint16_t pulsecount = 0;
    uint8_t pulseflip = 0;
    uint8_t pulseenable = 0;
#endif
```


```
// Pulse click count detection
 #ifdef PULSE
        #warning INFO - Pulse feature Enabled
        if (clickwe == 10)                 // 5 clicks to startup pulse mode
        {
            pulsecount = PULSELENGTH;        // reset counter to max
            pulseenable=!pulseenable;        // enable/disable pulsing
        }
#endif
```


```
#ifdef PULSE
        if (pulseenable)         // is pulse on?
        {
            if (pulseflip)            // if pulseflip enabled shutdown pwm for pulsecounter
            {
                --pulsecount;        // decrement pulse counter
                pwm = 0;        // shut off pwm during offtime
            }
            else                // if pulseflip disable enable pwm for pulsecounter
            {
                --pulsecount;        // decrement pulse counter
            }
            if (pulsecount == 0)        // check for end of pulse counter
            {
                pulseflip = !pulseflip;    //change on/off state for pulse
                pulsecount = PULSELENGTH;    //reset pulsecounter to pulselength
            }
        }
#endif
```
My question is: is this bad for the regulator?


----------



## Alan B (Sep 11, 2009)

Wow, real code hacking!! Great!!

Since the FET normally turns on/off at 250 hz, I can't imagine pulsing being a problem.

One thing that would be useful is to figure out what rates/duty cycle/etc would be useful for incorporation into the core code in the future??


----------



## sylathnie (Sep 11, 2009)

I haven't done coding since my college days so my methods may need some refinement. I'm certain I could do the above function more efficiently and perhaps with one less variable. Also the light ramps up and down quickly rather than "blinking". I know why it is doing it but I'm not quite to the point where I understand exactly how.

I'm still trying to wrap my head around your original code. I'm having quite a bit of trouble understanding the actual regulation code. I'm going to try and spend some time on it this weekend and get some documentation for the included libraries and the Atmel chip so I can really understand what this is doing.


----------



## Alan B (Sep 11, 2009)

For the most part, it is not necessary to understand the regulation code to make the interface changes.

The regulation code is essentially:

read the battery voltage
calculate the RMS from the battery voltage and the PWM
if it is low, increase the pwm
if it is high, lower the pwm
repeat


----------



## sylathnie (Sep 13, 2009)

Who says I'm just going to be making interface changes? 

I want this thing to blink out some voltages!


----------



## Alan B (Sep 13, 2009)

sylathnie said:


> Who says I'm just going to be making interface changes?
> 
> I want this thing to blink out some voltages!



OK. For that you need to figure out the scaling, not the regulation code. The scaling is pretty straightforward. Well, maybe. Most things are in ADC units. Rather than convert the ADC readings to some standard scale and work in that, the setup converts the targets into ADC relative values. It solves many issues about integer conversions, roundoff, etc.

Anyway, during calibration the coefficients between the ADC and the actual values are developed and applied. You just need to capture those and use them to do your conversion. It can lead to a lot of math, try to keep it very simple at runtime (like having thresholds for a few levels rather than trying to compute volts...). You can do a lot of heavy math as long as it is constant and can be folded by the compiler. If it leaks into the micro it will quickly eat up code space. and time. Which is fine as long as it fits and is fast enough...


----------



## Alan B (Oct 20, 2009)

Just upgraded instructions for programming in post #5 of this thread.


----------



## Drywolf (Oct 31, 2009)

Hi Alan,
I hope you can dumb this programming down for me. 
Here is the list of things I know about:

Programs 
1. WinAVR
2. Atmel AVR studio
3. Python
4. PhdConfig

Hardware and driver
1. Pololu USB Programmer
2. Pololu Driver

Questions:
1. Which of the four programs do I need to be running to make changes to my driver?

2. Is my programmer called the mini USB inside the GUI window?

3. Does my light driver need to be on or just have batteries installed when programmed?

4. If I take your settings from https://www.candlepowerforums.com/posts/3128131&postcount=6 and add them to a txt file and then change the .txt to .cfg is that all I need to do before it can be compiled?

I see my setting inside the GUI and I can change them and then compile the changes without errors.
I get a USB drivice error when I hit the program button inside the GUI.

Just color me stupid 

Thanks,
Frank


----------



## Alan B (Oct 31, 2009)

Drywolf said:


> Hi Alan,
> I hope you can dumb this programming down for me.
> Here is the list of things I know about:
> 
> ...


----------



## dan1million (May 12, 2010)

Hi All,

I have been reading alot posts, 
Specifically from JimmyM's pHd, AlanB's Sled, Wquile's M6 variant.. and Alan B's site with the code. etc.

First of all i want to say thanks to Alan b, JimmyM and Wquiles for kindly posting alot of helpful information i have been looking to try a uC project for a while now and decided to bread board a hotwire regulator.

anyhow i used the hwreg software and an attiny85 with a 75N06 and AVR studio with the Atmel AVRispMkII using some instructions from Alan B and some from JimmyM's pdfs. Loaded & got the "ALL OK" after some hassles

tried a pair of surplus 5mm white leds with 1k Ohm from 6x18650 (11.1V 2P3S) which got annihilated.

Anyhow.... Fired it up... trial bulb... Osram 64440 @ 16.5V gave about 5.07Amps - no software changes yet. see pic  I was seeing spots for a while.






this is on the low setting.

Ps: does anyone have any insight on how to fine tune / change the settings in the code "hwreg" or do you just read through and change where prompted ?

-Dan


----------



## Alan B (May 12, 2010)

Dan,

Congrats on getting it working. One of the goals of this project was to make a design simple enough to breadboard. Your example shows we succeeded there.

Not sure what exactly you are asking. The older code was adjusted by editing the file, the newer code you run the Python program and it does everything including running the programmer. It has been awhile since I had my fingers into the software. But a bunch of units are in the field working.

I haven't been around much due to some other pressing projects. The latest of which has been a hospital stay for my bride. She may be coming home tomorrow.


----------



## JimmyM (May 12, 2010)

dan1million said:


> Hi All,
> 
> I have been reading alot posts,
> Specifically from JimmyM's pHd, AlanB's Sled, Wquile's M6 variant.. and Alan B's site with the code. etc.
> ...


Nice going! Alan uses a ton of compile time "defines" to enable/disable different parts of the code so it compiles to a nice tidy bit of code without extra bloat. So you may need to read through the code to find the important bits that you need to change. The actual regulation code is quite simple. It's all if the options and warnings, etc that complicate things. Mine's like that too.


----------



## JimmyM (May 12, 2010)

Alan B said:


> I haven't been around much due to some other pressing projects. The latest of which has been a hospital stay for my bride. She may be coming home tomorrow.


I hope everything turn out OK. My wife was hospitalized for the last 2 weeks of her last pregnancy and for a week afterwards. Worrisome stuff. Everything worked out great. I wish you and your better-half the same luck.


----------



## dan1million (May 12, 2010)

Thanks Alan, Thanks Jimmy,

I will try the python program and read the code.

Alan I hope all goes well for your wife, 

I Will post how i go with it.

-Dan


----------



## wquiles (May 12, 2010)

JimmyM said:


> I hope everything turn out OK.


+1

Wish her the best


----------



## dan1million (May 13, 2010)

Hi Alan B,

I have tried the python GUI it works extremely well.

I have got as far as programming the regulator with the python config method

I only have one issue ! i have an error message saying that the uC is not a tiny45 (i am using tiny85) the program says use "-F" i am relatively new to all this, how do i use "-F" to disable the warning.

i tried another option using the config python generated in avr studio and it compiled AOK however when i loaded the elf file the software just pulses the bulb. 

any ideas / help would be appreciated - i will understand if you have too many projects at the moment

-Dan


----------



## BSBG (Aug 4, 2010)

Having some issues trying to reconfigure one of my PHDs....

It is SN113 and I have reprogrammed it before with good results.

Fired up the old laptop, called up the config file and changed some parameters - 4 Li Mn cells, FM 1909 bulb, 12.2v Vbulb.

Upload to regulator, no go. reload proper driver, programming successful. WA1166 tst bulb goes . Check voltage at pins, 16.2v - almost Vbatt.

Set it to 10v output, reload - get 14v at the bulb pins. try to calibrate - calibration error. Mange to fry another 1166 in the process.

What am I missing here?

Thanks in advance.


----------



## Alan B (Aug 4, 2010)

My apologies to dan1million, I didn't see his question until now.

You need to change the CPU type to the right one. I didn't set up the code to handle that, but it should be easy to go in and do that. Look in the python code for the cpu type. It must be compiled for the proper type and loaded for the proper type, so it is likely in two places. I did use the tiny85 early on, so I know it worked.

BSBG's query just triggered my email.

Not sure what the problem is here. I would not hook up a bulb until the RMS output was verified. Is the output "stuck on", or does it act like it is controlling with the pushbutton properly?


----------



## BSBG (Aug 5, 2010)

The switch on the programming plug toggles it on and off but apparently no levels.


----------



## Billy Ram (Aug 5, 2010)

Howdy Allen B
When will you be taking orders again?
Billy


----------



## Alan B (Aug 5, 2010)

BSBG said:


> The switch on the programming plug toggles it on and off but apparently no levels.



If the output voltage is the same as the input, and it does not go on/off with the toggle then perhaps the FET has shorted. Static electricity can cause that.


----------



## Alan B (Aug 5, 2010)

Billy Ram said:


> Howdy Allen B
> When will you be taking orders again?
> Billy



I hope to get back to this soon, I have a lot of parts to use up. My estimates of this have not been accurate so I won't try to estimate. I have a few other projects that are behind right now.


----------



## Billy Ram (Aug 5, 2010)

Alan B said:


> I hope to get back to this soon, I have a lot of parts to use up. My estimates of this have not been accurate so I won't try to estimate. I have a few other projects that are behind right now.


 Please let us know when you start taking orders
Thank you
Billy


----------



## BSBG (Aug 5, 2010)

Alan B said:


> If the output voltage is the same as the input, and it does not go on/off with the toggle then perhaps the FET has shorted. Static electricity can cause that.



The output is less than input:

12v setpoint = 16.2v out (16.8 in)
10v setpoint = 14 v out

It toggles on and off, _but nowhere in between - no ramp / multilevel._ **see edit below** The humidity here is borderline oppressive, so no static to worry about.

This one has been sitting in an empty host for a while, awaiting the proper build. I will try reloading a whole new config file based on another regulator and modified for the battery / output and see if that has any effect.

**Update**

OK, the levels do work, but the average value voltage is still too high. I did a few quick calcs and after trial and error I get 12.1v RMS with a set point of 8.6v. Tried a cheap 12v 10w bulb, no problems. Put in a precious FM1909, works fine on a mid range setting, double click to high gives a flash and immediate power reduction. 4 cells measure 16.45v when I remove them.

I'm thinking since I had to 'trick' the setpoint i have to adjust the low voltage cutoff, but that sort of scares me.



:duh2:


----------



## Alan B (Aug 7, 2010)

BSBG said:


> The output is less than input:
> 
> 12v setpoint = 16.2v out (16.8 in)
> 10v setpoint = 14 v out
> ...



Glad to hear things are not shorted. Hmmm. Sounds like the range jumper is out of phase with the config setting if it won't calibrate. I would definitely check that and try to make it calibrate properly.

For more efficient communications I can respond better by email, then we can summarize back here.


----------



## Alan B (Aug 8, 2010)

BSBG and I have been solving the problem via email, so here is an update.

The problem was the ADC range jumper not agreeing with the setting in the programming software. There are two ways to correct that. One is to install the jumper, the other is to adjust the software setting.

The Range Jumper is in for the lower set of voltage ranges, and out for the higher set. So if it is in the ranges are 2/4/8S, if out they are 3/6/12S.

In this case he was using 4 LiMn cells and the software was set for Auto, so it was recommending to put the jumper in and use the optimal 4S ADC range. But the jumper was not in.

With the jumper out it can only select between the 3S, 6S and 12S ranges. Setting it for AutoHi forces it to use the jumper out options and select the 6S range for 4 cells. This is fine, it just means that the ADC is less accurate by a very small amount. Not an issue. It is like using a digital voltmeter's 25 volt scale to measure a 16 volt circuit.

One can always put the jumper in but that is a bit difficult to do and it is probably not worthwhile in this case. It is easy to put the jumper in when the regulator is out of the light, but pretty hard to reach in and do it while it is inside the [email protected]


----------

