Continuity and diode mode initial implementation
Reads continuity at a fixed ~100ohm or lower, and diodes with intelligent detection of LEDs vs normal diodes. Some values may need to be changed still.
This commit is contained in:
parent
859c04f782
commit
0afa454588
|
@ -13,7 +13,7 @@
|
|||
|
||||
|
||||
|
||||
#define ADC_CHANNELS 6
|
||||
#define ADC_CHANNELS 5
|
||||
#define ADC_HISTLEN 16
|
||||
|
||||
|
||||
|
@ -25,6 +25,8 @@ extern uint16_t adc_avg[ADC_CHANNELS];
|
|||
void adc_init();
|
||||
uint8_t adc_next();
|
||||
|
||||
void adc_switch0();
|
||||
|
||||
|
||||
|
||||
#endif /* _INC_ADC_H */
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* probe.c: helping you probe things
|
||||
*
|
||||
* file creation: 20231021 1717
|
||||
*/
|
||||
|
||||
#ifndef _INC_PROBE_H
|
||||
#define _INC_PROBE_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
void probe_mode_switch(uint8_t mode);
|
||||
|
||||
void probe_measure();
|
||||
|
||||
|
||||
|
||||
#endif /* _INC_PROBE_H */
|
|
@ -77,9 +77,9 @@
|
|||
|
||||
#define ADC_PROBE 1
|
||||
|
||||
#define ADC_VREF_INT 5
|
||||
#define ADC_VREF_INT 4
|
||||
#define ADC_VREF_EXT 0
|
||||
#define ADC_THERM 4
|
||||
// #define ADC_THERM 4
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,9 +4,33 @@
|
|||
* file creation: 20231016 1505
|
||||
*/
|
||||
|
||||
#ifndef _INC_USERIO_H
|
||||
#define _INC_USERIO_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
#define MODE_CONT 0
|
||||
#define MODE_CONT_TARGET 3072 // (4096 * (1 - (1 / 4)))
|
||||
|
||||
#define MODE_FUN 1
|
||||
#define MODE_FUN_TARGET 2731 // (4096 * (1 - (1 / 3)))
|
||||
|
||||
#define MODE_DIODE 2
|
||||
#define MODE_DIODE_TARGET 2048 // (4096 * 1 - ((1 / 2)))
|
||||
|
||||
|
||||
|
||||
extern uint8_t knob[2];
|
||||
|
||||
|
||||
|
||||
void userio_parse();
|
||||
|
||||
uint8_t userio_get_mode();
|
||||
|
||||
|
||||
|
||||
#endif /* _INC_USERIO_H */
|
|
@ -161,7 +161,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
|
|||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
|
||||
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack));
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,7 +187,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
|
|||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
|
||||
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack));
|
||||
}
|
||||
|
||||
|
||||
|
|
20
src/adc.c
20
src/adc.c
|
@ -40,6 +40,7 @@
|
|||
|
||||
|
||||
|
||||
|
||||
static uint16_t adc_read[ADC_CHANNELS];
|
||||
static uint16_t adc_hist[ADC_CHANNELS][ADC_HISTLEN];
|
||||
|
||||
|
@ -61,16 +62,17 @@ void adc_init()
|
|||
// calibration configuration
|
||||
ADC1->CCSR = LL_ADC_CAL_SAMPLINGTIME_8CYCLES | ADC_CCSR_CALSEL;
|
||||
|
||||
// enable VREFINT and temperature sensor
|
||||
ADC->CCR = ADC_CCR_TSEN | ADC_CCR_VREFEN;
|
||||
// enable VREFINT
|
||||
ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN |
|
||||
|
||||
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
|
||||
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and PROBE are
|
||||
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are
|
||||
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
|
||||
ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL12;
|
||||
ADC_CHSELR_CHSEL12;
|
||||
ADC1->SMPR = SAMPLE_TIME;
|
||||
|
||||
// run in one-shot mode (scan all channels) but with wait mode active
|
||||
// run in one-shot mode (all channel conversion per trigger)
|
||||
// with wait mode (anti-overrun) active
|
||||
ADC1->CFGR1 = ADC_CFGR1_OVRMOD | ADC_CFGR1_WAIT;
|
||||
|
||||
// enable end of conversion interrupt
|
||||
|
@ -188,8 +190,6 @@ uint8_t adc_next()
|
|||
}
|
||||
|
||||
// check vref to determine if we need to recalibrate
|
||||
// the way this is written now,
|
||||
// this will always do a double-calibrate at the start
|
||||
w = adc_avg[ADC_VREF_INT];
|
||||
if ((abs(vref - w) > 3) || (abs(w - vref) > 3)) {
|
||||
calibrate = 1;
|
||||
|
@ -205,13 +205,17 @@ uint8_t adc_next()
|
|||
|
||||
void ADC_COMP_IRQHandler()
|
||||
{
|
||||
if (adc_seq != 0xff) {
|
||||
if (adc_seq < ADC_CHANNELS) {
|
||||
adc_read[adc_seq++] = ADC1->DR;
|
||||
|
||||
// is this the end of conversions?
|
||||
if (ADC1->ISR & ADC_ISR_EOSEQ) {
|
||||
adc_seq = ADC_SEQ_RDY;
|
||||
}
|
||||
} else {
|
||||
// we shouldn't be here. something with ADC fucked up.
|
||||
// reset ADC, clear sequence, and start again
|
||||
adc_go();
|
||||
}
|
||||
|
||||
// clear all interrupt flags
|
||||
|
|
26
src/led.c
26
src/led.c
|
@ -25,6 +25,9 @@ static uint8_t snd_buzz; // piezo sounder active?
|
|||
|
||||
static uint16_t rgb[2][3]; // RGBLED actual values to set
|
||||
|
||||
static uint8_t dualtone = 0; // buzzer dualtone mode
|
||||
static uint8_t dt_cntr = 0; // buzzer dualtone counter
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -57,8 +60,26 @@ void led_next()
|
|||
|
||||
// enable selected LED
|
||||
if (led_sel) {
|
||||
if ((led_mode == MODE_BUZZ) && !snd_buzz) return;
|
||||
switch (led_mode) {
|
||||
case MODE_RGB: {
|
||||
RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
|
||||
break;
|
||||
}
|
||||
case MODE_BUZZ: {
|
||||
if (!snd_buzz) return;
|
||||
|
||||
// dual tone
|
||||
dt_cntr++;
|
||||
dt_cntr &= 1;
|
||||
if (!dt_cntr) {
|
||||
dualtone ^= 1;
|
||||
}
|
||||
|
||||
if (!dt_cntr || dualtone) {
|
||||
RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RGBSEL0_PORT->BRR = (1 << RGBSEL0_PIN);
|
||||
}
|
||||
|
@ -146,9 +167,6 @@ void led_init()
|
|||
led_sel = 1;
|
||||
snd_buzz = 0;
|
||||
|
||||
rgb[0][0] = 100;
|
||||
rgb[1][1] = 100;
|
||||
|
||||
// start outputting data
|
||||
led_next();
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include "adc.h"
|
||||
#include "flash.h"
|
||||
#include "led.h"
|
||||
#include "probe.h"
|
||||
#include "userio.h"
|
||||
|
||||
|
||||
|
@ -143,9 +144,14 @@ __attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void)
|
|||
|
||||
// adc tested to result in about 61 reads/second
|
||||
if (!adc_next()) {
|
||||
// adc has new computed results, so we can do userio, probe, etc
|
||||
// adc has new computed results
|
||||
if (uptime || cs) {
|
||||
// figure out knobs, buttons, switches
|
||||
userio_parse();
|
||||
|
||||
// show probe measurement results, or if not in a measurement mode,
|
||||
// run RGBLED program
|
||||
probe_measure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
130
src/probe.c
130
src/probe.c
|
@ -6,3 +6,133 @@
|
|||
*
|
||||
* file creation: 20231016 0255
|
||||
*/
|
||||
|
||||
#include "py32f0xx_conf.h"
|
||||
|
||||
#include "testo.h"
|
||||
|
||||
#include "adc.h"
|
||||
#include "led.h"
|
||||
#include "userio.h"
|
||||
|
||||
|
||||
|
||||
#define CONT_OPEN 1240
|
||||
|
||||
|
||||
|
||||
// diode measurements at 3V3
|
||||
#define DIODE_OPEN 4000 // test unit measures ~4060
|
||||
#define DIODE_STANDARD 2330 // fairchild 5V2 zener, forward biased
|
||||
#define DIODE_SCHOTTKY 1960 // vishay 40V 1A SB140
|
||||
#define DIODE_LED_BLUE 3190
|
||||
#define DIODE_LED_GRN 3040 // very dim
|
||||
#define DIODE_LED_RED 3020
|
||||
#define DIODE_SHORT 1900 // test unit measures ~1820
|
||||
|
||||
#define SHORT_THRESHOLD 2
|
||||
|
||||
|
||||
|
||||
static uint16_t vref;
|
||||
static uint8_t latch = 0;
|
||||
|
||||
|
||||
|
||||
static inline void probe_measure_cont()
|
||||
{
|
||||
uint16_t probe, v_ext;
|
||||
uint32_t x;
|
||||
|
||||
probe = adc_avg[ADC_PROBE];
|
||||
v_ext = adc_avg[ADC_VREF_EXT];
|
||||
|
||||
// this LED will not set anything,
|
||||
// but zero it out anyway
|
||||
led_setrgb(1, 0, 0, 0);
|
||||
|
||||
if (vref) {
|
||||
x = probe << 12; // maximum possible level
|
||||
x /= vref; // normalize to 4096max
|
||||
if (x > 4095) x = 4095;
|
||||
|
||||
if (x < 2405) { // roughly 100ohm or lower
|
||||
latch = 4; // latch any continuity for a while
|
||||
}
|
||||
|
||||
if (latch) {
|
||||
if (x >= 2420) latch--; // hysteresis
|
||||
|
||||
led_setrgb(0, 0, 255, 0);
|
||||
led_buzz(0);
|
||||
if (knob[0] > 128) led_buzz(1);
|
||||
} else {
|
||||
led_setrgb(0, 64, 0, 0);
|
||||
led_buzz(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vref) vref = v_ext;
|
||||
vref += v_ext;
|
||||
vref >>= 1;
|
||||
}
|
||||
|
||||
static inline void probe_measure_diode()
|
||||
{
|
||||
uint16_t p;
|
||||
|
||||
p = adc_avg[ADC_PROBE];
|
||||
|
||||
led_setrgb(0, 0, 0, 0);
|
||||
|
||||
if (p < DIODE_SHORT) {
|
||||
// off on short
|
||||
led_setrgb(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (p >= DIODE_OPEN) {
|
||||
// red on open
|
||||
led_setrgb(1, 255, 0, 0);
|
||||
}
|
||||
|
||||
if (p >= 1940 && p < 2650) {
|
||||
// green on regular or schottky diodes
|
||||
led_setrgb(1, 0, 255, 0);
|
||||
}
|
||||
if (p >= 2650 && p < 3800) {
|
||||
// blue on LEDs
|
||||
led_setrgb(1, 0, 0, 255);
|
||||
}
|
||||
|
||||
// if we haven't set a value, flash red to indicate error state
|
||||
}
|
||||
|
||||
void probe_measure()
|
||||
{
|
||||
uint8_t mode;
|
||||
|
||||
mode = userio_get_mode();
|
||||
|
||||
switch (mode) {
|
||||
case MODE_CONT: probe_measure_cont(); break;
|
||||
case MODE_FUN: break; // todo: run RGBLED program
|
||||
case MODE_DIODE: probe_measure_diode(); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* switch probe mode.
|
||||
* sets up LED peripheral and mode pin as necessary.
|
||||
*/
|
||||
void probe_mode_switch(uint8_t mode)
|
||||
{
|
||||
if (mode == MODE_CONT) {
|
||||
// set LED to buzzer mode, set PROBESEL low
|
||||
led_mode_buzzer();
|
||||
PROBESEL_PORT->BRR = (1 << PROBESEL_PIN);
|
||||
} else {
|
||||
// set LED to dual RGB mode, set PROBESEL high
|
||||
led_mode_rgb();
|
||||
PROBESEL_PORT->BSRR = (1 << PROBESEL_PIN);
|
||||
}
|
||||
}
|
73
src/userio.c
73
src/userio.c
|
@ -27,52 +27,50 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "adc.h"
|
||||
#include "testo.h"
|
||||
#include "userio.h"
|
||||
|
||||
#include "adc.h"
|
||||
#include "probe.h"
|
||||
|
||||
|
||||
|
||||
#define MODE_CONT 0
|
||||
#define MODE_CONT_TARGET 3072 // (4096 * (1 - (1 / 4)))
|
||||
|
||||
#define MODE_FUN 1
|
||||
#define MODE_FUN_TARGET 2731 // (4096 * (1 - (1 / 3)))
|
||||
|
||||
#define MODE_DIODE 2
|
||||
#define MODE_DIODE_TARGET 2048 // (4096 * 1 - ((1 / 2)))
|
||||
|
||||
#define MODE_SET_LIMIT 60 // 3x worst case expected (1% tol)
|
||||
#define MODE_CHANGE_TICKS 4 // how many samples before switching modes
|
||||
|
||||
#define MODE_ANALOG_MIN 20
|
||||
|
||||
|
||||
#ifdef TESTO_REV1
|
||||
#define SET1_MAX 2047 // 3V net feeding into 1V24 via body diode above this
|
||||
#else
|
||||
#define SET1_MAX 1539 // 1.24Vref
|
||||
#endif
|
||||
|
||||
uint8_t mode;
|
||||
uint8_t mode_next;
|
||||
uint8_t mode_count;
|
||||
|
||||
|
||||
static uint8_t mode = 0xff;
|
||||
static uint8_t mode_next;
|
||||
static uint8_t mode_count;
|
||||
static const int16_t mode_targets[] = {
|
||||
MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET
|
||||
};
|
||||
|
||||
uint8_t knob[2];
|
||||
|
||||
uint8_t btn = 0;
|
||||
uint16_t btn_held = 0;
|
||||
static uint8_t btn = 0;
|
||||
static uint16_t btn_held = 0;
|
||||
|
||||
|
||||
|
||||
void userio_update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userio_parse()
|
||||
{
|
||||
uint8_t i;
|
||||
volatile int16_t m, w;
|
||||
int16_t m, w;
|
||||
uint32_t x;
|
||||
|
||||
// button
|
||||
{
|
||||
// debounce is handled by the fact that we've had to have averaged
|
||||
// about 16ms of measured hold time below the zero threshold.
|
||||
m = adc_avg[ADC_SET_MODE];
|
||||
|
@ -84,6 +82,7 @@ void userio_parse()
|
|||
// button is released
|
||||
btn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// mode
|
||||
if (!btn) {
|
||||
|
@ -110,6 +109,14 @@ void userio_parse()
|
|||
// we've got enough data to do a change of mode
|
||||
mode = i;
|
||||
mode_count = 0;
|
||||
|
||||
// MODE SWITCH ACTION IS HANDLED HERE
|
||||
// restart ADC on mode change to update values
|
||||
// to reflect selected measurement mode
|
||||
adc_switch0();
|
||||
// and set the probe measurement routines
|
||||
// to use the selected mode
|
||||
probe_mode_switch(mode);
|
||||
}
|
||||
} else {
|
||||
// set the next mode to the newly selected mode
|
||||
|
@ -121,4 +128,28 @@ void userio_parse()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// knobs
|
||||
{
|
||||
knob[0] = adc_avg[ADC_SET0] >> 4;
|
||||
|
||||
// SET1/VREFEXT input can be SET1 or VREFEXT, depending on PROBESEL.
|
||||
// only copy if not set to VREFEXT, and only if within valid range
|
||||
if (PROBESEL_PORT->ODR & (1 << PROBESEL_PIN)) {
|
||||
// PROBESEL is high, so SET1 is in use
|
||||
if (adc_avg[ADC_SET1] > SET1_MAX) {
|
||||
// knob is turned too far; warn the user.
|
||||
// TODO
|
||||
} else {
|
||||
x = adc_avg[ADC_SET1] << 12; // maximum possible level
|
||||
x /= SET1_MAX; // normalize to 4096max
|
||||
knob[0] = (x >> 4) & 0xff; // reduce to 8-bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t userio_get_mode()
|
||||
{
|
||||
return mode;
|
||||
}
|
Loading…
Reference in New Issue