Example Code Card
Cpp
// Blink an LED on Arduino pin 13 constexpr uint8_t LED_PIN = 13; void setup() { pinMode(LED_PIN, OUTPUT); } void loop() { digitalWrite(LED_PIN, HIGH); delay(500); digitalWrite(LED_PIN, LOW); delay(500); }
Wire built in, TM1637DisplayTable
| Function | MCU Pin | Arduino-style constant | Connected To | Notes |
|---|---|---|---|---|
| I2C SDA | PC4 / SDA0 | A4 | LIS3MDL SDA, R1 4.7k pull-up | Magnetometer data |
| I2C SCL | PC5 / SCL0 | A5 | LIS3MDL SCL, R2 4.7k pull-up | Magnetometer clock |
| Display CLK | PD5 | 5 | TM1637 CLK, R4 10k pull-up | Serial display clock |
| Display DIO | PD6 | 6 | TM1637 DIO, R5 10k pull-up | Serial display data |
| Reset | PC6 / RESET | n/a | R3 10k pull-up | Hardware reset |
| Power | VCC, AVCC | n/a | 3.3 V rail | Internal RC clock assumed |
platformio.iniIni
[env:atmega328pb] platform = atmelavr board = ATmega328PB framework = arduino board_build.f_cpu = 8000000L monitor_speed = 115200 lib_deps = avishorp/TM1637@^1.2.0
src/main.cpp)Cpp
#include <Arduino.h> #include <Wire.h> #include <TM1637Display.h> #include <math.h> // Schematic pin mapping static constexpr uint8_t PIN_TM_CLK = 5; // U1 PD5 -> U3 CLK static constexpr uint8_t PIN_TM_DIO = 6; // U1 PD6 -> U3 DIO static constexpr uint8_t LIS3MDL_ADDR = 0x1C; // SA1 tied low; use 0x1E if board/library variant reports alternate address // LIS3MDL registers static constexpr uint8_t REG_WHO_AM_I = 0x0F; static constexpr uint8_t REG_CTRL_REG1 = 0x20; static constexpr uint8_t REG_CTRL_REG2 = 0x21; static constexpr uint8_t REG_CTRL_REG3 = 0x22; static constexpr uint8_t REG_CTRL_REG4 = 0x23; static constexpr uint8_t REG_OUT_X_L = 0x28; TM1637Display display(PIN_TM_CLK, PIN_TM_DIO); struct MagRaw { int16_t x; int16_t y; int16_t z; }; // Calibration values: update after vehicle/dashboard calibration sweep. float hardIronX = 0.0f; float hardIronY = 0.0f; float softScaleX = 1.0f; float softScaleY = 1.0f; bool i2cWrite8(uint8_t reg, uint8_t value) { Wire.beginTransmission(LIS3MDL_ADDR); Wire.write(reg); Wire.write(value); return Wire.endTransmission() == 0; } bool i2cRead(uint8_t reg, uint8_t *buf, size_t len) { Wire.beginTransmission(LIS3MDL_ADDR); Wire.write(reg); if (Wire.endTransmission(false) != 0) return false; size_t got = Wire.requestFrom(LIS3MDL_ADDR, (uint8_t)len); if (got != len) return false; for (size_t i = 0; i < len; ++i) buf[i] = Wire.read(); return true; } bool initLIS3MDL() { uint8_t who = 0; if (!i2cRead(REG_WHO_AM_I, &who, 1)) return false; // Ultra-high-performance XY, 10 Hz ODR: CTRL_REG1 = 0b01110000 // +/-4 gauss full scale: CTRL_REG2 = 0b00000000 // Continuous-conversion mode: CTRL_REG3 = 0b00000000 // Ultra-high-performance Z: CTRL_REG4 = 0b00001100 bool ok = true; ok &= i2cWrite8(REG_CTRL_REG1, 0x70); ok &= i2cWrite8(REG_CTRL_REG2, 0x00); ok &= i2cWrite8(REG_CTRL_REG3, 0x00); ok &= i2cWrite8(REG_CTRL_REG4, 0x0C); return ok; } bool readMag(MagRaw &m) { uint8_t b[6]; if (!i2cRead(REG_OUT_X_L | 0x80, b, sizeof(b))) return false; m.x = (int16_t)((uint16_t)b[1] << 8 | b[0]); m.y = (int16_t)((uint16_t)b[3] << 8 | b[2]); m.z = (int16_t)((uint16_t)b[5] << 8 | b[4]); return true; } int headingDegrees(const MagRaw &m) { float x = ((float)m.x - hardIronX) * softScaleX; float y = ((float)m.y - hardIronY) * softScaleY; float heading = atan2f(y, x) * 180.0f / PI; if (heading < 0.0f) heading += 360.0f; int deg = (int)lroundf(heading); if (deg >= 360) deg -= 360; return deg; } void showHeading(int deg) { // Shows 000-359 on the three wired digits. Leading zeroes are useful for compass readout. display.showNumberDec(deg, true, 3, 0); } void setup() { Serial.begin(115200); Wire.begin(); Wire.setClock(100000); display.setBrightness(2); // Keep low for solar power budget; raise if needed. display.clear(); if (!initLIS3MDL()) { Serial.println(F("LIS3MDL init failed")); display.showNumberDec(888, true, 3, 0); } else { Serial.println(F("Solar compass firmware started")); } } void loop() { static uint32_t lastRead = 0; if (millis() - lastRead < 250) return; lastRead = millis(); MagRaw mag; if (readMag(mag)) { int deg = headingDegrees(mag); showHeading(deg); Serial.print(F("Heading: ")); Serial.println(deg); } else { Serial.println(F("Mag read failed")); display.showNumberDec(999, true, 3, 0); } }
pio run -e atmega328pbpio run -e atmega328pb -t upload --upload-port .Platform & Toolchain
Pin Mapping
`platformio.ini`
Complete Firmware Source (`src/main.cpp`)
Build & Flash