The sensor is the PmodCMPS2 compass sensor with the 3D magnetometer chip MMC34160PJ Data sheet https://download.mikroe.com/documents/datasheets/MMC3416xPJ_Rev_C_2013_10_30.pdf The values for Helsinki in December 2021 ( Model used WMM-2020 https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml#igrfwmm ) North component = 146 milli Gaus East component = 25 milli Gaus Vertical component = 502 milli Gaus Total field = 524 milli Gaus Connect: L432KC -- PmodCMPS2 PA_9 -- SCL PA_10 -- SDA GND -- GND 3V3 -- VCC Set the jumpers SDA and SCL on the PmodCMPS2.

Committer:
timo_k2
Date:
Mon Dec 06 20:46:15 2021 +0000
Revision:
0:2666acd6dfb3
The initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
timo_k2 0:2666acd6dfb3 1 /* mbed Microcontroller Library
timo_k2 0:2666acd6dfb3 2 * Copyright (c) 2019 ARM Limited
timo_k2 0:2666acd6dfb3 3 * SPDX-License-Identifier: Apache-2.0
timo_k2 0:2666acd6dfb3 4 *
timo_k2 0:2666acd6dfb3 5 * The sensor is the PmodCMPS2 compass sensor with
timo_k2 0:2666acd6dfb3 6 * the 3D magnetometer chip MMC34160PJ
timo_k2 0:2666acd6dfb3 7 * Data sheet
timo_k2 0:2666acd6dfb3 8 * https://download.mikroe.com/documents/datasheets/MMC3416xPJ_Rev_C_2013_10_30.pdf
timo_k2 0:2666acd6dfb3 9 *
timo_k2 0:2666acd6dfb3 10 * On the earth surface the world magnetic field points towards the north and
timo_k2 0:2666acd6dfb3 11 * in level with the horizon at the equador. Further north the field starts
timo_k2 0:2666acd6dfb3 12 * pointing downwards. In southern Europe it points downwards with inclination
timo_k2 0:2666acd6dfb3 13 * 60 degrees. In Scandinavia it points downwards with inclination 75 degrees.
timo_k2 0:2666acd6dfb3 14 * At the north pole it points straight down with inclination 90 degrees.
timo_k2 0:2666acd6dfb3 15 *
timo_k2 0:2666acd6dfb3 16 * The declination is the difference between geaographic and magnetic north pole.
timo_k2 0:2666acd6dfb3 17 * The declination depends where and when you are observing the field.
timo_k2 0:2666acd6dfb3 18 *
timo_k2 0:2666acd6dfb3 19 * The values for Helsinki in December 2021 ( Model used WMM-2020
timo_k2 0:2666acd6dfb3 20 * https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml#igrfwmm )
timo_k2 0:2666acd6dfb3 21 * Declination 9 degr 45 min
timo_k2 0:2666acd6dfb3 22 * Inclination 73 degr 35 min
timo_k2 0:2666acd6dfb3 23 * North component 14572 nT = 146 milli Gaus
timo_k2 0:2666acd6dfb3 24 * East component 2505 nT = 25 milli Gaus
timo_k2 0:2666acd6dfb3 25 * Vertical component 50222 nT = 502 milli Gaus
timo_k2 0:2666acd6dfb3 26 * Total field 52353 nT = 524 milli Gaus
timo_k2 0:2666acd6dfb3 27 *
timo_k2 0:2666acd6dfb3 28 * Connect:
timo_k2 0:2666acd6dfb3 29 * L432KC -- PmodCMPS2
timo_k2 0:2666acd6dfb3 30 * PA_9 -- SCL
timo_k2 0:2666acd6dfb3 31 * PA_10 -- SDA
timo_k2 0:2666acd6dfb3 32 * GND -- GND
timo_k2 0:2666acd6dfb3 33 * 3V3 -- VCC
timo_k2 0:2666acd6dfb3 34 * Set the jumpers SDA and SCL on the PmodCMPS2.
timo_k2 0:2666acd6dfb3 35 *
timo_k2 0:2666acd6dfb3 36 * version 06.12.2021
timo_k2 0:2666acd6dfb3 37 * Timo Karppinen Apache-2.0
timo_k2 0:2666acd6dfb3 38 **********************************************************************/
timo_k2 0:2666acd6dfb3 39
timo_k2 0:2666acd6dfb3 40
timo_k2 0:2666acd6dfb3 41 #include "mbed.h"
timo_k2 0:2666acd6dfb3 42
timo_k2 0:2666acd6dfb3 43
timo_k2 0:2666acd6dfb3 44 I2C i2c(PA_10, PA_9); // Pins D1 and D0 on the L432KC
timo_k2 0:2666acd6dfb3 45
timo_k2 0:2666acd6dfb3 46 const int CMPS2_address = 0x30; // 7 bit I2C address 0110000b for MMC34160PJ
timo_k2 0:2666acd6dfb3 47 const int addr8bit = 0x30 << 1; // address plus the 0 for write the 1 for read
timo_k2 0:2666acd6dfb3 48
timo_k2 0:2666acd6dfb3 49 int main()
timo_k2 0:2666acd6dfb3 50 {
timo_k2 0:2666acd6dfb3 51 char cmd[2]; // Typically command register address , command
timo_k2 0:2666acd6dfb3 52
timo_k2 0:2666acd6dfb3 53 // Initialize compass
timo_k2 0:2666acd6dfb3 54 ThisThread::sleep_for(2000ms);
timo_k2 0:2666acd6dfb3 55
timo_k2 0:2666acd6dfb3 56 //command internal control register 0 for set operation
timo_k2 0:2666acd6dfb3 57 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 58 cmd[1] = 0x80; // control register0 bit7 = true, "refill cap"
timo_k2 0:2666acd6dfb3 59 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 60 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 61
timo_k2 0:2666acd6dfb3 62 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 63 cmd[1] = 0x20; // control register0 bit5 = true, SET
timo_k2 0:2666acd6dfb3 64 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 65 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 66
timo_k2 0:2666acd6dfb3 67 //command internal control register 1 to 16 bit resolution, 8ms measurement time
timo_k2 0:2666acd6dfb3 68 cmd[0] = 0x08; // Control register1
timo_k2 0:2666acd6dfb3 69 cmd[1] = 0x00; // bit0 = false bit1 = false, 16 bits 8ms
timo_k2 0:2666acd6dfb3 70 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 71 ThisThread::sleep_for(500ms);
timo_k2 0:2666acd6dfb3 72
timo_k2 0:2666acd6dfb3 73
timo_k2 0:2666acd6dfb3 74 while (1) {
timo_k2 0:2666acd6dfb3 75
timo_k2 0:2666acd6dfb3 76
timo_k2 0:2666acd6dfb3 77 //Get heading
timo_k2 0:2666acd6dfb3 78 int xyzA[3];
timo_k2 0:2666acd6dfb3 79 for(int i = 0; i < 3; i++){
timo_k2 0:2666acd6dfb3 80 xyzA[i] = 0;
timo_k2 0:2666acd6dfb3 81 }
timo_k2 0:2666acd6dfb3 82 int xyzB[3];
timo_k2 0:2666acd6dfb3 83 for(int i = 0; i < 3; i++){
timo_k2 0:2666acd6dfb3 84 xyzB[i] = 0;
timo_k2 0:2666acd6dfb3 85 }
timo_k2 0:2666acd6dfb3 86 int xyz[3];
timo_k2 0:2666acd6dfb3 87 for(int i = 0; i < 3; i++){
timo_k2 0:2666acd6dfb3 88 xyz[i] = 0;
timo_k2 0:2666acd6dfb3 89 }
timo_k2 0:2666acd6dfb3 90
timo_k2 0:2666acd6dfb3 91 //command internal control register 0 for set operation
timo_k2 0:2666acd6dfb3 92 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 93 cmd[1] = 0x80; // control register0 bit7 = true, "refill cap"
timo_k2 0:2666acd6dfb3 94 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 95 ThisThread::sleep_for(100ms);
timo_k2 0:2666acd6dfb3 96
timo_k2 0:2666acd6dfb3 97 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 98 cmd[1] = 0x20; // control register0 bit5 = true, SET
timo_k2 0:2666acd6dfb3 99 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 100 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 101
timo_k2 0:2666acd6dfb3 102 //command internal control register 0 bit 0 (measure)
timo_k2 0:2666acd6dfb3 103 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 104 cmd[1] = 0x01; // bit0 = 1, Take measurement
timo_k2 0:2666acd6dfb3 105 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 106 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 107
timo_k2 0:2666acd6dfb3 108 // Wait for measurement data ready
timo_k2 0:2666acd6dfb3 109 ThisThread::sleep_for(500ms);
timo_k2 0:2666acd6dfb3 110
timo_k2 0:2666acd6dfb3 111 //Reading six bytes
timo_k2 0:2666acd6dfb3 112 char temp[6];
timo_k2 0:2666acd6dfb3 113 cmd[0] = 0x00;
timo_k2 0:2666acd6dfb3 114 i2c.write(addr8bit, cmd, 1);
timo_k2 0:2666acd6dfb3 115 i2c.read(addr8bit, temp, 6);
timo_k2 0:2666acd6dfb3 116
timo_k2 0:2666acd6dfb3 117 // converting to 16 bit integers
timo_k2 0:2666acd6dfb3 118 xyzA[0] = (int)((temp[1]<<8) | temp[0]);
timo_k2 0:2666acd6dfb3 119 xyzA[1] = (int)((temp[3]<<8) | temp[2]);
timo_k2 0:2666acd6dfb3 120 xyzA[2] = (int)((temp[5]<<8) | temp[4]);
timo_k2 0:2666acd6dfb3 121
timo_k2 0:2666acd6dfb3 122 printf("Bytes read from CMPS X %d %d Y %d %d Z %d %d\n", temp[0 ],temp[1], temp[2], temp[3], temp[4], temp[5]);
timo_k2 0:2666acd6dfb3 123 //printf(" Magnetic field X %d mG Y %d mG Z %d mG\n", xyz[0], xyz[1], xyz[2]);
timo_k2 0:2666acd6dfb3 124
timo_k2 0:2666acd6dfb3 125 //command internal control register 0 for set operation
timo_k2 0:2666acd6dfb3 126 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 127 cmd[1] = 0x80; // control register0 bit7 = true, "refill cap"
timo_k2 0:2666acd6dfb3 128 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 129 ThisThread::sleep_for(100ms);
timo_k2 0:2666acd6dfb3 130
timo_k2 0:2666acd6dfb3 131 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 132 cmd[1] = 0x40; // control register0 bit6 = true, RESET
timo_k2 0:2666acd6dfb3 133 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 134 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 135
timo_k2 0:2666acd6dfb3 136 //command internal control register 0 bit 0 (measure)
timo_k2 0:2666acd6dfb3 137 cmd[0] = 0x07; // Control register0
timo_k2 0:2666acd6dfb3 138 cmd[1] = 0x01; // bit0 = 1, Take measurement
timo_k2 0:2666acd6dfb3 139 i2c.write(addr8bit, cmd, 2);
timo_k2 0:2666acd6dfb3 140 ThisThread::sleep_for(50ms);
timo_k2 0:2666acd6dfb3 141
timo_k2 0:2666acd6dfb3 142 // Wait for measurement data ready
timo_k2 0:2666acd6dfb3 143 ThisThread::sleep_for(500ms);
timo_k2 0:2666acd6dfb3 144
timo_k2 0:2666acd6dfb3 145 //Reading six bytes
timo_k2 0:2666acd6dfb3 146 //char temp[6];
timo_k2 0:2666acd6dfb3 147 cmd[0] = 0x00;
timo_k2 0:2666acd6dfb3 148 i2c.write(addr8bit, cmd, 1);
timo_k2 0:2666acd6dfb3 149 i2c.read(addr8bit, temp, 6);
timo_k2 0:2666acd6dfb3 150
timo_k2 0:2666acd6dfb3 151 // converting to 16 bit integers
timo_k2 0:2666acd6dfb3 152 xyzB[0] = (int)((temp[1]<<8) | temp[0]);
timo_k2 0:2666acd6dfb3 153 xyzB[1] = (int)((temp[3]<<8) | temp[2]);
timo_k2 0:2666acd6dfb3 154 xyzB[2] = (int)((temp[5]<<8) | temp[4]);
timo_k2 0:2666acd6dfb3 155
timo_k2 0:2666acd6dfb3 156 printf("Bytes read from CMPS X %d %d Y %d %d Z %d %d\n", temp[0 ],temp[1], temp[2], temp[3], temp[4], temp[5]);
timo_k2 0:2666acd6dfb3 157 // Eliminate offset from X Y Z. The field was measured with both coil orientations.
timo_k2 0:2666acd6dfb3 158 for(int i = 0; i < 3; i++){
timo_k2 0:2666acd6dfb3 159 xyz[i] = xyzA[i] - xyzB[i];
timo_k2 0:2666acd6dfb3 160 // xyz[i] = ( xyz [i] *100)/yourfactor; // Scale factor. 100/(yourfactor)
timo_k2 0:2666acd6dfb3 161 }
timo_k2 0:2666acd6dfb3 162 printf(" Magnetic field X %d mG Y %d mG Z %d mG\n", xyz[0], xyz[1], xyz[2]);
timo_k2 0:2666acd6dfb3 163
timo_k2 0:2666acd6dfb3 164 // Get the correct scale factor by pointing each sensor axis x, y, z towards
timo_k2 0:2666acd6dfb3 165 // 73 degrees down and to the north to get the highest values.
timo_k2 0:2666acd6dfb3 166 // Devide your highest value by 524. You should get something between 3 and 4
timo_k2 0:2666acd6dfb3 167 // Multiply your value by 100 and replace "yourfactor" with the result.
timo_k2 0:2666acd6dfb3 168
timo_k2 0:2666acd6dfb3 169
timo_k2 0:2666acd6dfb3 170 ThisThread::sleep_for(1000ms);
timo_k2 0:2666acd6dfb3 171 }
timo_k2 0:2666acd6dfb3 172 }