calibration works
git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@7696 ddd99763-3ecb-0310-9145-efcb8ce7c51f
This commit is contained in:
parent
94a79e1964
commit
a9379588cf
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user