summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app/forced-convection/.config101
-rw-r--r--src/app/forced-convection/Kconfig6
-rw-r--r--src/app/forced-convection/Makefile.inc9
-rw-r--r--src/app/forced-convection/main.cc169
4 files changed, 285 insertions, 0 deletions
diff --git a/src/app/forced-convection/.config b/src/app/forced-convection/.config
new file mode 100644
index 0000000..b8305be
--- /dev/null
+++ b/src/app/forced-convection/.config
@@ -0,0 +1,101 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Configuration
+#
+
+#
+# System
+#
+CONFIG_loop=y
+# CONFIG_wakeup is not set
+# CONFIG_aspectc is not set
+CONFIG_i2c_freq=100000
+CONFIG_framebuffer=y
+# CONFIG_framebuffer_in_text_segment is not set
+CONFIG_framebuffer_width=128
+CONFIG_framebuffer_height=32
+
+#
+# Libraries
+#
+# CONFIG_lib_inflate is not set
+# CONFIG_arch_arduino_nano is not set
+CONFIG_arch_arduino_uno=y
+# CONFIG_arch_atmega2560 is not set
+# CONFIG_arch_blinkenrocket is not set
+# CONFIG_arch_infineon_tc299_mock is not set
+# CONFIG_arch_infineon_tc397_mock is not set
+# CONFIG_arch_lm4f120h5qr_stellaris is not set
+# CONFIG_arch_lora32u4ii is not set
+# CONFIG_arch_msp430fr5969lp is not set
+# CONFIG_arch_msp430fr5994lp is not set
+# CONFIG_arch_posix is not set
+# CONFIG_arch_rm46l8lp is not set
+# CONFIG_arch_stm32f103c8t6 is not set
+# CONFIG_arch_stm32f446re_nucleo is not set
+# CONFIG_arch_stm32f746zg_nucleo is not set
+# CONFIG_arch_stm32h747i_disco is not set
+# CONFIG_arch_tc1796_triboard is not set
+CONFIG_arch="arduino-uno"
+
+#
+# Arduino Uno Configuration
+#
+CONFIG_arch_arduino_uno_cpufreq=16000000
+CONFIG_arch_arduino_uno_driver_adc=y
+CONFIG_arch_arduino_uno_driver_i2c=y
+# CONFIG_arch_arduino_uno_driver_neopixel is not set
+# CONFIG_arch_arduino_uno_driver_spi is not set
+# CONFIG_arch_arduino_uno_driver_stdin is not set
+# CONFIG_arch_arduino_uno_driver_timer is not set
+# CONFIG_arch_arduino_uno_driver_dmx is not set
+# CONFIG_app_datalogger is not set
+CONFIG_app_forced_convection=y
+# CONFIG_app_ledblink is not set
+# CONFIG_app_lora32u4ii is not set
+# CONFIG_app_sdtest is not set
+# CONFIG_app_ssd1306_128x32_bad_apple is not set
+# CONFIG_app_ssd1306test is not set
+CONFIG_app="forced-convection"
+CONFIG_meta_driver_adc=y
+CONFIG_meta_driver_hardware_i2c=y
+CONFIG_meta_driver_i2c=y
+
+#
+# Drivers
+#
+# CONFIG_driver_ads111x is not set
+# CONFIG_driver_am2320 is not set
+# CONFIG_driver_bme280 is not set
+# CONFIG_driver_bme680 is not set
+# CONFIG_driver_ccs811 is not set
+# CONFIG_driver_ds2482 is not set
+# CONFIG_driver_eeprom24lc64 is not set
+# CONFIG_driver_hdc1080 is not set
+CONFIG_driver_lm75=y
+# CONFIG_driver_max44006 is not set
+# CONFIG_driver_max44009 is not set
+# CONFIG_driver_mmsimple is not set
+# CONFIG_driver_mmsubstate is not set
+# CONFIG_driver_mpu9250 is not set
+# CONFIG_driver_s5851a is not set
+# CONFIG_driver_scd4x is not set
+# CONFIG_driver_sen5x is not set
+# CONFIG_driver_sen66 is not set
+# CONFIG_driver_veml6075 is not set
+CONFIG_driver_ssd1306=y
+CONFIG_driver_ssd1306_width=128
+CONFIG_driver_ssd1306_height=32
+CONFIG_driver_ssd1306_mode_vertical=y
+# CONFIG_driver_ssd1306_mode_horizontal is not set
+CONFIG_driver_ssd1306_i2c_name="softi2c"
+# CONFIG_driver_tsl2591 is not set
+CONFIG_driver_softi2c=y
+
+#
+# SoftI2C Configuration
+#
+CONFIG_driver_softi2c_scl="a1"
+CONFIG_driver_softi2c_sda="a0"
+# CONFIG_driver_softi2c_pullup_none is not set
+CONFIG_driver_softi2c_pullup_dynamic_internal=y
diff --git a/src/app/forced-convection/Kconfig b/src/app/forced-convection/Kconfig
new file mode 100644
index 0000000..157728d
--- /dev/null
+++ b/src/app/forced-convection/Kconfig
@@ -0,0 +1,6 @@
+# Copyright 2026 Birte Kristina Friesel
+#
+# SPDX-License-Identifier: CC0-1.0
+
+prompt "Forced Convection"
+depends on loop && !wakeup
diff --git a/src/app/forced-convection/Makefile.inc b/src/app/forced-convection/Makefile.inc
new file mode 100644
index 0000000..538ac69
--- /dev/null
+++ b/src/app/forced-convection/Makefile.inc
@@ -0,0 +1,9 @@
+# vim:ft=make
+#
+# Copyright 2026 Birte Kristina Friesel
+#
+# SPDX-License-Identifier: CC0-1.0
+
+ifdef app
+ loop = 1
+endif
diff --git a/src/app/forced-convection/main.cc b/src/app/forced-convection/main.cc
new file mode 100644
index 0000000..052e3fc
--- /dev/null
+++ b/src/app/forced-convection/main.cc
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2026 Birte Kristina Friesel
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+#include "arch.h"
+#include "driver/adc.h"
+#include "driver/gpio.h"
+#include "driver/stdout.h"
+#include "driver/i2c.h"
+#include "driver/soft_i2c.h"
+#include "driver/lm75.h"
+#include "driver/ssd1306.h"
+#include "lib/pixelfont/pixeloperator_mirrored.h"
+#include "object/framebuffer.h"
+
+
+#define shift_ser GPIO::d8
+#define shift_clk GPIO::d4
+#define shift_latch GPIO::d12
+#define shift_en GPIO::d7
+
+#define PWM1 OCR2A
+#define PWM2 OCR2B
+#define PWM3 OCR0A
+#define PWM4 OCR0B
+
+#define PWM1_EN _BV(5)
+#define PWM2_EN _BV(3)
+#define PWM3_EN _BV(0)
+#define PWM4_EN _BV(7)
+
+unsigned char graph[88];
+unsigned char graph_offset = 0;
+
+void loop(void)
+{
+ static int seconds = 0;
+ static int fan_speed = 0;
+ gpio.led_on(0);
+ float temp = lm75.getTemp();
+
+ if (temp < 25) {
+ PWM1 = 0;
+ PWM2 = 0;
+ PWM3 = 0;
+ PWM4 = 0;
+ TCCR0A = 0;
+ TCCR2A = 0;
+ TCCR0B = 0;
+ TCCR2B = 0;
+ fan_speed = 0;
+ }
+ else if (temp >= 30) {
+ PWM1 = 255;
+ PWM2 = 255;
+ PWM3 = 255;
+ PWM4 = 255;
+ TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
+ TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
+ TCCR0B = _BV(CS00);
+ TCCR2B = _BV(CS20);
+ fan_speed = 100;
+ }
+
+ if (seconds++ == 60) {
+ if (temp < 20) {
+ graph[graph_offset ] = 0;
+ }
+ else if (temp > 40) {
+ graph[graph_offset ] = 31;
+ }
+ else {
+ graph[graph_offset] = (temp - 20) * 1.5;
+ }
+ seconds = 0;
+ graph_offset = (graph_offset + 1) % (sizeof(graph) / sizeof(graph[0]));
+ }
+
+ uint16_t vcc = adc.getVCC_mV() - 200;
+
+ fb.clear();
+ fb.setFont(pixeloperator_mirrored);
+ fb.setPos(88, 0);
+ fb << temp << "c";
+ fb.setPos(88, 16);
+ fb << vcc/1000 << "." << (vcc%1000)/100 << (vcc%100)/10 << "V";
+ fb.setPos(88, 24);
+ fb << fan_speed << "%";
+
+ for (unsigned char i = 0; i < (sizeof(graph) / sizeof(graph[0])); i++) {
+ unsigned char column_value = graph[(graph_offset + i) % (sizeof(graph) / sizeof(graph[0]))];
+ fb.data[i*4 + 3 - (column_value/8)] = 1 << ( 7 - column_value%8);
+ }
+ ssd1306.showImage(fb.data, fb.width * fb.height / 8);
+
+ kout << "temperature_celsius: ";
+ kout.printf_float(temp);
+ kout << endl;
+ gpio.led_off(0);
+}
+
+int main(void)
+{
+ arch.setup();
+ gpio.setup();
+ kout.setup();
+
+ gpio.led_on(0);
+
+ /*
+ * Ensure that the SSD1306 OLED display gets a clean reset / power cycle
+ */
+
+ gpio.output(GPIO::a2, 0);
+ gpio.output(GPIO::a3, 0);
+
+ arch.delay_ms(50);
+
+ gpio.write(GPIO::a2, 1);
+ gpio.write(GPIO::a3, 0);
+
+ arch.delay_ms(50);
+
+ if (i2c.setup() != 0) {
+ kout << "I2C setup FAILED" << endl;
+ return 1;
+ }
+ kout << "I2C setup OK" << endl;
+
+ if (softi2c.setup() != 0) {
+ kout << "SoftI2C setup FAILED" << endl;
+ return 1;
+ }
+ kout << "SoftI2C setup OK" << endl;
+
+ lm75.setOS(30);
+ lm75.setHyst(25);
+ ssd1306.init();
+
+ fb.setFont(pixeloperator_mirrored);
+
+ gpio.output(shift_ser, 0);
+ gpio.output(shift_clk, 0);
+ gpio.output(shift_latch, 0);
+ gpio.output(shift_en, 0);
+
+ gpio.output(GPIO::pd3, 0); // OC2B - D3
+ gpio.output(GPIO::pd5, 0); // OC0B - D5
+ gpio.output(GPIO::pd6, 0); // OC0A - D6
+ gpio.output(GPIO::pb3, 0); // OC2A - D11
+
+ // m4a m2a m1a m1b m2b m3a m4b m3b
+ uint8_t shift_out = 0b10101001;
+
+ for (unsigned int i = 0; i < 8; i++) {
+ gpio.write(shift_ser, shift_out & (1<<i));
+ gpio.write(shift_clk, 1);
+ gpio.write(shift_clk, 0);
+ }
+ gpio.write(shift_latch, 1);
+ gpio.write(shift_latch, 0);
+
+ gpio.led_off(0);
+
+ arch.idle_loop();
+
+ return 0;
+}