Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
However, the actual SCL frequency comes from dividing the CPU’s core clock by an even integer, so you can’t always get what you want. The Pi 3 ticks along at 1.2 GHz (actually 1.1 GHz, because marketing) from a core clock of 550 MHz, so a 200 kHz clock calls for a 2750 divider: 550 MHz / 2750 = 200 kHz.
Actually measuring the SCL frequencies suggests something else is going on:
I2C 200kHz – actual 125kHz
D0, the bottom trace, is SCL, D1 is SDA, and D2 is a trigger output not used in this setup. The yellow analog trace is the current in the SCL line between the Pi and the BNO055, about which more later.
So a 200 kHz nominal frequency produces a 125 kHz actual frequency.
The BNO055 pulls the clock low (“clock stretching”), which can (and does) cause problems, but it’s not active during the main part of the transfer where the Pi determines the SCL frequency.
More measurement along those lines produces a table:
CPU Core Clock:
550
MHz
I2C SCL kHz
Nominal
Ratio
Actual
Ratio
250
2200
156.20
3521
200
2750
125.00
4400
150
3667
92.59
5940
125
4400
78.12
7040
100
5500
62.50
8800
50
11000
31.25
17600
25
22000
15.63
35189
10
55000
6.25
88000
Apparently, the code converting the nominal I2C rate in config.txt uses a table of divider values intended for another CPU core clock. AFAICT, the boot code could divide the actual core clock by the desired I2C frequency to produce the appropriate value.
I have no particular desire to Use The Source to figure out what’s going on …
[Update: Perhaps this comes along with CPU clock throttling due to temperature. For completeness, I should dump the temperature and actual clock speed.]
So it’s not unusual to ride under a small plane on final approach. Having a Gulfstream V fly directly overhead, however, is a real attention-getter:
Gulfstream V on final – Maloney Rd – 2018-08-26
What’s not at all obvious from the picture is how big a GV looks when seen directly overhead through those trees just ahead on the corner where our paths crossed. There’s a 360 ft (above sea level) hill directly on the flight path, so it’s at maybe 600 ft ASL and 400-ish ft AGL.
Thrust-reversal thunder rolled over us 50 seconds later, as we rode up the rail trail access ramp. Figuring we’re 15 sound-seconds from the strip, the GV was 30 seconds from touchdown.
It’s certainly the shapeliest hydrant I’ve ever seen.
Of course, you need a special tool to remove the main cap, after which some internal lockwork releases the side caps, after which you can spin the valve stem recessed under the top cover. One hopes all those little bits continue sliding and releasing after a few decades, but … the status quo apparently isn’t all that good, either.
I’ve been coaching a high-school student (and his father!) on the intricacies of building a self-balancing robot; they’re doing all the hard work and I’m running interference with techie bugs. This one turned out to be particularly nasty.
Reading the chip’s temperature sensor once every second produced this output:
BNO055 Sensor – Temperature Register vs I2C
He now knows why you must always leading-zero-fill binary values.
The shorter values say the chip ran at 26 °C, which means the longer values have a bogus binary 1 in bit 7. I2C bus transfers proceed MSB-first, so the Pi occasionally reads a bogus 1 at the first clock transition while reading the single temperature byte from the BNO055.
After some flailing around, we observed two types of I2C bus transactions.
Without clock stretching:
BNO055 – Normal I2C transaction
With clock stretching:
BNO055 – Clock-stretched I2C transaction
Contrary to what one might think from the lead-in description, the non-stretched version always produces the incorrect leading bit and the stretched version usually delivers the correct result.
He had previously installed the clock stretch workaround and we verified it was active. Turning it off had no effect, as did turning it back on again. The value uses units of the SCL period, so the modified value of 20000 produces 20×103 counts of 1/(100 k bit/s) = 2 s, far longer than any delay we observed. In fact, the default 640 μs would (apparently) suffice for the BNO055.
We noticed, but I did not record, nasty positive-going pulses on both SDA and SCL which were not due to noise or supply problems. As far as I can tell, the Pi does not maintain control over the I2C bus lines during some phases of the transaction, perhaps when the BNO055 invokes clock stretching, allowing the pullups to produce narrow upward glitches crossing the logic threshold. This will merit further study.
The solution, such as it is, seems to require slowing the I2C bus transactions to 25 kb/s, by inserting a line in the /boot/config.txt file:
dtparam=i2c_arm_baudrate=25000 ... dummy line to reveal underscores ...
Slowing to 50 kb/s produced intermittent errors, while 25 kb/s seemed to completely eliminate them. This contradicts suggestions of proper operation at any speed other than the default 100 kb/s. Note: this applies to a single-byte data value and longer transactions remain to be tested.
I want to verify that the lower rate also eliminates the glitches, which will require running the Pi with the scope plumbed into its guts for some time. For obvious reasons, he’d rather get the robot working, so, until he encounters more problems, I won’t see the hardware …
Update: There’s now a way to do I²C with software bit-banging in a reasonably easy way. Thanks to Simon Blake for pointing this out!