|
|
@@ -1,48 +1,77 @@ |
|
|
|
#include "config.h"
|
|
|
|
#include "scaling.h"
|
|
|
|
#include "calibrate.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "adc.h"
|
|
|
|
#include "dac.h"
|
|
|
|
|
|
|
|
uint16_t current_to_dac(float amps)
|
|
|
|
{
|
|
|
|
float tmp;
|
|
|
|
uint16_t dacc;
|
|
|
|
|
|
|
|
tmp = 536.0 / 1.0 * amps + 32524;
|
|
|
|
if (tmp < 0)
|
|
|
|
tmp = 0;
|
|
|
|
if (tmp > 65535)
|
|
|
|
tmp = 65535;
|
|
|
|
dacc = (uint16_t)(tmp + 0.5);
|
|
|
|
static float scale; /* delta(DAC) / delta(ADC) */
|
|
|
|
|
|
|
|
return dacc;
|
|
|
|
/* Initialize. Assume some relatively-safe scaling if no calibration is run */
|
|
|
|
void calibrate_init(void)
|
|
|
|
{
|
|
|
|
scale = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert the DAC output value to an effective current in the measuring loop */
|
|
|
|
float dac_to_current(uint16_t dacv)
|
|
|
|
/* Seek with the DAC to reach a specific ADC value, adjusting
|
|
|
|
* calibration if necessary */
|
|
|
|
uint16_t seek(int16_t desired)
|
|
|
|
{
|
|
|
|
float amps;
|
|
|
|
amps = ((float)dacv - 32524.0) * 1.0 / 536.0;
|
|
|
|
return amps;
|
|
|
|
int32_t dac = 32768;
|
|
|
|
int16_t actual;
|
|
|
|
int32_t delta = 0;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
/* get current location */
|
|
|
|
dac_write(dac);
|
|
|
|
msleep(1);
|
|
|
|
actual = adc_get();
|
|
|
|
|
|
|
|
/* adjust scaling to match the jump we just saw */
|
|
|
|
if (delta) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actual == desired)
|
|
|
|
return dac;
|
|
|
|
|
|
|
|
/* figure out how much to change the DAC */
|
|
|
|
delta = (desired - actual) * scale;
|
|
|
|
|
|
|
|
|
|
|
|
dac -= (desired - actual) * scale;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
uint16_t dac = 0;
|
|
|
|
dac_write(0x8000
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
float adc12_to_current(int16_t picv)
|
|
|
|
/* Perform calibration */
|
|
|
|
void do_calibrate(void)
|
|
|
|
{
|
|
|
|
float amps;
|
|
|
|
|
|
|
|
if (picv < 0)
|
|
|
|
picv = 0;
|
|
|
|
if (picv > 2047)
|
|
|
|
picv = 2047;
|
|
|
|
|
|
|
|
amps = (picv - 1024.0) / 404.0;
|
|
|
|
return amps;
|
|
|
|
}
|
|
|
|
uint16_t daczero, x;
|
|
|
|
float x1, y1, x2, y2;
|
|
|
|
|
|
|
|
/* Zero ADC */
|
|
|
|
daczero = seek(1024);
|
|
|
|
|
|
|
|
float dac_current_min;
|
|
|
|
float dac_current_max;
|
|
|
|
/* Go halfway down and take an accurate sample */
|
|
|
|
x = seek(512);
|
|
|
|
oversample(x, &x1, &y1);
|
|
|
|
|
|
|
|
/* Go halfway up and take an accurate sample */
|
|
|
|
x = seek(768);
|
|
|
|
oversample(x, &x2, &y2);
|
|
|
|
|
|
|
|
/* Scale factor is 1/slope */
|
|
|
|
scale = (x2 - x1) / (y2 - y1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void scaling_init(void)
|
|
|
|
/* convert from (counts at ADC) to (counts at DAC) */
|
|
|
|
int32_t adc_toc(int16_t adc)
|
|
|
|
{
|
|
|
|
dac_current_min = dac_to_current(0x0000);
|
|
|
|
dac_current_max = dac_to_current(0xffff);
|
|
|
|
int32_t r = ((float) adc) * scale;
|
|
|
|
return r;
|
|
|
|
}
|