Unverified Commit dfd89d22 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

add preliminary fan control application (wip)

parent d7525456
Loading
Loading
Loading
Loading
Loading
+101 −0
Original line number Diff line number Diff line
#
# 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
+6 −0
Original line number Diff line number Diff line
# Copyright 2026 Birte Kristina Friesel
#
# SPDX-License-Identifier: CC0-1.0

prompt "Forced Convection"
depends on loop && !wakeup
+9 −0
Original line number Diff line number Diff line
# vim:ft=make
#
# Copyright 2026 Birte Kristina Friesel
#
# SPDX-License-Identifier: CC0-1.0

ifdef app
	loop = 1
endif
+169 −0
Original line number Diff line number Diff line
/*
 * 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;
}