Hatena::ブログ(Diary)

bootblackの日記 このページをアンテナに追加 RSSフィード

6/10/2009

[][]MacBook(旧式黒)のファンからありえない異音が聞こえてきました MacBook(旧式黒)のファンからありえない異音が聞こえてきましたを含むブックマーク

不愉快です(苦笑)。ノイズをわかってないし、うまく回せてない感じです。多分ファンはもうイカれてるんだと思います(苦笑)。機種はApple MacBook 13" 2GHz Intel Core Duo/512MB/ HD80GB/ SD/ Black [MA472J/A]です。

ので伝説のsmc.c(SMC tool 0.01 (GPL))を発掘してファンを微調整しました。

smc.cのプロバイダーとしてはFan ControlsmcFanControl等がメジャーです!?

smc.c中のAPIMac OS X 10.5 SDKでは一部変更になったようなので変えました。(64bit対応についてはhttp://d.hatena.ne.jp/bootblack/20090708/p1

#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5	
    return IOConnectCallStructMethod(
               		conn,
              		 index,
               		inputStructure,
               		structureInputSize,
               		outputStructure,
               		&structureOutputSize
		);
#else
    return IOConnectMethodStructureIStructureO(
               		conn,
               		index,
               		structureInputSize,
               		&structureOutputSize,
               		inputStructure,
               		outputStructure
		);	
#endif

smc.cのmain()をコメントアウト

本体プログラムプロジェクトXcodeにてコマンドラインユーティリティ(Foundationツール)として作成。

ありえない異音をさけつつFanの回転数を遷移させて用をたすよう、善処しているつもりです(基本的にノイジーですが(苦笑))

ファン回転数の最大値も調節しているので最悪、爆発炎上します。そう思ってください。ここは戦場ですよ(苦笑)

爆発の脅威は常にありますから想定しといて下さい(苦笑)

終了処理はsignal受け付けて(タイマーも止めて?)おこなわないとだめ?

あと、Fanを割り箸で叩いたり周辺のホコリの除去と除菌をおこなったところCPU温度が10〜5度下がりました。

ver 19 (2009/7/05) antiエコ簡易版 for 耐震マット3段(以降はhttp://d.hatena.ne.jp/bootblack/20090709/p1に以降しました)

#import <Foundation/Foundation.h>
#import <asl.h>
#import "smc.h"

@interface RpmMinMaxController : NSObject {
	int		rpmMax;
	int		rpmMin;
	double	t;
	double	old_t;
}
@end

@implementation RpmMinMaxController
- (void)SetFanRpmMax:(int)rpm
{
	kern_return_t result = SMCSetFanRpm("F0Mx", rpm);
	if (result == kIOReturnSuccess) {
		rpmMax = rpm;
	} else {
		asl_log(NULL, NULL, ASL_LEVEL_ERR, "Error: rpmMax = %d set failed.", rpm);
	}
}

- (void)SetFanRpmMin:(int)rpm
{
	kern_return_t result = SMCSetFanRpm(SMC_KEY_FAN0_RPM_MIN, rpm);
	if (result == kIOReturnSuccess) {
		rpmMin = rpm;
	} else {
		asl_log(NULL, NULL, ASL_LEVEL_ERR, "Error: rpmMin = %d set failed.", rpm);
	}
}

- (NSTimer *)setTimer
{
	return [NSTimer	scheduledTimerWithTimeInterval:5.0
					target:self
					selector:@selector(RpmMinMaxController_main)
					userInfo:nil
					repeats:YES];						
}

/***
 -(void)dealloc
 {
	SMCOpen();
	[self SetFanRpmMin:1500];
	[self SetFanRpmMax:6200];
	SMCClose();
	asl_log(NULL, NULL, ASL_LEVEL_ERR, "RpmMinMaxController dealloc");
	[super dealloc];
 }
***/

- (void)SetFanRpmLow
{
//	[self SetFanRpmMax:3000];
	[self SetFanRpmMax:4000];
	if (rpmMin != 1800) [self SetFanRpmMin:1800];
}

- (id)init
{
	self = [super init];
	if (self != nil) {
		SMCOpen();
		[self SetFanRpmLow];
		old_t = SMCGetTemperature(SMC_KEY_CPU_TEMP);
		SMCClose();
	}
	return self;
}

- (void)RpmMinMaxController_main
{
	SMCOpen();

	t = SMCGetTemperature(SMC_KEY_CPU_TEMP);
	if (t <= 0) {
		asl_log(NULL, NULL, ASL_LEVEL_ERR, 
				"Error: SMCGetTemperature() failed. (t = %.0f)", t);
	} else if ((t >= 72.0) && (old_t >= 72.0) && (rpmMax != 6200)) {
			[self SetFanRpmMax:6200];
			if (rpmMin != 5500) [self SetFanRpmMin:5500];
	} else if ((t >= 65.0) && (old_t >= 65.0) && (rpmMax < 6000)) {
			[self SetFanRpmMax:6000];
			if (rpmMin != 5000) [self SetFanRpmMin:5000];
	} else {
		switch (rpmMax) {
			case 6200:
				if ((t < 60.0) && (SMCGetFanRpm(SMC_KEY_FAN0_RPM_CUR) < 5600)) {
					[self SetFanRpmLow];
				} else {
					if (rpmMin != 5500) [self SetFanRpmMin:5500];
				}
				break;
			case 6000:
				if ((t < 60.0) && (SMCGetFanRpm(SMC_KEY_FAN0_RPM_CUR) < 5800)) {
//				if ((t < 60.0) && (SMCGetFanRpm(SMC_KEY_FAN0_RPM_CUR) < 4100)) {
					[self SetFanRpmLow];
				} else {
					if (rpmMin != 4000) [self SetFanRpmMin:4000];
//					if (rpmMin != 3500) [self SetFanRpmMin:3500];
//					if (rpmMin != 3000) [self SetFanRpmMin:3000];
				}
				break;
			default:
				break;				
		}
	}

	SMCClose();
	old_t = t;
}
@end


int main (int argc, const char * argv[]) {
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	RpmMinMaxController *theRpmMaxController = [[RpmMinMaxController alloc] init];

	NSTimer *theTimer = [theRpmMaxController setTimer];
	[[NSRunLoop currentRunLoop] addTimer: theTimer forMode: NSDefaultRunLoopMode];

	[[NSRunLoop currentRunLoop] run];

	[theRpmMaxController release];
	[pool drain];
	return 0;
}

起動用plist(/Library/LaunchDaemons/に投入して「sudo chown root:wheel」する)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>nf.mb.FanControl</string>
	<key>KeepAlive</key>
	<true/>
	<!--
	<key>HopefullyExitsFirst</key>
	<true/>
	-->
	<key>Program</key>
	<string>/opt/local/sbin/FanControl_nf</string>
	<key>ProgramArguments</key>
	<array>
		<string>FanControl_nf</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>
Connection: close