diff --git a/prosjekt.X/command-handler.c b/prosjekt.X/command-handler.c index 347043c..25ab39e 100644 --- a/prosjekt.X/command-handler.c +++ b/prosjekt.X/command-handler.c @@ -1,4 +1,5 @@ #include "command-handler.h" +#include "fan-speed.h" // Initialize empty, global command context volatile command_context_t context = {UNKNOWN_COMMAND, SRC_NONE, FAN_NONE, @@ -126,7 +127,7 @@ void parse_command(uint8_t command[], uint8_t command_len) { } // Store the parameter - param = command[2]; + param = command[1]; context.conf = param; @@ -148,8 +149,8 @@ void parse_command(uint8_t command[], uint8_t command_len) { uint8_t bytes[2]; } config_value; - config_value.bytes[0] = command[3]; - config_value.bytes[1] = command[4]; + config_value.bytes[0] = command[2]; + config_value.bytes[1] = command[3]; // Store the value context.conf_val = config_value.value; @@ -168,6 +169,10 @@ uint8_t route_command(int pos) { // Set the flag to store it in the EEPROM store_config = true; + return 0; + break; + case CNF_NONE: + return 0; break; } break; @@ -197,6 +202,9 @@ uint8_t route_command(int pos) { case READ_VOLTAGE: { + // Validate that pos is within range + if (pos >= 2) { return 0; } + // Create a union to store the data union { int16_t v; @@ -220,7 +228,7 @@ uint8_t route_command(int pos) { } // Send the data - return voltage.bytes[pos]; + return voltage.bytes[1-pos]; } case READ_TERMPERATURE: { @@ -234,19 +242,51 @@ uint8_t route_command(int pos) { } break; case READ_FAN_SPEED: + // Validate that pos is within range + if (pos >= 2) { return 0; } + + // Union to hold the u16 if (context.fan == FAN1) { - return fan1_history[0]; + union { + uint16_t val; + uint8_t bytes[2]; + } speed; + + speed.val = fan1_history[fan1_history_index]; + + return speed.bytes[1-pos]; } else if (context.fan == FAN2) { - return fan2_history[0]; + union { + uint16_t val; + uint8_t bytes[2]; + } speed; + + speed.val = fan2_history[fan2_history_index]; + + return speed.bytes[1-pos]; } else { return 0; } break; case READ_BULK_FAN_SPEED: if (context.fan == FAN1) { - return fan1_history[pos]; + // Validate that pos is valid, if not return 0 + if (pos >= 512) { return 0; } + + // Calculate the index position + int16_t index = fan1_history_index - pos; + if (index < 0) { index = 511-pos; } + + return fan1_history[index]; } else if (context.fan == FAN2) { - return fan2_history[pos]; + // Validate that pos is valid, if not return 0 + if (pos >= 512) { return 0; } + + // Calculate the index position + int16_t index = fan2_history_index - pos; + if (index < 0) { index = 511-pos; } + + return fan2_history[index]; } else { return 0; } @@ -258,6 +298,7 @@ uint8_t route_command(int pos) { } else if (context.fan == FAN2) { memset(fan2_history, 0, sizeof(fan2_history)); } + return 0; break; case UNKNOWN_COMMAND: default: diff --git a/prosjekt.X/command-handler.h b/prosjekt.X/command-handler.h index cf0f428..8fbdd74 100644 --- a/prosjekt.X/command-handler.h +++ b/prosjekt.X/command-handler.h @@ -66,6 +66,9 @@ typedef struct { // Fan history variables extern volatile uint16_t fan1_history[512]; extern volatile uint16_t fan2_history[512]; +// Fan history index variable +extern volatile uint16_t fan1_history_index; +extern volatile uint16_t fan2_history_index; // Config extern volatile config_t config; diff --git a/prosjekt.X/fan_speeeed.c b/prosjekt.X/fan-speed.c similarity index 67% rename from prosjekt.X/fan_speeeed.c rename to prosjekt.X/fan-speed.c index 38540af..0fa2085 100644 --- a/prosjekt.X/fan_speeeed.c +++ b/prosjekt.X/fan-speed.c @@ -1,7 +1,7 @@ -#include "fan_speeeed.h" +#include "fan-speed.h" #include "uart.h" -uint16_t timer_period_ms = 1; +uint16_t timer_period_ms = 1000; uint16_t fan_speed = 0; volatile uint16_t fan1_edge_counter = 0; volatile uint16_t fan2_edge_counter = 0; @@ -10,18 +10,21 @@ volatile uint16_t fan2_edge_counter = 0; void init_TCA0() { TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm ; TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV1024_gc ; /* Sysclk /1024 */ - TCA0_update_period(timer_period_ms); } -void TCA0_update_period(uint16_t timer_period) { - TCA0.SINGLE.PERBUF = (F_CPU * (1 / timer_period) / 1024); /* F_CPU * F_IRQ / TCA_prescaler */ +void TCA0_update_period(uint16_t period_ms) { + float period_s = period_ms / 1E3; // Convert the ms to s + float frequency = 1/ period_s; // convert the period to a frequency + float perbuf_val = frequency * F_CPU / 1024; // F_IQR * F_CPU / TCA_prescaler + TCA0.SINGLE.PERBUF = (uint16_t)perbuf_val; + timer_period_ms = period_ms; } // COUNTINGS / TIME = FREQUENCY // FREQ / 2 = GIVES ACTUAL FREQ // FREQ * SEC-IN-A-MINUTE(60) / FAN-BLADES uint16_t RPM_calculation(uint16_t edge_counter, uint16_t time_ms) { - fan_speed = (edge_counter / time_ms); + fan_speed = (edge_counter / (float)((float)time_ms/1000.0) ); fan_speed = fan_speed/2; fan_speed = fan_speed * 60/5; edge_counter = 0; @@ -98,8 +101,25 @@ ISR(AC1_AC_vect){ // AC1 vec flag // TIMER INTERUPT ISR (TCA0_OVF_vect) { cli(); - RPM_calculation(fan1_edge_counter,timer_period_ms); - RPM_calculation(fan2_edge_counter,timer_period_ms); + + // Increment the index, or reset if it is at the top + if (fan1_history_index < 512) { + fan1_history_index++; + } else { + fan1_history_index = 0; + } + + if (fan2_history_index < 512) { + fan2_history_index++; + } else { + fan2_history_index = 0; + } + + // Calculate the fanspeed + fan1_history[fan1_history_index] = RPM_calculation(fan1_edge_counter, timer_period_ms); + fan2_history[fan2_history_index] = RPM_calculation(fan2_edge_counter, timer_period_ms); + + // Reset the edge counter fan1_edge_counter = 0; fan2_edge_counter = 0; TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm ; diff --git a/prosjekt.X/fan_speeeed.h b/prosjekt.X/fan-speed.h similarity index 75% rename from prosjekt.X/fan_speeeed.h rename to prosjekt.X/fan-speed.h index 46f3a39..60c77b3 100644 --- a/prosjekt.X/fan_speeeed.h +++ b/prosjekt.X/fan-speed.h @@ -15,7 +15,7 @@ extern "C" { #endif #include -#include +#include #include #include #include @@ -29,6 +29,14 @@ extern "C" { * and inspiration form practice 6 for TCA0 setup */ + + // Fan history variables + extern volatile uint16_t fan1_history[512]; + extern volatile uint16_t fan2_history[512]; + // Fan history index variable + extern volatile uint16_t fan1_history_index; + extern volatile uint16_t fan2_history_index; + // INITALICE TIMER COUNTER void init_TCA0(); @@ -45,7 +53,7 @@ extern "C" { // INIT AC0 TO COMPARE PD6 AND PD7 void init_AC0(); - // INIT AC1 TO COMPARE PD4 AND PD7 + // INIT AC1 TO COMPARE PD4 AND PD7 void init_AC1(); #ifdef __cplusplus diff --git a/prosjekt.X/i2c.h b/prosjekt.X/i2c.h index 1272b11..859df15 100644 --- a/prosjekt.X/i2c.h +++ b/prosjekt.X/i2c.h @@ -14,7 +14,6 @@ extern "C" { // Include the IO for I2C #include "command-handler.h" -#include "uart.h" #include #include #include diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index 7dfb0f0..5690960 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -4,28 +4,39 @@ * * Created on March 6, 2024, 12:34 PM */ -#include "uart.h" -#include "voltage.h" -#include -#define RTC_PERIOD (511) -#define DELAY_TIME 1000 -#include "eeprom.h" +#define F_CPU 4E6 + +// Include AVR specific libs #include +#include +#include + +// Include standard C libraries +#include #include #include #include -#define F_CPU 4E6 +#include + +// Include custom source files +#include "eeprom.h" +#include "voltage.h" #include "command-handler.h" #include "i2c.h" #include "themistor-temp.h" +#include "fan-speed.h" + +// Only enable UART when required for debugging +#ifdef ENABLE_UART #include "uart.h" -#include -#include -#include +#endif // Fan history variables volatile uint16_t fan1_history[512] = {0}; volatile uint16_t fan2_history[512] = {0}; +// Fan history index variable +volatile uint16_t fan1_history_index = 0; +volatile uint16_t fan2_history_index = 0; // Default config is 500ms sample rate volatile config_t config = {500}; @@ -33,24 +44,40 @@ volatile bool store_config = false; int main() { // Initialize functionality - init_uart((uint16_t)9600); ADC0_init(); - init_led(); + init_alarm_gpio(); init_i2c(); + + // Fanspeed + init_AC0(); + init_AC1(); + init_TCA0(); + TCA0_update_period(config.ms_fanspeed_sample_rate); + + // Only enable UART when required for debugging +#ifdef ENABLE_UART + init_uart((uint16_t)9600); stdout = &USART_stream; +#endif // Read the stored config struct config = read_struct_from_EEPROM(); - PORTB.DIRSET = PIN3_bm; - + // Enable interrupts sei(); while (1) { - // If we have made a config change, store it. + // If we have made a config change, store it and recalculate the period. if (store_config) { + TCA0_update_period(config.ms_fanspeed_sample_rate); write_struct_from_EEPROM(config); store_config = false; } } + + // Check the temperature, and start the alarm if required + uint16_t thermistor_voltage = thermistor_voltage_read(); + float temperature = calculate_thermistor_temp(thermistor_voltage); + bool start_alarm = voltage_threshold_bool(temperature, 40); + alert_voltage_threshold_exceeded(start_alarm); } diff --git a/prosjekt.X/nbproject/configurations.xml b/prosjekt.X/nbproject/configurations.xml index 46b7e18..aaaca26 100644 --- a/prosjekt.X/nbproject/configurations.xml +++ b/prosjekt.X/nbproject/configurations.xml @@ -6,11 +6,11 @@ projectFiles="true"> uart.h voltage.h - fan_speeeed.h themistor-temp.h command-handler.h eeprom.h i2c.h + fan-speed.h main.c uart.c voltage.c - fan_speeeed.c thermistor-temp.c command-handler.c i2c.c eeprom.c + fan-speed.c Makefile diff --git a/prosjekt.X/themistor-temp.h b/prosjekt.X/themistor-temp.h index aff338c..4aa960f 100644 --- a/prosjekt.X/themistor-temp.h +++ b/prosjekt.X/themistor-temp.h @@ -19,12 +19,15 @@ extern "C" { #include #include #include -#define R_T0 10000 +#define R_T0 100E3 #define T_0 298.15 #define B 3950 #define R_1 1000 #define ledpin PIN3_bm +// Takes inn messured value +#define ALERT_PIN PIN3_bm + // Takes inn messured value // Calculates the temperature in celcius // Returns the thermistor themperature @@ -36,8 +39,8 @@ bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp); void alert_voltage_threshold_exceeded(bool voltage_threshold_bool); -// Initialise led -void init_led(); +// Initialise alarm GPIO +void init_alarm_gpio(); #ifdef __cplusplus } diff --git a/prosjekt.X/thermistor-temp.c b/prosjekt.X/thermistor-temp.c index 092acc9..b7440ea 100644 --- a/prosjekt.X/thermistor-temp.c +++ b/prosjekt.X/thermistor-temp.c @@ -1,8 +1,8 @@ #include "themistor-temp.h" -void init_led(){ - PORTB.DIRSET = ledpin; +void init_alarm_gpio(){ + PORTB.DIRSET = ALERT_PIN; } // The code is inspired by "Arduino thermistor guide" by valtentina Vogelman, 1 november 2023 @@ -14,7 +14,7 @@ float calculate_thermistor_temp(float thermistor_voltage){ float ln; float T_thermistor; float V_thermistor; - #define V_TOT 5 + #define V_TOT 3.3 // Calculate Voltage over thermistor V_thermistor = (V_TOT/1024)*thermistor_voltage; @@ -44,9 +44,9 @@ bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp){ //print if the maximum threshold is exceeded. void alert_voltage_threshold_exceeded(bool voltage_threshold_bool){ if (voltage_threshold_bool){ - printf("Error: maximum temperature exceeded"); - PORTB.OUTSET = ledpin; + //printf("Error: maximum temperature exceeded"); + PORTB.OUTSET = ALERT_PIN; } else{ - PORTB.OUTCLR = ledpin; + PORTB.OUTCLR = ALERT_PIN; } } diff --git a/prosjekt.X/voltage.c b/prosjekt.X/voltage.c index 3a7936a..dc18c8e 100644 --- a/prosjekt.X/voltage.c +++ b/prosjekt.X/voltage.c @@ -3,10 +3,10 @@ void ADC0_init(void) { /* Initializing ADC0 pin*/ - /*Voltage reading on pin pd6*/ - PORTD.PIN6CTRL &= ~PORT_ISC_gm; - PORTD.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */ - PORTD.PIN6CTRL &= PORT_PULLUPEN_bm; + /*Voltage reading on pin pd2*/ + PORTD.PIN2CTRL &= ~PORT_ISC_gm; + PORTD.PIN2CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */ + PORTD.PIN2CTRL &= PORT_PULLUPEN_bm; /* Thermistor */ PORTD.PIN3CTRL &= ~PORT_ISC_gm; @@ -43,7 +43,7 @@ uint16_t thermistor_voltage_read() { } // Gets the value over thermistor uint16_t external_voltage_read() { - ADC0.MUXPOS = 0x06; // Read PD6 + ADC0.MUXPOS = 0x02; // Read PD6 uint16_t adc_val = ADC0_read(); return adc_val;