From 1017bc7f9afd82e98a898b99adb14b69253e10e0 Mon Sep 17 00:00:00 2001 From: Karan Misra Date: Mon, 6 Jan 2014 02:26:45 +0530 Subject: [PATCH] support for MCP4725 DAC --- README.md | 10 +++- controller/mcp4725/mcp4725.go | 105 ++++++++++++++++++++++++++++++++++ samples/mcp4725.go | 36 ++++++++++++ 3 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 controller/mcp4725/mcp4725.go create mode 100644 samples/mcp4725.go diff --git a/README.md b/README.md index ebea876..6068858 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,13 @@ Use various sensors on the RaspberryPi with Golang (like a ninja!) ## Controllers ### PCA9685 + 16-channel, 12-bit PWM Controller with I2C protocol - [Datasheet] (http://www.adafruit.com/datasheets/PCA9685.pdf) - [Product Page] (http://www.adafruit.com/products/815) + [Documentation](http://godoc.org/github.com/kid0m4n/go-rpi/controller/pca9685) [Datasheet](http://www.adafruit.com/datasheets/PCA9685.pdf) [Product Page](http://www.adafruit.com/products/815) + +### MCP4725 + + 12-bit DAC + + [Documentation](http://godoc.org/github.com/kid0m4n/go-rpi/controller/mcp4725) [Datasheet](http://www.adafruit.com/datasheets/mcp4725.pdf) [Product Page](http://www.adafruit.com/products/935) diff --git a/controller/mcp4725/mcp4725.go b/controller/mcp4725/mcp4725.go new file mode 100644 index 0000000..858d32b --- /dev/null +++ b/controller/mcp4725/mcp4725.go @@ -0,0 +1,105 @@ +// Package mcp4725 allows interfacing with the MCP4725 DAC. +package mcp4725 + +import ( + "log" + "sync" + + "github.com/kid0m4n/go-rpi/i2c" +) + +const ( + dacReg = 0x40 + programReg = 0x60 + powerDown = 0x46 + + genReset = 0x06 + powerUp = 0x09 +) + +// MCP4725 represents a MCP4725 DAC. +type MCP4725 struct { + // Bus to communicate over. + Bus i2c.Bus + // Addr of the sensor. + Addr byte + + initialized bool + mu sync.RWMutex + + // Debug turns on additional debug output. + Debug bool +} + +// New creates a new MCP4725 sensor. +func New(bus i2c.Bus, addr byte) *MCP4725 { + return &MCP4725{ + Bus: bus, + Addr: addr, + } +} + +func (d *MCP4725) setup() (err error) { + d.mu.RLock() + if d.initialized { + d.mu.RUnlock() + return + } + d.mu.RUnlock() + + d.mu.Lock() + defer d.mu.Unlock() + + if d.Debug { + log.Print("mcp4725: general call reset") + } + if err = d.Bus.WriteByteToReg(d.Addr, 0x00, powerUp); err != nil { + return + } + if err = d.Bus.WriteByteToReg(d.Addr, 0x00, genReset); err != nil { + return + } + d.initialized = true + return +} + +func (d *MCP4725) setVoltage(voltage int, reg byte) (err error) { + if err = d.setup(); err != nil { + return + } + if voltage > 4095 { + voltage = 4095 + } + if voltage < 0 { + voltage = 0 + } + if d.Debug { + log.Printf("mcp4725: setting voltage to %04d", voltage) + } + if err = d.Bus.WriteWordToReg(d.Addr, reg, uint16(voltage<<4)); err != nil { + return + } + return +} + +// SetVoltage sets the output voltage. +func (d *MCP4725) SetVoltage(voltage int) (err error) { + return d.setVoltage(voltage, dacReg) +} + +// SetPersistedVoltage sets the voltage and programs the EEPROM so +// that the voltage is restored on reboot. +func (d *MCP4725) SetPersistedVoltage(voltage int) (err error) { + return d.setVoltage(voltage, programReg) +} + +// Close puts the DAC into power down mode. +func (d *MCP4725) Close() (err error) { + if d.Debug { + log.Print("mcp4725: powering down") + } + if err = d.Bus.WriteWordToReg(d.Addr, powerDown, 0); err != nil { + return + } + return +} diff --git a/samples/mcp4725.go b/samples/mcp4725.go new file mode 100644 index 0000000..1c8cefb --- /dev/null +++ b/samples/mcp4725.go @@ -0,0 +1,36 @@ +package main + +import ( + "log" + "math/rand" + "os" + "os/signal" + + "github.com/kid0m4n/go-rpi/controller/mcp4725" + "github.com/kid0m4n/go-rpi/i2c" +) + +func main() { + bus, err := i2c.NewBus(1) + if err != nil { + log.Panic(err) + } + + dac := mcp4725.New(bus, 0x62) + defer dac.Close() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt, os.Kill) + + for { + select { + case <-stop: + return + default: + voltage := rand.Intn(4096) + if err := dac.SetVoltage(voltage); err != nil { + log.Printf("mcp4725: %v", err) + } + } + } +}