diff --git a/firmware/calibrate.c b/firmware/calibrate.c index be3afa2..7300a8e 100644 --- a/firmware/calibrate.c +++ b/firmware/calibrate.c @@ -5,13 +5,14 @@ #include "dac.h" #include "led.h" #include "timer.h" +#include "uart.h" float g_scale; /* delta(DAC) / delta(ADC) */ /* Initialize. Assume some relatively-safe scaling if no calibration is run */ void calibrate_init(void) { - g_scale = 0.1; /* 1 count at DAC means 10 counts at ADC */ + g_scale = 0.5; /* 1 count at DAC means 4 counts at ADC */ } /* Given the current DAC and ADC values d1 and a1, @@ -22,7 +23,7 @@ uint16_t adc_to_dac(uint16_t d1, int16_t a1, int16_t a2, float scale) int32_t d2; delta = (int32_t)((a2 - a1) * scale + 0.5); - d2 = d1 - delta; + d2 = d1 + delta; return clamp(DAC_MIN, d2, DAC_MAX); } @@ -32,7 +33,7 @@ float calculate_scale(uint16_t d1, float a1, uint16_t d2, float a2) if (d1 == d2) return 1.0; else - return (a2 - a1) / (float)(d2 - d1); + return (a2 - a1) / ((float)d2 - d1); } /* Seek with the DAC to reach a specific ADC value. Uses g_scale as @@ -55,7 +56,7 @@ uint16_t seek(uint16_t starting_dac, int16_t desired_adc) { /* give up if we're not making progress */ if (steps++ > SEEK_MAX_STEPS) { - led_pattern(0b00000001); + led_pattern(0b00101000); break; } @@ -70,9 +71,21 @@ uint16_t seek(uint16_t starting_dac, int16_t desired_adc) msleep(1); adc = adc_get(); +#if 0 + uart1_put_hex16(dac); + uart1_put(' '); + uart1_put_hex16(adc); + uart1_put(' '); + uart1_put_hex16(desired_adc); + uart1_put(' '); + uart1_put_hex32(*(uint32_t *)&scale); + uart1_crlf(); +#endif + /* if we're close, accept it */ - if (abs(adc - desired_adc) <= SEEK_FUZZ_ADC) + if (abs(adc - desired_adc) <= SEEK_FUZZ_ADC) { break; + } /* otherwise, if we were within ADC clamp limits, and the DAC changed a non-trivial amount, readjust @@ -95,7 +108,7 @@ uint16_t seek(uint16_t starting_dac, int16_t desired_adc) } /* Perform calibration */ -float do_calibrate(void) +uint16_t do_calibrate(void) { uint16_t daczero, x1, x2; float y1, y2; @@ -103,18 +116,35 @@ float do_calibrate(void) /* Zero ADC */ daczero = seek((DAC_MIN + DAC_MAX) / 2, CALIBRATE_ADC_ZERO); - /* Go halfway down and take an accurate sample */ + /* Go down take an accurate sample */ x1 = seek(daczero, CALIBRATE_ADC_LOW); y1 = oversample(x1); - /* Go halfway up and take an accurate sample */ + /* Go up and take an accurate sample */ x2 = seek(daczero, CALIBRATE_ADC_HIGH); y2 = oversample(x2); /* Calculate scale */ g_scale = calculate_scale(x1, y1, x2, y2); - return g_scale; +#if 1 + uart1_put_string("calibrate x1="); + uart1_put_dec(x1); + uart1_put_string(" y1="); + uart1_put_float(y1); + uart1_put_string(" x2="); + uart1_put_dec(x2); + uart1_put_string(" y2="); + uart1_put_float(y2); + uart1_put_string(" scale="); + uart1_put_float(g_scale); + uart1_crlf(); +#endif + + /* Return to zero position */ + dac_write(daczero); + + return daczero; } /* Oversample to get a nice ADC value */ diff --git a/firmware/calibrate.h b/firmware/calibrate.h index b2664d6..010d880 100644 --- a/firmware/calibrate.h +++ b/firmware/calibrate.h @@ -7,10 +7,10 @@ #define DAC_MIN 0 #define DAC_MAX 65535 -#define OVERSAMPLE_COUNT 128 +#define OVERSAMPLE_COUNT 256 #define SEEK_MAX_STEPS 1000 -#define SEEK_FUZZ_ADC 20 +#define SEEK_FUZZ_ADC 10 #define SEEK_FUZZ_DAC 5 #define CALIBRATE_ADC_ZERO 1024 @@ -32,7 +32,7 @@ float calculate_scale(uint16_t d1, float a1, uint16_t d2, float a2); uint16_t seek(uint16_t starting_dac, int16_t desired_adc); /* Perform calibration */ -float do_calibrate(void); +uint16_t do_calibrate(void); /* Oversample to get a nice ADC value */ float oversample(uint16_t dac); diff --git a/firmware/led.h b/firmware/led.h index d5e1e66..c01520a 100644 --- a/firmware/led.h +++ b/firmware/led.h @@ -3,7 +3,7 @@ #include "config.h" -#define LED_BLINK_RATE 4 +#define LED_BLINK_RATE 8 extern int16_t __led_pattern; /* Initialize LED */ diff --git a/firmware/mode_debug.c b/firmware/mode_debug.c index 97ce744..ab83d6c 100644 --- a/firmware/mode_debug.c +++ b/firmware/mode_debug.c @@ -121,28 +121,21 @@ void run_debug(void) // test seeking case '1': uart1_put_string("seek 512\r\n"); - while (!uart1_can_get()) - dac = seek(dac, 512); - uart1_get(); + dac = seek(dac, 512); break; case '2': uart1_put_string("seek 1536\r\n"); - while (!uart1_can_get()) - dac = seek(dac, 1536); - uart1_get(); + dac = seek(dac, 1536); break; // run calibration case 'c': case 'C': - uart1_put_string("old g_scale "); - uart1_put_hex32(*(uint32_t *)&g_scale); - uart1_crlf(); uart1_put_string("calibrating...\r\n"); - do_calibrate(); + dac = do_calibrate(); uart1_put_string("new g_scale "); - uart1_put_hex32(*(uint32_t *)&g_scale); + uart1_put_float(g_scale); uart1_crlf(); break; diff --git a/firmware/uart.c b/firmware/uart.c index aa5aa87..1c05cbb 100644 --- a/firmware/uart.c +++ b/firmware/uart.c @@ -121,6 +121,22 @@ void uart_put_dec(int uart, int32_t x) } } +void uart_put_float(int uart, float x) +{ + int i; + int32_t v; + + v = (int32_t) x; + uart_put_dec(uart, v); + uart_put(uart, '.'); + for (i = 0; i < 6; i++) { + x -= v; + x *= 10; + v = (int32_t) x; + uart_put(uart, v + '0'); + } +} + void uart_crlf(int uart) { uart_put(uart, '\r'); diff --git a/firmware/uart.h b/firmware/uart.h index 24368a7..26edb43 100644 --- a/firmware/uart.h +++ b/firmware/uart.h @@ -15,6 +15,7 @@ void uart_put_hex16(int uart, uint16_t x); void uart_put_hex32(int uart, uint32_t x); void uart_put_bin(int uart, uint8_t x); void uart_put_dec(int uart, int32_t x); +void uart_put_float(int uart, float x); /* Blocking receives */ uint8_t uart_get(int uart); @@ -35,6 +36,7 @@ int uart_can_put(int uart); #define uart1_put_hex32(x) uart_put_hex32(1,x) #define uart1_put_bin(x) uart_put_bin(1,x) #define uart1_put_dec(x) uart_put_dec(1,x) +#define uart1_put_float(x) uart_put_float(1,x) #define uart2_init(x) uart_init(2, x) #define uart2_can_get() uart_can_get(2) @@ -47,5 +49,6 @@ int uart_can_put(int uart); #define uart2_put_hex32(x) uart_put_hex32(2,x) #define uart2_put_bin(x) uart_put_bin(2,x) #define uart2_put_dec(x) uart_put_dec(2,x) +#define uart2_put_float(x) uart_put_float(2,x) #endif diff --git a/firmware/util.h b/firmware/util.h index fe91d45..3c55022 100644 --- a/firmware/util.h +++ b/firmware/util.h @@ -36,6 +36,6 @@ int32_t hex_to_u16(char x[4]); #define abs(a) \ ({ typeof (a) _a = (a); \ - _a < 0 ? _a : -_a; }) + _a < 0 ? -_a : _a; }) #endif diff --git a/firmware/zoom.c b/firmware/zoom.c index c1b2d74..ee2da8a 100644 --- a/firmware/zoom.c +++ b/firmware/zoom.c @@ -8,6 +8,7 @@ #include "led.h" #include "mode.h" #include "zoom.h" +#include "calibrate.h" int main(void) { @@ -16,6 +17,7 @@ int main(void) config_init(); led_init(); led_on(); + calibrate_init(); /* debug output */ TRISAbits.TRISA9 = 0;