I’m not a Golang developer. Let’s just get that out of the way up front. I’ve developed a few things in Go, but a Go developer I’m not. I sort of need to be, but it hasn’t been essential. I decided that it was really time to take the plunge and get serious about Go. Seriously, there’s only so much you can learn by reading the internet.
To that end, I have taken 2 actions:
- I’m going to Gophercon in Denver next week
- I ported a library from C to Go
It’s #2 that I’ll write about here today and not because I think I did an exceptionally good job of it but because it may be useful to others, and just to record what I’ve done, in case I want to refer to it later.
Read on if you’re interested!
Background
I’ve been working on a little IoT project (duh) that is using a Raspberry Pi. It also uses a Bosch BME280 breakout board from Adafruit. Which would be super easy to deal with if I was running it on an Arduino. But I’m not. And yes, I’m aware that there are ways to just run Arduino sketches on Raspberry Pi but I really am not such a fan of Arduino sketches, so I decided to do it another way.
The sensor is I2C, of course, so there was that. It’s easy to make the I2C buss accessible on Raspberry Pi (just run raspi-config and Bob’s your Uncle), but dealing with I2C devices is a little harder. I tried a couple of C-based I2C libraries but most of them gave … unexpected results. The one I found that was the closest was by a GitHub user called “BitBank2” (https://github.com/bitbank2/bme280) so I decided to use his. I was able to compile it and run the example program with at least reasonable results. But then I still had to call it from some user-space program in order to get the results. I should have smelled a rathole coming, but of course I didn’t.
I’ll just port it to Go! Sounded reasonable at the time.
Porting to Go
It was actually a lot easier than I thought it would be. First, there’s a great Go I2C library from @rakyll that works great. I had used it to access a SenseAir K30 CO2 sensor, so I thought I’d start there.
Since the library I was starting from worked, I figured the easiest thing to do would be to just do a semi-straight translation. I’d copy in a few lines of the C code, and then make it Go. There were, of course, some things that just wouldn’t work well. For instance, the I2C library wants to deal in bytes and byte slices, so I couldn’t very well just use the ints that the C library used. Also, the C library used a slew of static global variables, and that was also not going to work well in go. So I made adjustments:
static int calT1,calT2,calT3;
static int calP1, calP2, calP3, calP4, calP5, calP6, calP7, calP8, calP9;
static int calH1, calH2, calH3, calH4, calH5, calH6;
became:
type BME280 struct {
Dev *i2c.Device
tConfig []int
pConfig []int
hConfig []int
}
and
device.tConfig = make([]int, 3)
device.pConfig = make([]int, 9)
device.hConfig = make([]int, 6)
Pretty much the rest of it was a simple translation of turning a C language construct into a Golang construct.
// Prepare temperature calibration data
calT1 = ucCal[0] + (ucCal[1] << 8);
calT2 = ucCal[2] + (ucCal[3] << 8);
if (calT2 > 32767) calT2 -= 65536; // negative value
calT3 = ucCal[4] + (ucCal[5] << 8);
if (calT3 > 32767) calT3 -= 65536;
Turned into:
// time to set up the calibration
device.tConfig[0] = int(ucCal[0]) + (int(ucCal[1]) << 8)
device.tConfig[1] = int(ucCal[2]) + (int(ucCal[3]) << 8)
if device.tConfig[1] > 32767 {
device.tConfig[1] -= 65536
}
device.tConfig[2] = int(ucCal[4]) + (int(ucCal[5]) << 8)
if device.tConfig[2] > 32767 {
device.tConfig[2] -= 65536
}
And so on.
Now any Go program can simply do the following:
package main
import (
"fmt"
"github.com/davidgs/bme280_go"
"time"
)
func main() {
dev := "/dev/i2c-1"
bme := bme280_go.BME280{}
r := bme.BME280Init(dev)
if r < 0 {
fmt.Println("Error")
}
rets := bme.BME280ReadValues()
f := 0.00
f = float64(rets[0]) / 100.00
fmt.Println("Temp: ", f)
f = float64(rets[2]) / 1024.00
fmt.Println("Humidity: ", f)
bme.Dev.Close()
}
because a call to BME280ReadValues
returns a simple slice of ints
as Temperature, Pressure, and Humidity, in that order. Note : The pressure calculation is currently broken, so I don’t suggest using it.
As I said, it was surprisingly easy to get it all working! I now have a motley-fully functioning library for the Adafruit ZBME280 Breakout Board in GoLang!
Next up is to write a similar library for the SenseAir K30 sensor. I’ve got the sensor working just fine, I just have to turn the code into a library.
If you’re interested in using this library, it’s freely available on my GitHub.
The post Adventures in Golang appeared first on David G. Simmons.
Top comments (1)
First let me correct you ;-)
You write some Go code, you're a Go developer!
You might be a learning developer, but guess what, we all are!
Don't let anybody fool you into thinking otherwise.
That being said, it's a great article, thanks for sharing, fellow Gopher!
I hope you enjoyed GopherCon...