192 lines
5.2 KiB
Go
192 lines
5.2 KiB
Go
package radar_lib
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"sync"
|
|
|
|
"go.bug.st/serial"
|
|
)
|
|
|
|
type configResponse struct {
|
|
CommandCode int
|
|
Success bool
|
|
}
|
|
|
|
type Direction int
|
|
type OutputLogic int
|
|
type Port int
|
|
type Baud int
|
|
type OutputType int
|
|
type TriggerMethod int
|
|
type OperatingMode int
|
|
|
|
const (
|
|
ControlPinRelay = iota
|
|
ControlPinCtrl1
|
|
ControlPinCtrl2
|
|
)
|
|
const (
|
|
DirectionBidirectional Direction = iota
|
|
DirectionIncoming
|
|
DirectionOutgoing
|
|
)
|
|
const (
|
|
TargetStateInvalid = iota
|
|
TargetStateMovingInside
|
|
TargetStateExit
|
|
TargetStateWithin
|
|
)
|
|
const (
|
|
OutputLogicLargestSpeed = iota
|
|
OutputLogicStrongestEngergy
|
|
OutputLogicMostPlausible
|
|
)
|
|
const (
|
|
PortTTL Port = iota
|
|
PortRS485
|
|
)
|
|
const (
|
|
Baud9600 Baud = iota
|
|
Baud19200
|
|
Baud57600
|
|
Baud115200
|
|
)
|
|
const (
|
|
OutputTypeNoOutput OutputType = iota
|
|
OutputTypePeriodicOutput
|
|
OutputTypeValidOutput
|
|
)
|
|
const (
|
|
TriggerMethodHigh TriggerMethod = iota
|
|
TriggerMethodLow
|
|
TriggerMethodPositivePulse
|
|
TriggerMethodNegativePulse
|
|
)
|
|
const (
|
|
OperatingModeNoOutput OperatingMode = iota
|
|
OperatingModeFirstProtocol
|
|
OperatingModeSecondProtocol
|
|
)
|
|
|
|
var (
|
|
startSequence = []byte{0x43, 0x46}
|
|
endSequence = []byte{0x0D, 0x0A}
|
|
)
|
|
|
|
func New(port string, baudrate int) *Radar {
|
|
s, err := serial.Open(port, &serial.Mode{
|
|
BaudRate: baudrate,
|
|
DataBits: 8,
|
|
Parity: serial.NoParity,
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
r := &Radar{
|
|
port: s,
|
|
baudrate: baudrate,
|
|
configResponseChannel: make(chan configResponse),
|
|
}
|
|
go r.listenSerial()
|
|
return r
|
|
}
|
|
|
|
type Radar struct {
|
|
port serial.Port
|
|
lock sync.RWMutex
|
|
configResponseChannel chan (configResponse)
|
|
baudrate int
|
|
handler func(int)
|
|
speedHandler func(int)
|
|
configLock sync.RWMutex
|
|
}
|
|
|
|
func (r *Radar) write(data []byte) error {
|
|
r.lock.Lock()
|
|
defer r.lock.Unlock()
|
|
log.Printf("writing %#x", data)
|
|
_, err := r.port.Write(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return r.port.Drain()
|
|
}
|
|
|
|
func (r *Radar) lockConfig() {
|
|
r.configLock.Lock()
|
|
}
|
|
|
|
// SetPinTrigger configures a pin to trigger on the radar when an object is detected in a specific range.
|
|
// controlPin defines the Pin to trigger, distance is the target distance in 0.5 meters, outputLevel is the voltage in 0.1V steps, direction defines weather to trigger on incoming / outgoing or both
|
|
func (r *Radar) SetPinTrigger(controlPin int, distance int, outputLevel int, direction Direction) error {
|
|
data := startSequence
|
|
data = append(data, 0x00, byte(controlPin), byte(distance), byte(outputLevel), byte(direction))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
// SetBaseConfig configures the base configuration. height defines the mounted height in 1cm steps, angle defines the vertical angle in degrees, waveformConfig is used to differentiate 2 different radars
|
|
func (r *Radar) SetBaseConfig(height int, angle int, waveformConfig int) error {
|
|
data := startSequence
|
|
data = append(data, 0x01, byte(height), byte(angle), byte(waveformConfig), 0x00)
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
// SetEventConfig can configure up to 8 events that will trigger a response from the radar. distances are in 0.5m, speeds are in km/h.
|
|
func (r *Radar) SetEventConfig(eventNumber, minDistance, maxDistance, minSpeed, maxSpeed, direction, state int) error {
|
|
r.lockConfig()
|
|
|
|
if eventNumber < 1 || eventNumber > 1 {
|
|
return errors.New("eventNumber needs to be between 1 and 8")
|
|
}
|
|
data := startSequence
|
|
data = append(data, 0x02, byte(eventNumber), byte(minDistance), byte(maxDistance), byte(minSpeed), byte(maxSpeed), byte(direction), byte(state))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
func (r *Radar) SetTargetSpeedConfig(direction Direction, minDistance, maxDistance, minSpeed, maxSpeed, speeding int, outputLogic OutputLogic) error {
|
|
r.lockConfig()
|
|
data := startSequence
|
|
data = append(data, 0x03, byte(direction), byte(minDistance), byte(maxDistance), byte(minSpeed), byte(maxSpeed), byte(speeding), byte(outputLogic))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
func (r *Radar) SetCommunicationConfig(port Port, baud Baud, speedOutput, targetOutput, triggerOutput OutputType, communicationPeriod int) error {
|
|
r.lockConfig()
|
|
data := startSequence
|
|
speed := byte(speedOutput)
|
|
target := byte(targetOutput)
|
|
trigger := byte(triggerOutput)
|
|
|
|
var outputProtocol byte = (speed << 4) | (target << 2) | trigger
|
|
|
|
data = append(data, 0x04, byte(port), byte(baud), outputProtocol, byte(int(communicationPeriod/50)))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
func (r *Radar) SetControlPinConfig(controlPin int, triggerMethod TriggerMethod, outputLevel int, triggerEvent int, span int) error {
|
|
data := startSequence
|
|
data = append(data, 0x05, byte(controlPin), byte(triggerMethod), byte(outputLevel), byte(triggerEvent), byte(span))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
func (r *Radar) SetLampBoardOutput(operatingMode OperatingMode, luminance int, span int) error {
|
|
data := startSequence
|
|
data = append(data, 0x06, byte(operatingMode), byte(luminance), byte(span))
|
|
data = append(data, endSequence...)
|
|
return r.write(data)
|
|
}
|
|
|
|
func (r *Radar) SetEventHandler(handler func(int)) {
|
|
r.handler = handler
|
|
}
|
|
|
|
func (r *Radar) SetSpeedHandler(handler func(int)) {
|
|
r.speedHandler = handler
|
|
}
|