Commit 6ee78744 authored by Oleg Nikulin's avatar Oleg Nikulin

В hddtempserial_rpm.ino сделано независимое управление 3 кулерами. Для этого…

В hddtempserial_rpm.ino сделано независимое управление 3 кулерами. Для этого нужно запускать скрипт с флагом -m и вводить без пробелов 3 скаважности ШИМ, от 0 до 255. Обязятально должно быть по 3 цифры. Например 050100200 запустит первую группу на 50, вторую на 100, третью на 200
parent c63a9324
......@@ -180,7 +180,7 @@ while True:
baudrate = SPEED
)
connected = True
except OSError: pass
except OSError: print('...')
time.sleep(RECONNECT_SLEEP_TIME)
......
......@@ -19,7 +19,7 @@
int pwmPins[3] = {3, 5, 6}; //Номера пинов ШИМ
volatile bool pwmState = 0; //Состояние ШИМ
volatile bool pwm_on = 1; // ==1, если ШИМ включен
volatile bool pwm_ons[3] = {1, 1, 1}; // ==1, если ШИМ включен
int tachPins[FAN_COUNT] = {14, 15, 16, 17, 18, 19}; //Номера пинов для считывания оборотов
volatile uint16_t tachRevs[FAN_COUNT] = {}; //Обороты (просто сколько насчитано оборотов, а не rpm)
......@@ -47,6 +47,8 @@ volatile bool tachStates[FAN_COUNT] = {}; //Состояния (оборот с
int temp; //Температура, полученная от пк
int target_rpm = 0;
int dutyCycles[3] = {DEFAULT_PWM_DUTY_CYCLE, DEFAULT_PWM_DUTY_CYCLE, DEFAULT_PWM_DUTY_CYCLE};
uint32_t last_beep_time = 0;
uint32_t last_check_time = 0;
uint32_t lastRpmCheck = 0;
......@@ -61,8 +63,7 @@ float k_i = 0.0004;
float k_d = 160;
bool flag = 0;
void wait_for_connection(bool beep) { //функция, которая мигает светодиодом и пищит (если beep == true) до тех пор, пока не будет установлено соединение с ПК
Serial.println("start_transmission");
......@@ -115,7 +116,7 @@ void tempFromPc()// получаем температуру от пк
}
}
Serial.println("req_temperature_" + rpm_string + "_debug_" + String(OCR2B)); //запрос к пк
Serial.println("req_temperature_" + rpm_string + "_debug_" + String(OCR2A) + "_" + String(OCR2B) + "_" + String(OCR1A)); //запрос к пк
unsigned long query_time = millis();
while (Serial.available() == 0) { //ждем пока ответит
if (millis() >= query_time + GET_TEMP_TIMEOUT) { //если слишком долго не отвечает
......@@ -127,8 +128,11 @@ void tempFromPc()// получаем температуру от пк
break;
}
}
String response = Serial.readStringUntil('\n');
temp = response.substring(12).toInt();
String response = Serial.readStringUntil('\n'); //выделяем строку до \n
response = response.substring(12); //отбрасываем temperature_ в начале
dutyCycles[0] = response.substring(0, 3).toInt();
dutyCycles[1] = response.substring(3, 6).toInt();
dutyCycles[2] = response.substring(6, 9).toInt();
}
......@@ -144,6 +148,7 @@ void autocontrol()//Автоконтроль температуры
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];
......@@ -151,90 +156,135 @@ void rpm_control() {
tachRpm[fan][RPM_VALUES_COUNT - 1] = (tachRevs[fan] * (60000 / uint32_t(millis() - lastRpmCheck))) / 2;
tachRevs[fan] = 0;
}
/*
uint32_t avg_rpm = 0;
const int fan = 0;
uint32_t avg_rpm = 0;
const int fan = 0;
for (int val = 0; val < RPM_VALUES_COUNT; val++) {
avg_rpm += tachRpm[fan][val];
}
avg_rpm /= RPM_VALUES_COUNT;
for (int val = 0; val < RPM_VALUES_COUNT; val++) {
avg_rpm += tachRpm[fan][val];
}
avg_rpm /= RPM_VALUES_COUNT;
float pwmDutyCycle = 0;
uint8_t byte_pwmDutyCycle = 0;
float pwmDutyCycle = 0;
uint8_t byte_pwmDutyCycle = 0;
d = (target_rpm - int(avg_rpm) - p) / float(millis() - lastRpmCheck);
p = target_rpm - int(avg_rpm);
i = i + p * (millis() - lastRpmCheck);
d = (target_rpm - int(avg_rpm) - p) / float(millis() - lastRpmCheck);
p = target_rpm - int(avg_rpm);
i = i + p * (millis() - lastRpmCheck);
pwmDutyCycle = round(p * k_p + i * k_i + d * k_d);
pwmDutyCycle = round(p * k_p + i * k_i + d * k_d);
if (pwmDutyCycle <= 1) {
byte_pwmDutyCycle = 1;
}
else if (pwmDutyCycle >= MAX_PWM_DUTY_CYCLE) {
byte_pwmDutyCycle = MAX_PWM_DUTY_CYCLE;
}
else {
byte_pwmDutyCycle = pwmDutyCycle;
}
if (pwmDutyCycle <= 1) {
byte_pwmDutyCycle = 1;
}
else if (pwmDutyCycle >= MAX_PWM_DUTY_CYCLE) {
byte_pwmDutyCycle = MAX_PWM_DUTY_CYCLE;
}
else {
byte_pwmDutyCycle = pwmDutyCycle;
}
byte_pwmDutyCycle = 255 - byte_pwmDutyCycle;
if (byte_pwmDutyCycle == 0) {
if (pwm_on == 1) {
pwm_on = 0; //выкл ШИМ
for (int i = 0; i < 3; i++) {//выкл пины ШИМ
digitalWrite(pwmPins[i], 0);
if (byte_pwmDutyCycle == 0) {
if (pwm_on == 1) {
pwm_on = 0; //выкл ШИМ
for (int i = 0; i < 3; i++) {//выкл пины ШИМ
digitalWrite(pwmPins[i], 0);
}
}
}
else {
if (pwm_on == 0) {
pwm_on = 1; //вкл ШИМ
}
OCR2B = byte_pwmDutyCycle; //установка скважности
}
//Почему-то иногда может заглючить: скважность стоит 254, pwm_on равно 1, но вентилятор не крутится (но пищит). Похоже каким-то образом меняется pwmState, когда не надо
//Serial.println("debug_" + String(byte_pwmDutyCycle));
*/
lastRpmCheck = millis();
for (int i = 0; i < 3; i++) {
if (uint8_t(dutyCycles[i]) == 0) {
if (pwm_ons[i]) {
pwm_ons[i] = 0;
}
}
}
else {
if (pwm_on == 0) {
pwm_on = 1; //вкл ШИМ
else {
if (!pwm_ons[i]) {
pwm_ons[i] = 1;
}
switch (i) {
case 0:
OCR2A = dutyCycles[i];
break;
case 1:
OCR2B = dutyCycles[i];
break;
case 2:
OCR1A = dutyCycles[i];
break;
}
}
OCR2B = byte_pwmDutyCycle; //установка скважности
}
//Почему-то иногда может заглючить: скважность стоит 254, pwm_on равно 1, но вентилятор не крутится (но пищит). Похоже каким-то образом меняется pwmState, когда не надо
//Serial.println("debug_" + String(byte_pwmDutyCycle));
lastRpmCheck = millis();
}
ISR(TIMER1_COMPA_vect) { //Функция, вызываемая при прерывании 1A
digitalWrite(6, 0);
}
ISR(TIMER2_COMPA_vect) { //Функция, вызываемая при прерывании 2A
digitalWrite(3, 0);
}
ISR(TIMER2_COMPB_vect) { //Функция, вызываемая при прерывании 2B
digitalWrite(5, 0);
}
ISR(TIMER2_OVF_vect) { //Функция, вызываемая при переполнении таймера 2
ISR(TIMER2_COMPA_vect) { //Функция, вызываемая при прерывании A
for (int i = 0; i < 3; i++) { //Вкл. питание
digitalWrite(pwmPins[i], 1);
if (pwm_ons[i]) {
digitalWrite(pwmPins[i], 1);
}
}
//Проверка тахометров
//считывание оборотов:
for (int i = 0; i < FAN_COUNT; i++) {
if (digitalRead(tachPins[i]) == 0 && tachStates[i] == 0) { //сигнал тахометра появился
tachStates[i] = 1;
//digitalWrite(13, 1);
digitalWrite(13, 1);
}
else if (digitalRead(tachPins[i]) == 1 && tachStates[i] == 1) { //сигнал тахометра пропал
//digitalWrite(13, 0);
digitalWrite(13, 0);
tachStates[i] = 0;
tachRevs[i]++; //засчитывается оборот
}
}
}
ISR(TIMER2_COMPB_vect) { //Функция, вызываемая при прерывании B
for (int i = 0; i < 3; i++) { //Выкл. питание
digitalWrite(pwmPins[i], 0);
}
}
bool getbitstate(int num, uint8_t bit_pos) {
bool bits_array[8];
for (int i = 0; i < 8; i++) {
bits_array[i] = num >> (8 - 1 - i) & 1;
}
return bits_array[bit_pos];
}
......@@ -250,14 +300,27 @@ void setup() {
pinMode(tachPins[i], INPUT_PULLUP);
}
//запуск таймера в режиме fast pwm
//таймер 2 сравнение A - пин 3
//таймер 2 сравнение B - пин 5
//таймер 1 сравнение A - пин 6
//режим таймера 1 (fast pwm):
TCCR1B |= (1 << WGM12);
TCCR1A |= (1 << WGM10);
//режим таймера 2 (fast pwm):
TCCR2A |= (1 << WGM21);
TCCR2A |= (1 << WGM20);
TIMSK2 |= (1 << OCIE2A); //вкл. вызов прерывания по сравнению A
TIMSK2 |= (1 << OCIE2B); //вкл. вызов прерывания по сравнению B
TIMSK1 |= (1 << OCIE1A); //вкл. вызов прерывания таймера 1 по сравнению A
TIMSK2 |= (1 << OCIE2A); //вкл. вызов прерывания таймера 2 по сравнению A
TIMSK2 |= (1 << OCIE2B); //вкл. вызов прерывания таймера 2 по сравнению B
TIMSK2 |= (1 << TOIE2); //вкл. вызов прерывания при переполнении таймера 2
OCR2B = DEFAULT_PWM_DUTY_CYCLE; //Прерывание B происходит, когда значение таймера совпадает с этим. (По сути это скважность ШИМ)
OCR1A = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 1A (скважность ШИМ)
OCR2A = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 2A (скважность ШИМ)
OCR2B = DEFAULT_PWM_DUTY_CYCLE; //Значение для сравнения 2B (скважность ШИМ)
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