|
|
@@ -0,0 +1,242 @@ |
|
|
/* |
|
|
A Project of Andrea Cioni |
|
|
|
|
|
Title: WiFi_Check |
|
|
Author: Andrea Cioni (andreacioni) |
|
|
[email protected] |
|
|
Project: FanD |
|
|
|
|
|
Copyright: Copyright (c) 2017 Andrea Cioni <[email protected]> |
|
|
https://github.com/dweeber/WiFi_Check |
|
|
|
|
|
Purpose: |
|
|
Simple utility program for GNU/Linux systems to control a fan motor of your miniPC (UDOO,Raspberry Pi,Orange Pi,etc) through a PWM signal. |
|
|
|
|
|
Compile: |
|
|
gcc fand.c -o fand |
|
|
|
|
|
Launch: |
|
|
fand <frequency of the PWM signal> <sleep seconds between temperature checks> <min temp in Celsius> <max temp in Celsius> <min dc percent> <max dc percent> |
|
|
|
|
|
Example: ./fand 2 3 20 30 10 100 |
|
|
|
|
|
*/ |
|
|
|
|
|
#include<stdio.h> |
|
|
#include<stdbool.h> |
|
|
#include<stdlib.h> |
|
|
#include<unistd.h> |
|
|
#include<signal.h> |
|
|
|
|
|
#define HELLO_BANNER "Fan Daemon" |
|
|
#define VERSION "(0.2v)" |
|
|
|
|
|
#define BASE_PATH "/sys/class/pwm/pwmchip0/" |
|
|
|
|
|
#define EXPORT_PATH BASE_PATH "pwm0/" |
|
|
|
|
|
static volatile bool go = true; |
|
|
|
|
|
struct console_args { |
|
|
unsigned long period; |
|
|
unsigned long sleep_timeout; |
|
|
unsigned long min_temp; |
|
|
unsigned long max_temp; |
|
|
unsigned short min_percent_dc; |
|
|
unsigned short max_percent_dc; |
|
|
}; |
|
|
|
|
|
bool export() { |
|
|
return system("echo 0 > " BASE_PATH "export") == 0; |
|
|
} |
|
|
|
|
|
bool unexport() { |
|
|
return system("echo 0 > " BASE_PATH "unexport") == 0; |
|
|
} |
|
|
|
|
|
bool enable(bool enable) { |
|
|
if(enable) |
|
|
return system("echo 1 > " EXPORT_PATH "enable") == 0; |
|
|
else |
|
|
return system("echo 0 > " EXPORT_PATH "enable") == 0; |
|
|
} |
|
|
|
|
|
bool setup(unsigned long period) { |
|
|
char buf[1024]; |
|
|
return (sprintf(buf,"echo %lu > " EXPORT_PATH "period",period) != 0) && (system(buf) == 0); |
|
|
} |
|
|
|
|
|
bool set_dc(float percent,unsigned long period) { |
|
|
char buf[1024]; |
|
|
percent = (percent>100.0f) ? 100.0f : percent; |
|
|
unsigned long dc_ns = (percent/100)*period; |
|
|
dc_ns = (dc_ns >= period) ? (period-1) : dc_ns; |
|
|
printf("Percent: %0.1f %%, DC: %lu/%lu\n",percent,dc_ns,period); |
|
|
|
|
|
return (sprintf(buf,"echo %lu > " EXPORT_PATH "duty_cycle",dc_ns) != 0) && (system(buf) == 0); |
|
|
} |
|
|
|
|
|
float read_cpu_temp() { |
|
|
float ret = -1.0f; |
|
|
FILE *fp = popen("/bin/cat /sys/devices/virtual/thermal/thermal_zone0/temp", "r"); |
|
|
char buf[1024] = {0}; |
|
|
|
|
|
if(fp != NULL) { |
|
|
if(fgets(buf,1023,fp) != NULL) { |
|
|
|
|
|
printf("Temperature read: %s",buf); |
|
|
|
|
|
if((ret=strtoul(buf,NULL,10)) != 0) { |
|
|
ret=ret/1000; |
|
|
} else { |
|
|
printf("Cannot convert output string\n"); |
|
|
} |
|
|
} else { |
|
|
printf("Cannot read CPU temperature from output\n"); |
|
|
} |
|
|
|
|
|
pclose(fp); |
|
|
} else { |
|
|
printf("Cannot read CPU temperature\n"); |
|
|
} |
|
|
|
|
|
return ret; |
|
|
} |
|
|
|
|
|
void kill_handler(int sig) { |
|
|
printf("Terminating...\n"); |
|
|
go=false; |
|
|
} |
|
|
|
|
|
int run(struct console_args _args) { |
|
|
int ret=0; |
|
|
|
|
|
signal(SIGINT,kill_handler); |
|
|
|
|
|
while(go) { |
|
|
float cpu_temp = read_cpu_temp(),percentdc=0; |
|
|
if(cpu_temp > _args.min_temp) { |
|
|
float ratio = (cpu_temp-_args.min_temp)/(_args.max_temp - _args.min_temp); |
|
|
percentdc = (ratio*(_args.max_percent_dc - _args.min_percent_dc))+_args.min_percent_dc; |
|
|
|
|
|
} |
|
|
|
|
|
if(!set_dc(percentdc,_args.period)) |
|
|
printf("There was an error setting the duty cicle"); |
|
|
|
|
|
sleep(_args.sleep_timeout); |
|
|
|
|
|
printf("\n"); |
|
|
} |
|
|
|
|
|
return ret; |
|
|
} |
|
|
|
|
|
bool parse_arguments(int argv, char **argc,struct console_args *_args) { |
|
|
bool ret=true; |
|
|
if(argv == 7) { |
|
|
|
|
|
unsigned long ul = strtoul(argc[1],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->period = (1.0f/ul)*100000000L; |
|
|
printf("Frequency: %lu Hz, Period: %lu s\n",ul,_args->period); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
ul = strtoul(argc[2],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->sleep_timeout = ul; |
|
|
printf("Sleep timeout: %lu s\n",_args->sleep_timeout); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
ul = strtoul(argc[3],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->min_temp = ul; |
|
|
printf("Min temperature: %lu *C\n",_args->min_temp); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
ul = strtoul(argc[4],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->max_temp = ul; |
|
|
printf("Max temperature: %lu *C\n",_args->max_temp); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
ul = strtoul(argc[5],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->min_percent_dc = (unsigned short) ul; |
|
|
printf("Min duty cycle: %i %%\n",_args->min_percent_dc); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
ul = strtoul(argc[6],NULL,10); |
|
|
if(ul != 0) { |
|
|
_args->max_percent_dc = (unsigned short) ul; |
|
|
printf("Max duty cycle: %i %%\n",_args->max_percent_dc); |
|
|
} else |
|
|
ret &= false; |
|
|
|
|
|
} else |
|
|
ret=false; |
|
|
|
|
|
return ret; |
|
|
} |
|
|
|
|
|
int main(int argv, char **argc) { |
|
|
int ret = 0; |
|
|
struct console_args _args; |
|
|
|
|
|
printf("%s %s\n",HELLO_BANNER,VERSION); |
|
|
|
|
|
if(!parse_arguments(argv,argc,&_args)) { |
|
|
printf("fand <frequency> <sleep seconds> <min temp> <max temp> <min dc percent> <max dc percent> \n"); |
|
|
ret = 100; |
|
|
} else { |
|
|
printf("Exporting..."); |
|
|
if(export()) { |
|
|
printf("OK!\n"); |
|
|
|
|
|
printf("Setupping (f=%lu)...",_args.period); |
|
|
if(setup(_args.period)) { |
|
|
printf("OK!\n"); |
|
|
|
|
|
printf("Enabling..."); |
|
|
if(enable(true)) { |
|
|
printf("OK!\n"); |
|
|
|
|
|
ret = run(_args); |
|
|
|
|
|
printf("Disabling..."); |
|
|
if(enable(false)) { |
|
|
printf("OK!\n"); |
|
|
} else { |
|
|
printf("FAIL!\n"); |
|
|
ret = 4; |
|
|
} |
|
|
} else { |
|
|
printf("FAIL!\n"); |
|
|
ret=3; |
|
|
} |
|
|
|
|
|
} else { |
|
|
printf("FAIL!\n"); |
|
|
ret=2; |
|
|
} |
|
|
} else { |
|
|
printf("FAIL!\n"); |
|
|
ret=1; |
|
|
} |
|
|
|
|
|
printf("Unexporting..."); |
|
|
if(unexport()) { |
|
|
printf("OK!\n"); |
|
|
} else { |
|
|
printf("FAIL!\n"); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return ret; |
|
|
} |