Scan an I²C sensor bus
Almost every Pi sensor speaks I²C: temperature/humidity, IMUs,
small OLED displays, port expanders. This example is the Amalgame
equivalent of i2cdetect -y 1 — it opens the bus, probes every
address, and prints what answers. Then we read one register from a
device to show the full round-trip.
Wiring
sensor VCC ── 3V3 sensor SDA ── GPIO2 (SDA1, pin 3)
sensor GND ── GND sensor SCL ── GPIO3 (SCL1, pin 5)
I²C is a shared two-wire bus, so several devices can hang off the same SDA/SCL pins. Make sure I²C is enabled (see setup, step 3).
Code
namespace Demo
import Amalgame.Hardware
public class Program {
// I²C addresses are read in hex; String_FromInt is decimal only, so
// format a byte as two hex digits — pure Amalgame, no inline C.
private static string Hex2(v: int) {
let digits: string = "0123456789abcdef"
let hi: int = (v / 16) % 16
let lo: int = v % 16
return String_CharAt1(digits, hi) + String_CharAt1(digits, lo)
}
public static void Main(string[] args) {
let busNum: int = 1
let bus: I2c = new I2c(busNum) // /dev/i2c-1
if (!bus.IsOpen()) {
Console.WriteLine("could not open /dev/i2c-1 — I2C enabled? permissions?")
return
}
let found: List<int> = bus.Scan() // probe 0x03..0x77
if (found.Count() == 0) {
Console.WriteLine("no devices on bus " + String_FromInt(busNum))
} else {
Console.WriteLine(String_FromInt(found.Count()) + " device(s):")
for addr in found {
Console.WriteLine(" 0x" + Program.Hex2(addr))
}
}
bus.Close()
}
}
Run
amc build main.am -o i2c_scan
./i2c_scan
You'll see something like:
1 device(s):
0x68
An MPU-6050 shows up at 0x68, a PCF8574 LCD backpack at 0x27, many
OLEDs at 0x3c, and so on.
Reading a register
Once you know an address, read or write its registers. For example, to
wake an MPU-6050 (clear its PWR_MGMT_1 register at 0x6B) and then
burst-read 6 bytes of accelerometer data:
bus.WriteReg(0x68, 0x6B, 0x00) // wake the device
let raw: List<int> = bus.ReadBytes(0x68, 6) // ACCEL_X/Y/Z high+low bytes
The I²C API at a glance:
| Method | Use |
|---|---|
new I2c(bus) / .IsOpen() / .Close() |
open /dev/i2c-<bus> |
.Scan() → List<int> |
list responders, like i2cdetect |
.ReadByte(addr) / .WriteByte(addr, v) |
single raw byte |
.ReadReg(addr, reg) / .WriteReg(addr, reg, v) |
register access |
.ReadBytes(addr, n) / .WriteBytes(addr, list) |
multi-byte burst |
Bytes cross the boundary as List<int> (each 0..255).
Next: LED bar chase →