Compare commits
No commits in common. "main" and "thermistor-temp" have entirely different histories.
main
...
thermistor
@ -1,307 +0,0 @@
|
|||||||
#include "command-handler.h"
|
|
||||||
#include "fan-speed.h"
|
|
||||||
|
|
||||||
// Initialize empty, global command context
|
|
||||||
volatile command_context_t context = {UNKNOWN_COMMAND, SRC_NONE, FAN_NONE,
|
|
||||||
CNF_NONE};
|
|
||||||
|
|
||||||
void parse_command(uint8_t command[], uint8_t command_len) {
|
|
||||||
///////////////////////
|
|
||||||
// Command selection //
|
|
||||||
///////////////////////
|
|
||||||
|
|
||||||
// Validate that we have a command
|
|
||||||
if (command_len < 1) {
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the first byte, which contains the command
|
|
||||||
uint8_t command_byte = command[0];
|
|
||||||
|
|
||||||
// Figure out which command to run
|
|
||||||
switch (command_byte) {
|
|
||||||
case 0x11: // Read config
|
|
||||||
context.command = READ_CONFIG;
|
|
||||||
break;
|
|
||||||
case 0x12: // Read voltage
|
|
||||||
context.command = READ_VOLTAGE;
|
|
||||||
break;
|
|
||||||
case 0x13: // Read temperature
|
|
||||||
context.command = READ_TERMPERATURE;
|
|
||||||
break;
|
|
||||||
case 0x14: // Read current fan speed
|
|
||||||
context.command = READ_FAN_SPEED;
|
|
||||||
break;
|
|
||||||
case 0x15: // Read bulk fan speed
|
|
||||||
context.command = READ_BULK_FAN_SPEED;
|
|
||||||
break;
|
|
||||||
case 0x21: // Write config
|
|
||||||
context.command = WRITE_CONFIG;
|
|
||||||
break;
|
|
||||||
case 0x22: // Clear stored fan speed data
|
|
||||||
context.command = CLEAR_BULK_FAN_SPEED;
|
|
||||||
break;
|
|
||||||
default: // Unrecognized command
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
// First parameter selection //
|
|
||||||
///////////////////////////////
|
|
||||||
|
|
||||||
// Check if the command does not require a parameter. If it does not, return.
|
|
||||||
if (context.command == READ_TERMPERATURE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that we have a second parameter, else requirements for command are
|
|
||||||
// not fulfilled. return unknown command.
|
|
||||||
if (command_len < 2) {
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the parameter
|
|
||||||
uint8_t param = command[1];
|
|
||||||
|
|
||||||
// Extract the parameter. Parameter is dependent on command
|
|
||||||
switch (command[0]) {
|
|
||||||
// Configuration parameters
|
|
||||||
case 0x11: // Read config
|
|
||||||
case 0x21: // Write config
|
|
||||||
if (param == 0x01) {
|
|
||||||
context.conf = SAMPLE_TIME;
|
|
||||||
} else {
|
|
||||||
context.conf = CNF_NONE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Voltage parameters
|
|
||||||
case 0x12: // Read voltage
|
|
||||||
if (param == 0x01) {
|
|
||||||
context.src_voltage = SRC_INTERNAL;
|
|
||||||
} else if (param == 0x02) {
|
|
||||||
context.src_voltage = SRC_EXTRNAL;
|
|
||||||
} else if (param == 0x03) {
|
|
||||||
context.src_voltage = SRC_THERMISTOR;
|
|
||||||
} else {
|
|
||||||
context.src_voltage = SRC_NONE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Fan parameters
|
|
||||||
case 0x14: // Read current fan speed
|
|
||||||
case 0x15: // Read bulk fan speed
|
|
||||||
case 0x22: // Clear stored fan speed data
|
|
||||||
if (param == 0x01) {
|
|
||||||
context.fan = FAN1;
|
|
||||||
} else if (param == 0x02) {
|
|
||||||
context.fan = FAN2;
|
|
||||||
} else {
|
|
||||||
context.fan = FAN_NONE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// This should never be reached
|
|
||||||
default: // Unrecognized command
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////
|
|
||||||
// Third parameter selection //
|
|
||||||
/////////////////////////////////
|
|
||||||
|
|
||||||
// Check if the command does not require a second parameter. If it does not,
|
|
||||||
// return. Only config write requires a second parameter.
|
|
||||||
if (context.command != WRITE_CONFIG) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that we have a third parameter, else requirements for command are
|
|
||||||
// not fulfilled. return unknown command.
|
|
||||||
if (command_len < 3) {
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the parameter
|
|
||||||
param = command[1];
|
|
||||||
|
|
||||||
context.conf = param;
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Fourth parameter selection //
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
// Validate that we have a fourth parameter, else requirements for command are
|
|
||||||
// not fulfilled. return unknown command. Second parameter is u16, thus two bytes.
|
|
||||||
if (command_len < 4) {
|
|
||||||
context.command = UNKNOWN_COMMAND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the value
|
|
||||||
union {
|
|
||||||
uint16_t value;
|
|
||||||
uint8_t bytes[2];
|
|
||||||
} config_value;
|
|
||||||
|
|
||||||
config_value.bytes[0] = command[2];
|
|
||||||
config_value.bytes[1] = command[3];
|
|
||||||
|
|
||||||
// Store the value
|
|
||||||
context.conf_val = config_value.value;
|
|
||||||
|
|
||||||
// exit
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t route_command(int pos) {
|
|
||||||
switch (context.command) {
|
|
||||||
case WRITE_CONFIG:
|
|
||||||
switch (context.conf) {
|
|
||||||
case SAMPLE_TIME:
|
|
||||||
// Overwrite the config value
|
|
||||||
config.ms_fanspeed_sample_rate = context.conf_val;
|
|
||||||
|
|
||||||
// Set the flag to store it in the EEPROM
|
|
||||||
store_config = true;
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case CNF_NONE:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case READ_CONFIG:
|
|
||||||
{
|
|
||||||
switch (context.conf) {
|
|
||||||
case SAMPLE_TIME:
|
|
||||||
{
|
|
||||||
// Validate that pos is within the valid range
|
|
||||||
if (pos >= 2) { return 0x00; }
|
|
||||||
|
|
||||||
// Config only has one parameter so we sent that parameter
|
|
||||||
// Create a union to store the data
|
|
||||||
union {
|
|
||||||
uint16_t value;
|
|
||||||
uint8_t bytes[2];
|
|
||||||
} config_value;
|
|
||||||
config_value.value = config.ms_fanspeed_sample_rate;
|
|
||||||
|
|
||||||
// Return the corresponding data byte
|
|
||||||
return config_value.bytes[1-pos];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
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;
|
|
||||||
uint8_t bytes[2];
|
|
||||||
} voltage;
|
|
||||||
|
|
||||||
// Figure out which voltage source to read
|
|
||||||
switch (context.src_voltage) {
|
|
||||||
case SRC_INTERNAL:
|
|
||||||
voltage.v = internal_voltage_read();
|
|
||||||
break;
|
|
||||||
case SRC_EXTRNAL:
|
|
||||||
voltage.v = external_voltage_read();
|
|
||||||
break;
|
|
||||||
case SRC_THERMISTOR:
|
|
||||||
voltage.v = thermistor_voltage_read();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0xFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the data
|
|
||||||
return voltage.bytes[1-pos];
|
|
||||||
}
|
|
||||||
case READ_TERMPERATURE:
|
|
||||||
{
|
|
||||||
uint16_t v_therm = thermistor_voltage_read();
|
|
||||||
union {
|
|
||||||
int16_t temp;
|
|
||||||
uint8_t bytes[2];
|
|
||||||
} temperature;
|
|
||||||
temperature.temp = (int16_t) ( calculate_thermistor_temp(v_therm) * 1000 );
|
|
||||||
return temperature.bytes[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) {
|
|
||||||
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) {
|
|
||||||
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) {
|
|
||||||
// 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) {
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CLEAR_BULK_FAN_SPEED:
|
|
||||||
// Overwrite the content of the desired fan array with zeroes
|
|
||||||
if (context.fan == FAN1) {
|
|
||||||
memset(fan1_history, 0, sizeof(fan1_history));
|
|
||||||
} else if (context.fan == FAN2) {
|
|
||||||
memset(fan2_history, 0, sizeof(fan2_history));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case UNKNOWN_COMMAND:
|
|
||||||
default:
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* File: command-handler.h
|
|
||||||
* Author: Sebastian H. Gabrielli
|
|
||||||
*
|
|
||||||
* Created on March 6, 2024, 12:43 PM
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COMMAND_HANDLER_H
|
|
||||||
#define COMMAND_HANDLER_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "eeprom.h"
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "voltage.h"
|
|
||||||
#include "themistor-temp.h"
|
|
||||||
|
|
||||||
// Enum of all valid command types
|
|
||||||
typedef enum {
|
|
||||||
WRITE_CONFIG = 0x21, // Change the configuration
|
|
||||||
READ_CONFIG = 0x11, // Read, and print the current configuration
|
|
||||||
READ_VOLTAGE = 0x12, // Read, and print a voltage
|
|
||||||
READ_TERMPERATURE = 0x13, // Read, and print the temperature
|
|
||||||
READ_FAN_SPEED = 0x14, // Read, and print the current fan speed
|
|
||||||
READ_BULK_FAN_SPEED = 0x15, // Read, and print the stored back fan speed data
|
|
||||||
CLEAR_BULK_FAN_SPEED = 0x22, // Clear the buffer of stored fan speed data
|
|
||||||
UNKNOWN_COMMAND // An unrecognized command has been sent
|
|
||||||
} command_t;
|
|
||||||
|
|
||||||
// Enum of all valid voltage sources
|
|
||||||
typedef enum {
|
|
||||||
SRC_INTERNAL, // Internal volage
|
|
||||||
SRC_EXTRNAL, // External voltage
|
|
||||||
SRC_THERMISTOR, // Thermistor voltage
|
|
||||||
SRC_NONE // No voltage source selected
|
|
||||||
} src_voltage_t;
|
|
||||||
|
|
||||||
// Enum of all valid config options
|
|
||||||
// TODO: Move into config header file
|
|
||||||
typedef enum {
|
|
||||||
SAMPLE_TIME = 0x01, // Time between each fan speed sample
|
|
||||||
CNF_NONE, // No config option
|
|
||||||
} config_option_t;
|
|
||||||
|
|
||||||
// Enum of all valid fans
|
|
||||||
// TODO: Consider moving into it's own fan page
|
|
||||||
typedef enum {
|
|
||||||
FAN1 = 1, // The first fan
|
|
||||||
FAN2 = 2, // The second fan
|
|
||||||
FAN_NONE // No fan
|
|
||||||
} fans_t;
|
|
||||||
|
|
||||||
// Struct with command context
|
|
||||||
typedef struct {
|
|
||||||
command_t command; // The command to execute
|
|
||||||
src_voltage_t src_voltage; // The selected voltage source
|
|
||||||
fans_t fan; // The selected fan
|
|
||||||
config_option_t conf; // The configuration option to cange
|
|
||||||
uint16_t conf_val; // The value of the config option to change
|
|
||||||
} command_context_t;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
extern volatile bool store_config;
|
|
||||||
|
|
||||||
// Parses the input string and outputs one of the valid commands
|
|
||||||
void parse_command(uint8_t *command, uint8_t command_len);
|
|
||||||
|
|
||||||
// Routes the provided command to the appropriate function to handle it
|
|
||||||
// If the command is a read command it then returns the current byte.
|
|
||||||
// The position is the byte to read when multiple bytes are being read.
|
|
||||||
uint8_t route_command(int pos);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* COMMAND_HANDLER_H */
|
|
||||||
Binary file not shown.
@ -1,42 +0,0 @@
|
|||||||
#include "eeprom.h"
|
|
||||||
|
|
||||||
// The start address for the controller data
|
|
||||||
uint16_t EEMEM start_address_controller = 0x1400;
|
|
||||||
|
|
||||||
// Checks if the EEPROM memory is ready to be written in and waits until it is.
|
|
||||||
void check_eeprom_is_ready(){
|
|
||||||
while(1){
|
|
||||||
if (eeprom_is_ready()){
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void write_struct_from_EEPROM(config_t write_struct){
|
|
||||||
// Calculate the required storage size
|
|
||||||
uint8_t struct_size = sizeof(write_struct);
|
|
||||||
|
|
||||||
// Wait for the EEPROM to be ready
|
|
||||||
check_eeprom_is_ready();
|
|
||||||
|
|
||||||
// Update the stored config stuct
|
|
||||||
eeprom_update_block((void*) &write_struct,(void*) &start_address_controller, struct_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
config_t read_struct_from_EEPROM(){
|
|
||||||
// Create a config struct to hold the received data
|
|
||||||
config_t read_struct = { 0 };
|
|
||||||
uint8_t struct_size = sizeof(read_struct);
|
|
||||||
|
|
||||||
// Wait for the EEPROM to be ready
|
|
||||||
check_eeprom_is_ready();
|
|
||||||
|
|
||||||
// Read the data from the EEPROM
|
|
||||||
eeprom_read_block((void *) &read_struct,(void*) &start_address_controller, struct_size);
|
|
||||||
|
|
||||||
// Return the data
|
|
||||||
return read_struct;
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* File: eeprom.h
|
|
||||||
* Author: Helle Augland Grasmo, Sebastian H. Gabrielli
|
|
||||||
*
|
|
||||||
* Created on 06 March 2024, 15:30
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EEPROM_H
|
|
||||||
#define EEPROM_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <avr/eeprom.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
// The code is inspired by "EEPROM handling" form avr-libc
|
|
||||||
// web link: https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html
|
|
||||||
|
|
||||||
|
|
||||||
// Struct for information on the controller.
|
|
||||||
typedef struct {
|
|
||||||
uint16_t ms_fanspeed_sample_rate;
|
|
||||||
} config_t;
|
|
||||||
|
|
||||||
// Check if EEPROM is ready to be written to
|
|
||||||
void check_eeprom_is_ready();
|
|
||||||
|
|
||||||
// Writes a config_t struct to the EEPROM
|
|
||||||
void write_struct_from_EEPROM(config_t write_struct);
|
|
||||||
|
|
||||||
// Read data from EEPROM and return it as a config_t struct
|
|
||||||
config_t read_struct_from_EEPROM();
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* EEPROM_H */
|
|
||||||
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
#include "fan-speed.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
void init_TCA0() {
|
|
||||||
TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm ;
|
|
||||||
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV1024_gc ; /* Sysclk /1024 */
|
|
||||||
}
|
|
||||||
|
|
||||||
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 / (float)((float)time_ms/1000.0) );
|
|
||||||
fan_speed = fan_speed/2;
|
|
||||||
fan_speed = fan_speed * 60/5;
|
|
||||||
edge_counter = 0;
|
|
||||||
return fan_speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_fan_gpio() {
|
|
||||||
// CONFIGURE PINS AS ANALOG INPUTS
|
|
||||||
|
|
||||||
// PIN FOR FAN 1
|
|
||||||
PORTD.DIRSET &= ~PIN6_bm;
|
|
||||||
PORTD.PIN6CTRL &= ~ PORT_ISC_gm;
|
|
||||||
PORTD.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;
|
|
||||||
|
|
||||||
// PIN FOR FAN 2
|
|
||||||
PORTD.DIRSET &= ~PIN4_bm;
|
|
||||||
PORTD.PIN4CTRL &= ~ PORT_ISC_gm ;
|
|
||||||
PORTD.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc;
|
|
||||||
|
|
||||||
// PIN FOR REFRENCE
|
|
||||||
PORTD.DIRSET &= PIN7_bm;
|
|
||||||
PORTD.PIN7CTRL &= ~ PORT_ISC_gm ;
|
|
||||||
PORTD.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_AC0(){
|
|
||||||
//Wincontroll disabled
|
|
||||||
AC0.CTRLB = 0x00;
|
|
||||||
|
|
||||||
//SELECT POSITIVE AND NEGATIVE INPUTS FOR COMPARRISON
|
|
||||||
// FAN USE PD6 COMPARE WITH PD3
|
|
||||||
AC0.MUXCTRL = AC_MUXPOS_AINP3_gc | AC_MUXNEG_AINN2_gc;
|
|
||||||
|
|
||||||
// ENABLE AC BY WRITING 1 TO ENABLE BIT IN ACN.CTRLA
|
|
||||||
AC0.CTRLA = AC_ENABLE_bm | AC_INTMODE_NORMAL_POSEDGE_gc | AC_OUTEN_bm;
|
|
||||||
|
|
||||||
// TURN ON INTERUPT
|
|
||||||
AC0.INTCTRL = 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_AC1(){
|
|
||||||
//Wincontroll disabled
|
|
||||||
AC1.CTRLB = 0x00;
|
|
||||||
|
|
||||||
//SELECT POSITIVE AND NEGATIVE INPUTS FOR COMPARRISON
|
|
||||||
// FAN USE PD4, COMPARE WITH PD3
|
|
||||||
AC1.MUXCTRL = AC_MUXPOS_AINP2_gc | AC_MUXNEG_AINN2_gc;
|
|
||||||
|
|
||||||
// ENABLE AC BY WRITING 1 TO ENABLE BIT IN ACN.CTRLA
|
|
||||||
AC1.CTRLA = AC_ENABLE_bm | AC_INTMODE_NORMAL_POSEDGE_gc | AC_OUTEN_bm;
|
|
||||||
|
|
||||||
// TURN ON INTERUPT
|
|
||||||
AC1.INTCTRL = 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(AC0_AC_vect){ // AC0 vec flag
|
|
||||||
cli();
|
|
||||||
fan1_edge_counter++;
|
|
||||||
AC0.STATUS |= 0x10; //CMP flag to 0
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(AC1_AC_vect){ // AC1 vec flag
|
|
||||||
cli();
|
|
||||||
fan2_edge_counter++;
|
|
||||||
AC1.STATUS |= 0x10; //CMP flag to 0
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TIMER INTERUPT
|
|
||||||
ISR (TCA0_OVF_vect) {
|
|
||||||
cli();
|
|
||||||
|
|
||||||
// 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 ;
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* File: fanseeeed.h
|
|
||||||
* Author: inami, Helle Augland Grasmo
|
|
||||||
*
|
|
||||||
* Created on 13. mars 2024, 13:38
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FANSEEEED_H
|
|
||||||
#define FANSEEEED_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
The code has inspiration from "Getting Started with Analog comparator(AC)" by Microchip for setting up analog comparrator.
|
|
||||||
* web link: https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ApplicationNotes/ApplicationNotes/TB3211-Getting-Started-with-AC-DS90003211.pdf
|
|
||||||
* 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();
|
|
||||||
|
|
||||||
// UPDATE TIMER PERIOD
|
|
||||||
void TCA0_update_period_ms (uint16_t timer_period);
|
|
||||||
|
|
||||||
// TAKES INN A TIME AND A THE COUNTED FAN DIPS
|
|
||||||
// RETURNS THE RPM OF THE FAN
|
|
||||||
uint16_t RPM_calculation(uint16_t edge_counter, uint16_t time_ms);
|
|
||||||
|
|
||||||
// INITIALISING FAN PORTS
|
|
||||||
void init_fan_gpio();
|
|
||||||
|
|
||||||
// INIT AC0 TO COMPARE PD6 AND PD7
|
|
||||||
void init_AC0();
|
|
||||||
|
|
||||||
// INIT AC1 TO COMPARE PD4 AND PD7
|
|
||||||
void init_AC1();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* FANSEEEED_H */
|
|
||||||
|
|
||||||
125
prosjekt.X/i2c.c
125
prosjekt.X/i2c.c
@ -1,125 +0,0 @@
|
|||||||
#include "i2c.h"
|
|
||||||
#include "command-handler.h"
|
|
||||||
|
|
||||||
// Basic I2C handling structure is heavily inspired by:
|
|
||||||
// https://github.com/microchip-pic-avr-examples/avr128db48-bare-metal-twi-mplab/blob/master/twi-client.X/peripherals/TWI/TWI_client.c
|
|
||||||
|
|
||||||
// We need to keep track of if the stop confition is in regards to a write or
|
|
||||||
// read request
|
|
||||||
volatile bool last_action_write = false;
|
|
||||||
|
|
||||||
// Buffer to hold the received data
|
|
||||||
volatile uint8_t i2c_recv_buf[I2C_RECV_BUF_SIZE] = {0};
|
|
||||||
// Counter to know which datapoint we're on
|
|
||||||
volatile uint8_t i2c_recv_len = 0;
|
|
||||||
|
|
||||||
void init_i2c(void) {
|
|
||||||
// Pin setup
|
|
||||||
PORTA.DIRSET = PIN2_bm | PIN3_bm;
|
|
||||||
PORTA.PINCTRLUPD = PIN2_bm | PIN3_bm;
|
|
||||||
|
|
||||||
// Enable operating in debug
|
|
||||||
TWI0.DBGCTRL = TWI_DBGRUN_bm;
|
|
||||||
|
|
||||||
// Initialize the control A register
|
|
||||||
TWI0.CTRLA = TWI_INPUTLVL_I2C_gc // I2C voltage transition level
|
|
||||||
| TWI_SDASETUP_4CYC_gc // Four clock cycles setup time
|
|
||||||
| TWI_SDAHOLD_50NS_gc // 50ns SDA hold time
|
|
||||||
| TWI_FMPEN_OFF_gc // Standard SPI timing
|
|
||||||
;
|
|
||||||
|
|
||||||
// The device's slave address
|
|
||||||
TWI0.SADDR = 0x42;
|
|
||||||
|
|
||||||
// Enable acting as a slave
|
|
||||||
TWI0.SCTRLA = TWI_DIEN_bm // Enable data interrupt
|
|
||||||
| TWI_APIEN_bm // Enable more interrupts
|
|
||||||
| TWI_PIEN_bm // Enable stop flag interrupt
|
|
||||||
| PIN2_bm // Respond to all TWI addresses
|
|
||||||
| TWI_ENABLE_bm // Enable acting as a slave
|
|
||||||
;
|
|
||||||
|
|
||||||
// Reset the received stuff
|
|
||||||
i2c_reset_recv();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset received counter and clear receive buffer
|
|
||||||
void i2c_reset_recv() {
|
|
||||||
i2c_recv_len = 0;
|
|
||||||
for (int i = 0; i < I2C_RECV_BUF_SIZE; i++) {
|
|
||||||
i2c_recv_buf[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_write_handler(uint8_t data) {
|
|
||||||
last_action_write = true;
|
|
||||||
|
|
||||||
// Validate that we are not overflowing the buffer
|
|
||||||
if (i2c_recv_len >= I2C_RECV_BUF_SIZE) { return; }
|
|
||||||
|
|
||||||
// Write the data to the receive buffer
|
|
||||||
i2c_recv_buf[i2c_recv_len] = data;
|
|
||||||
i2c_recv_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_read_handler() {
|
|
||||||
last_action_write = false;
|
|
||||||
TWI0.SDATA = route_command(i2c_recv_len);
|
|
||||||
i2c_recv_len++; // Increment the counter of the current amount of requests
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_stop_handler() {
|
|
||||||
if (last_action_write) {
|
|
||||||
// Parse the received command data
|
|
||||||
parse_command(i2c_recv_buf, i2c_recv_len);
|
|
||||||
|
|
||||||
// If the received command is a write only command we want to route it now.
|
|
||||||
if (i2c_recv_buf[0] == CLEAR_BULK_FAN_SPEED || i2c_recv_buf[0] == WRITE_CONFIG) {
|
|
||||||
route_command(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the buffer for future transmissions
|
|
||||||
i2c_reset_recv();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address received
|
|
||||||
ISR(TWI0_TWIS_vect) {
|
|
||||||
// Disable interrupts while handling I2C
|
|
||||||
cli();
|
|
||||||
|
|
||||||
// Check for the data interrupt flag
|
|
||||||
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
|
||||||
|
|
||||||
if (((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0) {
|
|
||||||
// Data write Controller -> Target
|
|
||||||
uint8_t data = TWI0.SDATA;
|
|
||||||
|
|
||||||
// Send the data to the write handler
|
|
||||||
i2c_write_handler(data);
|
|
||||||
} else {
|
|
||||||
// Data read Controller <- Target
|
|
||||||
i2c_read_handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acknowledge having received
|
|
||||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for address match or STOP
|
|
||||||
if (TWI0.SSTATUS & TWI_APIF_bm) {
|
|
||||||
|
|
||||||
if (TWI0.SSTATUS & TWI_AP_ADR_gc) {
|
|
||||||
// Address match, just send ack
|
|
||||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
|
||||||
} else {
|
|
||||||
// STOP condition received
|
|
||||||
i2c_stop_handler();
|
|
||||||
// Send ACK
|
|
||||||
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-enable interrupts
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* File: i2c.h
|
|
||||||
* Author: sebgab
|
|
||||||
*
|
|
||||||
* Created on March 6, 2024, 1:53 PM
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef I2C_H
|
|
||||||
#define I2C_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Include the IO for I2C
|
|
||||||
#include "command-handler.h"
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <util/twi.h>
|
|
||||||
|
|
||||||
// Received data buffer size
|
|
||||||
// The size is larger than any expected command length
|
|
||||||
#define I2C_RECV_BUF_SIZE 16
|
|
||||||
|
|
||||||
// Reset recv to initial state
|
|
||||||
void i2c_reset_recv();
|
|
||||||
|
|
||||||
// Initialize the I2C bus
|
|
||||||
void init_i2c(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* I2C_H */
|
|
||||||
@ -1,83 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* File: main.c
|
* File: main.c
|
||||||
* Author: Sebastian H. Gabrielli, Helle Augland Grasmo, Ina Min Rørnes
|
* Author: Sebastian H. Gabrielli
|
||||||
*
|
*
|
||||||
* Created on March 6, 2024, 12:34 PM
|
* Created on March 6, 2024, 12:34 PM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define F_CPU 4E6
|
#define F_CPU 4E6
|
||||||
|
|
||||||
// Include AVR specific libs
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <util/delay.h>
|
|
||||||
|
|
||||||
// Include standard C libraries
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// 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 "uart.h"
|
||||||
#endif
|
#include <util/delay.h>
|
||||||
|
#include <stdint.h>
|
||||||
// Fan history variables
|
#include "themistor-temp.h"
|
||||||
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};
|
|
||||||
volatile bool store_config = false;
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// Initialize functionality
|
|
||||||
ADC0_init();
|
|
||||||
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);
|
init_uart((uint16_t)9600);
|
||||||
stdout = &USART_stream;
|
stdout = &USART_stream;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read the stored config struct
|
|
||||||
config = read_struct_from_EEPROM();
|
|
||||||
|
|
||||||
// Enable interrupts
|
|
||||||
sei();
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// If we have made a config change, store it and recalculate the period.
|
printf("Hello, world!\n");
|
||||||
if (store_config) {
|
_delay_ms(500);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
@ -4,19 +4,13 @@
|
|||||||
<logicalFolder name="HeaderFiles"
|
<logicalFolder name="HeaderFiles"
|
||||||
displayName="Header Files"
|
displayName="Header Files"
|
||||||
projectFiles="true">
|
projectFiles="true">
|
||||||
<itemPath>uart.h</itemPath>
|
|
||||||
<itemPath>voltage.h</itemPath>
|
|
||||||
<itemPath>themistor-temp.h</itemPath>
|
<itemPath>themistor-temp.h</itemPath>
|
||||||
<itemPath>command-handler.h</itemPath>
|
<itemPath>uart.h</itemPath>
|
||||||
<itemPath>eeprom.h</itemPath>
|
|
||||||
<itemPath>i2c.h</itemPath>
|
|
||||||
<itemPath>fan-speed.h</itemPath>
|
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
<logicalFolder name="ExternalFiles"
|
<logicalFolder name="ExternalFiles"
|
||||||
displayName="Important Files"
|
displayName="Important Files"
|
||||||
projectFiles="true">
|
projectFiles="true">
|
||||||
<itemPath>Makefile</itemPath>
|
<itemPath>Makefile</itemPath>
|
||||||
<itemPath>prosjekt.mc3</itemPath>
|
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
<logicalFolder name="LinkerScript"
|
<logicalFolder name="LinkerScript"
|
||||||
displayName="Linker Files"
|
displayName="Linker Files"
|
||||||
@ -26,13 +20,8 @@
|
|||||||
displayName="Source Files"
|
displayName="Source Files"
|
||||||
projectFiles="true">
|
projectFiles="true">
|
||||||
<itemPath>main.c</itemPath>
|
<itemPath>main.c</itemPath>
|
||||||
<itemPath>uart.c</itemPath>
|
|
||||||
<itemPath>voltage.c</itemPath>
|
|
||||||
<itemPath>thermistor-temp.c</itemPath>
|
<itemPath>thermistor-temp.c</itemPath>
|
||||||
<itemPath>command-handler.c</itemPath>
|
<itemPath>uart.c</itemPath>
|
||||||
<itemPath>i2c.c</itemPath>
|
|
||||||
<itemPath>eeprom.c</itemPath>
|
|
||||||
<itemPath>fan-speed.c</itemPath>
|
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
<projectmakefile>Makefile</projectmakefile>
|
<projectmakefile>Makefile</projectmakefile>
|
||||||
@ -49,7 +38,7 @@
|
|||||||
<platform>2</platform>
|
<platform>2</platform>
|
||||||
</toolsSet>
|
</toolsSet>
|
||||||
<packs>
|
<packs>
|
||||||
<pack name="AVR-Dx_DFP" vendor="Microchip" version="2.4.286"/>
|
<pack name="AVR-Dx_DFP" vendor="Microchip" version="2.3.272"/>
|
||||||
</packs>
|
</packs>
|
||||||
<ScriptingSettings>
|
<ScriptingSettings>
|
||||||
</ScriptingSettings>
|
</ScriptingSettings>
|
||||||
@ -114,7 +103,6 @@
|
|||||||
</HI-TECH-COMP>
|
</HI-TECH-COMP>
|
||||||
<HI-TECH-LINK>
|
<HI-TECH-LINK>
|
||||||
<property key="additional-options-checksum" value=""/>
|
<property key="additional-options-checksum" value=""/>
|
||||||
<property key="additional-options-checksumAVR" value=""/>
|
|
||||||
<property key="additional-options-code-offset" value=""/>
|
<property key="additional-options-code-offset" value=""/>
|
||||||
<property key="additional-options-command-line" value=""/>
|
<property key="additional-options-command-line" value=""/>
|
||||||
<property key="additional-options-errata" value=""/>
|
<property key="additional-options-errata" value=""/>
|
||||||
@ -160,54 +148,7 @@
|
|||||||
<property key="remove-unused-sections" value="true"/>
|
<property key="remove-unused-sections" value="true"/>
|
||||||
</HI-TECH-LINK>
|
</HI-TECH-LINK>
|
||||||
<Tool>
|
<Tool>
|
||||||
<property key="AutoSelectMemRanges" value="auto"/>
|
|
||||||
<property key="communication.activationmode" value="nohv"/>
|
|
||||||
<property key="communication.interface" value="updi"/>
|
|
||||||
<property key="communication.speed" value="0,500"/>
|
|
||||||
<property key="debugoptions.debug-startup" value="Use system settings"/>
|
|
||||||
<property key="debugoptions.reset-behaviour" value="Use system settings"/>
|
|
||||||
<property key="debugoptions.useswbreakpoints" value="true"/>
|
<property key="debugoptions.useswbreakpoints" value="true"/>
|
||||||
<property key="event.recorder.debugger.behavior" value="Running"/>
|
|
||||||
<property key="event.recorder.enabled" value="false"/>
|
|
||||||
<property key="event.recorder.scvd.files" value=""/>
|
|
||||||
<property key="firmware.path"
|
|
||||||
value="Press to browse for a specific firmware version"/>
|
|
||||||
<property key="firmware.toolpack"
|
|
||||||
value="Press to select which tool pack to use"/>
|
|
||||||
<property key="firmware.update.action" value="firmware.update.use.latest"/>
|
|
||||||
<property key="freeze.timers" value="false"/>
|
|
||||||
<property key="lastid" value=""/>
|
|
||||||
<property key="memories.aux" value="false"/>
|
|
||||||
<property key="memories.bootflash" value="true"/>
|
|
||||||
<property key="memories.configurationmemory" value="true"/>
|
|
||||||
<property key="memories.configurationmemory2" value="true"/>
|
|
||||||
<property key="memories.dataflash" value="true"/>
|
|
||||||
<property key="memories.eeprom" value="true"/>
|
|
||||||
<property key="memories.exclude.configurationmemory" value="true"/>
|
|
||||||
<property key="memories.flashdata" value="true"/>
|
|
||||||
<property key="memories.id" value="true"/>
|
|
||||||
<property key="memories.instruction.ram.ranges"
|
|
||||||
value="${memories.instruction.ram.ranges}"/>
|
|
||||||
<property key="memories.programmemory" value="true"/>
|
|
||||||
<property key="memories.programmemory.ranges" value="0-ffff"/>
|
|
||||||
<property key="poweroptions.powerenable" value="false"/>
|
|
||||||
<property key="programmerToGoFilePath"
|
|
||||||
value="C:/Users/inami/Documents/mikrokontrollersystemer-prosjekt/prosjekt.X/debug/default/prosjekt_ptg"/>
|
|
||||||
<property key="programoptions.eraseb4program" value="true"/>
|
|
||||||
<property key="programoptions.preservedataflash" value="false"/>
|
|
||||||
<property key="programoptions.preservedataflash.ranges"
|
|
||||||
value="${memories.dataflash.default}"/>
|
|
||||||
<property key="programoptions.preserveeeprom" value="false"/>
|
|
||||||
<property key="programoptions.preserveeeprom.ranges" value="1400-15ff"/>
|
|
||||||
<property key="programoptions.preserveprogram.ranges" value=""/>
|
|
||||||
<property key="programoptions.preserveprogramrange" value="false"/>
|
|
||||||
<property key="programoptions.preserveuserid" value="false"/>
|
|
||||||
<property key="programoptions.programuserotp" value="false"/>
|
|
||||||
<property key="toolpack.updateoptions"
|
|
||||||
value="toolpack.updateoptions.uselatestoolpack"/>
|
|
||||||
<property key="toolpack.updateoptions.packversion"
|
|
||||||
value="Press to select which tool pack to use"/>
|
|
||||||
<property key="voltagevalue" value=""/>
|
|
||||||
</Tool>
|
</Tool>
|
||||||
<XC8-CO>
|
<XC8-CO>
|
||||||
<property key="coverage-enable" value=""/>
|
<property key="coverage-enable" value=""/>
|
||||||
@ -232,52 +173,7 @@
|
|||||||
<property key="wpo-lto" value="false"/>
|
<property key="wpo-lto" value="false"/>
|
||||||
</XC8-config-global>
|
</XC8-config-global>
|
||||||
<nEdbgTool>
|
<nEdbgTool>
|
||||||
<property key="AutoSelectMemRanges" value="auto"/>
|
|
||||||
<property key="communication.activationmode" value="nohv"/>
|
|
||||||
<property key="communication.interface" value="updi"/>
|
|
||||||
<property key="communication.speed" value="0,500"/>
|
|
||||||
<property key="debugoptions.debug-startup" value="Use system settings"/>
|
|
||||||
<property key="debugoptions.reset-behaviour" value="Use system settings"/>
|
|
||||||
<property key="debugoptions.useswbreakpoints" value="true"/>
|
<property key="debugoptions.useswbreakpoints" value="true"/>
|
||||||
<property key="event.recorder.debugger.behavior" value="Running"/>
|
|
||||||
<property key="event.recorder.enabled" value="false"/>
|
|
||||||
<property key="event.recorder.scvd.files" value=""/>
|
|
||||||
<property key="firmware.path"
|
|
||||||
value="Press to browse for a specific firmware version"/>
|
|
||||||
<property key="firmware.toolpack"
|
|
||||||
value="Press to select which tool pack to use"/>
|
|
||||||
<property key="firmware.update.action" value="firmware.update.use.latest"/>
|
|
||||||
<property key="freeze.timers" value="false"/>
|
|
||||||
<property key="lastid" value=""/>
|
|
||||||
<property key="memories.aux" value="false"/>
|
|
||||||
<property key="memories.bootflash" value="true"/>
|
|
||||||
<property key="memories.configurationmemory" value="true"/>
|
|
||||||
<property key="memories.configurationmemory2" value="true"/>
|
|
||||||
<property key="memories.dataflash" value="true"/>
|
|
||||||
<property key="memories.eeprom" value="true"/>
|
|
||||||
<property key="memories.exclude.configurationmemory" value="true"/>
|
|
||||||
<property key="memories.flashdata" value="true"/>
|
|
||||||
<property key="memories.id" value="true"/>
|
|
||||||
<property key="memories.instruction.ram.ranges"
|
|
||||||
value="${memories.instruction.ram.ranges}"/>
|
|
||||||
<property key="memories.programmemory" value="true"/>
|
|
||||||
<property key="memories.programmemory.ranges" value="0-ffff"/>
|
|
||||||
<property key="poweroptions.powerenable" value="false"/>
|
|
||||||
<property key="programoptions.eraseb4program" value="true"/>
|
|
||||||
<property key="programoptions.preservedataflash" value="false"/>
|
|
||||||
<property key="programoptions.preservedataflash.ranges"
|
|
||||||
value="${memories.dataflash.default}"/>
|
|
||||||
<property key="programoptions.preserveeeprom" value="false"/>
|
|
||||||
<property key="programoptions.preserveeeprom.ranges" value="1400-15ff"/>
|
|
||||||
<property key="programoptions.preserveprogram.ranges" value=""/>
|
|
||||||
<property key="programoptions.preserveprogramrange" value="false"/>
|
|
||||||
<property key="programoptions.preserveuserid" value="false"/>
|
|
||||||
<property key="programoptions.programuserotp" value="false"/>
|
|
||||||
<property key="toolpack.updateoptions"
|
|
||||||
value="toolpack.updateoptions.uselatestoolpack"/>
|
|
||||||
<property key="toolpack.updateoptions.packversion"
|
|
||||||
value="Press to select which tool pack to use"/>
|
|
||||||
<property key="voltagevalue" value=""/>
|
|
||||||
</nEdbgTool>
|
</nEdbgTool>
|
||||||
</conf>
|
</conf>
|
||||||
</confs>
|
</confs>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -19,15 +19,12 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#define R_T0 100E3
|
#define R_T0 10000
|
||||||
#define T_0 298.15
|
#define T_0 298.15
|
||||||
#define B 3950
|
#define B 3950
|
||||||
#define R_1 1000
|
#define R_1 1000
|
||||||
#define ledpin PIN3_bm
|
#define ledpin PIN3_bm
|
||||||
|
|
||||||
// Takes inn messured value
|
|
||||||
#define ALERT_PIN PIN3_bm
|
|
||||||
|
|
||||||
// Takes inn messured value
|
// Takes inn messured value
|
||||||
// Calculates the temperature in celcius
|
// Calculates the temperature in celcius
|
||||||
// Returns the thermistor themperature
|
// Returns the thermistor themperature
|
||||||
@ -39,8 +36,8 @@ bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp);
|
|||||||
|
|
||||||
void alert_voltage_threshold_exceeded(bool voltage_threshold_bool);
|
void alert_voltage_threshold_exceeded(bool voltage_threshold_bool);
|
||||||
|
|
||||||
// Initialise alarm GPIO
|
// Initialise led
|
||||||
void init_alarm_gpio();
|
void init_led();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,17 @@
|
|||||||
#include "themistor-temp.h"
|
#include "themistor-temp.h"
|
||||||
|
|
||||||
|
|
||||||
void init_alarm_gpio(){
|
void init_led(){
|
||||||
PORTB.DIRSET = ALERT_PIN;
|
PORTB.DIRSET = ledpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The code is inspired by "Arduino thermistor guide" by valtentina Vogelman, 1 november 2023
|
|
||||||
// https://www.build-electronic-circuits.com/arduino-thermistor/
|
|
||||||
|
|
||||||
float calculate_thermistor_temp(float thermistor_voltage){
|
float calculate_thermistor_temp(float thermistor_voltage){
|
||||||
float R_thermistor;
|
float R_thermistor;
|
||||||
float V_1;
|
float V_1;
|
||||||
float ln;
|
float ln;
|
||||||
float T_thermistor;
|
float T_thermistor;
|
||||||
float V_thermistor;
|
float V_thermistor;
|
||||||
#define V_TOT 3.3
|
#define V_TOT 5
|
||||||
// Calculate Voltage over thermistor
|
// Calculate Voltage over thermistor
|
||||||
V_thermistor = (V_TOT/1024)*thermistor_voltage;
|
V_thermistor = (V_TOT/1024)*thermistor_voltage;
|
||||||
|
|
||||||
@ -44,9 +41,9 @@ bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp){
|
|||||||
//print if the maximum threshold is exceeded.
|
//print if the maximum threshold is exceeded.
|
||||||
void alert_voltage_threshold_exceeded(bool voltage_threshold_bool){
|
void alert_voltage_threshold_exceeded(bool voltage_threshold_bool){
|
||||||
if (voltage_threshold_bool){
|
if (voltage_threshold_bool){
|
||||||
//printf("Error: maximum temperature exceeded");
|
printf("Error: maximum temperature exceeded");
|
||||||
PORTB.OUTSET = ALERT_PIN;
|
PORTB.OUTSET = ledpin;
|
||||||
} else{
|
} else{
|
||||||
PORTB.OUTCLR = ALERT_PIN;
|
PORTB.OUTCLR = ledpin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#include "themistor-temp.h"
|
|
||||||
|
|
||||||
|
|
||||||
void init_led(){
|
|
||||||
PORTB.DIRSET = ledpin;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
https://www.build-electronic-circuits.com/arduino-thermistor/
|
|
||||||
|
|
||||||
float calculate_thermistor_temp(float thermistor_voltage){
|
|
||||||
float R_thermistor;
|
|
||||||
float V_1;
|
|
||||||
float ln;
|
|
||||||
float T_thermistor;
|
|
||||||
float V_thermistor;
|
|
||||||
#define V_TOT 5
|
|
||||||
// Calculate Voltage over thermistor
|
|
||||||
V_thermistor = (V_TOT/1024)*thermistor_voltage;
|
|
||||||
|
|
||||||
// Voltage accross R_1
|
|
||||||
V_1 = V_TOT - V_thermistor;
|
|
||||||
|
|
||||||
// Calculate Thermistor resistanse
|
|
||||||
R_thermistor = (V_thermistor)/ (V_1 / R_1);
|
|
||||||
|
|
||||||
// Steinhart-Harts formula
|
|
||||||
ln = log(R_thermistor/R_T0);
|
|
||||||
T_thermistor = (1/ ((ln/B) + (1/T_0)));
|
|
||||||
|
|
||||||
// Temperatur in celcius
|
|
||||||
T_thermistor -= 273.15;
|
|
||||||
|
|
||||||
return T_thermistor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns error message if the messured thermistor temp is higher than
|
|
||||||
// Choosen max_temp
|
|
||||||
bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp){
|
|
||||||
// Return true if temp is higher then max value
|
|
||||||
return (thermistor_temp >= 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;
|
|
||||||
} else{
|
|
||||||
PORTB.OUTCLR = ledpin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
#include "voltage.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
void ADC0_init(void) {
|
|
||||||
/* Initializing ADC0 pin*/
|
|
||||||
/*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;
|
|
||||||
PORTD.PIN3CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */
|
|
||||||
PORTD.PIN3CTRL &= PORT_PULLUPEN_bm;
|
|
||||||
|
|
||||||
ADC0.CTRLC = ADC_PRESC_DIV4_gc;
|
|
||||||
VREF.ADC0REF = VREF_REFSEL_VDD_gc; /* Internal reference */
|
|
||||||
ADC0.CTRLA = ADC_ENABLE_bm /* ADC Enable: enabled */
|
|
||||||
| ADC_RESSEL_10BIT_gc; /* 10-bit mode */
|
|
||||||
|
|
||||||
/* Select ADC channel */
|
|
||||||
ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ADC0_read(void) {
|
|
||||||
/* Start ADC conversion */
|
|
||||||
ADC0.COMMAND = ADC_STCONV_bm;
|
|
||||||
/* Wait until ADC conversion done */
|
|
||||||
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm)) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
// Clear the interrupt flag by writing 1:
|
|
||||||
ADC0.INTFLAGS = ADC_RESRDY_bm;
|
|
||||||
return ADC0.RES;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t thermistor_voltage_read() {
|
|
||||||
/* Gets value for the diode */
|
|
||||||
ADC0.MUXPOS = 0x03; // Read PD3
|
|
||||||
uint16_t adc_val = ADC0_read();
|
|
||||||
|
|
||||||
return adc_val;
|
|
||||||
}
|
|
||||||
// Gets the value over thermistor
|
|
||||||
uint16_t external_voltage_read() {
|
|
||||||
ADC0.MUXPOS = 0x02; // Read PD6
|
|
||||||
uint16_t adc_val = ADC0_read();
|
|
||||||
|
|
||||||
return adc_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t internal_voltage_read() {
|
|
||||||
/* Gets value for the internal voltage reffreance*/
|
|
||||||
|
|
||||||
ADC0.MUXPOS = 0x44;
|
|
||||||
uint8_t adc_val = ADC0_read();
|
|
||||||
|
|
||||||
return adc_val * 10;
|
|
||||||
}
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
/* Microchip Technology Inc. and its subsidiaries. You may use this software
|
|
||||||
* and any derivatives exclusively with Microchip products.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
|
||||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
|
||||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
|
|
||||||
* WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
|
|
||||||
*
|
|
||||||
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
|
|
||||||
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
|
|
||||||
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
|
|
||||||
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
|
|
||||||
* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS
|
|
||||||
* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF
|
|
||||||
* ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
|
|
||||||
* TERMS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* File: Voltage.h
|
|
||||||
* Author: Sebastian Hernø Gabrielli, Helle Augland Grasmo, Ina Min Rørnes
|
|
||||||
* Comments:
|
|
||||||
* Revision history:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <util/delay.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
// This is a guard condition so that contents of this file are not included
|
|
||||||
// more than once.
|
|
||||||
#ifndef XC_HEADER_TEMPLATE_H
|
|
||||||
#define XC_HEADER_TEMPLATE_H
|
|
||||||
|
|
||||||
#include <xc.h> // include processor files - each processor file is guarded.
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
// Initializing of the ADC0 pins
|
|
||||||
|
|
||||||
void ADC0_init(void);
|
|
||||||
//
|
|
||||||
//void ADC0_start(void);
|
|
||||||
//Start ADC conversion
|
|
||||||
uint16_t ADC0_read(void);
|
|
||||||
// Gets the value from sensor and internal voltage
|
|
||||||
uint16_t internal_voltage_read();
|
|
||||||
// Gets the value over thermistor
|
|
||||||
uint16_t thermistor_voltage_read();
|
|
||||||
// Gets internal voltage
|
|
||||||
uint16_t external_voltage_read();
|
|
||||||
// Converts value to voltage
|
|
||||||
uint16_t convert_to_voltage(uint16_t adc_val);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* XC_HEADER_TEMPLATE_H */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user