Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Semerád Pavel
gt3b
Commits
8c7d049f
Commit
8c7d049f
authored
Apr 07, 2012
by
Pavel Semerad
Browse files
measure ADC every 1ms at timer code, compute averaged ADC value when used
parent
e0e4a285
Changes
7
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
8c7d049f
...
...
@@ -3,6 +3,7 @@
minimum battery voltage set to 2V for those experimenting with 1S cell
PPM length shortened to "NUM_CHANNELS x 2ms + 5ms" to send new data
to receiver as soon as possible
ADC measuring every 1ms, averaging last 4 samples when used
*0.4.1 (17 Aug 2011)
...
...
README.internal
View file @
8c7d049f
...
...
@@ -23,12 +23,14 @@ ppm_interrupt
- wakeups task CALC during SYNC signal
timer_interrupt
- timer2 overflow
- every 1ms read ADC values
- every 5ms
- increments time from start
- count LCD blink time and wakeups task LCD
- handles buzzer
- wakeups task INPUT
- handles task MENU delay and wakeups this task
- increments time from start
- count LCD blink time and wakeups task LCD
- handles buzzer
- wakeups task INPUT
- wakeups task MENU when it wants ADC values (calibrate, ...)
- handles task MENU delay and wakeups this task
...
...
@@ -40,7 +42,7 @@ LCD
- is waked up by lcd_update(), lcd_clear()
- is waked up from timer to do automatic blinking
INPUT
- is doing reading
of ADC values and key matrix
- is doing reading
key matrix and some ADC checks
- is waked up from timer every 5ms
CALC
- is computing values for each servo and sync signal
...
...
@@ -48,10 +50,9 @@ CALC
- also needed to wakeup after changing number of PPM channels in MENU
MENU
- is main program handling keys, menus, lcd
- is waked up from timer when menu_delay expired
- is waked up from timer when menu_delay expired
or when ADC values needed
- is waked up from INPUT task when
- buttons state changed
- MENU task wanted ADC values (for calibrate) or battery voltage
- status of battery low changed
...
...
TODO
View file @
8c7d049f
ADC wakeups - only every 1/2s instead of checking time at menu code
ADC - measure every 1ms - timer 1ms, buttons code still every 5ms
CALC - calc at end of SYNC signal
- measure durations of CALC
- at end of CALC PPM pulse and servo pulses
...
...
input.c
View file @
8c7d049f
...
...
@@ -118,7 +118,7 @@ u16 buttons;
u16
buttons_long
;
// >1s press
// variables for ADC values
@
near
u16
adc_all_last
[
3
],
adc_battery_last
;
@
near
u16
adc_all_ovs
[
3
],
adc_battery
;
@
near
u16
adc_battery
;
@
near
u32
adc_battery_filt
;
...
...
@@ -305,43 +305,26 @@ static void read_keys(void) {
// ADC buffers, last 4 values for each channel
#define ADC_BUFFERS 4
@
near
static
u16
adc_buffer
[
ADC_BUFFERS
][
3
];
static
u8
adc_buffer_pos
;
// define missing ADC buffer registers
volatile
u16
ADC_DB0R
@
0x53e0
;
volatile
u16
ADC_DB1R
@
0x53e2
;
volatile
u16
ADC_DB2R
@
0x53e4
;
volatile
u16
ADC_DB3R
@
0x53e6
;
// read ADC values and compute sum of last 4 for each channel
#define ADC_NEWVAL(id) \
adc_all_last[id] = ADC_DB ## id ## R; \
buf[id] = adc_all_last[id]; \
adc_all_ovs[id] = adc_buffer[0][id] + adc_buffer[1][id] \
+ adc_buffer[2][id] + adc_buffer[3][id];
static
void
read_ADC
(
void
)
{
u16
*
buf
=
adc_buffer
[
adc_buffer_pos
];
u8
dead
;
@
near
u16
adc_buffer0
[
ADC_BUFFERS
];
@
near
u16
adc_buffer1
[
ADC_BUFFERS
];
@
near
u16
adc_buffer2
[
ADC_BUFFERS
];
u16
adc_buffer_pos
;
ADC_NEWVAL
(
0
);
ADC_NEWVAL
(
1
);
ADC_NEWVAL
(
2
);
adc_battery_last
=
ADC_DB3R
;
adc_buffer_pos
++
;
adc_buffer_pos
&=
3
;
// read ADC values
static
void
read_ADC
(
void
)
{
READ_ADC
();
}
BRES
(
ADC_CSR
,
7
);
// remove EOC flag
BSET
(
ADC_CR1
,
0
);
// start new conversion
// average battery voltage and check battery low
// average battery voltage and check battery low
static
void
update_battery
(
void
)
{
// ignore very low, which means that it is supplied from SWIM connector
adc_battery_filt
=
adc_battery_filt
*
(
ADC_BAT_FILT
-
1
);
// splitted - compiler hack
adc_battery_filt
=
(
adc_battery_filt
+
(
ADC_BAT_FILT
/
2
))
/
ADC_BAT_FILT
+
adc_battery_last
;
adc_battery
=
(
u16
)((
adc_battery_filt
+
(
ADC_BAT_FILT
/
2
))
/
ADC_BAT_FILT
);
// start checking battery after 5s from power on
if
(
time_sec
>=
5
)
{
// wakeup task only when something changed
...
...
@@ -360,13 +343,12 @@ static void read_ADC(void) {
}
}
}
}
// wakeup MENU task when showing battery or at calibrate
if
(
menu_wants_adc
)
awake
(
MENU
);
// reset inactivity timer when some steering or throttle applied
dead
=
cg
.
steering_dead_zone
;
// reset inactivity timer when some steering or throttle applied
static
void
check_inactivity
(
void
)
{
u8
dead
=
cg
.
steering_dead_zone
;
if
(
dead
<
20
)
dead
=
20
;
// use some minimal dead zone for this check
if
(
adc_steering_last
<
(
cg
.
calib_steering_mid
-
dead
)
||
adc_steering_last
>
(
cg
.
calib_steering_mid
+
dead
))
...
...
@@ -388,9 +370,8 @@ static void read_ADC(void) {
// input task, awaked every 5ms
_Bool
input_initialized
;
#define ADC_BUFINIT(id) \
adc_buffer[1][id] = adc_buffer[2][id] = adc_buffer[3][id] = \
adc_buffer[0][id]; \
adc_all_ovs[id] = adc_buffer[0][id] << ADC_OVS_SHIFT;
adc_buffer ## id ## [1] = adc_buffer ## id ## [2] = \
adc_buffer ## id ## [3] = adc_buffer ## id ## [0];
static
void
input_loop
(
void
)
{
// read initial ADC values
...
...
@@ -410,10 +391,9 @@ static void input_loop(void) {
input_initialized
=
1
;
while
(
1
)
{
// read ADC only when EOC flag (only for first it will not be ready)
if
(
BCHK
(
ADC_CSR
,
7
))
read_ADC
();
read_keys
();
check_inactivity
();
update_battery
();
stop
();
}
}
...
...
input.h
View file @
8c7d049f
...
...
@@ -64,23 +64,6 @@ extern volatile u16 buttons_long; // >1s presses buttons
#define btnl_all(mask) ((buttons_long & (mask)) == (mask))
// variables for ADC values
extern
@
near
volatile
u16
adc_all_ovs
[
3
];
// oversampled from 4 samples and is 4* more
#define ADC_OVS_SHIFT 2
#define ADC_OVS_ROUND 2
#define adc_steering_ovs adc_all_ovs[0]
#define adc_throttle_ovs adc_all_ovs[1]
#define adc_ch3_ovs adc_all_ovs[2]
extern
@
near
volatile
u32
adc_battery_filt
;
// battery will be filtered more times
#define ADC_BAT_FILT 512
extern
@
near
volatile
u16
adc_battery
;
// adc_battery_filt >> ADC_BATTERY_SHIFT
extern
@
near
volatile
u16
adc_all_last
[
3
];
// last readed value
#define adc_steering_last adc_all_last[0]
#define adc_throttle_last adc_all_last[1]
#define adc_ch3_last adc_all_last[2]
extern
@
near
volatile
u16
adc_battery_last
;
// reset pressed button(s)
// do it after used that button in code
extern
void
button_reset
(
u16
btn
);
...
...
@@ -95,6 +78,65 @@ extern void button_autorepeat(u8 btn);
// variables for ADC values
// define missing ADC buffer registers
volatile
u16
ADC_DB0R
@
0x53e0
;
volatile
u16
ADC_DB1R
@
0x53e2
;
volatile
u16
ADC_DB2R
@
0x53e4
;
volatile
u16
ADC_DB3R
@
0x53e6
;
// last readed values
extern
@
near
volatile
u16
adc_all_last
[
3
];
#define adc_steering_last adc_all_last[0]
#define adc_throttle_last adc_all_last[1]
#define adc_ch3_last adc_all_last[2]
extern
@
near
volatile
u16
adc_battery_last
;
// ADC buffers, last 4 values for each channel
// average will be computed when used
#define ADC_BUFFERS 4
extern
@
near
u16
adc_buffer0
[
ADC_BUFFERS
];
extern
@
near
u16
adc_buffer1
[
ADC_BUFFERS
];
extern
@
near
u16
adc_buffer2
[
ADC_BUFFERS
];
#define ADC_OVS_SHIFT 2
#define ADC_OVS_ROUND 2
#define adc_steering_ovs (adc_buffer0[0] + adc_buffer0[1] + adc_buffer0[2] \
+ adc_buffer0[3])
#define adc_throttle_ovs (adc_buffer1[0] + adc_buffer1[1] + adc_buffer1[2] \
+ adc_buffer1[3])
#define adc_ch3_ovs (adc_buffer2[0] + adc_buffer2[1] + adc_buffer2[2] \
+ adc_buffer2[3])
#define ADC_OVS(name) \
((adc_ ## name ## _ovs + ADC_OVS_ROUND) >> ADC_OVS_SHIFT)
// battery will be filtered more times
extern
@
near
volatile
u32
adc_battery_filt
;
#define ADC_BAT_FILT 512
extern
@
near
volatile
u16
adc_battery
;
// adc_battery_filt / ADC_BAT_FILT
// code reading last ADC values
// retypes to force more optimized code produced by compiler
extern
u16
adc_buffer_pos
;
// step 2 (skip 16bit values)
#define ADC_NEWVAL(id) \
*(u16 *)((u8 *)adc_buffer ## id ## + adc_buffer_pos) = \
adc_all_last[id] = \
ADC_DB ## id ## R;
#define READ_ADC() \
ADC_NEWVAL(0); \
ADC_NEWVAL(1); \
ADC_NEWVAL(2); \
adc_battery_last = ADC_DB3R; \
*((u8 *)&adc_buffer_pos + 1) = (u8)((u8)((u8)adc_buffer_pos + 2) & 7); \
BRES(ADC_CSR, 7);
/* remove EOC flag */
\
BSET(ADC_CR1, 0); // start new conversion
// INPUT task
E_TASK
(
INPUT
);
extern
_Bool
input_initialized
;
...
...
menu_service.c
View file @
8c7d049f
...
...
@@ -88,7 +88,7 @@ void menu_calibrate(void) {
// select actual voltage for channel 4
if
(
channel
==
1
)
{
key_beep
();
val
=
(
adc_steering_ovs
+
ADC_OVS_ROUND
)
>>
ADC_OVS_SHIFT
;
val
=
ADC_OVS
(
steering
)
;
if
(
val
<
CALIB_ST_LOW_MID
)
{
cg
.
calib_steering_left
=
val
;
seg
=
LS_MENU_MODEL
;
...
...
@@ -106,7 +106,7 @@ void menu_calibrate(void) {
}
else
if
(
channel
==
2
)
{
key_beep
();
val
=
(
adc_throttle_ovs
+
ADC_OVS_ROUND
)
>>
ADC_OVS_SHIFT
;
val
=
ADC_OVS
(
throttle
)
;
if
(
val
<
CALIB_TH_LOW_MID
)
{
cg
.
calib_throttle_fwd
=
val
;
seg
=
LS_MENU_TRIM
;
...
...
@@ -157,8 +157,22 @@ void menu_calibrate(void) {
}
// show ADC value if other than last val
if
(
channel
==
4
)
val
=
adc_battery
;
else
val
=
(
adc_all_ovs
[
channel
-
1
]
+
ADC_OVS_ROUND
)
>>
ADC_OVS_SHIFT
;
switch
(
channel
)
{
case
1
:
val
=
ADC_OVS
(
steering
);
break
;
case
2
:
val
=
ADC_OVS
(
throttle
);
break
;
case
3
:
val
=
ADC_OVS
(
ch3
);
break
;
case
4
:
val
=
adc_battery
;
break
;
default:
// to eliminate compiler warning
val
=
0
;
}
// only update display every 1s
if
(
time_sec
>=
update_time
)
{
update_time
=
time_sec
+
1
;
...
...
timer.c
View file @
8c7d049f
...
...
@@ -33,14 +33,15 @@ static @near u16 inactivity;
// initialize timer 2 used to count seconds
#define TIMER_5MS (KHZ / 2 * 5)
#define TIMER_1MS (KHZ / 2)
void
timer_init
(
void
)
{
BSET
(
CLK_PCKENR1
,
5
);
// enable clock to TIM2
TIM2_CNTRH
=
0
;
// start at 0
TIM2_CNTRL
=
0
;
TIM2_PSCR
=
1
;
// clock / 2
TIM2_IER
=
0
b00000001
;
// enable update interrupt
TIM2_ARRH
=
hi8
(
TIMER_
5
MS
-
1
);
// count till
5
ms time
TIM2_ARRL
=
lo8
(
TIMER_
5
MS
-
1
);
TIM2_ARRH
=
hi8
(
TIMER_
1
MS
-
1
);
// count till
1
ms time
TIM2_ARRL
=
lo8
(
TIMER_
1
MS
-
1
);
TIM2_CR1
=
0
b00000101
;
// URS-overflow, enable
inactivity
=
cg
.
inactivity_alarm
*
60
;
...
...
@@ -50,13 +51,23 @@ void timer_init(void) {
// count seconds from power on
volatile
u16
time_sec
;
volatile
u8
time_5ms
;
volatile
u8
time_1ms
;
static
u16
menu_delay
;
// timer for delay in MENU task
// interrupt every
5
ms
// interrupt every
1
ms
@
interrupt
void
timer_interrupt
(
void
)
{
BRES
(
TIM2_SR1
,
0
);
// erase interrupt flag
// read ADC only when EOC flag (only for first it will not be ready)
if
(
input_initialized
&&
BCHK
(
ADC_CSR
,
7
))
{
READ_ADC
();
}
// increment 1ms steps
if
(
++
time_1ms
<
5
)
return
;
time_1ms
=
0
;
// increment time from start
if
(
++
time_5ms
>=
200
)
{
...
...
@@ -116,6 +127,10 @@ static u16 menu_delay; // timer for delay in MENU task
// wakeup INPUT task
awake
(
INPUT
);
// wakeup MENU task every 40ms when showing battery or at calibrate
if
(
menu_wants_adc
&&
!
(
time_5ms
&
0
b00000111
))
awake
(
MENU
);
// task MENU delay
if
(
menu_delay
&&
!--
menu_delay
)
awake
(
MENU
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment