Fenix E12: 14500, tiny10 FET, XP-G2, 40* TIR. Finally completed!!

You need to increase PWM freq, fast/phase-correct doesn’t really matter. IIRC comfy has now tested different frequencies and fast/phase-correct on several or all of the BLF/Oshpark DD drivers. They all operate.

I found HarleyQuin’s post here helpful on the topic of PWM freq. You want 19kHz PWM to minimize whine. Do you know what frequency PWM you are using currently? If not post what specific firmware you are running and what you use to flash it (such as the batch file you use or the string you use to call avrdude).

Good looking project so far!

Just switch the 0x21 back to 0x23 and you'll be back at ~19K PWM.

EDIT this looks a little better but it still deletes all the new row’s [return key’s] out of the cope/pasted code text.

This is the batch file I’m using:

And this is the code I’m using (modded from STAR v1.1 on-time, off the top of my head changes include the number and level of modes, 0x21, changing memory to default off, changing moon to default on):
See page two for properly formatted code

RMM is right, just switching back from phase-correct to fast will increase the freq appropriately. That’s the easiest/best way to get what you want.

change
TCCR0A = 0×21;
to
TCCR0A = 0×23;

With help from WarHawk I figured out it doesnt reset back to moonlight if it isnt left in the last level for atleast .5, sec so for it to remember to NOT have memory it has to be on for atleast 2WDT ticks, strange but I can deal with that now that I know whats going on, when its not on for more than .5 sec it pretty much acts like next mode memory, if I cant end up fixing that I could probably get use to it. The only other [possible] code issue is the preflash on moonlight. when first turning on in moonlight there is no preflash but when cycling threw the modes going from Turbo (or 185 if after the 37 tic [~20sec] step down) it does preflash.

Thats a direct copy/paste but its so hard to read, how do I make it look like code?

I suggest switching the “Input Format” on your post to Advanced Post Editor before you start, then copy/paste into that. You might want to put it in a “quote” too.

I think switching from the ontime firmware to the offtime firmware will help with the memory situation. I just tried ontime last night with memory disabled and I personally thought it sucked to use. You’ll need to add a small capacitor to the board for that to work, 1uF is specced but in the STAR firmware thread someone (Harleyquin?) mentioned that they’d used a 1nF with good results as well.

Not sure on the preflash.

EDIT

And what issues would that fix? the wine? what about the preflash or strange non-memory?

Not trying to be a dick, it sorta’ comes off like it but its a serious ??

Thanks all of you so far, its running a lot better than this time yesterday thats for sure.

Im having posting/editing posts issues tonight…

I’ll try it and see what happens (also try the posting thing). I have some of the cap’s on the way. So you use off-time with no mem and it works perfect? not as I described?
thx

I don’t use it, but it should fix the issue you described. I’d be happy to test it out for you and make sure it works as expected, but it probably wouldn’t fit the timeline you want to work on this project on (eg it wouldn’t be tonight).

The 0x21 to 0x23 switch will change PWM modes which happens to double the freq which should help/fix the whine.

The preflash is a mystery to me. Can you give a blow-by-blow account of an example where the preflash happens and an example where it doesn’t happen?

better yet a couple videos. It's much more pronounced IRL.

http://youtu.be/qOJkKtBJph0

http://youtu.be/WqHW6zOYgbQ

*EDIT* went all out, have a 10mm XP sinkPAD, an XP-G2 R5 3C and a LEDLink 40* TIR incoming, going to lengthen the turbo timer when I'm making the rest of the changes while I'm at it.

yup yup

// phase corrected PWM is 0×21 for PB1, fast-PWM is 0×23

going from PWM to Fast = 9~Khz to 19~Khz…alot higher whine noise, older folks the whine might just be drowned out by our tinnitus :smiley:

Possible solution would be to change

#define WDT_TIMEOUT 2 // Number of WTD ticks before mode is saved (.5 sec each)
To 0, (1 for ,25 seconds) but not sure if that would throw off the mode changes or not

The video moves pretty quickly for me (I understand it’s because of the ontime no-memory setup), but I think I see what we are talking about here. I’m still lost as to why it’s happening.

I wonder if the pre flash has anything to do with the code modifications you made.

A fair point.

@Cereal_killer - when did the preflash show up?

I guess this wasn’t such a great suggestion! Instead I’ll recommend using pastebin, if you can’t get that to work you’re really doing something wrong :wink:

Once you post a pastebin link we can easily use a diff tool to compare the original code with your modified code to look for errors.

I wrote the code before ever firing the light up for the first time so it's always done it. This is the only tiny10 I've built so far but I have flashed this code to a 17DD to mess with on the bench and it doesn't preflash but I had to edit moonlight to 3, my test XM-L wouldn't light at 1, other than tha it's exactly the same code (plus the 17DD V2 has a 130ohm resistor at R3 and of course a 70N02 FET as hardware differences).

I will get the code posted in a legible format in a couple hours, I'm away from my computer right now.

OK lets try this *again* (I think my phone is fighting my computer, now I'm having quotes not showing up in other threads)

/*
 * NANJG 105C Diagram
 *           ---
 *         -|   |- VCC
 *  Star 4 -|   |- Voltage ADC
 *  Star 3 -|   |- PWM
 *     GND -|   |- Star 2
 *           ---
  • CPU speed is 4.8Mhz without the 8x divider when low fuse is 0x75
  • define F_CPU 4800000 CPU: 4.8MHz PWM: 9.4kHz ####### use low fuse: 0x75 #######
  •                         /8     PWM: 1.176kHz     ####### use low fuse: 0x65  #######
    
  • define F_CPU 9600000 CPU: 9.6MHz PWM: 19kHz ####### use low fuse: 0x7a #######
  •                         /8     PWM: 2.4kHz       ####### use low fuse: 0x6a  #######
    
  • Above PWM speeds are for phase-correct PWM. This program uses Fast-PWM, which when the CPU is 4.8MHz will be 18.75 kHz
  • FUSES
  •   I use these fuse settings
    
  • Low:  0x75
    
  •    High: 0xff
    
  • STARS
  •  Star 2 = Moon if connected
    
  •    Star 3 = H-L if connected, L-H if not
    
  • Star 4 = Memory if not connected
    
  • VOLTAGE
  •  Resistor values for voltage divider (reference BLF-VLD README for more info)
    
  •  Reference voltage can be anywhere from 1.0 to 1.2, so this cannot be all that accurate
    
  •       VCC
    
  •        |
    
  •       Vd (~.25 v drop from protection diode)
    
  •        |
    
  •      1912 (R1 19,100 ohms)
    
  •        |
    
  •        |---- PB2 from MCU
    
  •        |
    
  •      4701 (R2 4,700 ohms)
    
  •        |
    
  •       GND
    
  • ADC = ((V_bat - V_diode) * R2   * 255) / ((R1    + R2  ) * V_ref)
    
  • 125 = ((3.0   - .25    ) * 4700 * 255) / ((19100 + 4700) * 1.1  )
    
  • 121 = ((2.9   - .25    ) * 4700 * 255) / ((19100 + 4700) * 1.1  )
    
  •   Well 125 and 121 were too close, so it shut off right after lowering to low mode, so I went with
    
  •  130 and 120
    
  • To find out what value to use, plug in the target voltage (V) to this equation
    
  •        value = (V * 4700 * 255) / (23800 * 1.1)
    

*/
#define F_CPU 4800000UL

/*

  • =========================================================================
  • Settings to modify per driver
    */

#define VOLTAGE_MON // Comment out to disable

#define MODE_MOON 1 // Can comment out to remove mode, but should be set through soldering stars
#define MODE_1 8 // Can comment out to remove mode
#define MODE_2 75 // Can comment out to remove mode
#define MODE_TURBO 255 // Can comment out to remove mode
#define TURBO_TIMEOUT 37 // How many WTD ticks before before dropping down (.5 sec each)

#define WDT_TIMEOUT 2 // Number of WTD ticks before mode is saved (.5 sec each)

#define ADC_LOW 130 // When do we start ramping
#define ADC_CRIT 120 // When do we shut the light off

/*

  • =========================================================================
    */

#ifdef MODE_TURBO
#undef MODE_HIGH
#define MODE_HIGH MODE_HIGH_W_TURBO
#endif

//#include <avr/pgmspace.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
//#include <avr/power.h>

#define STAR2_PIN PB0
#define STAR3_PIN PB4
#define STAR4_PIN PB3
#define PWM_PIN PB1
#define VOLTAGE_PIN PB2
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
#define ADC_PRSCL 0x06 // clk/64

#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1

/*

  • global variables
    */

// Mode storage
uint8_t eepos = 0;
uint8_t eep[32];
uint8_t memory = 0;

// Modes (gets set when the light starts up based on stars)
static uint8_t modes[10]; // Don't need 10, but keeping it high enough to handle all
volatile uint8_t mode_idx = 0;
int mode_dir = 0; // 1 or -1. Determined when checking stars. Do we increase or decrease the idx when moving up to a higher mode.
uint8_t mode_cnt = 0;

uint8_t lowbatt_cnt = 0;

void store_mode_idx(uint8_t lvl) { //central method for writing (with wear leveling)
uint8_t oldpos=eepos;
eepos=(eepos+1)&31; //wear leveling, use next cell
// Write the current mode
EEARL=eepos; EEDR=lvl; EECR=32+4; EECR=32+4+2; //WRITE //32:write only (no erase) 4:enable 2:go
while(EECR & 2); //wait for completion
// Erase the last mode
EEARL=oldpos; EECR=16+4; EECR=16+4+2; //ERASE //16:erase only (no write) 4:enable 2:go
}
inline void read_mode_idx() {
eeprom_read_block(&eep, 0, 32);
while((eep[eepos] == 0xff) && (eepos < 32)) eepos++;
if (eepos < 32) mode_idx = eep[eepos];//&0x10; What the?
else eepos=0;
}

inline void next_mode() {
if (mode_idx == 0 && mode_dir == -1) {
// Wrap around
mode_idx = mode_cnt - 1;
} else {
mode_idx += mode_dir;
if (mode_idx > (mode_cnt - 1)) {
// Wrap around
mode_idx = 0;
}
}
}

inline void WDT_on() {
// Setup watchdog timer to only interrupt, not reset, every 500ms.
cli(); // Disable interrupts
wdt_reset(); // Reset the WDT
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR = (1<<WDTIE) | (1<<WDP2) | (1<<WDP0); // Enable interrupt every 500ms
sei(); // Enable interrupts
}

inline void WDT_off()
{
cli(); // Disable interrupts
wdt_reset(); // Reset the WDT
MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR = 0x00; // Disable WDT
sei(); // Enable interrupts
}

inline void ADC_on() {
ADMUX = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
DIDR0 |= (1 << ADC_DIDR); // disable digital input on ADC pin to reduce power consumption
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
}

inline void ADC_off() {
ADCSRA &= ~(1<<7); //ADC off
}

#ifdef VOLTAGE_MON
uint8_t low_voltage(uint8_t voltage_val) {
// Start conversion
ADCSRA |= (1 << ADSC);
// Wait for completion
while (ADCSRA & (1 << ADSC));
// See if voltage is lower than what we were looking for
if (ADCH < voltage_val) {
// See if it's been low for a while
if (++lowbatt_cnt > 8) {
lowbatt_cnt = 0;
return 1;
}
} else {
lowbatt_cnt = 0;
}
return 0;
}
#endif

ISR(WDT_vect) {
static uint8_t ticks = 0;
if (ticks < 255) ticks++;

if (ticks == WDT_TIMEOUT) {
 if (memory) {
       store_mode_idx(mode_idx);
   } else {
        // Reset the mode to the start for next time
        store_mode_idx((mode_dir == 1) ? 0 : (mode_cnt - 1));
   }

#ifdef MODE_TURBO
//} else if (ticks == TURBO_TIMEOUT && modes[mode_idx] == MODE_TURBO) { // Doesn't make any sense why this doesn't work
} else if (ticks == TURBO_TIMEOUT && mode_idx == (mode_cnt - 1)) {
// Turbo mode is always at end
PWM_LVL =185;
#endif
}

}

int main(void)
{
// All ports default to input, but turn pull-up resistors on for the stars (not the ADC input! Made that mistake already)
PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN) | (1 << STAR4_PIN);

// Set PWM pin to output
DDRB = (1 &lt;&lt; PWM_PIN);

// Set timer to do PWM for correct output pin and set prescaler timing
TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
TCCR0B = 0x01; // pre-scaler for timer (1 =&gt; 1, 2 =&gt; 8, 3 =&gt; 64...)

// Turn features on or off as needed
#ifdef VOLTAGE_MON

ADC_on();
#else
ADC_off();
#endif
ACSR |= (1<<7); //AC off

// Load up the modes based on stars

// Always load up the modes array in order of lowest to highest mode
// 0 being low for soldered, 1 for pulled-up for not soldered
// Moon (stock is 1 then 0)
#ifdef MODE_MOON
if ((PINB & (1 << STAR2_PIN))> 0) { // Stock is ==, ( > for moon default to on, soldering star will disable moon)
modes[mode_cnt++] = MODE_MOON;
}
#endif
#ifdef MODE_1
modes[mode_cnt++] = MODE_1;
#endif
#ifdef MODE_2
modes[mode_cnt++] = MODE_2;
#endif
#ifdef MODE_TURBO
modes[mode_cnt++] = MODE_TURBO;
#endif
if ((PINB & (1 << STAR3_PIN)) == 0) {
// High to Low
mode_dir = -1;
} else {
mode_dir = 1;
}
// Not soldered (1) should disable memory
memory = ((PINB & (1 << STAR4_PIN)) > 0 ) ? 0 : 1; //to disable momory without soldering star use ? 0: 1; (stock is ? 1 : 0;)

// Enable sleep mode set to Idle that will be triggered by the sleep_mode() command.
// Will allow us to go idle between WDT interrupts

set_sleep_mode(SLEEP_MODE_IDLE);

// Determine what mode we should fire up
// Read the last mode that was saved
read_mode_idx();
if (mode_idx&amp;0x10) {
    // Indicates we did a short press last time, go to the next mode
    // Remove short press indicator first
   mode_idx &amp;= 0x0f;
   next_mode(); // Will handle wrap arounds
} else {
    // Didn&#39;t have a short press, keep the same mode
}

// Store mode with short press indicator
store_mode_idx(mode_idx|0x10);

WDT_on();

// Now just fire up the mode
PWM_LVL = modes[mode_idx];

uint8_t i = 0;

uint8_t hold_pwm;
while(1) {
#ifdef VOLTAGE_MON
if (low_voltage(ADC_LOW)) {
// We need to go to a lower level
if (mode_idx == 0 && PWM_LVL <= modes[mode_idx]) {
// Can't go any lower than the lowest mode
// Wait until we hit the critical level before flashing 10 times and turning off
while (!low_voltage(ADC_CRIT));
i = 0;
while (i++<10) {
PWM_LVL = 0;
_delay_ms(250);
PWM_LVL = modes[0];
_delay_ms(500);
}
// Turn off the light
PWM_LVL = 0;
// Disable WDT so it doesn't wake us up
WDT_off();
// Power down as many components as possible
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
} else {
// Flash 3 times before lowering
hold_pwm = PWM_LVL;
i = 0;
while (i++<3) {
PWM_LVL = 0;
_delay_ms(250);
PWM_LVL = hold_pwm;
_delay_ms(500);
}
// Lower the mode by half, but don't go below lowest level
if ((PWM_LVL >> 1) < modes[0]) {
PWM_LVL = modes[0];
mode_idx = 0;
} else {
PWM_LVL = (PWM_LVL >> 1);
}
// See if we should change the current mode level if we've gone under the current mode.
if (PWM_LVL < modes[mode_idx]) {
// Lower our recorded mode
mode_idx–;
}
}
// Wait 3 seconds before lowering the level again
_delay_ms(3000);
}
#endif
sleep_mode();
}

return 0; // Standard Return Code

}

I think you still didn’t get a good paste, the beginning is missing some stuff. Good enough to do a diff though, ignoring that stuff:

I’m not sure why you changed the variable names, but I don’t see a problem there.

At a glance I’m not sure what this section is for or why you changed it.

EDIT: also I should point out that I’m assuming your code does actually contain this line at the top although it did not appear in your paste:

I changed the names cause this is modified from my 5-static modes version (plus moonlight) from a different build, when I needed to have more levels than stock it was just easier for me to number them than to make a "med-high/med-low".

I'm having lots of posting issues, I think its cause I'm using the standard mobile editor from my phone and now the advanced editor here and logged in from both at the same time, I am also having issues with quotes not showing up or just showing up as empty boxes. Lets pretend I'm not computer illiterate for a minute lol.

Later today I'm going to build a second Tiny10 FET for testing and load it up with the same code, maybe try adding a gate resistor somewhere (not sure where I'll fit anything else)

You didn’t address what this change was for, do you know?

PWM_LVL = modes[—mode_idx];