Compare commits
76 Commits
calculate-
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b2e729683 | |||
| c5521a08fa | |||
|
|
25d27c1e1b | ||
|
|
cd65b8fd1f | ||
|
|
bc9e3f6885 | ||
|
|
d215e204d4 | ||
|
|
458ae00f24 | ||
|
|
b858d29ce8 | ||
|
|
1671476f41 | ||
|
|
bcd631001b | ||
|
|
dd53b4dbf2 | ||
|
|
275c40498f | ||
| 495cbbba44 | |||
| 772960d046 | |||
|
|
91cffd78f4 | ||
|
|
4666f79dd3 | ||
|
|
d31f03b6c7 | ||
|
|
6acdb2beb6 | ||
|
|
ba54ff20ef | ||
|
|
8f61e6b998 | ||
| ac5a054f8b | |||
| f0a435d578 | |||
| e01c4d41ad | |||
|
|
ae1c50ee09 | ||
|
|
f654ae96f6 | ||
|
|
dd624d4d48 | ||
| 10c82d001e | |||
| f2019dd57a | |||
| 022ccb13a0 | |||
| 6528a82b04 | |||
| eb7d96dd82 | |||
| 8649d59d8d | |||
|
|
fb24365469 | ||
|
|
b8d19731ad | ||
| c9b220616d | |||
|
|
822845cc7a | ||
|
|
1eaeeef9a0 | ||
|
|
d964ebea37 | ||
|
|
bf3753a012 | ||
| a48a089a3c | |||
| e6a3815dc2 | |||
| 933949dcff | |||
|
|
a9fec3f661 | ||
|
|
5ea7be0728 | ||
|
|
b1ca4c05bf | ||
| 9f27bc8454 | |||
|
|
7e59368252 | ||
|
|
9fd877aab5 | ||
| 1b8ca0c7f6 | |||
| ca28e23b70 | |||
| 7f3c1fa7c1 | |||
| ee6e6a6d07 | |||
| b0c0efa4fc | |||
| 91ee8b1af8 | |||
| ae28be55d3 | |||
| 953034cab8 | |||
| a9f5c42243 | |||
| 81ebcd2c79 | |||
|
|
8e3607cbda | ||
|
|
4e0b810346 | ||
|
|
e1c607514b | ||
| 849c719b59 | |||
| 7bcec13f6e | |||
| 5b884a50e2 | |||
| bf4f3aaa81 | |||
| a8be04b583 | |||
| 4a8b6137d1 | |||
| c48f87bcea | |||
| 6d6ea9606e | |||
| bd424b78d1 | |||
| 7008037de9 | |||
| 27d8d44d34 | |||
|
|
ac78f33c98 | ||
| 8b73051ece | |||
|
|
45bc800397 | ||
|
|
06d5c3c464 |
307
prosjekt.X/command-handler.c
Normal file
307
prosjekt.X/command-handler.c
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
89
prosjekt.X/command-handler.h
Normal file
89
prosjekt.X/command-handler.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
||||||
42
prosjekt.X/eeprom.c
Normal file
42
prosjekt.X/eeprom.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
46
prosjekt.X/eeprom.h
Normal file
46
prosjekt.X/eeprom.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
|
||||||
127
prosjekt.X/fan-speed.c
Normal file
127
prosjekt.X/fan-speed.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#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();
|
||||||
|
}
|
||||||
64
prosjekt.X/fan-speed.h
Normal file
64
prosjekt.X/fan-speed.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
#include "fan_speeeed.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
uint16_t timer_period_ms = 1;
|
|
||||||
uint16_t fan_speed;
|
|
||||||
volatile uint16_t falling_edge_counter = 0;
|
|
||||||
|
|
||||||
void TCA0_init() {
|
|
||||||
TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm ;
|
|
||||||
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV1024_gc ; /* Sysclk /1024 */
|
|
||||||
TCA0_update_period_ms();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA0_update_period_ms() {
|
|
||||||
TCA0.SINGLE.PERBUF = (F_CPU*(1/timer_period_ms)/1024); /* F_CPU * F_IRQ / TCA_prescaler */
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t RPM_calculation() {
|
|
||||||
fan_speed = (falling_edge_counter/timer_period_ms)*6000*3;
|
|
||||||
falling_edge_counter= 0;
|
|
||||||
printf("%u", fan_speed);
|
|
||||||
return fan_speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PORT_init(){
|
|
||||||
//compare or capture
|
|
||||||
//TCB3.CCMP = 0x00;
|
|
||||||
//count
|
|
||||||
TCB3.CNT = 0x00;
|
|
||||||
|
|
||||||
PORTA.IN = PIN0_bm;
|
|
||||||
PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
|
|
||||||
|
|
||||||
//PORTD.PIN2CTRL = PORT_ISC_FALLING_gc | 0b01000000;
|
|
||||||
// TCB3.CTRLB =0<< TCB_ASYNC_bp /* Asynchronous Enable: disabled */|0<< TCB_CCMPEN_bp /* Pin Output Enable: disabled */|0<< TCB_CCMPINIT_bp /* Pin Initial State: disabled */| TCB_CNTMODE_FRQ_gc;/* Input Capture Frequency measurement */
|
|
||||||
// TCB3.EVCTRL =1<< TCB_CAPTEI_bp /* Event Input Enable: enabled */|0<< TCB_EDGE_bp /* Event Edge: disabled */|0<< TCB_FILTER_bp;/* Input Capture Noise Cancellation Filter: disabled */
|
|
||||||
// TCB3.INTCTRL =1<< TCB_CAPT_bp /* Capture or Timeout: enabled */|0<< TCB_OVF_bp;/* OverFlow Interrupt: disabled */
|
|
||||||
// TCB3.CTRLA = TCB_CLKSEL_DIV1_gc /* CLK_PER */|1<< TCB_ENABLE_bp /* Enable: enabled */|0<< TCB_RUNSTDBY_bp /* Run Standby: disabled */|0<< TCB_SYNCUPD_bp /* Synchronize Update: disabled */|0<< TCB_CASCADE_bp;/* Cascade Two Timer/Counters: disabled */
|
|
||||||
|
|
||||||
//ASYNC disabled; CCMPINIT disabled; CCMPEN disabled; CNTMODE FRQPW;
|
|
||||||
TCB3.CTRLB = 0x04;
|
|
||||||
|
|
||||||
//DBGRUN disabled;
|
|
||||||
//TCB3.DBGCTRL = 0x00;
|
|
||||||
|
|
||||||
//FILTER disabled; EDGE disabled; CAPTEI enabled;
|
|
||||||
TCB3.EVCTRL = 0x01;
|
|
||||||
|
|
||||||
//OVF disabled; CAPT enabled;
|
|
||||||
TCB3.INTCTRL = 0x01;
|
|
||||||
|
|
||||||
//OVF disabledAPT disabled;
|
|
||||||
//TCB3.INTFLAGS = 0; CAPT disabled;
|
|
||||||
//TCB3.INTFLAGS = 0x00;
|
|
||||||
|
|
||||||
//Temporary Value
|
|
||||||
//TCB3.TEMP = 0x00;
|
|
||||||
|
|
||||||
|
|
||||||
EVSYS.CHANNEL0 = 0x40;
|
|
||||||
//EVSYS.SWEVENTA = 0x01;
|
|
||||||
EVSYS.USERTCB3CAPT = 0x01;
|
|
||||||
|
|
||||||
//RUNSTDBY disabled; CASCADE disabled; SYNCUPD disabled; CLKSEL DIV1; ENABLE enabled;
|
|
||||||
TCB3.CTRLA = 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCB0_Init(void){
|
|
||||||
TCB3.CTRLB = TCB_CNTMODE_FRQPW_gc; /* Input Capture Frequency */
|
|
||||||
TCB3.EVCTRL = TCB_CAPTEI_bm; /* Event Input Enable: enabled */
|
|
||||||
TCB3.EVCTRL |= (1 << TCB_CAPTEI_bp | 1 << TCB_EDGE_bp | 1 << TCB_FILTER_bp); /* Event Input Enable: enabled */
|
|
||||||
TCB3.INTCTRL = TCB_CAPT_bm; /* Capture or Timeout: enabled */
|
|
||||||
TCB3.CTRLA = TCB_CLKSEL_DIV1_gc /* CLK_PER/1 (From Prescaler) - This is needed to be able to count to 40 Hz with a 4 Mhz system clock */
|
|
||||||
| TCB_ENABLE_bm /* Enable: enabled */
|
|
||||||
| TCB_RUNSTDBY_bm; /* Run Standby: enabled */
|
|
||||||
}
|
|
||||||
void EVSYS_Init(void)
|
|
||||||
{
|
|
||||||
/* Zero-cross detector 0 out linked to event channel 0 */
|
|
||||||
EVSYS.CHANNEL0 = EVSYS_CHANNEL0_PORTA_PIN5_gc;
|
|
||||||
/* TCB uses event channel 0 */
|
|
||||||
EVSYS.USERTCB0CAPT = EVSYS_USER_CHANNEL0_gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PORT_Init(void)
|
|
||||||
{
|
|
||||||
PORTB.OUTSET |= PIN5_bm;
|
|
||||||
PORTB.DIRSET |= PIN5_bm;
|
|
||||||
}
|
|
||||||
//-----------------------------------------------------------------------------------------------------
|
|
||||||
//-------------------------------------- S E T U P-----------------------------------------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
ISR ( TCA0_OVF_vect ) {
|
|
||||||
cli();
|
|
||||||
RPM_calculation();
|
|
||||||
|
|
||||||
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm ;
|
|
||||||
|
|
||||||
sei();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void printnie(uint8_t en, uint8_t to){
|
|
||||||
printf("CNT %u", en);
|
|
||||||
printf("ccmp %u", to);
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR (TCB3_INT_vect){
|
|
||||||
uint16_t yo = TCB3.CNT;
|
|
||||||
|
|
||||||
uint16_t stewui = TCB3.CCMP;
|
|
||||||
|
|
||||||
printnie(yo, stewui);
|
|
||||||
TCB3.INTFLAGS = 0x03;
|
|
||||||
//TCB3.INTFLAGS = PIN0_bm;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
ISR(PORTD_PORT_vect){
|
|
||||||
// cli();
|
|
||||||
falling_edge_counter ++;
|
|
||||||
|
|
||||||
PORTD.INTFLAGS = PIN2_bm;
|
|
||||||
//sei();
|
|
||||||
}
|
|
||||||
* */
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* File: fanseeeed.h
|
|
||||||
* Author: inami
|
|
||||||
*
|
|
||||||
* 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>
|
|
||||||
#include <avr/cpufunc.h>
|
|
||||||
|
|
||||||
void TCA0_init ();
|
|
||||||
void PORT_init();
|
|
||||||
|
|
||||||
void TCA0_update_period_ms ();
|
|
||||||
uint16_t RPM_calculation();
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* FANSEEEED_H */
|
|
||||||
|
|
||||||
125
prosjekt.X/i2c.c
Normal file
125
prosjekt.X/i2c.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#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();
|
||||||
|
}
|
||||||
36
prosjekt.X/i2c.h
Normal file
36
prosjekt.X/i2c.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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,65 +1,83 @@
|
|||||||
/*
|
/*
|
||||||
* File: main.c
|
* File: main.c
|
||||||
* Author: Sebastian H. Gabrielli
|
* Author: Sebastian H. Gabrielli, Helle Augland Grasmo, Ina Min Rørnes
|
||||||
*
|
*
|
||||||
* Created on March 6, 2024, 12:34 PM
|
* Created on March 6, 2024, 12:34 PM
|
||||||
*/
|
*/
|
||||||
#include "voltage.h"
|
#define F_CPU 4E6
|
||||||
#include "uart.h"
|
|
||||||
#define RTC_PERIOD (511)
|
// Include AVR specific libs
|
||||||
#define DELAY_TIME 1000
|
#include <avr/interrupt.h>
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <util/delay.h>
|
||||||
#include <util/delay.h>
|
|
||||||
#include <string.h>
|
// Include standard C libraries
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
//#define F_CPU 4E6
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
// Include custom source files
|
||||||
#include "uart.h"
|
#include "eeprom.h"
|
||||||
#include <util/delay.h>
|
#include "voltage.h"
|
||||||
#include <stdint.h>
|
#include "command-handler.h"
|
||||||
#include "themistor-temp.h"
|
#include "i2c.h"
|
||||||
#include "fan_speeeed.h"
|
#include "themistor-temp.h"
|
||||||
|
#include "fan-speed.h"
|
||||||
|
|
||||||
int main() {
|
// Only enable UART when required for debugging
|
||||||
init_uart((uint16_t)9600);
|
#ifdef ENABLE_UART
|
||||||
stdout = &USART_stream;
|
#include "uart.h"
|
||||||
TCA0_init ();
|
#endif
|
||||||
//PORT_init();
|
|
||||||
//test
|
// Fan history variables
|
||||||
|
volatile uint16_t fan1_history[512] = {0};
|
||||||
TCB0_Init();
|
volatile uint16_t fan2_history[512] = {0};
|
||||||
EVSYS_Init();
|
// Fan history index variable
|
||||||
PORT_Init();
|
volatile uint16_t fan1_history_index = 0;
|
||||||
TCB3.INTCTRL = 0b00000001; // Bit 0 ? CAPT Capture Interrupt Enable
|
volatile uint16_t fan2_history_index = 0;
|
||||||
|
|
||||||
sei();
|
// Default config is 500ms sample rate
|
||||||
|
volatile config_t config = {500};
|
||||||
while (1) {
|
volatile bool store_config = false;
|
||||||
/*
|
|
||||||
printf("loop");
|
int main() {
|
||||||
uint16_t yo = TCB3.CNT;
|
// Initialize functionality
|
||||||
printf("CNT %u", yo);
|
ADC0_init();
|
||||||
uint16_t stewui = TCB3.CCMP;
|
init_alarm_gpio();
|
||||||
printf("CCMP %u", stewui);
|
init_i2c();
|
||||||
*/
|
|
||||||
;
|
// Fanspeed
|
||||||
}
|
init_AC0();
|
||||||
}
|
init_AC1();
|
||||||
|
init_TCA0();
|
||||||
/*ISR (TCB3_INT_vect){
|
TCA0_update_period(config.ms_fanspeed_sample_rate);
|
||||||
uint16_t yo = TCB3.CNT;
|
|
||||||
printf("CNT %u", yo);
|
// Only enable UART when required for debugging
|
||||||
|
#ifdef ENABLE_UART
|
||||||
uint16_t stewui = TCB3.CCMP;
|
init_uart((uint16_t)9600);
|
||||||
printf("CCMP %u", stewui);
|
stdout = &USART_stream;
|
||||||
|
#endif
|
||||||
TCB3.INTFLAGS = 0x03;
|
|
||||||
//TCB3.INTFLAGS = PIN0_bm;
|
// Read the stored config struct
|
||||||
|
config = read_struct_from_EEPROM();
|
||||||
}*/
|
|
||||||
|
// Enable interrupts
|
||||||
|
sei();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|||||||
@ -6,8 +6,11 @@
|
|||||||
projectFiles="true">
|
projectFiles="true">
|
||||||
<itemPath>uart.h</itemPath>
|
<itemPath>uart.h</itemPath>
|
||||||
<itemPath>voltage.h</itemPath>
|
<itemPath>voltage.h</itemPath>
|
||||||
<itemPath>fan_speeeed.h</itemPath>
|
|
||||||
<itemPath>themistor-temp.h</itemPath>
|
<itemPath>themistor-temp.h</itemPath>
|
||||||
|
<itemPath>command-handler.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"
|
||||||
@ -25,8 +28,11 @@
|
|||||||
<itemPath>main.c</itemPath>
|
<itemPath>main.c</itemPath>
|
||||||
<itemPath>uart.c</itemPath>
|
<itemPath>uart.c</itemPath>
|
||||||
<itemPath>voltage.c</itemPath>
|
<itemPath>voltage.c</itemPath>
|
||||||
<itemPath>fan_speeeed.c</itemPath>
|
|
||||||
<itemPath>thermistor-temp.c</itemPath>
|
<itemPath>thermistor-temp.c</itemPath>
|
||||||
|
<itemPath>command-handler.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>
|
||||||
|
|||||||
@ -13,24 +13,34 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#define R_t0 10000
|
#include <avr/io.h>
|
||||||
|
#define R_T0 100E3
|
||||||
#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
|
||||||
// Takes inn messured value
|
|
||||||
|
// Takes inn messured value
|
||||||
|
#define ALERT_PIN PIN3_bm
|
||||||
|
|
||||||
|
// Takes inn messured value
|
||||||
// Calculates the temperature in celcius
|
// Calculates the temperature in celcius
|
||||||
// Returns the thermistor themperature
|
// Returns the thermistor themperature
|
||||||
float calculate_thermistor_temp(float readValue);
|
float calculate_thermistor_temp(float readValue);
|
||||||
// Returns true if temperatur is higher then high_temp int
|
|
||||||
bool error_message(float thermistor_temp);
|
|
||||||
|
|
||||||
|
|
||||||
|
// Returns true if temperatur is higher than max_temp
|
||||||
|
bool voltage_threshold_bool(float thermistor_temp, uint8_t max_temp);
|
||||||
|
|
||||||
|
void alert_voltage_threshold_exceeded(bool voltage_threshold_bool);
|
||||||
|
|
||||||
|
// Initialise alarm GPIO
|
||||||
|
void init_alarm_gpio();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,41 +1,52 @@
|
|||||||
#include "themistor-temp.h"
|
#include "themistor-temp.h"
|
||||||
|
|
||||||
float calculate_thermistor_temp(float readValue){
|
|
||||||
float R_therm;
|
void init_alarm_gpio(){
|
||||||
float V_1;
|
PORTB.DIRSET = ALERT_PIN;
|
||||||
float ln;
|
|
||||||
float T_therm;
|
|
||||||
float V_therm;
|
|
||||||
uint8_t V_tot = 5;
|
|
||||||
// Calculate Voltage over thermistor
|
|
||||||
V_therm = (V_tot/1024)*readValue;
|
|
||||||
|
|
||||||
// Voltage accross R_1
|
|
||||||
V_1 = V_tot - V_therm;
|
|
||||||
|
|
||||||
// Calculate Thermistor resistanse
|
|
||||||
R_therm = (V_therm)/ (V_1 / R_1);
|
|
||||||
|
|
||||||
// Steinhart-Harts formula
|
|
||||||
ln = log(R_therm/R_t0);
|
|
||||||
T_therm = (1/ ((ln/B) + (1/T_0)));
|
|
||||||
|
|
||||||
// Temperatur in celcius
|
|
||||||
T_therm -= 273.15;
|
|
||||||
|
|
||||||
return T_therm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns error message
|
// The code is inspired by "Arduino thermistor guide" by valtentina Vogelman, 1 november 2023
|
||||||
bool error_message(float thermistor_temp){
|
// https://www.build-electronic-circuits.com/arduino-thermistor/
|
||||||
// Max value
|
|
||||||
int high_temp = 0;
|
float calculate_thermistor_temp(float thermistor_voltage){
|
||||||
|
float R_thermistor;
|
||||||
|
float V_1;
|
||||||
|
float ln;
|
||||||
|
float T_thermistor;
|
||||||
|
float V_thermistor;
|
||||||
|
#define V_TOT 3.3
|
||||||
|
// 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 true if temp is higher then max value
|
||||||
if (thermistor_temp > high_temp){
|
return (thermistor_temp >= max_temp);
|
||||||
printf("Error");
|
}
|
||||||
return true;
|
|
||||||
|
//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 = ALERT_PIN;
|
||||||
|
} else{
|
||||||
|
PORTB.OUTCLR = ALERT_PIN;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
52
prosjekt.X/thermistor-temp.c.save
Normal file
52
prosjekt.X/thermistor-temp.c.save
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,7 +20,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define USART3_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
|
#define USART3_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
|
||||||
|
|
||||||
// Initialize the USART3 controller
|
// Initialize the USART3 controller
|
||||||
void init_uart(uint16_t baud);
|
void init_uart(uint16_t baud);
|
||||||
|
|
||||||
|
|||||||
@ -2,40 +2,58 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
void ADC0_init(void) {
|
void ADC0_init(void) {
|
||||||
/* Initializing ADC0 pin*/
|
/* Initializing ADC0 pin*/
|
||||||
PORTD.PIN6CTRL &= ~PORT_ISC_gm;
|
/*Voltage reading on pin pd2*/
|
||||||
PORTD.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */
|
PORTD.PIN2CTRL &= ~PORT_ISC_gm;
|
||||||
PORTD.PIN6CTRL &= PORT_PULLUPEN_bm;
|
PORTD.PIN2CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */
|
||||||
|
PORTD.PIN2CTRL &= PORT_PULLUPEN_bm;
|
||||||
|
|
||||||
ADC0.CTRLC = ADC_PRESC_DIV4_gc;
|
/* Thermistor */
|
||||||
VREF.ADC0REF = VREF_REFSEL_VDD_gc; /* Internal reference */
|
PORTD.PIN3CTRL &= ~PORT_ISC_gm;
|
||||||
ADC0.CTRLA = ADC_ENABLE_bm /* ADC Enable: enabled */
|
PORTD.PIN3CTRL |= PORT_ISC_INPUT_DISABLE_gc; /* Disable */
|
||||||
| ADC_RESSEL_10BIT_gc; /* 10-bit mode */
|
PORTD.PIN3CTRL &= PORT_PULLUPEN_bm;
|
||||||
/* Select ADC channel */
|
|
||||||
ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc;
|
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) {
|
uint16_t ADC0_read(void) {
|
||||||
/* Start ADC conversion */
|
/* Start ADC conversion */
|
||||||
ADC0.COMMAND = ADC_STCONV_bm;
|
ADC0.COMMAND = ADC_STCONV_bm;
|
||||||
/* Wait until ADC conversion done */
|
/* Wait until ADC conversion done */
|
||||||
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm)) {
|
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm)) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
// Clear the interrupt flag by writing 1:
|
// Clear the interrupt flag by writing 1:
|
||||||
ADC0.INTFLAGS = ADC_RESRDY_bm;
|
ADC0.INTFLAGS = ADC_RESRDY_bm;
|
||||||
return ADC0.RES;
|
return ADC0.RES;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t diode_voltage_read() {
|
uint16_t thermistor_voltage_read() {
|
||||||
/* Gets value for the diode */
|
/* Gets value for the diode */
|
||||||
uint8_t adcVal = ADC0_read();
|
ADC0.MUXPOS = 0x03; // Read PD3
|
||||||
|
uint16_t adc_val = ADC0_read();
|
||||||
|
|
||||||
return adcVal;
|
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() {
|
uint16_t internal_voltage_read() {
|
||||||
/* Gets value for the internal voltage reffreance*/
|
/* Gets value for the internal voltage reffreance*/
|
||||||
|
|
||||||
VREF.ADC0REF = VREF_REFSEL_VDD_gc;
|
ADC0.MUXPOS = 0x44;
|
||||||
|
uint8_t adc_val = ADC0_read();
|
||||||
|
|
||||||
|
return adc_val * 10;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,9 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File:
|
* File: Voltage.h
|
||||||
* Author:
|
* Author: Sebastian Hernø Gabrielli, Helle Augland Grasmo, Ina Min Rørnes
|
||||||
* Comments:
|
* Comments:
|
||||||
* Revision history:
|
* Revision history:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -54,7 +54,13 @@ extern "C" {
|
|||||||
uint16_t ADC0_read(void);
|
uint16_t ADC0_read(void);
|
||||||
// Gets the value from sensor and internal voltage
|
// Gets the value from sensor and internal voltage
|
||||||
uint16_t internal_voltage_read();
|
uint16_t internal_voltage_read();
|
||||||
uint16_t diode_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user