100% working! Variable input voltage.

This commit is contained in:
cnlohr
2023-04-22 17:59:53 -04:00
parent 25baa9c21e
commit c3626a4700
2 changed files with 130 additions and 44 deletions

View File

@@ -8,24 +8,29 @@
uint32_t count;
#define ENABLE_TUNING
#define ABSOLUTE_MAX_ADC_SET 408 //190ish volts (definitely do not exceed)
// Specifically, 84 and 38 are tuned for this specific circuit.
// Do not mess with them unless you know what you are doing.
//#define ENABLE_TUNING
// VDD Adjusted.
#define ABSOLUTE_MAX_ADC_SET 204 // Actually around 188V (0 to 204 maps to 0 to 190V)
// Do not mess with PWM_ values unless you know what you are willing to go down a very deep rabbit hole.
#ifndef ENABLE_TUNING
#define PWM_PERIOD 96
#define PWM_MAXIMUM_DUTY 48
#define PWM_PERIOD 140
#else
int PWM_PERIOD = 96;
int PWM_MAXIMUM_DUTY = 48;
int PWM_PERIOD = 140;
#endif
int PWM_MAXIMUM_DUTY = 48; //This actually gets overwrittenin the first few milliseconds onces a system VDD is read.
#define ERROR_P_TERM 1 // Actually a shift. 0 is rattl-y but averages out and gives tight control. -1 is EVEN RATTLIER.
int update_targ_based_on_vdd = 0;
#define ERROR_P_TERM 1 // Actually a shift. Normally we would do the opposite to smooth out, but we can realy bang this around! It's OK if we rattle like crazy.
int target_feedback = 0;
int target_feedback_vdd_adjusted = 0;
int lastadc = 0;
int lastvdd = 0;
int fade_enable = 0;
int fade_time0;
int fade_time1;
@@ -44,7 +49,7 @@ void ADC1_IRQHandler(void)
{
// This interrupt should happen ~3.5uS on current settings.
int adc = lastadc = ADC1->RDATAR;
int err = target_feedback - adc;
int err = target_feedback_vdd_adjusted - adc;
ADC1->STATR &= ~ADC_EOC;
if( err < 0 )
@@ -56,9 +61,47 @@ void ADC1_IRQHandler(void)
TIM1->CH2CVR = err;
}
int fadepos = (++count) & 0xff;
if( fadepos == 0 )
{
ADC1->CTLR2 |= ADC_JSWSTART;
}
else if( fadepos == 2 )
{
// Use injection channel data to read vref.
// Ballparks:
// 0xF0 / 240 for 5V input << lastvdd
// 0x175 / 373 for 3.3v input << lastvdd
// Tunings (experimentally found)
// Duty/Period
// 100/160 will literally cook the LEDs but can get up to 180V @ 3.3V under load.
// 48/120 is more efficient than 48/96 at 3.3v. (139V)
// 60/112 is pretty efficient, too. (150V)
// 84/140 = 176V (reported, 180 actual) with 8 at 3.3 <<< This is a really nice thing to run at on 3.3V
// The transformer DOES get very warm though.
// Backto 5V.
// 54/140 --> Is what it is is for 5V if period is set to 140.
//
// therefore I want to map, for maximum duty cycle, the following:
// 373 -> 84 // Ratio is 4.440
// 240 -> 56 // Ratio is 4.444
// Wow! That's nice!
lastvdd = ADC1->IDATAR1;
#ifndef ENABLE_TUNING
// IF we aren't enabling tuning, we can update max-on-time with this value.
// There's a neat hack where you can divide by weird decimal divisors by adding and subtracing terms.
// I apply that weird trick here.
// 1÷(1÷41÷641÷1281÷1024) is roughly equal to dividing by 4.43290
// We actually can simplify it for our purposes as: 1÷(1÷41÷641÷128)
//
PWM_MAXIMUM_DUTY = (lastvdd>>2) - (lastvdd>>6) - (lastvdd>>7); // lastvdd / 4.44. For ~5V, this works out to 45, for ~3.3V it works out to ~70.
#endif
update_targ_based_on_vdd = 1;
}
if( fade_enable )
{
int fadepos = count & 0xff;
if( fadepos < fade_time0 )
ApplyOnMask( fade_disp0 );
else if( fadepos == fade_time0 )
@@ -67,7 +110,6 @@ void ADC1_IRQHandler(void)
ApplyOnMask( fade_disp1 );
else
ApplyOnMask( 0 );
count++;
}
}
@@ -118,31 +160,30 @@ static void SetupADC()
ADC1->RSQR2 = 0;
ADC1->RSQR3 = 7; // 0-9 for 8 ext inputs and two internals
ADC1->ISQR = 8 | (3<<20); //Injection group is 8. NOTE: See note in 9.3.12 (ADC_ISQR) of TRM.
// set sampling time for chl 7
ADC1->SAMPTR2 = 6<<(3*7); // 0:7 => 3/9/15/30/43/57/73/241 cycles
ADC1->SAMPTR2 = (6<<(3*7)) | (6<<(3*8)); // 0:7 => 3/9/15/30/43/57/73/241 cycles
// (4 == 43 cycles), (6 = 73 cycles) Note these are alrady /2, so
// setting this to 73 cycles actually makes it wait 256 total cycles
// @ 48MHz.
// turn on ADC and set rule group to sw trig
ADC1->CTLR2 |= ADC_ADON; // 0 = Use TRGO event for Timer 1.
ADC1->CTLR2 = ADC_ADON | ADC_JEXTTRIG | ADC_JEXTSEL | ADC_EXTTRIG; // 0 = Use TRGO event for Timer 1 to fire ADC rule.
// Reset calibration
ADC1->CTLR2 |= ADC_RSTCAL;
while(ADC1->CTLR2 & ADC_RSTCAL);
// Calibrate
ADC1->CTLR2 |= ADC_CAL;
while(ADC1->CTLR2 & ADC_CAL);
// Allow Timer1 TRGO to trigger ADC conversion.
ADC1->CTLR2 |= ADC_EXTTRIG;
// enable the ADC Conversion Complete IRQ
NVIC_EnableIRQ( ADC_IRQn );
// Enable the End-of-conversion interrupt.
ADC1->CTLR1 = ADC_EOCIE;
ADC1->CTLR1 = ADC_EOCIE | ADC_SCAN | ADC_JDISCEN;
}
uint16_t GenOnMask( int segmenton )
@@ -224,7 +265,7 @@ static void HandleCommand( uint32_t dmdword )
}
}
*DMDATA0 = lastadc << 16;
*DMDATA0 = (lastadc << 12) | (lastvdd << 22);
}
int main()
@@ -275,6 +316,22 @@ int main()
{
HandleCommand( dmdword );
}
if( update_targ_based_on_vdd )
{
// target_feedback is in volts. 0..200 maps to the physical device voltage.
// lastvdd = 0xF0 for 5V input.
// lastvdd = 0x175 for 3.3v input.
//
// target_feedback_vdd_adjusted = 408 for ~192V @ 5
// target_feedback_vdd_adjusted = 680 for ~192V @ 3.3
//
// 408 = 192 * 240 / x = (192*240)/408 = 112.941176471
// 680 = 192 * 373 / x = (373*680)/192 = 105.317647059
// Close enough to 128.
//
target_feedback_vdd_adjusted = (target_feedback * lastvdd) >> 7;
update_targ_based_on_vdd = 0;
}
}
}

View File

@@ -45,6 +45,7 @@ void HandleDestroy() { }
#define VOLTHISTSIZE 2048
float volthist[VOLTHISTSIZE];
float volthistvdd[VOLTHISTSIZE];
int volthisthead = 0;
int main()
@@ -69,6 +70,9 @@ int main()
while(CNFGHandleInput())
{
const uint32_t GLOW = 0xFFD010FF;
const uint32_t GLOWDIM = 0x806008FF;
const uint32_t BLUEGLOW = 0x2080d0ff;
short w, h;
int x, y;
CNFGClearFrame();
@@ -80,16 +84,16 @@ int main()
static int last_set_v = 0;
{
CNFGColor( 0x303030ff );
CNFGTackSegment( w-100, 65, w-100, h );
CNFGTackSegment( w-100, 45, w-100, h );
#ifdef ENABLE_TUNING
CNFGTackSegment( w-200, 65, w-200, h );
CNFGTackSegment( w-300, 65, w-300, h );
CNFGTackSegment( w-200, 45, w-200, h );
CNFGTackSegment( w-300, 45, w-300, h );
#endif
CNFGColor( 0xD0D0D0FF );
CNFGPenX = w-100+2; CNFGPenY = 67; sprintf( cts, "VTG %d", last_set_v ); CNFGDrawText( cts, 2 );
CNFGPenX = w-100+2; CNFGPenY = 47; sprintf( cts, "VTG %d", last_set_v ); CNFGDrawText( cts, 2 );
#ifdef ENABLE_TUNING
CNFGPenX = w-200+2; CNFGPenY = 67; sprintf( cts, "Per %d", set_period ); CNFGDrawText( cts, 2 );
CNFGPenX = w-300+2; CNFGPenY = 67; sprintf( cts, "Duty %d", set_max_duty ); CNFGDrawText( cts, 2 );
CNFGPenX = w-200+2; CNFGPenY = 47; sprintf( cts, "Per %d", set_period ); CNFGDrawText( cts, 2 );
CNFGPenX = w-300+2; CNFGPenY = 47; sprintf( cts, "Duty %d", set_max_duty ); CNFGDrawText( cts, 2 );
#endif
}
@@ -151,11 +155,14 @@ int main()
if( ( status & 0xc0 ) == 0x40 ) goto retry;
if( r ) { printf( "R: %d\n", r ); status = 0; goto retry; }
//printf( "%08x\n", status );
float voltage = ((float)(status>>16))/VOLTAGE_SCALE;
printf( "%08x\n", status );
float voltvdd = 1.21/(((status>>22)&0x3ff)/1023.0f); // vref = 2.2v
float voltage = ((((float)((status>>12)&0x3ff))/1023.0f)*100.0)*voltvdd;
// Measured @ 176 reported here, but 180 in reality if ref is 1.2. But 1.21 fixes it.
volthist[volthisthead] = voltage;
volthistvdd[volthisthead] = voltvdd;
volthisthead = (volthisthead + 1) % VOLTHISTSIZE;
CNFGColor( (voltage > 192)?0xff0000ff:GLOW );
CNFGColor( (voltage > 198)?0xff0000ff:GLOW );
CNFGPenX = 1;
CNFGPenY = 1;
sprintf( cts, "HV Line: %3.0f V\nRStatus: %d", voltage, r );
@@ -168,14 +175,18 @@ int main()
CNFGDrawText( targdisp[targetnum+1], 10 );
}
CNFGColor( BLUEGLOW );
CNFGPenX = 300;
CNFGPenY = 1;
sprintf( cts, "VDD: %3.3f V\n", voltvdd );
CNFGDrawText( cts, 4 );
int i;
int vhp = (volthisthead - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
float vl = voltage;
CNFGColor( 0xff0000ff );
CNFGTackSegment( 0, 450-192*2-6, w, 450-192*2-6 );
CNFGPenX = w - 250; CNFGPenY = 450-192*2-10-6;
CNFGDrawText( "WARNING: DO NOT EXCEED THIS LINE (192)", 2 );
CNFGTackSegment( 0, 450-200*2-6, w, 450-200*2-6 );
CNFGPenX = w - 250; CNFGPenY = 450-200*2-10-6;
CNFGDrawText( "WARNING: DO NOT EXCEED THIS LINE (200)", 2 );
for( i = 0; i < 10; i++ )
{
@@ -185,17 +196,35 @@ int main()
sprintf( cts, "%d volts", i * 20 );
CNFGDrawText( cts, 2 );
CNFGTackSegment( 0,450 - i * 40, w, 450 - i * 40 );
CNFGColor( GLOW );
}
for( i = 0; i < w*2; i++ )
{
float v = volthist[vhp];
CNFGTackSegment( i/2, 450 - vl*2, i/2+1, 450 - v*2 );
vhp = (vhp - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
//printf( "%f\n", v );
vl = v;
CNFGColor( BLUEGLOW );
int vhp = (volthisthead - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
float vl = voltvdd*10;
for( i = 0; i < w*2; i++ )
{
float v = volthistvdd[vhp]*10;
CNFGTackSegment( i/2, 450 - vl*2, (i+1)/2, 450 - v*2 );
vhp = (vhp - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
//printf( "%f\n", v );
vl = v;
}
}
{
int vhp = (volthisthead - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
float vl = voltage;
CNFGColor( GLOW );
for( i = 0; i < w*2; i++ )
{
float v = volthist[vhp];
CNFGTackSegment( i/2, 450 - vl*2, (i+1)/2, 450 - v*2 );
vhp = (vhp - 1 + VOLTHISTSIZE*100)%VOLTHISTSIZE;
//printf( "%f\n", v );
vl = v;
}
}
CNFGSwapBuffers();