![](/media/cache/profiles/Timo_01_DSC_4754_533x533.jpg.50x50_q85.jpg)
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.
main.cpp@0:2666acd6dfb3, 2021-12-06 (annotated)
- Committer:
- timo_k2
- Date:
- Mon Dec 06 20:46:15 2021 +0000
- Revision:
- 0:2666acd6dfb3
The initial commit.
Who changed what in which revision?
User | Revision | Line number | New 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 | } |