Commit 750c1fd4 authored by Oleg Nikulin's avatar Oleg Nikulin

В прошивке добавлены структуры вентиляторов и групп управления

parent 922852f7
#include <Wire.h>
#define FAN_COUNT 6 //Количество вентиляторов
#define CONTROL_COUNT 3 //Количество групп управления
#define BAUDRATE 19200 //Скорость serial порта
#define CHECK_TEMP_DELAY 200 //Интервал получения температуры от пк (мс)
#define GET_TEMP_TIMEOUT 1000 //Если в течение этого времени температура не была прислана, считается что пк не отвечает (мс)
......@@ -18,44 +19,107 @@
#define SOUND_PIN 10 //Номер пина пищалки
#define LED_PIN 13 //Номер пина светодиода
int pwmPins[3] = {3, 5, 6}; //Номера пинов ШИМ
volatile bool pwmState = 0; //Состояние ШИМ
volatile uint8_t pwm_modes[3] = {1, 1, 1}; // 0 - всегда выкл, 1 - шим, 2 - всегда вкл
float a;
int tachPins[FAN_COUNT] = {14, 15, 16, 17, 18, 19}; //Номера пинов для считывания оборотов
volatile uint16_t tachRevs[FAN_COUNT] = {}; //Обороты (просто сколько насчитано оборотов, а не rpm)
uint16_t tachRpm[FAN_COUNT][RPM_VALUES_COUNT] = {}; //rpm
volatile bool tachStates[FAN_COUNT] = {}; //Состояния (оборот считывается только если состояние == 0, и считывается 0)
uint8_t *control_a_addr = 0x88; //адрес сравнения А таймера 1
uint8_t *control_b_addr = 0xB3; //адрес сравнения А таймера 2
uint8_t *control_c_addr = 0xB4; //адрес сравнения B таймера 2
struct control {//Данные о группе управления
uint8_t pin; //Номер пина
volatile uint8_t mode; //Текущий режим работы. 0 - всегда выкл, 1 - шим, 2 - всегда вкл
uint8_t &dutyCycle; //Скважность ШИМ
};
control controls[CONTROL_COUNT] = {
{
3,
1,
*control_a_addr
},
{
5,
1,
*control_b_addr
},
{
6,
1,
*control_c_addr
}
};
control &control_a = controls[0];
control &control_b = controls[1];
control &control_c = controls[2];
struct fan { //Данные о вентиляторе
int pin; //Номер пина тахометра
bool type; //Тип датчика. 0 = униполярный, 1 = биполярный
volatile bool state; //Состояние тахометра
volatile uint16_t revs; //Количество оборотов (просто, не в минуту)
uint16_t rpm[RPM_VALUES_COUNT]; //Обороты в минуту
};
fan fans[FAN_COUNT] = {
{
14,
1,
0,
0,
0
},
{
15,
1,
0,
0,
0
},
{
16,
1,
0,
0,
0
},
{
17,
1,
0,
0,
0
},
{
18,
1,
0,
0,
0
},
{
19,
2,
0,
0,
0
}
};
/*
struct fan { //Данные о вентиляторе
int tachPin; //Номер пина тахометра
bool tachState; //Состояние тахометра
bool tachType; //Тип датчика. 0 = униполярный, 1 = биполярный
uint16_t revs; //Количество оборотв (просто, не в минуту)
uint16_t rpm; //Обороты в минуту
uint32_t lastSignalStart; //Время начала последнего сигнала тахометра
uint32_t lastSignalEnd; //Время окончания последнего сигнала тахометра
};
fan &fan_1 = fans[0];
fan &fan_2 = fans[1];
fan &fan_3 = fans[2];
fan &fan_4 = fans[3];
fan &fan_5 = fans[4];
fan &fan_6 = fans[5];
struct control { //Данные о контроллерах вентилятора
int pwmPin; //Номер пина ШИМ
bool pwmState; //Состояние пина ШИМ
};
*/
int temps[3] = {}; //Температуры, полученные от пк
int target_rpms[3] = {};
int target_rpms[3] = {}; //Обороты, которые нужно держать (в этой прошивке target_rpms и temps это одно и то же)
uint32_t last_beep_time = 0;
uint32_t last_check_time = 0;
uint32_t lastRpmCheck = 0;
uint32_t lastRevTime = 0;
float p[3] = {};
float i[3] = {};
......@@ -110,7 +174,7 @@ void tempFromPc()// получаем температуру от пк
uint32_t avg_rpm = 0;
for (int val = 0; val < RPM_VALUES_COUNT; val++) {
avg_rpm += tachRpm[fan][val];
avg_rpm += fans[fan].rpm[val];
}
avg_rpm /= RPM_VALUES_COUNT;
......@@ -125,8 +189,8 @@ void tempFromPc()// получаем температуру от пк
while (Serial.available() == 0) { //ждем пока ответит
if (millis() >= query_time + GET_TEMP_TIMEOUT) { //если слишком долго не отвечает
//Венитялторы на максимум
for (int i = 0; i < 3; i++) {
OCR2B = 254;
for (int i = 0; i < CONTROL_COUNT; i++) {
controls[i].dutyCycle = MAX_PWM_DUTY_CYCLE; //установка скважности по умолчанию
}
wait_for_connection(true);//снова ждем подключения
break;
......@@ -199,22 +263,23 @@ void rpm_control() {
for (int fan = 0; fan < FAN_COUNT; fan++) { //подсчет об/мин, обнуление насчитанных оборотов
for (int val = 0; val < RPM_VALUES_COUNT - 1; val++) {
tachRpm[fan][val] = tachRpm[fan][val + 1];
fans[fan].rpm[val] = fans[fan].rpm[val + 1];
}
tachRpm[fan][RPM_VALUES_COUNT - 1] = (tachRevs[fan] * (60000 / uint32_t(millis() - lastRpmCheck))) / 2;
tachRevs[fan] = 0;
fans[fan].rpm[RPM_VALUES_COUNT - 1] = (fans[fan].revs * (60000 / uint32_t(millis() - lastRpmCheck))) / (1 + fans[fan].type);
fans[fan].revs = 0;
}
for (int group = 0; group < 3; group++) { //PID управление скоростью 3-х групп вентиляторов
uint8_t duty_cycle = 0;
/*
uint8_t duty_cycle = 0;
if (target_rpms[group] > 0) {
if (target_rpms[group] > 0) {
uint32_t avg_rpm = 0;
//вычисление средних rpm из нескольких значений, записанных для фильтра
for (int val = 0; val < RPM_VALUES_COUNT; val++) {
avg_rpm += tachRpm[group * 2][val];
avg_rpm += fans[group * 2].rpm[val];
}
avg_rpm /= RPM_VALUES_COUNT;
......@@ -237,36 +302,27 @@ void rpm_control() {
duty_cycle = pwmDutyCycle;
}
}
else {
duty_cycle = 0;
}
}
else {
duty_cycle = 0;
}
*/
uint8_t duty_cycle = target_rpms[group];
if (duty_cycle < MIN_PWM_DUTY_CYCLE) {
pwm_modes[group] = 0; //всегда выкл
digitalWrite(pwmPins[group], 0);
controls[group].mode = 0; //всегда выкл
digitalWrite(controls[group].pin, 0);
}
else if (duty_cycle > MAX_PWM_DUTY_CYCLE) {
pwm_modes[group] = 2; //всегда вкл
digitalWrite(pwmPins[group], 1);
controls[group].mode = 2; //всегда вкл
digitalWrite(controls[group].pin, 1);
}
else {
pwm_modes[group] = 1; //шим
controls[group].mode = 1; //шим
}
switch (group) {
case 0:
OCR1A = duty_cycle;
break;
case 1:
OCR2A = duty_cycle;
break;
case 2:
OCR2B = duty_cycle;
break;
}
controls[group].dutyCycle = duty_cycle;
}
......@@ -279,23 +335,20 @@ void rpm_control() {
ISR(TIMER1_COMPA_vect) { //Функция, вызываемая при прерывании 1A
// digitalWrite(3, 0);
if (pwm_modes[0] < 2) { //если не всегда вкл
if (control_a.mode < 2) { //если не всегда вкл
PORTD &= 0b1110111; //выкл питание на пине 3
}
}
ISR(TIMER2_COMPA_vect) { //Функция, вызываемая при прерывании 2A
// digitalWrite(5, 0);
if (pwm_modes[0] < 2) { //если не всегда вкл
if (control_b.mode < 2) { //если не всегда вкл
PORTD &= 0b11011111; //выкл питание на пине 5
}
}
ISR(TIMER2_COMPB_vect) { //Функция, вызываемая при прерывании 2B
// digitalWrite(6, 0);
if (pwm_modes[0] < 2) { //если не всегда вкл
if (control_c.mode < 2) { //если не всегда вкл
PORTD &= 0b10111111; //выкл питание на пине 6
}
}
......@@ -303,20 +356,19 @@ ISR(TIMER2_COMPB_vect) { //Функция, вызываемая при прер
ISR(TIMER1_OVF_vect) { //Функция, вызываемая при переполнении таймера 1
int i = 0;
if (pwm_modes[i] > 0) { //если режим шим или всегда вкл
digitalWrite(pwmPins[i], 1);
if (control_a.mode > 0) { //если режим шим или всегда вкл
digitalWrite(control_a.pin, 1);
}
delayMicroseconds(15);
for (int i = 0; i < 2; i++) { //проверка тахометров 0-1
if (digitalRead(tachPins[i]) == 0 && tachStates[i] == 0) { //сигнал тахометра появился
tachStates[i] = 1;
if (digitalRead(fans[i].pin) == 0 && fans[i].state == 0) { //сигнал тахометра появился
fans[i].state = 1;
//digitalWrite(13, 1);
}
else if (digitalRead(tachPins[i]) == 1 && tachStates[i] == 1) { //сигнал тахометра пропал
else if (digitalRead(fans[i].pin) == 1 && fans[i].state == 1) { //сигнал тахометра пропал
//digitalWrite(13, 0);
tachStates[i] = 0;
tachRevs[i]++; //засчитывается оборот
fans[i].state = 0;
fans[i].revs++; //засчитывается оборот
}
}
}
......@@ -324,22 +376,22 @@ ISR(TIMER1_OVF_vect) { //Функция, вызываемая при переп
ISR(TIMER2_OVF_vect) { //Функция, вызываемая при переполнении таймера 2
if (pwm_modes[1] > 0) { //если режим шим или всегда вкл
if (control_b.mode > 0) { //если режим шим или всегда вкл
PORTD |= 0b00100000; //вкл питание на пине 5
}
if (pwm_modes[2] > 0) { //если режим шим или всегда вкл
if (control_c.mode > 0) { //если режим шим или всегда вкл
PORTD |= 0b01000000; //вкл питание на пине 6
}
//delayMicroseconds(10);
for (int i = 2; i < 6; i++) { //проверка тахометров 2-5
if (digitalRead(tachPins[i]) == 0 && tachStates[i] == 0) { //сигнал тахометра появился
tachStates[i] = 1;
if (digitalRead(fans[i].pin) == 0 && fans[i].state == 0) { //сигнал тахометра появился
fans[i].state = 1;
//digitalWrite(13, 1);
}
else if (digitalRead(tachPins[i]) == 1 && tachStates[i] == 1) { //сигнал тахометра пропал
else if (digitalRead(fans[i].pin) == 1 && fans[i].state == 1) { //сигнал тахометра пропал
//digitalWrite(13, 0);
tachStates[i] = 0;
tachRevs[i]++; //засчитывается оборот
fans[i].state = 0;
fans[i].revs++; //засчитывается оборот
}
}
......@@ -361,12 +413,12 @@ void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(SOUND_PIN, OUTPUT);
for (int i = 0; i < 3; i++) {
pinMode(pwmPins[i], OUTPUT);
for (int i = 0; i < CONTROL_COUNT; i++) {
pinMode(controls[i].pin, OUTPUT);
}
for (int i = 0; i < FAN_COUNT; i++) {
pinMode(tachPins[i], INPUT_PULLUP);
pinMode(fans[i].pin, INPUT_PULLUP);
}
//таймер 1 сравнение A - пин 3
......@@ -391,10 +443,9 @@ void setup() {
TIMSK2 |= (1 << OCIE2B); //вкл. вызов прерывания таймера 2 по сравнению B
TIMSK2 |= (1 << TOIE2); //вкл. вызов прерывания при переполнении таймера 2
OCR1A = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 1A (скважность ШИМ пина 3)
OCR2A = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 2A (скважность ШИМ пина 5)
OCR2B = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 2B (скважность ШИМ пина 6)
for (int i = 0; i < CONTROL_COUNT; i++) {
controls[i].dutyCycle = DEFAULT_PWM_DUTY_CYCLE; //установка скважности по умолчанию
}
Serial.begin(BAUDRATE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment