git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@7696 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/zoom-1.0
@@ -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 */ | |||
@@ -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); | |||
@@ -3,7 +3,7 @@ | |||
#include "config.h" | |||
#define LED_BLINK_RATE 4 | |||
#define LED_BLINK_RATE 8 | |||
extern int16_t __led_pattern; | |||
/* Initialize LED */ | |||
@@ -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; | |||
@@ -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'); | |||
@@ -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 |
@@ -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 |
@@ -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; | |||