/* standard headers */ #include #include #include #include #include #include #include #include #include #include #include #include /* mraa headers */ #include "mraa/common.hpp" #include "mraa/pwm.hpp" /* для HDD*/ #include #include #include #include #include #include #define PWM_PORT 13 #define CPU_TEMPERATURE_FILE "/sys/class/thermal/thermal_zone0/temp" #define T_MIN 30 #define T_MAX 50 #define INVERT_CONTROL_CURVE 1 const std::array HDD_NAMES = {"/dev/sda", "/dev/sdb", "/dev/sdc", "/dev/sdd"}; volatile sig_atomic_t flag = 1; mraa::Pwm pwm(PWM_PORT); // power^ // 100%| *--------- // | / // | / // | / // | / // | / // | / // | / // | / // | / // ---====*--------*---------------> // 0 | T_MIN T_MAX max[TEMP], celsius float calcPower(int temperature) { float value = 0.0f; if (temperature < T_MIN) { value = 0.0f; } if (temperature >= T_MIN && temperature <= T_MAX) { value = (float(temperature)-float(T_MIN))/(float(T_MAX)-float(T_MIN)); if (value < 0.25) { value = 0.0f; } } if (temperature > T_MAX) { value = 1.0f; } std::cout << "T:" << temperature << "С power:"<< value * 100 << "%\n"; if (INVERT_CONTROL_CURVE) { value = 1.0f-value; } return value; } void checkControlCurve() { std::cout << "PWM power 0%" << std::endl; pwm.write(0.0f); usleep(2000000); std::cout << "PWM power 25%" << std::endl; pwm.write(0.25f); usleep(2000000); std::cout << "PWM power 50%" << std::endl; pwm.write(0.5f); usleep(2000000); std::cout << "PWM power 75%" << std::endl; pwm.write(0.75f); usleep(2000000); std::cout << "PWM power 100%" << std::endl; pwm.write(1.0f); usleep(2000000); } void initPWM() { std::cout << "Cycling PWM on pin " << PWM_PORT << std::endl; pwm.enable(true); } int readTempCPU() { std::fstream ftemp; std::string raw; ftemp.open(CPU_TEMPERATURE_FILE,std::ios::in); if (ftemp.is_open()){ getline(ftemp, raw); ftemp.close(); return std::stoi(raw)/1000; } else { std::cerr << "Read temperature error. Cannot open file.\n"; } return -1; } std::string exec(const char* cmd) { std::array buffer; std::string result; std::unique_ptr pipe(popen(cmd, "r"), pclose); if (!pipe) { throw std::runtime_error("popen() failed!"); } while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); } return result; } int readTempHDD(const std::string& drive) { std::string cmd = "smartctl -A " + drive + " | grep Temperature_Celsius | awk '{print $10}'"; std::string output = exec(cmd.c_str()); return std::stoi(output); } int readTemp() { int T_CPU = readTempCPU(); int max = T_CPU; std::array T_HDD; for (int i = 0; i < HDD_NAMES.size(); ++i) { T_HDD[i] = readTempHDD(HDD_NAMES[i]); if (T_HDD[i] > max) { max = T_HDD[i]; } } return max; } void sig_handler(int signum) { if (signum == SIGINT) { std::cout << "Exiting..." << std::endl; flag = 0; } } int main(void) { signal(SIGINT, sig_handler); std::cout << "!!!Control fan connected to RockPi4 pin " << PWM_PORT << " according to CPU&HDD temperature!!!\n"; initPWM(); checkControlCurve(); float power = 0.0f; int temperature = 0; while (flag) { temperature = readTemp(); power = calcPower(temperature); pwm.write(power); usleep(2000000); } return EXIT_SUCCESS; }