Comments (11)
I totally agree this is desired but I couldn't work on it on the short term as I had more pressing issues. My feeling for an optimal solution is:
- Refactor
devices.Environmental
to have a function toSenseNow(env *Environment)
now vsSenseEvery(chan<-Environment, d time.Duration)
to sense continuously at a specified frequency. Not sure about the names, how to handle do this (blocking? channel?) - Implement this in
bme280
. Stop exportingbme280.Standby
and instead chose the closest lower value and when rate is above 1s, the driver use forced mode behind the scene. - In the calculation of the correct
Stanby
value, take in account the actual measurement overheadTmeasure,max
is described in section 9.1 of the datasheet. A time.Sleep() of slightly less thanTmeasure,typ
should be done then a continuous read should be done until the value is available.
from periph.
I have to ask another general question.
I do not see why its defined Sense(env *Environment) error
instead of Sense() Environment, error
?
The same applies to the planned SenseEvery() method. Why not use something like the time package:
func Tick(d Duration) <-chan Time
so this would be: SenseEvery(d Duration) <-chan Environment
from periph.
In general allocating a channel and returning it is not great because you then have to decide in the library how much buffering you allocate for the channel. I don't think this is a big issue here, but it's annoying to have to make that choice when writing the code.
from periph.
For Sense()
, I felt it made the code easier to code as you can do:
var e devices.Environment
for (
if err := d.Sense(&e); err != nil {
return err
}
// use e
}
and save on memory but I agree it's not really much a big deal either way as returning a struct is merely copying it on the stack, it is not using the heap. TL;DR; I don't have a strong opinion there, the API just eventually need to be consistent.
About the channel as input or as output, Thorsten resumed my thought. Some users may want a buffered channel, some may not want that. The issue is that sending data over a channel is unpredictable, it can block. This is tricky for the sender. In some way, you may see this as I am advocating to create the channel internally but I am not, the data should also include timing information, likely adding time.Time to the message sent over the channel.
Another way is to add instead WaitForNextSensing()
which is the pattern I used for gpio with PinIn.WaitForEdge()
. Not sure it's actually great but it leaves more options to the caller.
I'm open with experimentation for trial and errors, so we can see what works out best in practice. Just be warned up front I may change my mind frequently through the process. :D
from periph.
FWIW I really like the WaitXx() pattern for the gpio edges, it puts control over goroutines into the caller.
from periph.
why not use consts for register adresses? that would also make some comments useless.
// ctrl_hum
0xF2, byte(opts.Humidity),
// config
0xF5, byte(opts.Standby)<<5 | byte(opts.Filter)<<2,
// ctrl_meas
0xF4, byte(opts.Temperature)<<5 | byte(opts.Pressure)<<2 | byte(normal),
would become
regCtrlHum, byte(opts.Humidity),
regConfig, byte(opts.Standby)<<5 | byte(opts.Filter)<<2,
regCtrlMeas, byte(opts.Temperature)<<5 | byte(opts.Pressure)<<2 | byte(normal),
from periph.
I don't like const that are used exactly once. It actually makes the code less readable, the reader has to jump through the file to get the actual value.
from periph.
the proper ide has the tooltip which tells the value. so there is no point to jump anywhere in the code.
and if one address ever has to change (because version 2 of the hardware comes out and the driver could be nearly the same) then you would only have to change the value of the const.
and you gain the benifit of auto-completion on symbols. the magic number does not have it.
also many other hardware projects do it like that. through all other languages.
one of the most known projects also doing this is the linux kernel ;)
for example the i2c-driver for at91 of the linux kernel has many definitions like that:
#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */
#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */
#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */
#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */
#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
#define AT91_TWI_ACR 0x0040 /* Alternative Command Register */
#define AT91_TWI_ACR_DATAL(len) ((len) & 0xff)
#define AT91_TWI_ACR_DIR BIT(8)
#define AT91_TWI_FMR 0x0050 /* FIFO Mode Register */
#define AT91_TWI_FMR_TXRDYM(mode) (((mode) & 0x3) << 0)
#define AT91_TWI_FMR_TXRDYM_MASK (0x3 << 0)
#define AT91_TWI_FMR_RXRDYM(mode) (((mode) & 0x3) << 4)
#define AT91_TWI_FMR_RXRDYM_MASK (0x3 << 4)
also the "exactly once" is no argument. the config register is used in more than two places.
making exceptions just for one register doesnt make sense. so we either stay or convert all.
from periph.
so just wanted to start a little bit and play in that direction. if you want you can look at
github.com/quinte17/pio/tree/feature/bme280-forced-mode
another question that came up:
when using forced mode I cannot write only the forced bits without reading it in the first place.
we have 2 options
- use read modify write to trigger forced mode
- remember a copy of registers or a copy of options in the device struct
whats your opinion?
from periph.
Interesting I don't have access to the repository (i.e. ACL doesn't propagate when forking), so you'll have to grant me access to it.
from periph.
Fixed with af3fbce.
from periph.
Related Issues (20)
- [Question] How do I set a pin to alt0? HOT 6
- All pins are exported during bcm283x Init HOT 3
- Support for firmata HOT 2
- gpio-read: bcm283x-gpio (GPIO7): pull cannot be used when subsystem gpiomem not initialized. HOT 21
- Go get fetches v3.4.0 if using go modules HOT 3
- Support for BME680 HOT 3
- Halt() does not unblock WaitForEdge() HOT 3
- Feature SSD1322 HOT 5
- mfrc522 constantly returns "IRQ error" after first read HOT 11
- spi to slow HOT 5
- onewire didnot work HOT 9
- Omega2: declare headers HOT 3
- Experimental serial package doesn't export essential func HOT 7
- Unable to set GPIO pin pull on Raspberry Pi 4 HOT 19
- MFRC522 hang on WaitForEdge HOT 2
- HX711: unstable readings and reading before data is ready HOT 2
- spi: rename MISO/MOSI to COPI/CIPO HOT 2
- I2C documentation not clear on read/write operation HOT 2
- MFRC522 - Problem reading Tag HOT 3
- pmem example code incorrect HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from periph.