Programming the Programmable Hotwire Regulated Driver drop-in for D-M@g

Alan B

Flashlight Enthusiast
Joined
Nov 19, 2007
Messages
1,964
Location
San Francisco Bay Area
This is the Advanced User's Programming thread for the Programmable Hotwire Regulated Driver drop-in for D-M@g. 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:
http://www.candlepowerforums.com/vb/showthread.php?t=231656

Order Thread:
http://www.candlepowerforums.com/vb/showthread.php?t=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
 
Last edited:
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:
 
Last edited:
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
 
Last edited:
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.

Code:
/* 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
 
Last edited:
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
 
Last edited:
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!
 
Last edited:
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
 
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.
 
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.
 
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.
 
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.
 
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, 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.
 
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.
 
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.
 
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.
 
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.
 
Top