공간벡터제어 적용
This commit is contained in:
parent
ec0c7112b1
commit
08e83afe52
50
main.go
50
main.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
"amuz.es/src/infra/cpu_ctrl/pid"
|
||||||
|
|
||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
"github.com/shirou/gopsutil/cpu"
|
"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()
|
defer waiter.Done()
|
||||||
tempeturePathGlob := path.Join(info.TempeturePath, "temp?_input")
|
tempeturePathGlob := path.Join(info.TempeturePath, "temp?_input")
|
||||||
ticker := time.Tick(3 * time.Second)
|
ticker := time.Tick(sampleDuration)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker:
|
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) {
|
func CpuTempetureScraper(processorCount int, notifier <-chan TempetureChange, errorChan chan<- error, ctx context.Context, waiter *sync.WaitGroup) {
|
||||||
defer waiter.Done()
|
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 {
|
for {
|
||||||
select {
|
select {
|
||||||
case change := <-notifier:
|
case change := <-notifier:
|
||||||
delta := int(change.Tempeture) - 33
|
controller:=controllers[change.Id]
|
||||||
fan := 0x4 + (delta - delta%0x4)
|
resp:=controller.Update(change)
|
||||||
if fan < 0x4 {
|
|
||||||
fan = 0x4
|
adj_noob := -resp + minNoob
|
||||||
} else if fan > 0x50 {
|
if adj_noob > maxNoob{
|
||||||
fan = 0x0
|
adj_noob=maxNoob
|
||||||
}
|
}
|
||||||
|
|
||||||
if pastFan[change.Id] != fan {
|
if noobs[change.Id]== adj_noob{
|
||||||
pastFan[change.Id] = fan
|
|
||||||
} else {
|
|
||||||
continue
|
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 := make([]string, 0)
|
||||||
args = append(args,
|
args = append(args,
|
||||||
"raw",
|
"raw",
|
||||||
"0x3a", "0x01",
|
"0x3a", "0x01",
|
||||||
)
|
)
|
||||||
for _, item := range pastFan {
|
for _, item := range noobs {
|
||||||
args = append(args, fmt.Sprintf("0x%x", item))
|
args = append(args, fmt.Sprintf("0x%x", item))
|
||||||
}
|
}
|
||||||
args = append(args,
|
args = append(args,
|
||||||
|
@ -172,12 +189,13 @@ func CpuTempetureScraper(processorCount int, notifier <-chan TempetureChange, er
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
processorCount = 0 //getProcessorCount()
|
processorCount = getProcessorCount()
|
||||||
ctx, canceled = context.WithCancel(context.Background())
|
ctx, canceled = context.WithCancel(context.Background())
|
||||||
waiter = &sync.WaitGroup{}
|
waiter = &sync.WaitGroup{}
|
||||||
exitSignal = make(chan os.Signal, 1)
|
exitSignal = make(chan os.Signal, 1)
|
||||||
errorChan = make(chan error, 1)
|
errorChan = make(chan error, 1)
|
||||||
tempetureChange = make(chan TempetureChange)
|
tempetureChange = make(chan TempetureChange)
|
||||||
|
sampleDuration = time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
if processorCount == 0 {
|
if processorCount == 0 {
|
||||||
|
@ -188,7 +206,7 @@ func main() {
|
||||||
errorChan <- err
|
errorChan <- err
|
||||||
} else {
|
} else {
|
||||||
waiter.Add(1)
|
waiter.Add(1)
|
||||||
go CpuTempetureMonitoring(info, tempetureChange, errorChan, ctx, waiter)
|
go CpuTempetureMonitoring(info,sampleDuration, tempetureChange, errorChan, ctx, waiter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waiter.Add(1)
|
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