Skip to content

Instantly share code, notes, and snippets.

@minimum-necessary-change
Forked from andreacioni/fand.c
Created August 2, 2019 18:22
Show Gist options
  • Save minimum-necessary-change/e12b8553a9723dad3a37bf92488e373f to your computer and use it in GitHub Desktop.
Save minimum-necessary-change/e12b8553a9723dad3a37bf92488e373f to your computer and use it in GitHub Desktop.

Revisions

  1. @andreacioni andreacioni revised this gist Apr 21, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion fand.c
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ Author: Andrea Cioni (andreacioni)
    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 -std=gnu99 -c fand.c -o fand
    gcc -std=gnu99 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>
  2. @andreacioni andreacioni revised this gist Apr 21, 2017. 1 changed file with 7 additions and 6 deletions.
    13 changes: 7 additions & 6 deletions fand.c
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,20 @@
    /*
    A Project of Andrea Cioni
    Title: WiFi_Check
    Title: Fan Daemon (FanD)
    Author: Andrea Cioni (andreacioni)
    [email protected]
    Project: FanD
    [email protected]
    Copyright: Copyright (c) 2017 Andrea Cioni <[email protected]>
    https://github.com/dweeber/WiFi_Check
    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
    gcc -std=gnu99 -c 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>
  3. @andreacioni andreacioni revised this gist Apr 21, 2017. 1 changed file with 6 additions and 5 deletions.
    11 changes: 6 additions & 5 deletions fand.c
    Original file line number Diff line number Diff line change
    @@ -7,18 +7,19 @@ Author: Andrea Cioni (andreacioni)
    Project: FanD
    Copyright: Copyright (c) 2017 Andrea Cioni <[email protected]>
    https://github.com/dweeber/WiFi_Check
    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.
    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
    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>
    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
    Example usage:
    ./fand 2 3 20 30 10 100
    */

  4. @andreacioni andreacioni created this gist Apr 21, 2017.
    242 changes: 242 additions & 0 deletions fand.c
    Original file line number Diff line number Diff line change
    @@ -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;
    }