MOVED FROM SVN
This commit is contained in:
commit
11677dfa2b
|
|
@ -0,0 +1,16 @@
|
||||||
|
cmake_minimum_required(VERSION 3.17)
|
||||||
|
set(AVR_PROJECT ${CMAKE_CURRENT_SOURCE_DIR}/avr-project.cmake)
|
||||||
|
if (EXISTS ${AVR_PROJECT})
|
||||||
|
INCLUDE(${AVR_PROJECT})
|
||||||
|
else (EXISTS ${AVR_PROJECT})
|
||||||
|
set("AVR_PROJECT_NAME" "Unconfigured project")
|
||||||
|
endif (EXISTS ${AVR_PROJECT})
|
||||||
|
project(${AVR_PROJECT_NAME})
|
||||||
|
#check avr build tools installed
|
||||||
|
if (DEFINED ENV{AVR_BUILD_TOOLS})
|
||||||
|
set(BUILD_TOOLS_ROOT "$ENV{AVR_BUILD_TOOLS}")
|
||||||
|
else (DEFINED ENV{AVR_BUILD_TOOLS})
|
||||||
|
message(FATAL_ERROR "Build tools is not installed or ENV{AVR_BUILD_TOOLS} is not defined")
|
||||||
|
endif (DEFINED ENV{AVR_BUILD_TOOLS})
|
||||||
|
|
||||||
|
INCLUDE("${BUILD_TOOLS_ROOT}/scripts/commons.cmake")
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
|
@ -0,0 +1,2 @@
|
||||||
|
input = ADC6
|
||||||
|
output = PC0
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
set(AVR_EX_FUSE 0xFF)
|
||||||
|
set(AVR_H_FUSE 0xD7)
|
||||||
|
set(AVR_L_FUSE 0xE2)
|
||||||
|
set(AVR_MCU atmega48)
|
||||||
|
set(AVR_PROGRAMMER usbasp)
|
||||||
|
set(AVR_PROJECT_NAME cooler-controller)
|
||||||
|
set(AVR_UPLOADTOOL_PORT usb)
|
||||||
|
set(AVR_UPLOADTOOL_BITRATE 9600)
|
||||||
|
set(MCU_FREQ 8000000)
|
||||||
|
|
||||||
|
#additional compiler parameters
|
||||||
|
|
||||||
|
#set(EXTRA_FLAGS "-Wl,-u,vfprintf -lprintf_min")
|
||||||
|
#add_definitions("-Wno-shift-overflow")
|
||||||
|
|
||||||
|
#Add defines
|
||||||
|
#add_definitions("-DNAME=VALUE")
|
||||||
|
add_definitions("-DUSART_READING")
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include "usart.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USART_READING
|
||||||
|
|
||||||
|
int USART::bufferReadIndex = 0;
|
||||||
|
int USART::bufferWriteIndex = 0;
|
||||||
|
int USART::incomingBytes = 0;
|
||||||
|
uint8_t USART::buffer[USART_BUFFER_SIZE];
|
||||||
|
|
||||||
|
ISR(USART_RX_vect){
|
||||||
|
USART::fillBuffer(UDR0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::reset(){
|
||||||
|
incomingBytes=0;
|
||||||
|
bufferWriteIndex = 0;
|
||||||
|
bufferReadIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int USART::available(){
|
||||||
|
return incomingBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::fillBuffer(uint8_t byte){
|
||||||
|
incomingBytes++;
|
||||||
|
buffer[bufferWriteIndex] = byte;
|
||||||
|
bufferWriteIndex++;
|
||||||
|
if(bufferWriteIndex>=USART_BUFFER_SIZE) bufferWriteIndex=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USART::read(){
|
||||||
|
while(!available());
|
||||||
|
uint8_t byte = buffer[bufferReadIndex];
|
||||||
|
bufferReadIndex++;
|
||||||
|
if(bufferReadIndex>=USART_BUFFER_SIZE) bufferReadIndex = 0;
|
||||||
|
incomingBytes--;
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USART::USART(uint32_t baud_rate) {
|
||||||
|
uint32_t UBRR_VALUE = ((uint32_t) F_CPU) / 8 / baud_rate - 1;
|
||||||
|
UBRR0H = (uint8_t) (UBRR_VALUE >> 8);
|
||||||
|
UBRR0L = (uint8_t) (UBRR_VALUE);
|
||||||
|
|
||||||
|
#ifdef USART_READING
|
||||||
|
UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
|
||||||
|
#else
|
||||||
|
UCSR0B = (1 << TXEN0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UCSR0A |= (1 << U2X0);
|
||||||
|
UCSR0C = (1 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::waitForBufferBeFree() {
|
||||||
|
while (!(UCSR0A & (1 << UDRE0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::send(uint8_t b) {
|
||||||
|
waitForBufferBeFree();
|
||||||
|
UDR0 = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::send(void *ptr, size_t count) {
|
||||||
|
for (size_t i = 0; i < count; i++) send(((uint8_t *) ptr)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::send(char *string) {
|
||||||
|
send(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::send_P(const char *string) {
|
||||||
|
for (size_t i = 0; i < strlen_P(string); i++) send(pgm_read_byte(string + i));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void USART::sendFloat(float f, uint8_t p) {
|
||||||
|
int64_t value = f;
|
||||||
|
float frac = f-value;
|
||||||
|
frac*=pow(10, p);
|
||||||
|
char str[64];
|
||||||
|
itoa(value, str, 10);
|
||||||
|
send(str);
|
||||||
|
|
||||||
|
value = frac;
|
||||||
|
if(value > 0){
|
||||||
|
send('.');
|
||||||
|
itoa(value, str, 10);
|
||||||
|
uint8_t d = p - strlen(str);
|
||||||
|
for(uint8_t i=0;i<d;i++) send('0');
|
||||||
|
send(str);
|
||||||
|
}else{
|
||||||
|
send('.');
|
||||||
|
send('0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART::sendInt(int64_t i, int radix) {
|
||||||
|
char str[64];
|
||||||
|
itoa(i, str, radix);
|
||||||
|
send(str);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USART_H_
|
||||||
|
#define USART_H_
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#ifndef USART_BUFFER_SIZE
|
||||||
|
#define USART_BUFFER_SIZE 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_CPU
|
||||||
|
#warning "F_CPU is used to calculate baud rate and should be defined!"
|
||||||
|
#define F_CPU 1000000UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class USART{
|
||||||
|
public:
|
||||||
|
USART(uint32_t baud_rate);
|
||||||
|
void send(uint8_t b);
|
||||||
|
void send(void*ptr, size_t count);
|
||||||
|
void send(char * string);
|
||||||
|
void send_P(const char * string);
|
||||||
|
void sendFloat(float f, uint8_t p);
|
||||||
|
void sendInt(int64_t i, int radix);
|
||||||
|
|
||||||
|
#ifdef USART_READING
|
||||||
|
uint8_t read();
|
||||||
|
static void fillBuffer(uint8_t byte);
|
||||||
|
int available();
|
||||||
|
void reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef USART_READING
|
||||||
|
static uint8_t buffer[USART_BUFFER_SIZE];
|
||||||
|
static int bufferReadIndex;
|
||||||
|
static int bufferWriteIndex;
|
||||||
|
static int incomingBytes;
|
||||||
|
#endif
|
||||||
|
void waitForBufferBeFree();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// Created by User on 018 18.05.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ADC.h"
|
||||||
|
#define ADC_PORT_SELECTION_MASK ((1<<REFS0) | (1<<REFS1) | (1<<ADLAR))
|
||||||
|
|
||||||
|
void ADCIO::setup() {
|
||||||
|
ADCSRA |= (1<<ADEN); //включаем ADC
|
||||||
|
ADCSRA |= (1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);//выставляем делитель частоты 128
|
||||||
|
ADMUX |= (1<<REFS0); //используем внешнее опорное напряжение
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ADCIO::read(ADCPort port) {
|
||||||
|
ADMUX &= ADC_PORT_SELECTION_MASK;
|
||||||
|
ADMUX |= port;
|
||||||
|
uint16_t result = 0;
|
||||||
|
for(uint8_t i=0;i<ADC_READ_COUNT;i++){
|
||||||
|
ADCSRA |= (1<<ADSC);//включаем АЦП
|
||||||
|
while((ADCSRA & (1<<ADSC))); //ждём готовность
|
||||||
|
result+=(uint16_t)ADCW;
|
||||||
|
}
|
||||||
|
return result/ADC_READ_COUNT;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Created by User on 018 18.05.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AVR_IOHELP_ADC_H
|
||||||
|
#define AVR_IOHELP_ADC_H
|
||||||
|
#include <avr/io.h>
|
||||||
|
#define ADC_READ_COUNT 5
|
||||||
|
|
||||||
|
enum ADCPort{
|
||||||
|
ADC0 = 0x00,
|
||||||
|
ADC1 = 0x01,
|
||||||
|
ADC2 = 0x02,
|
||||||
|
ADC3 = 0x03,
|
||||||
|
ADC4 = 0x04,
|
||||||
|
ADC5 = 0x05,
|
||||||
|
ADC6 = 0x06,
|
||||||
|
ADC7 = 0x07
|
||||||
|
//ADC8_INTERNAL = 0b1000
|
||||||
|
};
|
||||||
|
namespace ADCIO{
|
||||||
|
void setup();
|
||||||
|
uint16_t read(ADCPort port);
|
||||||
|
}
|
||||||
|
#endif //AVR_IOHELP_ADC_H
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "EEPROM.h"
|
||||||
|
|
||||||
|
namespace EEPROM {
|
||||||
|
void set(uint16_t address, uint8_t data) {
|
||||||
|
if (get(address) != data) {
|
||||||
|
/* Wait for completion of previous write */
|
||||||
|
while (EECR & (1 << EEPE));
|
||||||
|
/* Set up address and Data Registers */
|
||||||
|
EEAR = address;
|
||||||
|
EEDR = data;
|
||||||
|
/* Write logical one to EEMPE */
|
||||||
|
EECR |= (1 << EEMPE);
|
||||||
|
/* Start eeprom write by setting EEPE */
|
||||||
|
EECR |= (1 << EEPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(uint16_t address, void *dataSource, size_t dataSize) {
|
||||||
|
uint8_t *data = (uint8_t *) dataSource;
|
||||||
|
for (size_t i = 0; i < dataSize; i++) {
|
||||||
|
set(address + i, data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t get(uint16_t address) {
|
||||||
|
/* Wait for completion of previous write */
|
||||||
|
while (EECR & (1 << EEPE));
|
||||||
|
/* Set up address register */
|
||||||
|
EEAR = address;
|
||||||
|
/* Start eeprom read by writing EERE */
|
||||||
|
EECR |= (1 << EERE);
|
||||||
|
/* Return data from Data Register */
|
||||||
|
return EEDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get(uint16_t address, void *dataDest, size_t dataSize) {
|
||||||
|
uint8_t *data = (uint8_t *) dataDest;
|
||||||
|
for (size_t i = 0; i < dataSize; i++) {
|
||||||
|
data[i] = get(address + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef AVR_IOHELP_EEPROM_H
|
||||||
|
#define AVR_IOHELP_EEPROM_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace EEPROM{
|
||||||
|
void set(uint16_t address, uint8_t data);
|
||||||
|
void set(uint16_t address, void * dataSource, size_t dataSize);
|
||||||
|
|
||||||
|
uint8_t get(uint16_t address);
|
||||||
|
void get(uint16_t address, void * dataDest, size_t dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AVR_IOHELP_EEPROM_H
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
#include "TWI.h"
|
||||||
|
|
||||||
|
namespace TWI {
|
||||||
|
BusState startMessage(Address addr) {
|
||||||
|
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT);
|
||||||
|
wait();
|
||||||
|
uint8_t status = sendByte(addr);
|
||||||
|
|
||||||
|
if (status == 0x18 || status == 0x40) return TWI_OK;
|
||||||
|
else return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BusState sendByte(uint8_t byte) {
|
||||||
|
TWDR = byte;
|
||||||
|
TWCR = (1 << TWEN) | (1 << TWINT);
|
||||||
|
wait();
|
||||||
|
uint8_t status = (TWSR & 0xF8);
|
||||||
|
if (status != 0x28 && status != 0x30) return status;
|
||||||
|
else return TWI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait() {
|
||||||
|
while (!(TWCR & (1 << TWINT)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BusState nack() {
|
||||||
|
TWCR = (1 << TWEN) | (1 << TWINT);
|
||||||
|
wait();
|
||||||
|
uint8_t status = (TWSR & 0xF8);
|
||||||
|
if (status != 0x50 && status != 0x58) return status;
|
||||||
|
else return TWI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BusState ack() {
|
||||||
|
TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA);
|
||||||
|
wait();
|
||||||
|
uint8_t status = (TWSR & 0xF8);
|
||||||
|
if (status != 0x50 && status != 0x58) return status;
|
||||||
|
else return TWI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t readByte() {
|
||||||
|
return TWDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(uint32_t busSpeed) {
|
||||||
|
|
||||||
|
// TWSR = ~(1 << TWPS0);
|
||||||
|
// TWSR = ~(1 << TWPS1);
|
||||||
|
TWBR = ((F_CPU / busSpeed - 16) / (2 * 4));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// initialize twi prescaler and bit rate
|
||||||
|
cbi(TWSR, TWPS0);
|
||||||
|
cbi(TWSR, TWPS1);
|
||||||
|
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;*/
|
||||||
|
|
||||||
|
/* twi bit rate formula from atmega128 manual pg 204
|
||||||
|
SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||||
|
note: TWBR should be 10 or higher for master mode
|
||||||
|
It is 72 for a 16mhz Wiring board with 100kHz TWI */
|
||||||
|
|
||||||
|
// enable twi module, acks, and twi interrupt
|
||||||
|
TWCR = _BV(TWEN) | _BV(TWEA); //| _BV(TWIE);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef TWI_H
|
||||||
|
#define TWI_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#define TWI_OK 0x00
|
||||||
|
namespace TWI {
|
||||||
|
typedef uint8_t BusState;
|
||||||
|
typedef uint8_t Address;
|
||||||
|
|
||||||
|
|
||||||
|
void init(uint32_t busSpeed);
|
||||||
|
void close();
|
||||||
|
BusState startMessage(Address addr);
|
||||||
|
BusState sendByte(uint8_t byte);
|
||||||
|
BusState ack();
|
||||||
|
uint8_t readByte();
|
||||||
|
BusState nack();
|
||||||
|
void wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// Created by User on 018 18.05.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
void Timer1::setup(TimerPrescaler prescaler, uint16_t OCR) {
|
||||||
|
TCCR1B |= (1 << WGM12); //режим сброса по свпадению
|
||||||
|
|
||||||
|
switch (prescaler) {
|
||||||
|
case PRESCALER_NO:
|
||||||
|
TCCR1B |= (1 << CS10);
|
||||||
|
break;
|
||||||
|
case PRESCALER_8:
|
||||||
|
TCCR1B |= (1 << CS11);
|
||||||
|
break;
|
||||||
|
case PRESCALER_64:
|
||||||
|
TCCR1B |= (1 << CS10) | (1 << CS10);
|
||||||
|
break;
|
||||||
|
case PRESCALER_256:
|
||||||
|
TCCR1B |= (1 << CS12);
|
||||||
|
break;
|
||||||
|
case PRESCALER_1024:
|
||||||
|
TCCR1B |= (1 << CS12) | (1 << CS10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMSK1 |= (1 << OCIE1A); //устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)
|
||||||
|
|
||||||
|
OCR1AH = (OCR & 0xFF00) >> 8;
|
||||||
|
OCR1AL = (OCR & 0x00FF);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// Created by User on 018 18.05.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AVR_IOHELP_TIMER_H
|
||||||
|
#define AVR_IOHELP_TIMER_H
|
||||||
|
#include <avr/io.h>
|
||||||
|
#define onTimer1Triggered() ISR(TIMER1_COMPA_vect)
|
||||||
|
|
||||||
|
enum TimerPrescaler{
|
||||||
|
PRESCALER_NO,
|
||||||
|
PRESCALER_8,
|
||||||
|
PRESCALER_64,
|
||||||
|
PRESCALER_256,
|
||||||
|
PRESCALER_1024
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Timer1{
|
||||||
|
void setup(TimerPrescaler prescaler, uint16_t OCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AVR_IOHELP_TIMER_H
|
||||||
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 20.04.2020.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AVR_IOHELP_H
|
||||||
|
#define AVR_IOHELP_H
|
||||||
|
|
||||||
|
//Пример: pinmode_input(DDRB, PORTB1);
|
||||||
|
|
||||||
|
#define pinmode_input(DDREGISTER, PINNAME) (DDREGISTER &= ~(1<<PINNAME))
|
||||||
|
#define pinmode_output(DDREGISTER, PINNAME) (DDREGISTER |= (1<<PINNAME))
|
||||||
|
|
||||||
|
|
||||||
|
//Пример: pinstateset(PORTB, PORTB1, true);
|
||||||
|
|
||||||
|
#define pinstateset(PORTREGISTER, PINNAME, STATE) do{ if(STATE){ PORTREGISTER |= (1<<PINNAME); }else{ PORTREGISTER &= ~(1<<PINNAME); } }while(0)
|
||||||
|
|
||||||
|
//Пример: int state = pinstateget(PINB, PORTB1);
|
||||||
|
|
||||||
|
#define pinstateget(PINREGISTER, PINNAME) (PINREGISTER & (1<<PINNAME))
|
||||||
|
|
||||||
|
#endif //AVR_IOHELP_H
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 25.09.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
|
uint8_t SPI::transfer(uint8_t byte){
|
||||||
|
SPDR = byte;
|
||||||
|
while(!(SPSR & (1<<SPIF))); //ожидание готовности SPI
|
||||||
|
return SPDR; //возврат того, что пришло
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPI::send(uint8_t byte){
|
||||||
|
SPI::transfer(byte);
|
||||||
|
}
|
||||||
|
uint8_t SPI::receive(){
|
||||||
|
return SPI::transfer(0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SPI::data() {
|
||||||
|
return SPDR;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 25.09.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AVR_IOHELP_SPI_H
|
||||||
|
#define AVR_IOHELP_SPI_H
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#define SPI(MOSI, MISO, SCK) do{DDRB = ((DDRB&~(1<<MISO))|(1<<MOSI)|(1<<SCK)); (SPCR |= (1<<SPE)|(1<<MSTR)); SPSR |= (1<<SPI2X);}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
namespace SPI{
|
||||||
|
uint8_t transfer(uint8_t byte);
|
||||||
|
void send(uint8_t byte);
|
||||||
|
uint8_t receive();
|
||||||
|
uint8_t data();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AVR_IOHELP_SPI_H
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COOLER_CONTROLLER_COMMESSAGE_H
|
||||||
|
#define COOLER_CONTROLLER_COMMESSAGE_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
enum MessageType {
|
||||||
|
SAVE,
|
||||||
|
PING,
|
||||||
|
REBOOT,
|
||||||
|
READ,
|
||||||
|
WRITE,
|
||||||
|
ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ErrorCodes{
|
||||||
|
ERR_UNSUPPORTED_OPERATION,
|
||||||
|
ERR_UNKNOWN_DATA_TYPE,
|
||||||
|
ERR_UNKNOWN_ACTION_TYPE,
|
||||||
|
ERR_INVALID_CHECKSUM
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DataType{
|
||||||
|
NONE,
|
||||||
|
TEMP,
|
||||||
|
LEVEL,
|
||||||
|
START_TEMP,
|
||||||
|
STOP_TEMP,
|
||||||
|
MAX_TEMP,
|
||||||
|
MIN_LEVEL,
|
||||||
|
MAX_LEVEL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message {
|
||||||
|
public:
|
||||||
|
MessageType action;
|
||||||
|
DataType dataType;
|
||||||
|
uint8_t value;
|
||||||
|
uint8_t checksum;
|
||||||
|
|
||||||
|
void validate() {
|
||||||
|
checksum = calcChecksum();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() {
|
||||||
|
return checksum == calcChecksum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t calcChecksum() {
|
||||||
|
return 18 + value + action * 23 + 42 * value+5*dataType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COOLER_CONTROLLER_COMMESSAGE_H
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COOLER_CONTROLLER_CONFIGURATION_H
|
||||||
|
#define COOLER_CONTROLLER_CONFIGURATION_H
|
||||||
|
#define CONFIG_EEPROM_ADDR 0x42
|
||||||
|
|
||||||
|
struct Configuration {
|
||||||
|
uint8_t startTemp;
|
||||||
|
uint8_t maxTemp;
|
||||||
|
uint8_t minLevel;
|
||||||
|
uint8_t maxLevel;
|
||||||
|
uint8_t signature;
|
||||||
|
uint8_t stopTemp;
|
||||||
|
|
||||||
|
bool isValid() {
|
||||||
|
return signature == 0x42;
|
||||||
|
}
|
||||||
|
|
||||||
|
void validate() {
|
||||||
|
signature = 0x42;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate() {
|
||||||
|
signature = 0x00;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COOLER_CONTROLLER_CONFIGURATION_H
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "FanController.h"
|
||||||
|
#include <utils/iohelp.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
FanController::FanController() {
|
||||||
|
|
||||||
|
pinmode_output(DDRC, PORTC0);
|
||||||
|
TCCR0A = 0;
|
||||||
|
TCCR0B = 0;
|
||||||
|
TCCR0A |= (1 << WGM01);// Режим CTC (сброс по совпадению)
|
||||||
|
TCCR0B |= (1 << CS01);// Тактирование от CLK CLK/8
|
||||||
|
OCR0A = 64;
|
||||||
|
TIMSK0 |= (1 << OCIE0A);// Прерывание по совпадению
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t FanController::PWM, FanController::PWMCounter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
ISR(TIMER0_COMPA_vect) {
|
||||||
|
if (FanController::PWM == 0) {
|
||||||
|
PORTC &= ~(1 << PORTC0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (++FanController::PWMCounter == 0) {
|
||||||
|
PORTC |= (1 << PORTC0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (FanController::PWMCounter == FanController::PWM) {
|
||||||
|
PORTC &= ~(1 << PORTC0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COOLER_CONTROLLER_FANCONTROLLER_H
|
||||||
|
#define COOLER_CONTROLLER_FANCONTROLLER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class FanController {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static uint8_t PWM;
|
||||||
|
static uint8_t PWMCounter;
|
||||||
|
|
||||||
|
FanController();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COOLER_CONTROLLER_FANCONTROLLER_H
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
* NTC.cpp
|
||||||
|
*
|
||||||
|
* Created: Ср 11.12.19 21:51:00
|
||||||
|
* Author: User
|
||||||
|
*/
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include "NTC.h"
|
||||||
|
|
||||||
|
namespace NTC {
|
||||||
|
|
||||||
|
|
||||||
|
const PROGMEM NTCValue NTCTable[] = {
|
||||||
|
{-50, 1012},
|
||||||
|
{-49, 1011},
|
||||||
|
{-48, 1010},
|
||||||
|
{-47, 1009},
|
||||||
|
{-46, 1008},
|
||||||
|
{-45, 1007},
|
||||||
|
{-44, 1006},
|
||||||
|
{-43, 1005},
|
||||||
|
{-42, 1003},
|
||||||
|
{-41, 1002},
|
||||||
|
{-40, 1000},
|
||||||
|
{-39, 999},
|
||||||
|
{-38, 997},
|
||||||
|
{-37, 995},
|
||||||
|
{-36, 993},
|
||||||
|
{-35, 991},
|
||||||
|
{-34, 989},
|
||||||
|
{-33, 987},
|
||||||
|
{-32, 984},
|
||||||
|
{-31, 982},
|
||||||
|
{-30, 979},
|
||||||
|
{-29, 976},
|
||||||
|
{-28, 973},
|
||||||
|
{-27, 970},
|
||||||
|
{-26, 967},
|
||||||
|
{-25, 962},
|
||||||
|
{-24, 959},
|
||||||
|
{-23, 956},
|
||||||
|
{-22, 952},
|
||||||
|
{-21, 947},
|
||||||
|
{-20, 942},
|
||||||
|
{-19, 938},
|
||||||
|
{-18, 933},
|
||||||
|
{-17, 928},
|
||||||
|
{-16, 922},
|
||||||
|
{-15, 916},
|
||||||
|
{-14, 910},
|
||||||
|
{-13, 905},
|
||||||
|
{-12, 898},
|
||||||
|
{-11, 891},
|
||||||
|
{-10, 884},
|
||||||
|
{-9, 877},
|
||||||
|
{-8, 870},
|
||||||
|
{-7, 863},
|
||||||
|
{-6, 854},
|
||||||
|
{-5, 845},
|
||||||
|
{-4, 837},
|
||||||
|
{-3, 829},
|
||||||
|
{-2, 820},
|
||||||
|
{-1, 810},
|
||||||
|
{0, 799},
|
||||||
|
{1, 791},
|
||||||
|
{2, 781},
|
||||||
|
{3, 771},
|
||||||
|
{4, 760},
|
||||||
|
{5, 748},
|
||||||
|
{6, 739},
|
||||||
|
{7, 728},
|
||||||
|
{8, 717},
|
||||||
|
{9, 705},
|
||||||
|
{10, 692},
|
||||||
|
{11, 682},
|
||||||
|
{12, 671},
|
||||||
|
{13, 659},
|
||||||
|
{14, 647},
|
||||||
|
{15, 633},
|
||||||
|
{16, 622},
|
||||||
|
{17, 611},
|
||||||
|
{18, 599},
|
||||||
|
{19, 586},
|
||||||
|
{20, 573},
|
||||||
|
{21, 562},
|
||||||
|
{22, 550},
|
||||||
|
{23, 538},
|
||||||
|
{24, 525},
|
||||||
|
{25, 512},
|
||||||
|
{26, 501},
|
||||||
|
{27, 490},
|
||||||
|
{28, 478},
|
||||||
|
{29, 466},
|
||||||
|
{30, 453},
|
||||||
|
{31, 443},
|
||||||
|
{32, 432},
|
||||||
|
{33, 421},
|
||||||
|
{34, 409},
|
||||||
|
{35, 397},
|
||||||
|
{36, 387},
|
||||||
|
{37, 377},
|
||||||
|
{38, 367},
|
||||||
|
{39, 356},
|
||||||
|
{40, 345},
|
||||||
|
{41, 336},
|
||||||
|
{42, 327},
|
||||||
|
{43, 317},
|
||||||
|
{44, 308},
|
||||||
|
{45, 298},
|
||||||
|
{46, 290},
|
||||||
|
{47, 282},
|
||||||
|
{48, 273},
|
||||||
|
{49, 265},
|
||||||
|
{50, 256},
|
||||||
|
{51, 249},
|
||||||
|
{52, 242},
|
||||||
|
{53, 234},
|
||||||
|
{54, 227},
|
||||||
|
{55, 219},
|
||||||
|
{56, 213},
|
||||||
|
{57, 207},
|
||||||
|
{58, 200},
|
||||||
|
{59, 194},
|
||||||
|
{60, 187},
|
||||||
|
{61, 182},
|
||||||
|
{62, 176},
|
||||||
|
{63, 171},
|
||||||
|
{64, 165},
|
||||||
|
{65, 160},
|
||||||
|
{66, 155},
|
||||||
|
{67, 150},
|
||||||
|
{68, 146},
|
||||||
|
{69, 141},
|
||||||
|
{70, 136},
|
||||||
|
{71, 132},
|
||||||
|
{72, 128},
|
||||||
|
{73, 124},
|
||||||
|
{74, 120},
|
||||||
|
{75, 116},
|
||||||
|
{76, 112},
|
||||||
|
{77, 109},
|
||||||
|
{78, 106},
|
||||||
|
{79, 102},
|
||||||
|
{80, 99},
|
||||||
|
{81, 96},
|
||||||
|
{82, 93},
|
||||||
|
{83, 90},
|
||||||
|
{84, 87},
|
||||||
|
{85, 84},
|
||||||
|
{86, 82},
|
||||||
|
{87, 80},
|
||||||
|
{88, 77},
|
||||||
|
{89, 75},
|
||||||
|
{90, 72},
|
||||||
|
{91, 70},
|
||||||
|
{92, 68},
|
||||||
|
{93, 66},
|
||||||
|
{94, 64},
|
||||||
|
{95, 62},
|
||||||
|
{96, 60},
|
||||||
|
{97, 59},
|
||||||
|
{98, 57},
|
||||||
|
{99, 55},
|
||||||
|
{100, 53},
|
||||||
|
{101, 52},
|
||||||
|
{102, 50},
|
||||||
|
{103, 49},
|
||||||
|
{104, 47},
|
||||||
|
{105, 46},
|
||||||
|
{106, 45},
|
||||||
|
{107, 43},
|
||||||
|
{108, 42},
|
||||||
|
{109, 41},
|
||||||
|
{110, 40},
|
||||||
|
{111, 39},
|
||||||
|
{112, 38},
|
||||||
|
{113, 37},
|
||||||
|
{114, 36},
|
||||||
|
{115, 35},
|
||||||
|
{116, 34},
|
||||||
|
{117, 33},
|
||||||
|
{118, 32},
|
||||||
|
{119, 31},
|
||||||
|
{120, 30}
|
||||||
|
};
|
||||||
|
size_t NTCTableCount = sizeof(NTCTable) / sizeof(NTCValue);
|
||||||
|
|
||||||
|
int8_t getTemperature(uint16_t volt) {
|
||||||
|
for (uint8_t i = 0; i < NTCTableCount; i++) {
|
||||||
|
NTCValue item;
|
||||||
|
memcpy_P(&item, &NTCTable[i], sizeof(NTCValue));
|
||||||
|
if (item.value < volt) return item.temp;
|
||||||
|
}
|
||||||
|
return 120;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#ifndef COOLER_CONTROLLER_NTC_H
|
||||||
|
#define COOLER_CONTROLLER_NTC_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
namespace NTC {
|
||||||
|
struct NTCValue {
|
||||||
|
int8_t temp;
|
||||||
|
uint16_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
int8_t getTemperature(uint16_t volt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COOLER_CONTROLLER_NTC_H
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include <utils/ADC.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include "ServiceApp.h"
|
||||||
|
#include "NTC.h"
|
||||||
|
#include <utils/EEPROM.h>
|
||||||
|
|
||||||
|
FanController ServiceApp::Fan;
|
||||||
|
USART ServiceApp::Serial(9600);
|
||||||
|
|
||||||
|
ServiceApp::ServiceApp() {
|
||||||
|
wdt_enable(WDTO_8S);
|
||||||
|
ADCIO::setup();
|
||||||
|
readConfig();
|
||||||
|
FanController::PWM = 255;
|
||||||
|
level = 0;
|
||||||
|
temp = 0;
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ServiceApp::lerp(uint8_t a, uint8_t b, uint8_t t) {
|
||||||
|
return (uint8_t)((float) a + (float) (b - a) * (float) t / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::update() {
|
||||||
|
setFanPWM();
|
||||||
|
communicate();
|
||||||
|
wdt_reset();
|
||||||
|
_delay_ms(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::readConfig() {
|
||||||
|
EEPROM::get(CONFIG_EEPROM_ADDR, &Config, sizeof(Configuration));
|
||||||
|
if (!Config.isValid()) {
|
||||||
|
//default config
|
||||||
|
Config.minLevel = 32;
|
||||||
|
Config.maxLevel = 255;
|
||||||
|
Config.startTemp = 30;
|
||||||
|
Config.maxTemp = 40;
|
||||||
|
Config.stopTemp = 26;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::writeConfig() {
|
||||||
|
Config.validate();
|
||||||
|
EEPROM::set(CONFIG_EEPROM_ADDR, &Config, sizeof(Configuration));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServiceApp::readMessage(Message *dest) {
|
||||||
|
if (Serial.available() >= 4) {
|
||||||
|
dest->action = static_cast<MessageType>(Serial.read());
|
||||||
|
dest->dataType = static_cast<DataType>(Serial.read());
|
||||||
|
dest->value = Serial.read();
|
||||||
|
dest->checksum = Serial.read();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::sendMessage(Message *src) {
|
||||||
|
src->validate();
|
||||||
|
Serial.send(src->action);
|
||||||
|
Serial.send(src->dataType);
|
||||||
|
Serial.send(src->value);
|
||||||
|
Serial.send(src->checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::communicate() {
|
||||||
|
Message message;
|
||||||
|
if (readMessage(&message)) {
|
||||||
|
if (message.isValid()) {
|
||||||
|
switch (message.action) {
|
||||||
|
case SAVE:
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = 255;
|
||||||
|
sendMessage(&message);
|
||||||
|
writeConfig();
|
||||||
|
break;
|
||||||
|
case PING:
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case READ:
|
||||||
|
switch (message.dataType) {
|
||||||
|
case TEMP:
|
||||||
|
message.value = temp;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case LEVEL:
|
||||||
|
message.value = level;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case START_TEMP:
|
||||||
|
message.value = Config.startTemp;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MAX_TEMP:
|
||||||
|
message.value = Config.maxTemp;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MIN_LEVEL:
|
||||||
|
message.value = Config.minLevel;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MAX_LEVEL:
|
||||||
|
message.value = Config.maxLevel;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message.action = ERROR;
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = ERR_UNKNOWN_DATA_TYPE;
|
||||||
|
sendMessage(&message);
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case STOP_TEMP:
|
||||||
|
message.value = Config.stopTemp;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WRITE:
|
||||||
|
switch (message.dataType) {
|
||||||
|
case STOP_TEMP:
|
||||||
|
Config.stopTemp = message.value;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case TEMP:
|
||||||
|
case LEVEL:
|
||||||
|
message.action = ERROR;
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = ERR_UNSUPPORTED_OPERATION;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case START_TEMP:
|
||||||
|
Config.startTemp = message.value;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MAX_TEMP:
|
||||||
|
Config.maxTemp = message.value;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MIN_LEVEL:
|
||||||
|
Config.minLevel = message.value;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
case MAX_LEVEL:
|
||||||
|
Config.maxLevel = message.value;
|
||||||
|
sendMessage(&message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message.action = ERROR;
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = ERR_UNKNOWN_DATA_TYPE;
|
||||||
|
sendMessage(&message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REBOOT:
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = 255;
|
||||||
|
sendMessage(&message);
|
||||||
|
wdt_disable();
|
||||||
|
wdt_enable(WDTO_500MS);
|
||||||
|
while (true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message.action = ERROR;
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = ERR_UNKNOWN_ACTION_TYPE;
|
||||||
|
sendMessage(&message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.action = ERROR;
|
||||||
|
message.dataType = NONE;
|
||||||
|
message.value = ERR_INVALID_CHECKSUM;
|
||||||
|
sendMessage(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comCounter++ == 0) {
|
||||||
|
message.action = PING;
|
||||||
|
message.value = 0x42;
|
||||||
|
message.dataType = NONE;
|
||||||
|
sendMessage(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServiceApp::setFanPWM() {
|
||||||
|
temp = NTC::getTemperature(ADCIO::read(ADC6));
|
||||||
|
uint8_t minTemp = min(Config.startTemp, Config.stopTemp);
|
||||||
|
|
||||||
|
if (temp >= Config.maxTemp) { //выставить макс. мощность если темп выше или равна максимальной
|
||||||
|
level = Config.maxLevel;
|
||||||
|
} else if (temp <= minTemp) { //вылкючить если температура меньше или равна минимальной из двух (старт или стоп)
|
||||||
|
level = 0;
|
||||||
|
FanController::PWM = 0;
|
||||||
|
return;
|
||||||
|
} else if (temp >= Config.startTemp) { //мощность вычисляется в зависимости от температуры если темп больше стартовой
|
||||||
|
uint8_t interpolation = (uint8_t)(100.0f * (float) (temp - Config.startTemp) /
|
||||||
|
(float) (Config.maxTemp - Config.startTemp));
|
||||||
|
level = lerp(Config.minLevel, Config.maxLevel, interpolation > 100 ? 100 : interpolation);
|
||||||
|
}else if(level > 0){
|
||||||
|
//если темп больше stopTemp но меньше startTemp то задаем минимальную мощность
|
||||||
|
level = Config.minLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FanController::PWM == 0 && level > 0) {
|
||||||
|
//не стартуем с 0 мощности
|
||||||
|
FanController::PWM = 32;
|
||||||
|
} else {
|
||||||
|
if (FanController::PWM > level) {
|
||||||
|
//slow decrease
|
||||||
|
if (FanController::PWM - level > 5) {
|
||||||
|
FanController::PWM -= 1;
|
||||||
|
} else {
|
||||||
|
FanController::PWM = level;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FanController::PWM = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ServiceApp::clamp(float a, float min, float max) {
|
||||||
|
return (a < min ? min : (a > max ? max : a));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ServiceApp::min(uint8_t a, uint8_t b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// Created by kirillius on 09.04.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COOLER_CONTROLLER_SERVICEAPP_H
|
||||||
|
#define COOLER_CONTROLLER_SERVICEAPP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <usart/usart.h>
|
||||||
|
#include "FanController.h"
|
||||||
|
#include "Configuration.h"
|
||||||
|
#include "ComMessage.h"
|
||||||
|
|
||||||
|
class ServiceApp {
|
||||||
|
private:
|
||||||
|
static USART Serial;
|
||||||
|
static FanController Fan;
|
||||||
|
Configuration Config;
|
||||||
|
int8_t temp;
|
||||||
|
uint8_t level;
|
||||||
|
uint8_t comCounter;
|
||||||
|
|
||||||
|
|
||||||
|
void readConfig();
|
||||||
|
|
||||||
|
void writeConfig();
|
||||||
|
|
||||||
|
bool readMessage(Message *dest);
|
||||||
|
|
||||||
|
void sendMessage(Message *src);
|
||||||
|
|
||||||
|
void communicate();
|
||||||
|
|
||||||
|
void setFanPWM();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ServiceApp();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
static uint8_t lerp(uint8_t a, uint8_t b, uint8_t t);
|
||||||
|
static float clamp(float a, float min, float max);
|
||||||
|
static uint8_t min(uint8_t a, uint8_t b);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COOLER_CONTROLLER_SERVICEAPP_H
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include "ServiceApp.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
wdt_disable();
|
||||||
|
ServiceApp app;
|
||||||
|
do app.update(); while (true);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"modules":[{"path":"lib/utils","uri":"https://svn.kirillius.ru/mcu-avr/avr-iohelp/trunk/lib/utils","revision":"HEAD"},{"path":"lib/usart","uri":"https://svn.kirillius.ru/mcu-avr/avr-usart/trunk/lib/usart","revision":"HEAD"}]}
|
||||||
Reference in New Issue