aboutsummaryrefslogtreecommitdiff
path: root/FanController/fan_controller/hw/ad_converter.c
diff options
context:
space:
mode:
authorJan Sucan <sucanjan@fit.cvut.cz>2019-09-22 21:17:50 +0200
committerJan Sucan <sucanjan@fit.cvut.cz>2019-09-22 21:17:50 +0200
commitcefd0601b91fa642163c82021d454b3c17d8adf4 (patch)
tree0470eaa5d2186905f439c10e2bea8e86020d5cbe /FanController/fan_controller/hw/ad_converter.c
Initial commit
Diffstat (limited to 'FanController/fan_controller/hw/ad_converter.c')
-rw-r--r--FanController/fan_controller/hw/ad_converter.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/FanController/fan_controller/hw/ad_converter.c b/FanController/fan_controller/hw/ad_converter.c
new file mode 100644
index 0000000..1285826
--- /dev/null
+++ b/FanController/fan_controller/hw/ad_converter.c
@@ -0,0 +1,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;
+}