공간벡터제어 적용
This commit is contained in:
parent
ec0c7112b1
commit
08e83afe52
50
main.go
50
main.go
|
@ -15,6 +15,7 @@ import (
|
|||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"amuz.es/src/infra/cpu_ctrl/pid"
|
||||
|
||||
"github.com/coreos/go-systemd/daemon"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
|
@ -92,10 +93,10 @@ func ReadTempeture(path string, senseChan chan<- float64, errorChan chan<- error
|
|||
}
|
||||
}
|
||||
|
||||
func CpuTempetureMonitoring(info *Processor, notifier chan<- TempetureChange, errorChan chan<- error, ctx context.Context, waiter *sync.WaitGroup) {
|
||||
func CpuTempetureMonitoring(info *Processor,sampleDuration time.Duration, notifier chan<- TempetureChange, errorChan chan<- error, ctx context.Context, waiter *sync.WaitGroup) {
|
||||
defer waiter.Done()
|
||||
tempeturePathGlob := path.Join(info.TempeturePath, "temp?_input")
|
||||
ticker := time.Tick(3 * time.Second)
|
||||
ticker := time.Tick(sampleDuration)
|
||||
for {
|
||||
select {
|
||||
case <-ticker:
|
||||
|
@ -129,31 +130,47 @@ func CpuTempetureMonitoring(info *Processor, notifier chan<- TempetureChange, er
|
|||
}
|
||||
func CpuTempetureScraper(processorCount int, notifier <-chan TempetureChange, errorChan chan<- error, ctx context.Context, waiter *sync.WaitGroup) {
|
||||
defer waiter.Done()
|
||||
pastFan := make([]int, processorCount)
|
||||
var (
|
||||
P,I,D=1.5, 0.4, 2.0
|
||||
SetPoint=40.0
|
||||
SampleTime=time.Second
|
||||
WindupGuard=96.0
|
||||
maxNoob,minNoob=0x64,0x4
|
||||
)
|
||||
noobs := make([]int,processorCount)
|
||||
controllers := make([]pid.Controller, 0,processorCount)
|
||||
for i:=0 ;i<processorCount;i++{
|
||||
controller:=pid.New(PID)
|
||||
controller.SetSetPoint(SetPoint)
|
||||
controller.SetSampleTime(SampleTime)
|
||||
controller.SetWindupGuard(WindupGuard)
|
||||
controllers := append(controllers,controller)
|
||||
}
|
||||
|
||||
|
||||
for {
|
||||
select {
|
||||
case change := <-notifier:
|
||||
delta := int(change.Tempeture) - 33
|
||||
fan := 0x4 + (delta - delta%0x4)
|
||||
if fan < 0x4 {
|
||||
fan = 0x4
|
||||
} else if fan > 0x50 {
|
||||
fan = 0x0
|
||||
controller:=controllers[change.Id]
|
||||
resp:=controller.Update(change)
|
||||
|
||||
adj_noob := -resp + minNoob
|
||||
if adj_noob > maxNoob{
|
||||
adj_noob=maxNoob
|
||||
}
|
||||
|
||||
if pastFan[change.Id] != fan {
|
||||
pastFan[change.Id] = fan
|
||||
} else {
|
||||
if noobs[change.Id]== adj_noob{
|
||||
continue
|
||||
}
|
||||
noobs[change.Id]=adj_noob
|
||||
fmt.Printf("cpu %d fan 0x%x\n", change.Id, adj_noob)
|
||||
|
||||
fmt.Printf("cpu %d fan 0x%x\n", change.Id, fan)
|
||||
args := make([]string, 0)
|
||||
args = append(args,
|
||||
"raw",
|
||||
"0x3a", "0x01",
|
||||
)
|
||||
for _, item := range pastFan {
|
||||
for _, item := range noobs {
|
||||
args = append(args, fmt.Sprintf("0x%x", item))
|
||||
}
|
||||
args = append(args,
|
||||
|
@ -172,12 +189,13 @@ func CpuTempetureScraper(processorCount int, notifier <-chan TempetureChange, er
|
|||
|
||||
func main() {
|
||||
var (
|
||||
processorCount = 0 //getProcessorCount()
|
||||
processorCount = getProcessorCount()
|
||||
ctx, canceled = context.WithCancel(context.Background())
|
||||
waiter = &sync.WaitGroup{}
|
||||
exitSignal = make(chan os.Signal, 1)
|
||||
errorChan = make(chan error, 1)
|
||||
tempetureChange = make(chan TempetureChange)
|
||||
sampleDuration = time.Second
|
||||
)
|
||||
|
||||
if processorCount == 0 {
|
||||
|
@ -188,7 +206,7 @@ func main() {
|
|||
errorChan <- err
|
||||
} else {
|
||||
waiter.Add(1)
|
||||
go CpuTempetureMonitoring(info, tempetureChange, errorChan, ctx, waiter)
|
||||
go CpuTempetureMonitoring(info,sampleDuration, tempetureChange, errorChan, ctx, waiter)
|
||||
}
|
||||
}
|
||||
waiter.Add(1)
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package pid
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type controller struct {
|
||||
Kp float64
|
||||
Ki float64
|
||||
Kd float64
|
||||
lastTime time.Time
|
||||
SetPoint float64
|
||||
SampleTime time.Duration
|
||||
WindupGuard float64
|
||||
Output float64
|
||||
|
||||
pTerm float64
|
||||
iTerm float64
|
||||
dTerm float64
|
||||
lastError float64
|
||||
}
|
||||
|
||||
/*
|
||||
PID Controller
|
||||
*/
|
||||
type Controller interface {
|
||||
GetKp() float64
|
||||
GetKi() float64
|
||||
GetKd() float64
|
||||
GetSetPoint() float64
|
||||
GetSampleTime() time.Duration
|
||||
GetWindupGuard() float64
|
||||
GetOutput() float64
|
||||
|
||||
SetKp(float64)
|
||||
SetKi(float64)
|
||||
SetKd(float64)
|
||||
SetSetPoint(float64)
|
||||
SetSampleTime(time.Duration)
|
||||
SetWindupGuard(float64)
|
||||
SetOutput(float64)
|
||||
|
||||
Clear()
|
||||
Update(float64) float64
|
||||
}
|
||||
|
||||
/*
|
||||
create PID Controller
|
||||
*/
|
||||
func New(proportionalGain float64, integralGain float64, derivativeGain float64) Controller {
|
||||
return &controller{
|
||||
Kp: proportionalGain,
|
||||
Ki: integralGain,
|
||||
Kd: derivativeGain,
|
||||
WindupGuard: 20.0,
|
||||
lastTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Clears PID computations and coefficients
|
||||
*/
|
||||
func (c *controller) Clear() {
|
||||
c.SetPoint = 0.0
|
||||
c.pTerm = 0.0
|
||||
c.iTerm = 0.0
|
||||
c.dTerm = 0.0
|
||||
c.lastError = 0.0
|
||||
c.WindupGuard = 20.0
|
||||
c.Output = 0.0
|
||||
}
|
||||
|
||||
/*
|
||||
Calculates PID value for given reference feedback
|
||||
.. math::
|
||||
u(t) = K_p e(t) + K_i \int_{0}^{t} e(t)dt + K_d {de}/{dt}
|
||||
|
||||
.. figure:: images/pid_1.png
|
||||
:align: center
|
||||
|
||||
Test PID with Kp=1.2, Ki=1, Kd=0.001 (test_pid.py)
|
||||
*/
|
||||
func (c *controller) Update(feedbackValue float64) float64 {
|
||||
var (
|
||||
errorValue = c.SetPoint - feedbackValue
|
||||
currentTime = time.Now()
|
||||
deltaTime, deltaError = currentTime.Sub(c.lastTime), errorValue - c.lastError
|
||||
)
|
||||
|
||||
if deltaTime >= c.SampleTime {
|
||||
c.pTerm = c.Kp * errorValue
|
||||
c.iTerm += errorValue * deltaTime.Seconds()
|
||||
|
||||
if c.iTerm < -c.WindupGuard {
|
||||
c.iTerm = -c.WindupGuard
|
||||
} else if c.iTerm > c.WindupGuard {
|
||||
c.iTerm = c.WindupGuard
|
||||
}
|
||||
|
||||
c.dTerm = 0.0
|
||||
if deltaTime.Seconds() > 0.0 {
|
||||
c.dTerm = deltaError / deltaTime.Seconds()
|
||||
}
|
||||
c.lastTime = currentTime
|
||||
c.lastError = errorValue
|
||||
|
||||
c.Output = c.pTerm + (c.Ki * c.iTerm) + (c.Kd * c.dTerm)
|
||||
}
|
||||
return c.Output
|
||||
}
|
||||
|
||||
func (c *controller) GetKp() float64 { return c.Kp }
|
||||
func (c *controller) GetKi() float64 { return c.Ki }
|
||||
func (c *controller) GetKd() float64 { return c.Kd }
|
||||
func (c *controller) GetSetPoint() float64 { return c.SetPoint }
|
||||
func (c *controller) GetSampleTime() time.Duration { return c.SampleTime }
|
||||
func (c *controller) GetWindupGuard() float64 { return c.WindupGuard }
|
||||
func (c *controller) GetOutput() float64 { return c.Output }
|
||||
|
||||
func (c *controller) SetKp(v float64) { c.Kp = v }
|
||||
func (c *controller) SetKi(v float64) { c.Ki = v }
|
||||
func (c *controller) SetKd(v float64) { c.Kd = v }
|
||||
func (c *controller) SetSetPoint(v float64) { c.SetPoint = v }
|
||||
func (c *controller) SetSampleTime(v time.Duration) { c.SampleTime = v }
|
||||
func (c *controller) SetWindupGuard(v float64) { c.WindupGuard = v }
|
||||
func (c *controller) SetOutput(v float64) { c.Output = v }
|
|
@ -0,0 +1,50 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"amuz.es/src/infra/cpu_ctrl/pid"
|
||||
)
|
||||
|
||||
// 실제 CPU온도환경 모델링
|
||||
func test_pid(P float64, I float64, D float64, L int) {
|
||||
pid := pid.New(P, I, D)
|
||||
pid.SetSetPoint(40.0)
|
||||
pid.SetSampleTime(time.Second)
|
||||
pid.SetWindupGuard(96.0)
|
||||
|
||||
END := L
|
||||
|
||||
feedback := 60.0
|
||||
|
||||
minTemp := 28.0
|
||||
|
||||
for i := 0; i < END; i++ {
|
||||
output := pid.Update((feedback * 1000.0) / 1000.0)
|
||||
adj := output
|
||||
if output > 0 {
|
||||
adj = 0.0
|
||||
} else if output < -96.0 {
|
||||
adj = -96.0
|
||||
}
|
||||
|
||||
adj_noob := int(-adj + 4)
|
||||
|
||||
adj /= 10.0
|
||||
adj += 1.1
|
||||
fmt.Printf("feedback: %0.17f output: %0.17f adj: %0.17f noob: 0x%x\n", feedback, output, adj, adj_noob)
|
||||
|
||||
feedback += adj
|
||||
|
||||
if feedback < minTemp {
|
||||
feedback = minTemp
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
}
|
||||
}
|
||||
func main() {
|
||||
test_pid(1.5, 0.4, 2.0, 500)
|
||||
}
|
Loading…
Reference in New Issue