mcp3008: added package and samples for mcp3008 10-bit 8-channel adc

This commit is contained in:
kunalpowar 2014-05-03 21:35:09 +05:30
parent 42033238e2
commit 59958d7dfc
7 changed files with 163 additions and 4 deletions

View File

@ -0,0 +1,52 @@
package mcp3008
import (
"github.com/golang/glog"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/all"
)
type mcp3008 struct {
mode int
bus embd.SPIBus
}
const (
SingleMode = int(1)
DifferenceMode = int(0)
)
func New(mode, spiChan, speed int) (*mcp3008, error) {
if err := embd.InitSPI(); err != nil {
return nil, err
}
glog.V(3).Infof("mcp3008: getting spiBus with mode: %v, channel: %v, speed: %v", mode, spiChan, speed)
spiBus := embd.NewSPIBus(embd.SpiMode0, byte(spiChan), speed, 0, 0)
return &mcp3008{mode, spiBus}, nil
}
func (m *mcp3008) AnalogValueAt(chanNum int) (int, error) {
data := make([]uint8, 3)
data[0] = 1
data[1] = uint8(m.mode)<<7 | uint8(chanNum)<<4
data[2] = 0
if err := m.bus.TransferAndRecieveData(data); err != nil {
return 0, err
}
return int(uint16(data[1]&0x03)<<8 | uint16(data[2])), nil
}
func (m *mcp3008) Close() error {
glog.V(2).Infoln("mcp3008: performing cleanup")
if err := m.bus.Close(); err != nil {
return err
}
if err := embd.CloseSPI(); err != nil {
return err
}
return nil
}

View File

@ -15,6 +15,8 @@ import (
"os"
"strings"
"github.com/golang/glog"
"github.com/kidoman/embd"
"github.com/kidoman/embd/host/generic"
)
@ -97,6 +99,7 @@ var ledMap = embd.LEDMap{
var spiDeviceMinor = byte(1)
func ensureFeatureEnabled(id string) error {
glog.V(3).Infof("bbb: enabling feature %v", id)
pattern := "/sys/devices/bone_capemgr.*/slots"
file, err := embd.FindFirstMatchingFile(pattern)
if err != nil {
@ -108,6 +111,7 @@ func ensureFeatureEnabled(id string) error {
}
str := string(bytes)
if strings.Contains(str, id) {
glog.V(3).Infof("bbb: feature %v already enabled", id)
return nil
}
slots, err := os.OpenFile(file, os.O_WRONLY, os.ModeExclusive)
@ -115,6 +119,7 @@ func ensureFeatureEnabled(id string) error {
return err
}
defer slots.Close()
glog.V(3).Infof("bbb: writing %v to slots file", id)
_, err = slots.WriteString(id)
return err
}

View File

@ -76,6 +76,10 @@ func NewSPIBus(spiDevMinor, mode, channel byte, speed, bpw, delay int, shouldIni
}
func (b *spiBus) init() error {
if b.initialized {
return nil
}
if b.shouldInitialize {
if err := b.initializer(); err != nil {
return err
@ -83,14 +87,11 @@ func (b *spiBus) init() error {
b.shouldInitialize = false
}
if b.initialized {
return nil
}
var err error
if b.file, err = os.OpenFile(fmt.Sprintf("/dev/spidev%v.%v", b.spiDevMinor, b.channel), os.O_RDWR, os.ModeExclusive); err != nil {
return err
}
glog.V(3).Infof("spi: sucessfully opened file /dev/spidev%v.%v", b.spiDevMinor, b.channel)
err = b.setMode()
if err != nil {
@ -112,6 +113,7 @@ func (b *spiBus) init() error {
b.setDelay()
glog.V(2).Infof("spi: bus %v initialized", b.channel)
glog.V(3).Infof("spi: bus %v initialized with spiIocTransfer as %v", b.channel, b.spiTransferData)
b.initialized = true
return nil
@ -187,6 +189,10 @@ func (b *spiBus) setDelay() {
}
func (b *spiBus) TransferAndRecieveData(dataBuffer []uint8) error {
if err := b.init(); err != nil {
return err
}
len := len(dataBuffer)
dataCarrier := b.spiTransferData
@ -194,16 +200,22 @@ func (b *spiBus) TransferAndRecieveData(dataBuffer []uint8) error {
dataCarrier.txBuf = uint64(uintptr(unsafe.Pointer(&dataBuffer[0])))
dataCarrier.rxBuf = uint64(uintptr(unsafe.Pointer(&dataBuffer[0])))
glog.V(3).Infof("spi: sending dataBuffer %v with carrier %v", dataBuffer, dataCarrier)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, b.file.Fd(), uintptr(spiIocMessageN(1)), uintptr(unsafe.Pointer(&dataCarrier)))
if errno != 0 {
err := syscall.Errno(errno)
glog.V(3).Infof("spi: failed to read due to %v", err.Error())
return err
}
glog.V(3).Infof("spi: read into dataBuffer %v", dataBuffer)
return nil
}
func (b *spiBus) ReceiveData(len int) ([]uint8, error) {
if err := b.init(); err != nil {
return nil, err
}
data := make([]uint8, len)
var err error
err = b.TransferAndRecieveData(data)
@ -214,6 +226,10 @@ func (b *spiBus) ReceiveData(len int) ([]uint8, error) {
}
func (b *spiBus) TransferAndReceiveByte(data byte) (byte, error) {
if err := b.init(); err != nil {
return 0, err
}
d := make([]uint8, 1)
d[0] = uint8(data)
err := b.TransferAndRecieveData(d)
@ -224,6 +240,10 @@ func (b *spiBus) TransferAndReceiveByte(data byte) (byte, error) {
}
func (b *spiBus) ReceiveByte() (byte, error) {
if err := b.init(); err != nil {
return 0, err
}
d := make([]uint8, 1)
err := b.TransferAndRecieveData(d)
if err != nil {

2
samples/.gitignore vendored
View File

@ -24,3 +24,5 @@ universalblinker
us020
watersensor
spi
mcp3008
spimcp3008

33
samples/mcp3008.go Normal file
View File

@ -0,0 +1,33 @@
// +build ignore
package main
import (
"flag"
"fmt"
"time"
"github.com/kidoman/embd/convertors/mcp3008"
)
func main() {
flag.Parse()
fmt.Println("This is a sample code for mcp3008 10bit 8 channel ADC")
adc, err := mcp3008.New(mcp3008.SingleMode, 0, 1000000)
if err != nil {
panic(err)
}
defer adc.Close()
for i := 0; i < 20; i++ {
time.Sleep(1 * time.Second)
val, err := adc.AnalogValueAt(0)
if err != nil {
panic(err)
}
fmt.Printf("Analog value is: %v\n", val)
}
}

46
samples/spimcp3008.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"flag"
"fmt"
"time"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/all"
)
func main() {
flag.Parse()
if err := embd.InitSPI(); err != nil {
panic(err)
}
bus := embd.NewSPIBus(embd.SpiMode0, 0, 1000000, 8, 0)
defer clean(bus)
for i := 0; i < 30; i++ {
time.Sleep(1 * time.Second)
val, _ := getSensorValue(bus)
fmt.Printf("value is: %v\n", val)
}
}
func clean(bus embd.SPIBus) {
bus.Close()
embd.CloseSPI()
}
func getSensorValue(bus embd.SPIBus) (uint16, error) {
data := make([]uint8, 3)
data[0] = 1
data[1] = 128
data[2] = 0
var err error
err = bus.TransferAndRecieveData(data)
if err != nil {
return uint16(0), err
}
return uint16(data[1]&0x03)<<8 | uint16(data[2]), nil
}

View File

@ -29,6 +29,7 @@ func (s *spiDriver) Bus(mode, channel byte, speed, bpw, delay int) SPIBus {
defer s.busMapLock.Unlock()
b := s.sbf(s.spiDevMinor, mode, channel, speed, bpw, delay, s.shouldInitialize, s.initializer)
s.busMap = make(map[byte]SPIBus)
s.busMap[channel] = b
return b
}