DIY Compass Project

continue
6 days

1:12

Planning skill implementation.

Thinking deeply about your request.

Formulating a concise plan.

Creating a project plan.

Planning the PCB implementation.

Working on your request.

Proposing knowledge suggestion.

Working on your request.

Proposing knowledge suggestion.

Finalizing the plan.

I've made a plan, and started work on it.
Add ESD protection
Check ERC/DRC
Document decisions
6 days

Started implementing a plan

#Goal

- Complete final implementation steps on the FJ Cruiser Digital Compass project by verifying the schematic, finalizing PCB component placement, applying layout and routing rules, cleaning up DRC issues, and updating all project documentation, ensuring that the current baseline and pre-selected parts are preserved.

#Implementation plan

1. **Schematic and Baseline Verification**

1. Review the existing schematic and component connections, ensuring all key nets (e.g., VBAT_12V, VIN_PROT, +5V, +3V3, GND, I2C_SDA, etc.) remain intact.

2. Confirm that previous verification results are incorporated before proceeding with layout tasks.

2. **PCB Component Placement**

1. Place all PCB components on the 100 mm x 50 mm board per design constraints.

2. Group functional blocks:

1. Place input/power components (J1, U1) near the board edge for easy access.

2. Align U6 (seven-segment display module) for optimum dashboard viewing.

3. Isolate U5 (magnetometer) from high-noise or magnetic interfering components.

4. Arrange SW1 (calibration button) and supporting passives near associated ICs (e.g., U2, U3).

5. Position mounting holes (H1-H4) at corners with proper spacing and account for the 3 mm corner radius.

3. **Routing and Layout Rule Configuration**

1. Set and apply PCB layout rules such as trace width, clearance, and keepout/inset dimensions (0.2 mm).

2. Route remaining airwires using Auto-Route, addressing any overlapping copper issues detected earlier.

3. Run DRC/ERC checks to verify that all errors (e.g., airwires and DRC issues) have been resolved.

4. **Documentation and Project Updates**

1. Update project notes and metadata with final implementation details, component placement decisions, routing and layout rule choices, and any identified risks.

2. Archive verification status and detailed DRC cleanup actions for future reference.

#Success criteria

- The schematic remains compliant with the original design and all key nets are preserved.

- All components are correctly placed according to the grouping and positioning guidelines.

- All airwires and DRC issues are resolved with a clean DRC report.

- Project documentation is updated with final implementation notes and verification status.

6 days

Task unable to complete.

5:24:27

6 days

Task unable to complete.

5:23:46

Running design review.

Accessing knowledge base.

Analyzing the schematic.

Analyzing the PCB layout.

6 days

Reviewed schematic baseline and current layout violations

0:27

Started: reviewing schematic baseline and layout constraints

Searching for skills documentation.

6 days

Failed

18:15

Accessing knowledge base.

6 days

Refine this doc
Ask about this doc
Firmware Starter
Target
Arduino/PlatformIO firmware starter for the Toyota FJ Cruiser digital compass.

Pin map from schematic


NetMCU pinPurpose
I2C_SDAPA22Magnetometer SDA
I2C_SCLPA23Magnetometer SCL
DISP_CLK_MCUPA16TM1637 display clock through R5
DISP_DIO_MCUPA17TM1637 display data through R4
CAL_BTNPA27Calibration/mode button input
MAG_INTPA15Magnetometer interrupt input
SWDCLKPA30Debug clock
SWDIOPA31Debug data
RESET_NRESETNReset input
platformio.ini

Ini


[env:fj_compass_samd21]
platform = atmelsam
board = mkrzero
framework = arduino
monitor_speed = 115200
lib_deps =
  avishorp/TM1637@^1.2.0
src/main.cpp

Cpp


#include 
#include 
#include 
#include 

// Schematic net mapping
#define PIN_I2C_SDA PIN_WIRE_SDA
#define PIN_I2C_SCL PIN_WIRE_SCL
#define PIN_DISP_CLK 16
#define PIN_DISP_DIO 17
#define PIN_CAL_BTN 27
#define PIN_MAG_INT 15

// MMC5883MA I2C address is commonly 0x30 for the MEMSIC MMC58xx family.
// Confirm against the exact populated device before production release.
#define MMC5883_ADDR 0x30

TM1637Display display(PIN_DISP_CLK, PIN_DISP_DIO);

struct MagSample {
  float x;
  float y;
  float z;
};

MagSample hardIronOffset = {0.0f, 0.0f, 0.0f};
MagSample softIronScale = {1.0f, 1.0f, 1.0f};
unsigned long lastUpdateMs = 0;
bool calibrationRequested = false;

static bool i2cWrite8(uint8_t reg, uint8_t value) {
  Wire.beginTransmission(MMC5883_ADDR);
  Wire.write(reg);
  Wire.write(value);
  return Wire.endTransmission() == 0;
}

static bool i2cRead(uint8_t reg, uint8_t *buf, size_t len) {
  Wire.beginTransmission(MMC5883_ADDR);
  Wire.write(reg);
  if (Wire.endTransmission(false) != 0) return false;
  size_t n = Wire.requestFrom(MMC5883_ADDR, len);
  for (size_t i = 0; i = 360) bearing = 0;
  display.showNumberDec(bearing, false, 3, 1);
}

static void runCalibrationRoutine() {
  display.showNumberDec(8888, false);
  Serial.println("Calibration: rotate vehicle slowly through full circle, away from large metal objects if possible.");

  MagSample minV = {999999.0f, 999999.0f, 999999.0f};
  MagSample maxV = {-999999.0f, -999999.0f, -999999.0f};
  unsigned long start = millis();

  while (millis() - start  1.0f) softIronScale.x = avgSpan / spanX;
  if (spanY > 1.0f) softIronScale.y = avgSpan / spanY;
  if (spanZ > 1.0f) softIronScale.z = avgSpan / spanZ;

  Serial.println("Calibration complete. Store these constants in NVM for production firmware.");
  calibrationRequested = false;
}

void setup() {
  Serial.begin(115200);
  delay(1000);

  pinMode(PIN_CAL_BTN, INPUT_PULLUP);
  pinMode(PIN_MAG_INT, INPUT);

  Wire.begin();
  Wire.setClock(400000);

  display.setBrightness(3, true);
  display.clear();

  initMagnetometer();
  Serial.println("FJ Cruiser digital compass firmware started.");
}

void loop() {
  if (digitalRead(PIN_CAL_BTN) == LOW) {
    delay(30);
    if (digitalRead(PIN_CAL_BTN) == LOW) calibrationRequested = true;
  }

  if (calibrationRequested) {
    runCalibrationRoutine();
  }

  if (millis() - lastUpdateMs >= 200UL) {
    lastUpdateMs = millis();
    MagSample raw;
    if (readMagnetometerRaw(raw)) {
      MagSample calibrated = applyCalibration(raw);
      float heading = headingDegrees(calibrated);
      showHeading(heading);
      Serial.print("Heading: ");
      Serial.print(heading, 1);
      Serial.print(" deg ");
      Serial.println(cardinalFromHeading(heading));
    } else {
      display.showNumberDec(0, false);
      Serial.println("Magnetometer read failed");
    }
  }
}
Calibration and installation notes
  • Run calibration after mounting in the FJ Cruiser dashboard because nearby steel, wiring harnesses, speakers, and brackets affect heading.
  • Keep the magnetometer physically separated from the buck inductor and display current paths.
  • Store final hard-iron offsets and soft-iron scale factors in nonvolatile memory after production firmware is finalized.
  • Add tilt compensation later if the dashboard mounting angle or off-road pitch/roll error is significant.

    Target

    Pin map from schematic

    platformio.ini

    src/main.cpp

    Calibration and installation notes

Documents

    Firmware Starter

    Design Notes

Assets

Assets are files uploaded to this project which can be used in various ways.

FJ Cruiser Compass thumbnail
Dashboard-mounted automotive digital compass with protected 12V power input, regulated logic supply, 3-axis magnetometer sensing, MCU control, seven-segment display output, calibration controls, and mounting provisions for Toyota FJ Cruiser installation.

Properties

Pricing & Availability

Distributor

Qty 1

Controls