OpenWrt Forum Archive

Topic: Update on Linksys WRT1900AC support

The content of this topic has been archived between 16 Sep 2014 and 7 May 2018. Unfortunately there are posts – most likely complete pages – missing.

gufus wrote:

Yes, I agree.

"Description:  This file implements debug related functions."

https://github.com/kaloz/mwlwifi/commit … 691952be8c

Yeah, I've been watching those commits land as a well (although I didn't see this mornings - thanks!).  It's not clear to me if those are resolving any of the outstanding issues, or more just cleanup.  Most of these latest commits look like code polishing to get this driver cleaned up for inclusion in the kernel.

JimWright wrote:

It would certainly be possible to add a 4th level to the fans (0%, 33%, 66%, 100%), etc, should this be seen as a good thing.

Good idea smile

I'll test here latter on today.

JimWright wrote:

It would certainly be possible to add a 4th level to the fans (0%, 33%, 66%, 100%), etc, should this be seen as a good thing.

Generally, when you have fine control of a fan speed and reasonable sensor data as we seem to have here, the right way to control the fan will be a PID loop.  PID = proportional-integral-derivative, IIRC.  This is a standard method of control used in industrial equipment, where there is a rate setting for how quickly the fan is sped up and another for how quickly it is slowed down and so on.  The result is the fan speed tracking the temperature in a controlled way, with hysteresis so that it is not turning on and off all the time, or speeding up and slowing down over short periods in a way that creates an annoying noise.  With a PID loop, it is possible to have a setpoint temperature you want to achieve and use the fan settings to keep the temperature pretty close to that.  But I am not sure how well it would work if the CPU workload changes dramatically over very short time periods.  In industrial use, a PID loop can often keep a temperature within 0.1 C of the setpoint, but that is with large equipment that can not change temperature as fast as a CPU can.

I have not looked at PID stuff for more than 20 years, but I expect there is a lot of information on the web now.

quagga wrote:
gufus wrote:

Yes, I agree.

"Description:  This file implements debug related functions."

https://github.com/kaloz/mwlwifi/commit … 691952be8c

Yeah, I've been watching those commits land as a well (although I didn't see this mornings - thanks!).  It's not clear to me if those are resolving any of the outstanding issues, or more just cleanup.  Most of these latest commits look like code polishing to get this driver cleaned up for inclusion in the kernel.

Yes, which is a good sign.

I fear that they will have to do a couple of more rounds on that, though....  Some of the latest changes modified lots of comments to look like this:

/* CONSTANTS AND MACROS
*/

which of course is a single line comment and therefore should have been formatted as

/* CONSTANTS AND MACROS */

to follow the kernel coding style.

The current "fixup" wouldn't even be valid as multiline comments, because the asterisks are supposed to line up.  Like this (in the networking subsystem - else we would expect an empty first line):

/* CONSTANTS AND MACROS
 * next line
 */

Oh, well.  That comment is pointless in any case, and shold really have been deleted instead of fixed up smile

fe31nz wrote:

Generally, when you have fine control of a fan speed and reasonable sensor data as we seem to have here, the right way to control the fan will be a PID loop.  PID = proportional-integral-derivative, IIRC.  This is a standard method of control used in industrial equipment, where there is a rate setting for how quickly the fan is sped up and another for how quickly it is slowed down and so on.  The result is the fan speed tracking the temperature in a controlled way, with hysteresis so that it is not turning on and off all the time, or speeding up and slowing down over short periods in a way that creates an annoying noise.

I understand what you are saying, and generally agree with that.  It would require a more involved script though to accomplish what I think you are asking for.

My take would be that as the heat is going up, you'd want to ramp the fan speed more quickly, and as the temp is coming down, back off on the fan more gradually.  Since this script is not maintaining any values through each iteration (unless we add a data file that is read and written each loop, with X values of past history each time), the best we can do is check what the current fan speed is set to, and I'm not sure if it's actually possible to read the fan speed, I've only seen examples where the speed is getting set.

Assuming we can read the fan speed, if the fan is off and we need to turn it on, instead of starting at 33%, start at 50%, if we are already running, increase by 20% (actual % based on how frequently script is called).  If we need to slow down the fan, just drop it by 10% each time through the loop to back it off, depending on how frequently the script is getting called (1 minute calls, back off 20%, 5 second calls, back off 5%, etc).

JimWright wrote:
fe31nz wrote:

Generally, when you have fine control of a fan speed and reasonable sensor data as we seem to have here, the right way to control the fan will be a PID loop.  PID = proportional-integral-derivative, IIRC.  This is a standard method of control used in industrial equipment, where there is a rate setting for how quickly the fan is sped up and another for how quickly it is slowed down and so on.  The result is the fan speed tracking the temperature in a controlled way, with hysteresis so that it is not turning on and off all the time, or speeding up and slowing down over short periods in a way that creates an annoying noise.

I understand what you are saying, and generally agree with that.  It would require a more involved script though to accomplish what I think you are asking for.

My take would be that as the heat is going up, you'd want to ramp the fan speed more quickly, and as the temp is coming down, back off on the fan more gradually.  Since this script is not maintaining any values through each iteration (unless we add a data file that is read and written each loop, with X values of past history each time), the best we can do is check what the current fan speed is set to, and I'm not sure if it's actually possible to read the fan speed, I've only seen examples where the speed is getting set.

Assuming we can read the fan speed, if the fan is off and we need to turn it on, instead of starting at 33%, start at 50%, if we are already running, increase by 20% (actual % based on how frequently script is called).  If we need to slow down the fan, just drop it by 10% each time through the loop to back it off, depending on how frequently the script is getting called (1 minute calls, back off 20%, 5 second calls, back off 5%, etc).

Yes, that is sort of what a PID loop does, but much better.  I have never actually written one myself - the code I was writing at the time I met them was actually a display controller for a dairy factory's cream seperators, and it interfaced to the the control equipment that was doing the PID control.  But my understanding is that all the information that is needed is the current fan output setting and current temperature and previous temperature.  Then you run the PID calculation using the rate and setpoint settings and the current data and that gives you the new fan output setting.  Back then (when an 8080 was a fast CPU), the calculation was pretty CPU intensive, but I think that will not be a problem for a modern ARM CPU.

JimWright wrote:

I took the code posted, and revised it slightly to add a midpoint setting.

I tested your midpoint logic and the script failed,  your code didn' even start. My code and yours both failed, I'm still using on/off.

I'm doing something wrong (but I can't see it)

I'd be interested in your modified code, maybe PID code eh smile

(Last edited by gufus on 3 Jun 2015, 21:21)

I'll give it a shot writing a script for our router. Quick question what is ddr and wifi on the scripts? I'm assuming wifi is the temps recorded by the wifi sensor but what is ddr?

Thank You

lifehacksback wrote:

I'll give it a shot writing a script for our router. Quick question what is ddr and wifi on the scripts? I'm assuming wifi is the temps recorded by the wifi sensor but what is ddr?

Thank You

/usr/sbin$ sensors
tmp421-i2c-0-4c
Adapter: mv64xxx_i2c adapter
temp1:        +47.3 C  WIFI
temp2:        +49.8 C  DDR

armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +55.9 C  CPU

I'm not sure about your question.

looking for new firmware reliable wifi connection and a link to download Thanks

lifehacksback wrote:

I'll give it a shot writing a script for our router. Quick question what is ddr and wifi on the scripts? I'm assuming wifi is the temps recorded by the wifi sensor but what is ddr?

Thank You

I think DDR = flash or ram chips?

LIVADITISD wrote:

looking for new firmware reliable wifi connection and a link to download Thanks

Looks like a craigslist ad smile   

I think the RC1 link was few pages back if im not mistaken.

alirz wrote:
lifehacksback wrote:

I'll give it a shot writing a script for our router. Quick question what is ddr and wifi on the scripts? I'm assuming wifi is the temps recorded by the wifi sensor but what is ddr?

Thank You

I think DDR = flash or ram chips?

Board: RD-AXP-GP rev 1.0
SoC:   MV78230 B0
       running 2 CPUs
       Custom configuration
CPU:   Marvell PJ4B (584) v7 (Rev 2) LE
       CPU 0
       CPU    @ 1200 [MHz]
       L2     @ 600 [MHz]
       TClock @ 250 [MHz]
       DDR    @ 600 [MHz]
       DDR 32Bit Width, FastPath Memory Access
       DDR ECC Disabled
DRAM:  256 MiB

NAND:  Spansion 1Gb(ID=F101) 128 MiB

NAND is the flash chip

(Last edited by gufus on 3 Jun 2015, 21:56)

Perhaps a solution here is to take a rolling average of say 5 temperature samples a few seconds apart, average them and the next sample replaces the oldest one.

If five samples were 55 55 55 62 55; the fan might start for a few seconds and go off.

IF the temp was     55 55 55 55 55 55 55 58   55     61    55    60    65    62   65    . . . .

The rolling average would be     55 55 55 55.6 55.6 56.8 56.8 57.8 59.2 60.6 61.4  . . . .

While the temperature is going up and down; the rolling average shows a steady but slower increase.

The code for this one temperature sample is simple and would be more complicated for 3 - CPU, memory and the radio (s).

The issue then becomes how many samples to average, how many seconds apart and then do you use the radio (s), the memory or the CPU, all three and are they equally weighted.

On routers where the load swings wildly; using a single sample to set the fan would likely create too many stop/start or speed change cycles.

The rolling average can produce an optimum fan speed to keep a constant temperature under a constant heavy load; but it would take a few seconds longer to react; but eliminate "knee jerk reactions" of a simple piece of code.

In addition, another piece of could monitor the differential over time and ramp up the fan IF the differential is continuing to widen as opposed to stabilizing or decreasing.

gufus wrote:
JimWright wrote:

I took the code posted, and revised it slightly to add a midpoint setting.

I tested your midpoint logic and the script failed,  your code didn' even start. My code and yours both failed, I'm still using on/off.

I'm doing something wrong (but I can't see it)

I'd be interested in your modified code, maybe PID code eh smile

OK, I blame your script, since I used that as a base.  LOL

Actually, I think you're setting the temps wrong, based on the original script at /sbin/fan_ctrl.sh.  You are taking the entire values return, rather than just the first two characters.  Also, your CPU_OFF temp was set higher than the CPU_ON.

So, I just now used the original /sbin/fan_ctrl.sh as a base, and created the following:

#!/bin/sh

CPU_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon2/temp1_input`
DDR_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon1/temp1_input`
WIFI_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon1/temp2_input`

echo "CPU_TEMP = $CPU_TEMP, DDR_TEMP = $DDR_TEMP, WIFI_TEMP = $WIFI_TEMP"

CPU_LOW=55    # Script default is 85
CPU_MID=65    # Script default not specified
CPU_HIGH=80   # Script default is 95
DDR_LOW=55    # Script default is 65
DDR_MID=65    # Script default not specified
DDR_HIGH=70   # Script default is 75
WIFI_LOW=55  # Script default is 100
WIFI_MID=65  # Script default not specified
WIFI_HIGH=75 # Script default is 115

if [ -d /sys/devices/pwm_fan ];then
        FAN_CTRL=/sys/devices/pwm_fan/hwmon/hwmon0/pwm1
elif [ -d /sys/devices/platform/pwm_fan ];then
        FAN_CTRL=/sys/devices/platform/pwm_fan/hwmon/hwmon0/pwm1
else
        exit 0
fi

FAN_SPEED=`cat $FAN_CTRL`

echo "CPU_TEMP = $CPU_TEMP, DDR_TEMP = $DDR_TEMP, WIFI_TEMP = $WIFI_TEMP, FAN = $FAN_SPEED"

if [ "$CPU_TEMP" -ge "$CPU_HIGH" -o "$DDR_TEMP" -ge "$DDR_HIGH" -o "$WIFI_TEMP" -ge "$WIFI_HIGH" ];then
        echo "255" > $FAN_CTRL
elif [ "$CPU_TEMP" -ge "$CPU_MID" -o "$DDR_TEMP" -ge "$DDR_MID" -o "$WIFI_TEMP" -ge "$WIFI_MID" ];then
        echo "192" > $FAN_CTRL
elif [ "$CPU_TEMP" -ge "$CPU_LOW" -o "$DDR_TEMP" -ge "$DDR_LOW" -o "$WIFI_TEMP" -ge "$WIFI_LOW" ];then
        echo "64" > $FAN_CTRL
else
        echo "0" > $FAN_CTRL
fi

One thing that I noticed since I last checked this script was that there is a midpoint set, my version actually has 4 setpoints as a result, and the Belkin numbers listed in your script were different than the ones in the the /sbin/fan_ctrl.sh one.

Also, I checked the sensor output, and saw that my running temp was far lower than what would trigger the script, so I lowered the triggers for the fans to kick in.  My current values are:

root@OpenWrt:/sbin# sensors
tmp421-i2c-0-4c
Adapter: mv64xxx_i2c adapter
temp1:        +44.5 C
temp2:        +47.9 C

armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +50.8 C

Also, in my script, I'm echoing back the varlables so I can monitor when testing manually, including the current fan speed before any changes.  So, fan speed is readable to use for some calculations.

As I mentioned earlier, this script is called on a regular interval and no values are preserved between runs, so collecting a history of values to use in calculations isn't really feasable without creating a data file to store these, without rewriting the script to stay running constantly.

(Last edited by JimWright on 4 Jun 2015, 01:18)

@JimWright

I am running much warmer than what you show.....

root@WRT1900AC-P:/sbin# sensors
tmp421-i2c-0-4c
Adapter: mv64xxx_i2c adapter
temp1:        +53.3 C
temp2:        +52.7 C

armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +64.6 C

Will give your script a spin and advise

Cheers

*EDIT*

Played with the numbers a bit:

CPU_LOW=50    # Script default is 85
CPU_MID=55    # Script default not specified
CPU_HIGH=60   # Script default is 95
DDR_LOW=50    # Script default is 65
DDR_MID=55    # Script default not specified
DDR_HIGH=60   # Script default is 75
WIFI_LOW=50   # Script default is 100
WIFI_MID=60   # Script default not specified
WIFI_HIGH=70  # Script default is 115

Better results:

root@WRT1900AC-P:/sbin# sensors
tmp421-i2c-0-4c
Adapter: mv64xxx_i2c adapter
temp1:        +44.3 C
temp2:        +44.9 C

armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +54.5 C

I still think the temps are too high compared to my tower (quad core CPU is running at 32 C, DRAM at 36 C, and mb at 41 C)

(Last edited by doITright on 4 Jun 2015, 03:48)

Slightly left field question, but does luci_statsitics have support for displaying temp and environmental data via RRDTool? I see the collectd exec plug supported and I was able to take the scripts in this thread and get collectd to grab the data into an RRD file, but it is looking like I have to roll my own graphs.

Unless I am missing something... is there an alternative to using the collectd exec plugin?

Paul

gofus, I've gotten your script working with some tweaks:

#!/bin/sh

# put in /usr/sbin/fan_monitor
# fan_monitor
# Utility script to monitor temperatures and turn on/off the fan in accordance
# with the original Belkin specs.

INTERVAL=5 # Poll every 5 seconds

# The fan will turn on if any of these temperatures is exceeded
CPU_ON=60000    # Belkin default is 85
DDR_ON=60000    # Belkin default is 65
WIFI_ON=65000   # Belkin default is 105

# The fan will run at reduced speed if any of these temperatures are below these values
CPU_MID=55000     # Belkin sets no default
DDR_MID=55000     # Belkin sets no default
WIFI_MID=60000    # Belkin sets no default


# The fan will turn off if all of the temperatures are below these values
CPU_OFF=50000     # Belkin default is 80
DDR_OFF=50000     # Belkin default is 60
WIFI_OFF=55000    # Belkin default is 100

old_pwm=-1

fan_set() {
    if [ "$1" -eq 2 ]; then
        pwm=255
    elif [ "$1" -eq 1 ]; then
        pwm=128
    elif [ "$1" -eq 0 ]; then
        pwm=0
    fi
    if [ "$pwm" -ne "$old_pwm" ]; then
        echo "Setting fan PWM to: $pwm"
        echo "$pwm" > /sys/devices/pwm_fan/hwmon/hwmon0/pwm1
        old_pwm=$pwm
    fi
}

# Turn fan on when exiting
trap "{ fan_set 1; exit; }" SIGINT SIGTERM

# Main fan control loop
while :
do
    cpu=`cat /sys/class/hwmon/hwmon2/temp1_input`
    ddr=`cat /sys/class/hwmon/hwmon1/temp1_input`
    wifi=`cat /sys/class/hwmon/hwmon1/temp2_input`

    if [ "$cpu" -ge $CPU_ON -o "$ddr" -ge $DDR_ON -o "$wifi" -ge $WIFI_ON ]
    then
        fan_set 2
    elif [ "$cpu" -le $CPU_OFF -a "$ddr" -le $DDR_OFF -a "$wifi" -le $WIFI_OFF ]
    then
        fan_set 0
    elif [ "$cpu" -le $CPU_MID -a "$ddr" -le $DDR_MID -a "$wifi" -le $WIFI_MID ]
    then
        fan_set 1
    fi

    sleep $INTERVAL
done

I lowered the setpoints a bit for my testing, since my sensors were reporting numbers that wouldn't have triggered this script.  I'm running my unit with the cover off, and actually had a lamp up against the heatsink to give more heat.

Also figured out what you were doing reading the temps, and that you later were doing a divide by 1000 to adjust the numbers.  I just set the setpoints accordingly (60000 instead of 60, etc), and took the division out of the script.  Other minor script cleanup, your sleep/wait wasn't being processed correctly, this version seems to work OK.  5 Second interval for testing only, maybe 10-15 seconds for real use?

I just tested the script standalone, not with your init.d script running.

Suggestion if implementing this would be to change the cron job from running the default fan control script to instead call a script to call your fan_control start script to keep it running.

Side question, I've been trying to figure out where those original Belkin numbers came from, I've seen various references to them, but no definitive source.  Any ideas on that?  I'm wondering if we are using the right numbers at all there for a baseline?

(Last edited by JimWright on 4 Jun 2015, 04:47)

Some useful info I found tonight on setting the fan speed.  Setting a fan speed of less than 95 won't actually start the fan, my fan at least.  The speed is set too low to get the fan running from a stop, if already running, you can set lower values, to a point, before the fan stops running.  Essentially, any fan speed less than 100 will effectively be stopped.

I spent quite a bit of time tonight working on a script that set the fan to a percentage speed based on various numbers, and couldn't figure out why the fan wasn't spinning.  So having specific setpoints looks like the way to go here, OFF, 50%, 75%, 100%.

RickStep wrote:

Perhaps a solution here is to take a rolling average of say 5 temperature samples a few seconds apart, average them and the next sample replaces the oldest one.

Before creating too advanced solutions specifically for the WRT1900AC, you might consider adapting some of the existing fancontrol solutions. The presence of a fan is somewhat exceptional for embedded router devices, but if we extend the view to consider x86 systems, then these requirements aren't really new or exceptional in any way.

See for example http://www.lm-sensors.org/wiki/man/fancontrol

JimWright wrote:

gofus, I've gotten your script working with some tweaks:

Thanks for your feedback smile

Something came up today, tomorrow I'll have more time. My original scrip works, with your old modifications and testing then... it was broken. My original scrip is working/running right now.

Got my first router lockup today after about a week. Is there a build that I should focus on to help iron out issues? Anything that needs to be captured when the lockup occurs?

I have edited the fan control script so that it incrementally changes the fan speed.
This isn't done extremely well but it is an initial step in the direction it appears we are attempting to accomplish.
TODO: Fix the way that the fan speeds are changed so that they are more dynamic then increments of 10

#!/bin/sh

# put in /usr/sbin/fan_monitor
# fan_monitor
# Utility script to monitor temperatures and turn on/off the fan in accordance
# with the original Belkin specs.

INTERVAL=5 # Poll every 5 seconds

# The fan will turn on if any of these temperatures is exceeded
CPU_ON=60000    # Belkin default is 85
DDR_ON=60000    # Belkin default is 65
WIFI_ON=65000   # Belkin default is 105

# The fan will run at reduced speed if any of these temperatures are below these values
CPU_MID=55000     # Belkin sets no default
DDR_MID=55000     # Belkin sets no default
WIFI_MID=60000    # Belkin sets no default


# The fan will turn off if all of the temperatures are below these values
CPU_OFF=50000     # Belkin default is 80
DDR_OFF=50000     # Belkin default is 60
WIFI_OFF=55000    # Belkin default is 100

# Fan Speeds
current_pwm=0 # 100 starts fan moving
target_pwm=0

fan_set() {
    if [ "$1" -eq 2 ]; then
        target_pwm=255
    elif [ "$1" -eq 1 ]; then
        target_pwm=128
    elif [ "$1" -eq 0 ]; then
        target_pwm=0
    fi
    if [ "$current_pwm" -ne "$target_pwm" ]; then
        echo "Spinning fan up to: $target_pwm"
    echo "Currnently at: $current_pwm"

    # If speed is lower then the target speed increase the speed
    if [ "$target_pwm" -gt "$current_pwm" ]; then
        current_pwm=$((current_pwm + 10))

        # if the current speed is now more then the current set to the target speed
        if [ "$target_pwm" -lt "$current_pwm" ]; then
        current_pwm=target_pwm
        fi

    fi

    # If speed is higher then the target speed decrease the speed
    if [ "$target_pwm" -lt "$current_pwm" ]; then
        current_pwm=$((current_pwm - 10))

        # if the current speed is now more then the current set to the target speed
        if [ "$target_pwm" -gt "$current_pwm" ]; then
        current_pwm=target_pwm
        fi

    fi

    echo "Changing speed to: $current_pwm"
        echo "$current_pwm" > /sys/devices/pwm_fan/hwmon/hwmon0/pwm1
    fi
}

# Turn fan on when exiting
trap "{ fan_set 1; exit; }" SIGINT SIGTERM

# Main fan control loop
while :
do
    cpu=`cat /sys/class/hwmon/hwmon2/temp1_input`
    ddr=`cat /sys/class/hwmon/hwmon1/temp1_input`
    wifi=`cat /sys/class/hwmon/hwmon1/temp2_input`

    if [ "$cpu" -ge $CPU_ON -o "$ddr" -ge $DDR_ON -o "$wifi" -ge $WIFI_ON ]
    then
        fan_set 2
    elif [ "$cpu" -le $CPU_OFF -a "$ddr" -le $DDR_OFF -a "$wifi" -le $WIFI_OFF ]
    then
        fan_set 0
    elif [ "$cpu" -le $CPU_MID -a "$ddr" -le $DDR_MID -a "$wifi" -le $WIFI_MID ]
    then
        fan_set 1
    fi

    sleep $INTERVAL
done
JimWright wrote:

gofus, I've gotten your script working with some tweaks:

Nice code, it's working here. I'll stress the unit out and watch.

/usr/sbin$ sensors
tmp421-i2c-0-4c
Adapter: mv64xxx_i2c adapter
temp1:        +43.3 C 
temp2:        +47.0 C 

armada_thermal-virtual-0
Adapter: Virtual device
temp1:        +50.8 C 

/usr/sbin$ cat /sys/devices/pwm_fan/hwmon/hwmon0/pwm1
128

Made some more changes to the Fan Monitor script to access variables properly, log messages to the system log and some small spelling mistakes

#!/bin/sh

# put in /usr/sbin/fan_monitor.sh
# fan_monitor
# Utility script to monitor temperatures and turn on/off the fan in accordance
# with the original Belkin specs.

INTERVAL=5 # Poll every 5 seconds

# The fan will turn on if any of these temperatures is exceeded
CPU_ON=60000    # Belkin default is 85
DDR_ON=60000    # Belkin default is 65
WIFI_ON=65000   # Belkin default is 105

# The fan will run at reduced speed if any of these temperatures are below these values
CPU_MID=55000     # Belkin sets no default
DDR_MID=55000     # Belkin sets no default
WIFI_MID=60000    # Belkin sets no default


# The fan will turn off if all of the temperatures are below these values
CPU_OFF=50000     # Belkin default is 80
DDR_OFF=50000     # Belkin default is 60
WIFI_OFF=55000    # Belkin default is 100

# Fan Speeds
current_pwm=0 # 100 starts fan moving
target_pwm=0

fan_set() {
    if [ "$1" -eq 2 ]; then
        target_pwm=255
    elif [ "$1" -eq 1 ]; then
        target_pwm=128
    elif [ "$1" -eq 0 ]; then
        target_pwm=0
    fi

    if [ "$current_pwm" -ne "$target_pwm" ]; then
        logger Spinning fan up to: $target_pwm, Currently at: $current_pwm

    # If speed is lower then the target speed increase the speed
    if [ "$target_pwm" -gt "$current_pwm" ]; then
        current_pwm=$(($current_pwm + 10))

        # if the current speed is now more then the current set to the target speed
        if [ "$target_pwm" -lt "$current_pwm" ]; then
        current_pwm=$target_pwm
        fi

    fi

    # If speed is higher then the target speed decrease the speed
    if [ "$target_pwm" -lt "$current_pwm" ]; then
        current_pwm=$(($current_pwm - 10))

        # if the current speed is now more then the current set to the target speed
        if [ "$target_pwm" -gt "$current_pwm" ]; then
        current_pwm=$target_pwm
        fi

    fi

    logger Changing fan speed to: $current_pwm
        echo "$current_pwm" > /sys/devices/pwm_fan/hwmon/hwmon0/pwm1
    fi
}

# Turn fan on when exiting
trap "{ echo 255 >> /sys/devices/pwm_fan/hwmon/hwmon0/pwm1; exit; }" SIGINT SIGTERM

# Main fan control loop
while true:
do
    cpu=`cat /sys/class/hwmon/hwmon2/temp1_input`
    ddr=`cat /sys/class/hwmon/hwmon1/temp1_input`
    wifi=`cat /sys/class/hwmon/hwmon1/temp2_input`

    if [ "$cpu" -ge $CPU_ON -o "$ddr" -ge $DDR_ON -o "$wifi" -ge $WIFI_ON ]
    then
        fan_set 2
    elif [ "$cpu" -le $CPU_OFF -a "$ddr" -le $DDR_OFF -a "$wifi" -le $WIFI_OFF ]
    then
        fan_set 0
    elif [ "$cpu" -le $CPU_MID -a "$ddr" -le $DDR_MID -a "$wifi" -le $WIFI_MID ]
    then
        fan_set 1
    fi

    sleep $INTERVAL
done