1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* Autor: Ján Suèan <jan@jansucan.sk>
*
* Zdrojove kody, ich casti a subory z nich vzniknute priamo alebo nepriamo
* (objektove subory, Intel Hex, ...) prosim nepouzivajte komercne, ani ako
* sucast komercnych diel. Vsetky ostatne pripady pouzitia su dovolene.
*
* Please don't use the source codes, their parts and files created from them
* directly or indirectly, (object files, Intel Hex files, ...) for commercial
* purposes, not even as a part of commercial products. All other use cases
* are allowed.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <fan_controller/hw/ad_converter.h>
#include <fan_controller/median.h>
#include <fan_controller/hw/fan.h>
/** Pocet naposledy nameranych vzoriek z ktorych sa bude brat median. */
#define ADC_SAMPLE_COUNT 5U
/** Buffer pre median nameranych vzoriek. */
static median_buffer_t adc_median_buffer;
/** Naposledy ziskany median z nameranych vzoriek. */
static uint8_t adc_converted_value;
/** Ci sa ma nastavit konstantna hodnota pre otacky, namiesto nastavenia podla hodnoty z potenciometra. */
static bool adc_is_value_overriden = false;
/** Konstanta hodnota na ktoru sa nastavia otacky ventilatora pri aktivovani pouzitia pevnej hodnoty pre otacky. */
static uint8_t adc_override_value;
/**
* @brief Obsluha prerusenia od AD prevodnika pri dokonceni prevodu.
*
* Namerana hodnota sa ulozi medzi vzorky pre median, ziska sa median
* a bud sa otacky nastavia podla ziskaneho medianu, alebo ked je
* aktivovane pouzitie konstantnej hodnoty, bude sa napatie z potenciometra
* ignorovat a hodnota sa bude nastavovat na zvolenu konstantu.
*/
ISR(ADC_vect)
{
// Povolenie preruseni s vyssou prioritou (pretecenie PWM casovaca pre ovladanie otacok ventilatora)
sei();
median_save_sample(&adc_median_buffer, ADCH);
adc_converted_value = median_get(&adc_median_buffer);
if (adc_is_value_overriden) {
fan_rpm_set(adc_override_value);
} else {
fan_rpm_set(adc_converted_value);
}
}
/**
* @brief Inicializacia AD prevodnika.
*
* Spusti sa AD prevodnik, bude stale konvertovat napatie
* z potenciometra (free-running mod) a povoli sa prerusenie
* pri dokonceni prevodu.
*/
void
adc_init(void)
{
// Kanal ADC0
// Napatova referencia na pine AREF MCU
// Zarovnanie vysledku dolava
ADMUX = (1 << ADLAR);
// ADC enable
// Najnizsia ADC frekvencia, preddelicka 128
// Free-runnung mod predvolene v SFIOR
// Povolenie prerusenia
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIE) | (1 << ADATE);
median_init_buffer(&adc_median_buffer, ADC_SAMPLE_COUNT);
for (uint8_t i = 0; i < ADC_SAMPLE_COUNT; ++i) {
median_save_sample(&adc_median_buffer, 0);
}
// Spustenie A/D prevodu
ADCSRA |= 1 << ADSC;
}
/**
* @brief Ziskanie hodnoty z AD prevodnika spocitanej ako median niekolkych predchadzajucich merani.
*
* @param Hodnota namerana AD prevodnikom.
*/
uint8_t
adc_get_converted_value(void)
{
uint8_t v;
// Zakaze sa prerusenie aby k premennej nepristupovala zaroven aj obsluha prerusenia
ADCSRA &= ~(1 << ADIE);
v = adc_converted_value;
// Znovu sa prerusenie povoli
ADCSRA |= (1 << ADIE);
return v;
}
/**
* @brief Nastavenie konstantej hodnoty pre otacky ventilatora.
*
* Pri nastaveni konstantnej hodnoty sa bude ignorovat hodnota z potenciometra.
*
* @param val Konstantna hodnota otacok ventilatora.
*/
void
adc_override_value_set(uint8_t val)
{
adc_override_value = val;
adc_is_value_overriden = true;
}
/**
* @brief Deaktivacia konstantnej hodnoty pre nastavenie otacok ventilatora.
*
* Otacky budu zase nastavovane podla napatia z potenciometra.
*/
void
adc_override_value_delete(void)
{
adc_is_value_overriden = false;
}
|