diff --git a/F0-nolib/Socket_fans/adc.c b/F0-nolib/Socket_fans/adc.c index 8c8cc8a..c347e23 100644 --- a/F0-nolib/Socket_fans/adc.c +++ b/F0-nolib/Socket_fans/adc.c @@ -98,16 +98,16 @@ uint32_t getU5(){ * @return */ int16_t getNTC(int nch){ -#define NKNOTS (9) - const int16_t ADU[NKNOTS] = {427, 468, 514, 623, 754, 910, 1087, 1295, 1538}; - const int16_t T[NKNOTS] = {-200, -180, -159, -116, -72, -26, 23, 75, 132}; +#define NKNOTS (14) + const int16_t ADU[NKNOTS] = {732, 945, 1197, 2035, 2309, 2542, 2739, 2859, 2969, 3068, 3154, 3228, 3293, 3347}; + const int16_t T[NKNOTS] = {100, 160, 227, 438, 508, 571, 628, 666, 702, 738, 772, 805, 837, 869}; /* - * coefficients: 0.050477 0.045107 0.039150 0.033639 0.029785 0.027017 0.024996 0.023522 0.022514 + * coefficients: 0.028261 0.026536 0.025136 0.025738 0.027044 0.028922 0.031038 0.033255 0.036056 0.039606 0.044173 0.050296 0.058920 0.071729 * use - * [N D] = rat(K*10); printf("%d, ", N); printf("%d, ", D); + * [N D] = rat(K*10); printf("N="); printf("%d, ", N); printf("\nD="); printf("%d, ", D);printf("\n"); */ - const int16_t N[NKNOTS] = {1377, 295, 258, 110, 291, 77, 1657, 191, 120}; - const int16_t D[NKNOTS] = {2728, 654, 659, 327, 977, 285, 6629, 812, 533}; + const int16_t N[NKNOTS] = {13, 95, 185, 96, 43, 153, 347, 141, 128, 261, 235, 85, 393, 307}; + const int16_t D[NKNOTS] = {46, 358, 736, 373, 159, 529, 1118, 424, 355, 659, 532, 169, 667, 428}; if(nch < 0 || nch > 3) return -30000; uint16_t val = getADCval(nch); diff --git a/F0-nolib/Socket_fans/hardware.c b/F0-nolib/Socket_fans/hardware.c index 9b5d832..5689cb7 100644 --- a/F0-nolib/Socket_fans/hardware.c +++ b/F0-nolib/Socket_fans/hardware.c @@ -25,6 +25,7 @@ #include "hardware.h" #include "proto.h" +volatile uint32_t Cooler1RPM; // Cooler1 RPM counter by EXTI @PA7 buzzer_state buzzer = BUZZER_OFF; // buzzer state void adc_setup(){ @@ -103,9 +104,6 @@ static inline void timers_setup(){ RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable clocking TIM1->PSC = 19; // F=48/20 = 2.4MHz TIM1->ARR = 100; // PWM frequency = 2.4/101 = 23.76kHz - TIM1->CCR1 = 20; // near 20% PWM duty cycle - TIM1->CCR2 = 20; // near 20% PWM duty cycle - //TIM1->CCR3 = 20; // CCR3 is zero - should be activated on cooler3 settings // PWM mode 1 (OCxM = 110), preload enable TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE; diff --git a/F0-nolib/Socket_fans/hardware.h b/F0-nolib/Socket_fans/hardware.h index 5f45d2d..86cfbbb 100644 --- a/F0-nolib/Socket_fans/hardware.h +++ b/F0-nolib/Socket_fans/hardware.h @@ -75,8 +75,7 @@ typedef enum{ #define SHORT_BUZZER_PAUSE (9500) extern volatile uint32_t Tms; -extern volatile uint32_t Cooler0speed; -extern volatile uint32_t Cooler1speed; +extern volatile uint32_t Coolerspeed[2]; extern volatile uint32_t Cooler1RPM; extern buzzer_state buzzer; diff --git a/F0-nolib/Socket_fans/main.c b/F0-nolib/Socket_fans/main.c index 645f69e..93e2524 100644 --- a/F0-nolib/Socket_fans/main.c +++ b/F0-nolib/Socket_fans/main.c @@ -20,20 +20,23 @@ */ #include "hardware.h" +#include "monitor.h" #include "proto.h" #include "usb.h" #include "usb_lib.h" volatile uint32_t Tms = 0; +volatile uint32_t Coolerspeed[2]; // RPM of cooler0/1 + /* Called when systick fires */ void sys_tick_handler(void){ static uint32_t actr = 0; ++Tms; if(++actr == 1000){ // RPM counter - Cooler0speed = TIM3->CNT/2; + Coolerspeed[0] = TIM3->CNT/2; TIM3->CNT = 0; - Cooler1speed = Cooler1RPM/2; + Coolerspeed[1] = Cooler1RPM/2; Cooler1RPM = 0; actr = 0; } @@ -73,7 +76,7 @@ static char *get_USB(){ } int main(void){ - //uint32_t lastT = 0; + uint32_t lastT = 0; char *txt; sysreset(); SysTick_Config(6000, 1); @@ -82,12 +85,15 @@ int main(void){ RCC->CSR |= RCC_CSR_RMVF; // remove reset flags iwdg_setup(); + ON(COOLER0); // turn on power, manage only by PWM + ON(COOLER1); + while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog - /*if(lastT && (Tms - lastT > 199)){ - LED_off(LED0); - lastT = 0; - }*/ + if(Tms - lastT > MONITOR_PERIOD){ + process_monitor(); + lastT = Tms; + } usb_proc(); if((txt = get_USB())){ IWDG->KR = IWDG_REFRESH; diff --git a/F0-nolib/Socket_fans/monitor.c b/F0-nolib/Socket_fans/monitor.c new file mode 100644 index 0000000..48f5a15 --- /dev/null +++ b/F0-nolib/Socket_fans/monitor.c @@ -0,0 +1,180 @@ +/* + * This file is part of the SockFans project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "adc.h" +#include "monitor.h" +#include "proto.h" + +// when critical T reached wait for TturnOff ms and after that turn off system +#define TturnOff (20000) +// don't mind when button 2 pressed again after t<5s +#define TbtnPressed (5000) + +// settings +// T0 - CPU, T1 - HDD, T2 - inner T, T3 - power source +static const int16_t Thysteresis = 30; // hysteresis by T=3degC +static const int16_t tmin[3] = {400, 350, 350}; // turn off fans when T[x]tmin+Th +static const int16_t tmax[3] = {900, 800, 600}; // critical T, turn off power after TturnOff milliseconds +static const int16_t t3max = 850; + +static uint8_t dontprocess = 0; // don't process monitor + +static uint32_t TOff = 0; // time to turn off power +static void chkOffRelay(){ + if(Tms > TOff){ + TOff = 0; + OFF(RELAY); + SEND("Turn off power"); + buzzer = BUZZER_OFF; + }else SEND("TCRITSHUTDOWNn"); + NL(); +} +static void startOff(){ + SEND("TCRITSHUTDOWN"); NL(); + TOff = Tms + TturnOff; + if(TOff == 0) TOff = 1; + buzzer = BUZZER_LONG; +} + +// check buttons state +static void chkButtons(){ + static uint32_t Tpressed = 0; + if(CHK(BUTTON0) == 0){ // button 0 pressed - turn on power if was off + if(CHK(RELAY) == 0){ + ON(RELAY); + SEND("Button0: relay ON");NL(); + } + dontprocess = 0; + } + if(CHK(BUTTON1) == 0){ // button 1 - all OFF + if(Tpressed){ // already pressed recently + if(Tms - Tpressed < TbtnPressed) return; + } + Tpressed = Tms; + if(Tpressed == 0) Tpressed = 1; + buzzer = BUZZER_OFF; + TIM1->CCR1 = 0; TIM1->CCR2 = 0; TIM1->CCR3 = 0; + OFF(RELAY); + dontprocess = 1; + SEND("Everything is OFF immediately");NL(); + }else Tpressed = 0; +} + +// monitor temperatures and do something +void process_monitor(){ + chkButtons(); + if(dontprocess) return; + int16_t T; + static uint8_t coolerproblem[2] = {0,0}; // cooler don't run + static uint8_t offreason[4] = {0}; // whos T was critical for turning power off + // check all 4 temperatures + // T0..1 - coolers + for(int x = 0; x < 2; ++x){ + T = getNTC(x); + volatile uint32_t *ccr = (x == 0) ? &TIM1->CCR1 : &TIM1->CCR2; + uint32_t RPM = *ccr; + uint32_t speed = Coolerspeed[x]; + if(T < tmin[x] - Thysteresis){ // turn off fan + *ccr = 0; + }else if(T > tmax[x] + Thysteresis){ + if(TOff){ + chkOffRelay(); + }else{ + offreason[x] = 1; + startOff(); + *ccr = 100; + } + }else{ + offreason[x] = 0; + // check working fan + int chk = (x==0) ? CHK(COOLER0) : CHK(COOLER1); + if(chk){ // fan is working, check RPM + if(RPM && speed == 0){ +SEND("RPM: "); printu(RPM); SEND(", speed: "); printu(speed); newline(); + SEND("Cooler"); bufputchar('0'+x); SEND(" died!");NL(); + buzzer = BUZZER_SHORT; + coolerproblem[x] = 1; + }else if(coolerproblem[x]){ + buzzer = BUZZER_OFF; + coolerproblem[x] = 0; + SEND("Cooler OK");NL(); + } + }else{ // turn on fan + SEND("Turn fan ON"); NL(); + if(x==0) ON(COOLER0); + else ON(COOLER1); + } + if(T > tmin[x] && T < tmax[x]){ // T between tmin and tmax + int32_t tx = 80*(T - tmin[x]); + tx /= (tmax[x] - tmin[x]); + uint32_t pwm = 20 + tx; + if(pwm < 20) pwm = 20; + else if(pwm > 100) pwm = 100; +SEND("Set pwm"); bufputchar('0'+x);SEND(" to "); printu(pwm);NL(); + *ccr = pwm; + } + } + } + // T2 - not controlled cooler + T = getNTC(2); + if(T < tmin[2] - Thysteresis){ // turn off fan + TIM1->CCR3 = 0; + }else if(T > tmax[2] + Thysteresis){ + if(TOff){ + chkOffRelay(); + }else{ + offreason[2] = 1; + startOff(); + TIM1->CCR3 = 100; + } + }else{ // T between tmin and tmax + offreason[2] = 0; + if(T > tmin[2] && T < tmax[2]){ + int32_t tx = 60*(T - tmin[2]); + tx /= (tmax[2] - tmin[2]); + uint32_t pwm = 40 + tx; + if(pwm < 40) pwm = 40; + else if(pwm > 100) pwm = 100; +SEND("Set pwm3 to "); printu(pwm);NL(); + TIM1->CCR3 = pwm; + } + } + // T3 - turn off power after TturnOff + if(getNTC(3) > t3max){ + if(TOff){ + chkOffRelay(); + }else{ + offreason[3] = 1; + startOff(); + } + }else offreason[3] = 0; + // check offreason + if(TOff){ + uint8_t stillbad = 0; + for(int x = 0; x < 4; ++x) + if(offreason[x]){ + stillbad = 1; + break; + } + if(!stillbad){ + SEND("No reason to panic");NL(); + TOff = 0; + buzzer = BUZZER_OFF; + } + } +} diff --git a/F0-nolib/Socket_fans/monitor.h b/F0-nolib/Socket_fans/monitor.h new file mode 100644 index 0000000..4b278ac --- /dev/null +++ b/F0-nolib/Socket_fans/monitor.h @@ -0,0 +1,28 @@ +/* + * This file is part of the SockFans project. + * Copyright 2020 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#ifndef MONITOR_H__ + +// run monitor each 1s +#define MONITOR_PERIOD (999) + +void process_monitor(); + +#define MONITOR_H__ +#endif // MONITOR_H__ diff --git a/F0-nolib/Socket_fans/proto.c b/F0-nolib/Socket_fans/proto.c index e9fd16e..0e5c383 100644 --- a/F0-nolib/Socket_fans/proto.c +++ b/F0-nolib/Socket_fans/proto.c @@ -29,9 +29,6 @@ static char buff[BUFSZ+1], *bptr = buff; static uint8_t blen = 0; -volatile uint32_t Cooler0speed; // RPM of cooler0 -volatile uint32_t Cooler1RPM; // Cooler1 RPM counter by EXTI @PA7 -volatile uint32_t Cooler1speed; // RPM of cooler0 void sendbuf(){ IWDG->KR = IWDG_REFRESH; @@ -171,11 +168,7 @@ static inline void coolerRPM(char n){ SEND("RPM"); bufputchar(n); bufputchar('='); - if(n == '0'){ // cooler0 - printu(Cooler0speed); - }else{ // cooler1 - printu(Cooler1speed); - } + printu(Coolerspeed[n - '0']); } // change Coolerx RPM @@ -227,6 +220,15 @@ static inline void buzzercmd(char cmd){ } } +static inline void gett(char chno){ + if(chno < '0' || chno > '3'){ + SEND("Temperature channel should be 0..3"); + return; + } + bufputchar('T'); bufputchar(chno); bufputchar('='); + printi(getNTC(chno - '0')); +} + /** * @brief cmd_parser - command parsing * @param txt - buffer with commands & data @@ -266,6 +268,10 @@ void cmd_parser(char *txt){ changeRPM(txt+1); goto eof; break; + case 't': + gett(txt[1]); + goto eof; + break; } if(txt[1] != '\n') *txt = '?'; // help for wrong message length switch(_1st){ @@ -326,6 +332,7 @@ void cmd_parser(char *txt){ "'rx' - relay on/off (x=1/0) or get status\n" "'Sx y' - set coolerx RPM to y\n" "'T' - get time from start (ms)\n" + "'tx' - get temperature x (0..3)\n" "'V' - get voltage\n" "'Z' - reinit ADC\n" ); @@ -351,6 +358,15 @@ void printu(uint32_t val){ addtobuf(bufptr); } +// print 32bit signed int +void printi(int32_t val){ + if(val < 0){ + val = -val; + bufputchar('-'); + } + printu(val); +} + // print 32bit unsigned int as hex void printuhex(uint32_t val){ addtobuf("0x"); diff --git a/F0-nolib/Socket_fans/proto.h b/F0-nolib/Socket_fans/proto.h index 82b1fa8..dc10223 100644 --- a/F0-nolib/Socket_fans/proto.h +++ b/F0-nolib/Socket_fans/proto.h @@ -46,6 +46,7 @@ void cmd_parser(char *buf); void addtobuf(const char *txt); void bufputchar(char ch); void printu(uint32_t val); +void printi(int32_t val); void printuhex(uint32_t val); void sendbuf(); diff --git a/F0-nolib/Socket_fans/sockfans.bin b/F0-nolib/Socket_fans/sockfans.bin index 5cc2114..ee8a43b 100755 Binary files a/F0-nolib/Socket_fans/sockfans.bin and b/F0-nolib/Socket_fans/sockfans.bin differ diff --git a/F0-nolib/inc/Fx/stm32f0.h b/F0-nolib/inc/Fx/stm32f0.h index a6065f0..55fcffe 100644 --- a/F0-nolib/inc/Fx/stm32f0.h +++ b/F0-nolib/inc/Fx/stm32f0.h @@ -181,6 +181,80 @@ TRUE_INLINE void StartHSI48(){ #define GPIO_MODER_MODER15_O ((uint32_t)0x40000000) #define GPIO_MODER_MODER15_AF ((uint32_t)0x80000000) +/******************* Bit definition for GPIO_PUPDR register *****************/ +// no/pullup/pulldown/reserved +// for n in $(seq 0 15); do echo "#define GPIO_PUPDR${n}_PU ((uint32_t)(1<<$((n*2))))"; +// echo "#define GPIO_PUPDR${n}_PD ((uint32_t)(1<<$((n*2+1))))"; done +// alt+select column -> delete +#define GPIO_PUPDR0_PU ((uint32_t)(1<<0)) +#define GPIO_PUPDR0_PD ((uint32_t)(1<<1)) +#define GPIO_PUPDR1_PU ((uint32_t)(1<<2)) +#define GPIO_PUPDR1_PD ((uint32_t)(1<<3)) +#define GPIO_PUPDR2_PU ((uint32_t)(1<<4)) +#define GPIO_PUPDR2_PD ((uint32_t)(1<<5)) +#define GPIO_PUPDR3_PU ((uint32_t)(1<<6)) +#define GPIO_PUPDR3_PD ((uint32_t)(1<<7)) +#define GPIO_PUPDR4_PU ((uint32_t)(1<<8)) +#define GPIO_PUPDR4_PD ((uint32_t)(1<<9)) +#define GPIO_PUPDR5_PU ((uint32_t)(1<<10)) +#define GPIO_PUPDR5_PD ((uint32_t)(1<<11)) +#define GPIO_PUPDR6_PU ((uint32_t)(1<<12)) +#define GPIO_PUPDR6_PD ((uint32_t)(1<<13)) +#define GPIO_PUPDR7_PU ((uint32_t)(1<<14)) +#define GPIO_PUPDR7_PD ((uint32_t)(1<<15)) +#define GPIO_PUPDR8_PU ((uint32_t)(1<<16)) +#define GPIO_PUPDR8_PD ((uint32_t)(1<<17)) +#define GPIO_PUPDR9_PU ((uint32_t)(1<<18)) +#define GPIO_PUPDR9_PD ((uint32_t)(1<<19)) +#define GPIO_PUPDR10_PU ((uint32_t)(1<<20)) +#define GPIO_PUPDR10_PD ((uint32_t)(1<<21)) +#define GPIO_PUPDR11_PU ((uint32_t)(1<<22)) +#define GPIO_PUPDR11_PD ((uint32_t)(1<<23)) +#define GPIO_PUPDR12_PU ((uint32_t)(1<<24)) +#define GPIO_PUPDR12_PD ((uint32_t)(1<<25)) +#define GPIO_PUPDR13_PU ((uint32_t)(1<<26)) +#define GPIO_PUPDR13_PD ((uint32_t)(1<<27)) +#define GPIO_PUPDR14_PU ((uint32_t)(1<<28)) +#define GPIO_PUPDR14_PD ((uint32_t)(1<<29)) +#define GPIO_PUPDR15_PU ((uint32_t)(1<<30)) +#define GPIO_PUPDR15_PD ((uint32_t)(1<<31)) +// OSPEEDR +// for n in $(seq 0 15); do echo "#define GPIO_OSPEEDR${n}_MED ((uint32_t)(1<<$((n*2))))"; +// echo "#define GPIO_OSPEEDR${n}_HIGH ((uint32_t)(3<<$((2*n))))"; done +#define GPIO_OSPEEDR0_MED ((uint32_t)(1<<0)) +#define GPIO_OSPEEDR0_HIGH ((uint32_t)(3<<0)) +#define GPIO_OSPEEDR1_MED ((uint32_t)(1<<2)) +#define GPIO_OSPEEDR1_HIGH ((uint32_t)(3<<2)) +#define GPIO_OSPEEDR2_MED ((uint32_t)(1<<4)) +#define GPIO_OSPEEDR2_HIGH ((uint32_t)(3<<4)) +#define GPIO_OSPEEDR3_MED ((uint32_t)(1<<6)) +#define GPIO_OSPEEDR3_HIGH ((uint32_t)(3<<6)) +#define GPIO_OSPEEDR4_MED ((uint32_t)(1<<8)) +#define GPIO_OSPEEDR4_HIGH ((uint32_t)(3<<8)) +#define GPIO_OSPEEDR5_MED ((uint32_t)(1<<10)) +#define GPIO_OSPEEDR5_HIGH ((uint32_t)(3<<10)) +#define GPIO_OSPEEDR6_MED ((uint32_t)(1<<12)) +#define GPIO_OSPEEDR6_HIGH ((uint32_t)(3<<12)) +#define GPIO_OSPEEDR7_MED ((uint32_t)(1<<14)) +#define GPIO_OSPEEDR7_HIGH ((uint32_t)(3<<14)) +#define GPIO_OSPEEDR8_MED ((uint32_t)(1<<16)) +#define GPIO_OSPEEDR8_HIGH ((uint32_t)(3<<16)) +#define GPIO_OSPEEDR9_MED ((uint32_t)(1<<18)) +#define GPIO_OSPEEDR9_HIGH ((uint32_t)(3<<18)) +#define GPIO_OSPEEDR10_MED ((uint32_t)(1<<20)) +#define GPIO_OSPEEDR10_HIGH ((uint32_t)(3<<20)) +#define GPIO_OSPEEDR11_MED ((uint32_t)(1<<22)) +#define GPIO_OSPEEDR11_HIGH ((uint32_t)(3<<22)) +#define GPIO_OSPEEDR12_MED ((uint32_t)(1<<24)) +#define GPIO_OSPEEDR12_HIGH ((uint32_t)(3<<24)) +#define GPIO_OSPEEDR13_MED ((uint32_t)(1<<26)) +#define GPIO_OSPEEDR13_HIGH ((uint32_t)(3<<26)) +#define GPIO_OSPEEDR14_MED ((uint32_t)(1<<28)) +#define GPIO_OSPEEDR14_HIGH ((uint32_t)(3<<28)) +#define GPIO_OSPEEDR15_MED ((uint32_t)(1<<30)) +#define GPIO_OSPEEDR15_HIGH ((uint32_t)(3<<30)) + + /****************** FLASH Keys **********************************************/ #define RDP_Key ((uint16_t)0x00A5)