Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Welcome to the code repository for PixArt's PMW3901MB sensor and evaluation board.
For general information about this product, please visit this product's components page here:
https://os.mbed.com/components/PMW3901MB-Far-Field-Optical-Motion-Track/
For guides and tips on how to setup and evaluate the PMW3901MB sensor with the Nordic nRF52-DK microcontroller using this reference code, please visit this guide:
https://os.mbed.com/teams/PixArt/code/3901_referenceFirmware/wiki/Guide-for-nRF52-DK-Platform
For guides and tips on how to setup and evaluate the PMW3901MB sensor with any microcontroller using this reference code, please visit this guide:
https://os.mbed.com/teams/PixArt/code/3901_referenceFirmware/wiki/Guide-for-Any-Platform
commHeaders/SPIcommFunctions.h@0:c00f2464eee3, 2018-03-14 (annotated)
- Committer:
- PixArtVY
- Date:
- Wed Mar 14 21:22:43 2018 +0000
- Revision:
- 0:c00f2464eee3
First release.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| PixArtVY | 0:c00f2464eee3 | 1 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 2 | //Communication pinouts for serial COM port, SPI, and interrupts |
| PixArtVY | 0:c00f2464eee3 | 3 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 4 | static Serial pc(USBTX, USBRX); //PC comm |
| PixArtVY | 0:c00f2464eee3 | 5 | static SPI spi(p23, p24, p25); //mosi, miso, sclk |
| PixArtVY | 0:c00f2464eee3 | 6 | static DigitalOut cs(p22); //chip select |
| PixArtVY | 0:c00f2464eee3 | 7 | |
| PixArtVY | 0:c00f2464eee3 | 8 | |
| PixArtVY | 0:c00f2464eee3 | 9 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 10 | //Variables and arrays used for communications and data storage |
| PixArtVY | 0:c00f2464eee3 | 11 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 12 | int8_t deltaX_low, deltaY_low; //Stores the low-bits of movement data. |
| PixArtVY | 0:c00f2464eee3 | 13 | int16_t deltaX_high, deltaY_high; //Stores the high-bits of movement data. |
| PixArtVY | 0:c00f2464eee3 | 14 | int16_t deltaX, deltaY; //Stores the combined value of low and high bits. |
| PixArtVY | 0:c00f2464eee3 | 15 | int16_t totalX, totalY = 0; //Stores the total deltaX and deltaY moved during runtime. |
| PixArtVY | 0:c00f2464eee3 | 16 | |
| PixArtVY | 0:c00f2464eee3 | 17 | |
| PixArtVY | 0:c00f2464eee3 | 18 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 19 | //Functions used to communicate with the sensor and grab/print data |
| PixArtVY | 0:c00f2464eee3 | 20 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 21 | uint8_t readRegister(uint8_t addr); |
| PixArtVY | 0:c00f2464eee3 | 22 | //This function takes an 8-bit address in the form 0x00 and returns an 8-bit value in the form 0x00. |
| PixArtVY | 0:c00f2464eee3 | 23 | |
| PixArtVY | 0:c00f2464eee3 | 24 | void writeRegister(uint8_t addr, uint8_t data); |
| PixArtVY | 0:c00f2464eee3 | 25 | //This function takes an 8-bit address and 8-bit data. Writes the given data to the given address. |
| PixArtVY | 0:c00f2464eee3 | 26 | |
| PixArtVY | 0:c00f2464eee3 | 27 | void initializeSensor(void); |
| PixArtVY | 0:c00f2464eee3 | 28 | //Sets all of the registers needed for initialization and performance optimization. |
| PixArtVY | 0:c00f2464eee3 | 29 | |
| PixArtVY | 0:c00f2464eee3 | 30 | void grabData(void); |
| PixArtVY | 0:c00f2464eee3 | 31 | //Grabs the deltaX and deltaY information from the proper registers and formats it into the proper format. |
| PixArtVY | 0:c00f2464eee3 | 32 | |
| PixArtVY | 0:c00f2464eee3 | 33 | void printData(void); |
| PixArtVY | 0:c00f2464eee3 | 34 | //Prints the data out to a serial terminal. |
| PixArtVY | 0:c00f2464eee3 | 35 | |
| PixArtVY | 0:c00f2464eee3 | 36 | |
| PixArtVY | 0:c00f2464eee3 | 37 | |
| PixArtVY | 0:c00f2464eee3 | 38 | |
| PixArtVY | 0:c00f2464eee3 | 39 | |
| PixArtVY | 0:c00f2464eee3 | 40 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 41 | //Functions definitions |
| PixArtVY | 0:c00f2464eee3 | 42 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 43 | uint8_t readRegister(uint8_t addr) |
| PixArtVY | 0:c00f2464eee3 | 44 | { |
| PixArtVY | 0:c00f2464eee3 | 45 | cs = 0; //Set chip select low/active |
| PixArtVY | 0:c00f2464eee3 | 46 | addr = addr & 0x7F; //Set MSB to 0 to indicate read operation |
| PixArtVY | 0:c00f2464eee3 | 47 | spi.write(addr); //Write the given address |
| PixArtVY | 0:c00f2464eee3 | 48 | wait_us(35); //Add a tiny delay after sending address for some internal cycle timing. |
| PixArtVY | 0:c00f2464eee3 | 49 | uint8_t data_read = spi.write(0x00); //Throw dummy byte after sending address to receieve data |
| PixArtVY | 0:c00f2464eee3 | 50 | cs = 1; //Set chip select back to high/inactive |
| PixArtVY | 0:c00f2464eee3 | 51 | return data_read; //Returns 8-bit data from register |
| PixArtVY | 0:c00f2464eee3 | 52 | } |
| PixArtVY | 0:c00f2464eee3 | 53 | |
| PixArtVY | 0:c00f2464eee3 | 54 | |
| PixArtVY | 0:c00f2464eee3 | 55 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 56 | void writeRegister(uint8_t addr, uint8_t data) |
| PixArtVY | 0:c00f2464eee3 | 57 | { |
| PixArtVY | 0:c00f2464eee3 | 58 | cs = 0; //Set chip select low/active |
| PixArtVY | 0:c00f2464eee3 | 59 | addr = addr | 0x80; //Set MSB to 1 to indicate write operation |
| PixArtVY | 0:c00f2464eee3 | 60 | spi.write(addr); //Write the given address |
| PixArtVY | 0:c00f2464eee3 | 61 | spi.write(data); //Write the given data |
| PixArtVY | 0:c00f2464eee3 | 62 | cs = 1; //Set chip select back to high/inactive |
| PixArtVY | 0:c00f2464eee3 | 63 | |
| PixArtVY | 0:c00f2464eee3 | 64 | //pc.printf("R:%2X, D:%2X\n\r", addr, readRegister(addr)); |
| PixArtVY | 0:c00f2464eee3 | 65 | //Uncomment this line for debugging. Prints every register write operation. |
| PixArtVY | 0:c00f2464eee3 | 66 | } |
| PixArtVY | 0:c00f2464eee3 | 67 | |
| PixArtVY | 0:c00f2464eee3 | 68 | |
| PixArtVY | 0:c00f2464eee3 | 69 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 70 | void initializeSensor(void) |
| PixArtVY | 0:c00f2464eee3 | 71 | { |
| PixArtVY | 0:c00f2464eee3 | 72 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 73 | writeRegister(0x55, 0x01); |
| PixArtVY | 0:c00f2464eee3 | 74 | writeRegister(0x50, 0x07); |
| PixArtVY | 0:c00f2464eee3 | 75 | writeRegister(0x7F, 0x0E); |
| PixArtVY | 0:c00f2464eee3 | 76 | writeRegister(0x43, 0x10); |
| PixArtVY | 0:c00f2464eee3 | 77 | |
| PixArtVY | 0:c00f2464eee3 | 78 | if(readRegister(0x67) & 0x40) |
| PixArtVY | 0:c00f2464eee3 | 79 | writeRegister(0x48, 0x04); |
| PixArtVY | 0:c00f2464eee3 | 80 | |
| PixArtVY | 0:c00f2464eee3 | 81 | else |
| PixArtVY | 0:c00f2464eee3 | 82 | writeRegister(0x48, 0x02); |
| PixArtVY | 0:c00f2464eee3 | 83 | |
| PixArtVY | 0:c00f2464eee3 | 84 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 85 | writeRegister(0x51, 0x7B); |
| PixArtVY | 0:c00f2464eee3 | 86 | writeRegister(0x50, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 87 | writeRegister(0x55, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 88 | writeRegister(0x7F, 0x0E); |
| PixArtVY | 0:c00f2464eee3 | 89 | |
| PixArtVY | 0:c00f2464eee3 | 90 | if(readRegister(0x73) == 0x00) |
| PixArtVY | 0:c00f2464eee3 | 91 | { |
| PixArtVY | 0:c00f2464eee3 | 92 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 93 | writeRegister(0x61, 0xAD); |
| PixArtVY | 0:c00f2464eee3 | 94 | writeRegister(0x51, 0x70); |
| PixArtVY | 0:c00f2464eee3 | 95 | writeRegister(0x7F, 0x0E); |
| PixArtVY | 0:c00f2464eee3 | 96 | |
| PixArtVY | 0:c00f2464eee3 | 97 | if(readRegister(0x70) <= 28) |
| PixArtVY | 0:c00f2464eee3 | 98 | writeRegister(0x70, readRegister(0x70) + 14); |
| PixArtVY | 0:c00f2464eee3 | 99 | |
| PixArtVY | 0:c00f2464eee3 | 100 | else |
| PixArtVY | 0:c00f2464eee3 | 101 | writeRegister(0x70, readRegister(0x70) + 11); |
| PixArtVY | 0:c00f2464eee3 | 102 | |
| PixArtVY | 0:c00f2464eee3 | 103 | writeRegister(0x71, readRegister(0x71) * 45/100); |
| PixArtVY | 0:c00f2464eee3 | 104 | } |
| PixArtVY | 0:c00f2464eee3 | 105 | |
| PixArtVY | 0:c00f2464eee3 | 106 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 107 | writeRegister(0x61, 0xAD); |
| PixArtVY | 0:c00f2464eee3 | 108 | writeRegister(0x7F, 0x03); |
| PixArtVY | 0:c00f2464eee3 | 109 | writeRegister(0x40, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 110 | writeRegister(0x7F, 0x05); |
| PixArtVY | 0:c00f2464eee3 | 111 | writeRegister(0x41, 0xB3); |
| PixArtVY | 0:c00f2464eee3 | 112 | writeRegister(0x43, 0xF1); |
| PixArtVY | 0:c00f2464eee3 | 113 | writeRegister(0x45, 0x14); |
| PixArtVY | 0:c00f2464eee3 | 114 | writeRegister(0x5B, 0x32); |
| PixArtVY | 0:c00f2464eee3 | 115 | writeRegister(0x5F, 0x34); |
| PixArtVY | 0:c00f2464eee3 | 116 | writeRegister(0x7B, 0x08); |
| PixArtVY | 0:c00f2464eee3 | 117 | writeRegister(0x7F, 0x06); |
| PixArtVY | 0:c00f2464eee3 | 118 | writeRegister(0x44, 0x1B); |
| PixArtVY | 0:c00f2464eee3 | 119 | writeRegister(0x40, 0xBF); |
| PixArtVY | 0:c00f2464eee3 | 120 | writeRegister(0x4E, 0x3F); |
| PixArtVY | 0:c00f2464eee3 | 121 | writeRegister(0x7F, 0x06); |
| PixArtVY | 0:c00f2464eee3 | 122 | writeRegister(0x44, 0x1B); |
| PixArtVY | 0:c00f2464eee3 | 123 | writeRegister(0x40, 0xBF); |
| PixArtVY | 0:c00f2464eee3 | 124 | writeRegister(0x4E, 0x3F); |
| PixArtVY | 0:c00f2464eee3 | 125 | writeRegister(0x7F, 0x08); |
| PixArtVY | 0:c00f2464eee3 | 126 | writeRegister(0x65, 0x20); |
| PixArtVY | 0:c00f2464eee3 | 127 | writeRegister(0x6A, 0x18); |
| PixArtVY | 0:c00f2464eee3 | 128 | writeRegister(0x7F, 0x09); |
| PixArtVY | 0:c00f2464eee3 | 129 | writeRegister(0x4F, 0xAF); |
| PixArtVY | 0:c00f2464eee3 | 130 | writeRegister(0x5F, 0x40); |
| PixArtVY | 0:c00f2464eee3 | 131 | writeRegister(0x48, 0x80); |
| PixArtVY | 0:c00f2464eee3 | 132 | writeRegister(0x49, 0x80); |
| PixArtVY | 0:c00f2464eee3 | 133 | writeRegister(0x57, 0x77); |
| PixArtVY | 0:c00f2464eee3 | 134 | writeRegister(0x60, 0x78); |
| PixArtVY | 0:c00f2464eee3 | 135 | writeRegister(0x61, 0x78); |
| PixArtVY | 0:c00f2464eee3 | 136 | writeRegister(0x62, 0x08); |
| PixArtVY | 0:c00f2464eee3 | 137 | writeRegister(0x63, 0x50); |
| PixArtVY | 0:c00f2464eee3 | 138 | writeRegister(0x7F, 0x0A); |
| PixArtVY | 0:c00f2464eee3 | 139 | writeRegister(0x45, 0x60); |
| PixArtVY | 0:c00f2464eee3 | 140 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 141 | writeRegister(0x4D, 0x11); |
| PixArtVY | 0:c00f2464eee3 | 142 | writeRegister(0x55, 0x80); |
| PixArtVY | 0:c00f2464eee3 | 143 | writeRegister(0x74, 0x21); |
| PixArtVY | 0:c00f2464eee3 | 144 | writeRegister(0x75, 0x1F); |
| PixArtVY | 0:c00f2464eee3 | 145 | writeRegister(0x4A, 0x78); |
| PixArtVY | 0:c00f2464eee3 | 146 | writeRegister(0x4B, 0x78); |
| PixArtVY | 0:c00f2464eee3 | 147 | writeRegister(0x44, 0x08); |
| PixArtVY | 0:c00f2464eee3 | 148 | writeRegister(0x45, 0x50); |
| PixArtVY | 0:c00f2464eee3 | 149 | writeRegister(0x64, 0xFF); |
| PixArtVY | 0:c00f2464eee3 | 150 | writeRegister(0x65, 0x1F); |
| PixArtVY | 0:c00f2464eee3 | 151 | writeRegister(0x7F, 0x14); |
| PixArtVY | 0:c00f2464eee3 | 152 | writeRegister(0x65, 0x67); |
| PixArtVY | 0:c00f2464eee3 | 153 | writeRegister(0x66, 0x08); |
| PixArtVY | 0:c00f2464eee3 | 154 | writeRegister(0x63, 0x70); |
| PixArtVY | 0:c00f2464eee3 | 155 | writeRegister(0x7F, 0x15); |
| PixArtVY | 0:c00f2464eee3 | 156 | writeRegister(0x48, 0x48); |
| PixArtVY | 0:c00f2464eee3 | 157 | writeRegister(0x7F, 0x07); |
| PixArtVY | 0:c00f2464eee3 | 158 | writeRegister(0x41, 0x0D); |
| PixArtVY | 0:c00f2464eee3 | 159 | writeRegister(0x43, 0x14); |
| PixArtVY | 0:c00f2464eee3 | 160 | writeRegister(0x4B, 0x0E); |
| PixArtVY | 0:c00f2464eee3 | 161 | writeRegister(0x45, 0x0F); |
| PixArtVY | 0:c00f2464eee3 | 162 | writeRegister(0x44, 0x42); |
| PixArtVY | 0:c00f2464eee3 | 163 | writeRegister(0x4C, 0x80); |
| PixArtVY | 0:c00f2464eee3 | 164 | writeRegister(0x7F, 0x10); |
| PixArtVY | 0:c00f2464eee3 | 165 | writeRegister(0x5B, 0x02); |
| PixArtVY | 0:c00f2464eee3 | 166 | writeRegister(0x7F, 0x07); |
| PixArtVY | 0:c00f2464eee3 | 167 | writeRegister(0x40, 0x41); |
| PixArtVY | 0:c00f2464eee3 | 168 | writeRegister(0x70, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 169 | |
| PixArtVY | 0:c00f2464eee3 | 170 | wait_ms(10); |
| PixArtVY | 0:c00f2464eee3 | 171 | |
| PixArtVY | 0:c00f2464eee3 | 172 | writeRegister(0x32, 0x44); |
| PixArtVY | 0:c00f2464eee3 | 173 | writeRegister(0x7F, 0x07); |
| PixArtVY | 0:c00f2464eee3 | 174 | writeRegister(0x40, 0x40); |
| PixArtVY | 0:c00f2464eee3 | 175 | writeRegister(0x7F, 0x06); |
| PixArtVY | 0:c00f2464eee3 | 176 | writeRegister(0x62, 0xF0); |
| PixArtVY | 0:c00f2464eee3 | 177 | writeRegister(0x63, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 178 | writeRegister(0x7F, 0x0D); |
| PixArtVY | 0:c00f2464eee3 | 179 | writeRegister(0x48, 0xC0); |
| PixArtVY | 0:c00f2464eee3 | 180 | writeRegister(0x6F, 0xD5); |
| PixArtVY | 0:c00f2464eee3 | 181 | writeRegister(0x7F, 0x00); |
| PixArtVY | 0:c00f2464eee3 | 182 | writeRegister(0x5B, 0xA0); |
| PixArtVY | 0:c00f2464eee3 | 183 | writeRegister(0x4E, 0xA8); |
| PixArtVY | 0:c00f2464eee3 | 184 | writeRegister(0x5A, 0x50); |
| PixArtVY | 0:c00f2464eee3 | 185 | writeRegister(0x40, 0x80); |
| PixArtVY | 0:c00f2464eee3 | 186 | } |
| PixArtVY | 0:c00f2464eee3 | 187 | |
| PixArtVY | 0:c00f2464eee3 | 188 | |
| PixArtVY | 0:c00f2464eee3 | 189 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 190 | void grabData(void) |
| PixArtVY | 0:c00f2464eee3 | 191 | { |
| PixArtVY | 0:c00f2464eee3 | 192 | deltaX_low = readRegister(0x03); //Grabs data from the proper registers. |
| PixArtVY | 0:c00f2464eee3 | 193 | deltaX_high = (readRegister(0x04)<<8) & 0xFF00; //Grabs data and shifts it to make space to be combined with lower bits. |
| PixArtVY | 0:c00f2464eee3 | 194 | deltaY_low = readRegister(0x05); |
| PixArtVY | 0:c00f2464eee3 | 195 | deltaY_high = (readRegister(0x06)<<8) & 0xFF00; |
| PixArtVY | 0:c00f2464eee3 | 196 | |
| PixArtVY | 0:c00f2464eee3 | 197 | deltaX = deltaX_high | deltaX_low; //Combines the low and high bits. |
| PixArtVY | 0:c00f2464eee3 | 198 | deltaY = deltaY_high | deltaY_low; |
| PixArtVY | 0:c00f2464eee3 | 199 | } |
| PixArtVY | 0:c00f2464eee3 | 200 | |
| PixArtVY | 0:c00f2464eee3 | 201 | |
| PixArtVY | 0:c00f2464eee3 | 202 | //========================================================================= |
| PixArtVY | 0:c00f2464eee3 | 203 | void printData(void) |
| PixArtVY | 0:c00f2464eee3 | 204 | { |
| PixArtVY | 0:c00f2464eee3 | 205 | if((deltaX != 0) || (deltaY != 0)) //If there is deltaX or deltaY movement, print the data. |
| PixArtVY | 0:c00f2464eee3 | 206 | { |
| PixArtVY | 0:c00f2464eee3 | 207 | totalX += deltaX; |
| PixArtVY | 0:c00f2464eee3 | 208 | totalY += deltaY; |
| PixArtVY | 0:c00f2464eee3 | 209 | |
| PixArtVY | 0:c00f2464eee3 | 210 | pc.printf("deltaX: %d\t\t\tdeltaY: %d\n\r", deltaX, deltaY); //Prints each individual count of deltaX and deltaY. |
| PixArtVY | 0:c00f2464eee3 | 211 | pc.printf("X-axis Counts: %d\t\tY-axis Counts: %d\n\r", totalX, totalY); //Prints the total movement made during runtime. |
| PixArtVY | 0:c00f2464eee3 | 212 | } |
| PixArtVY | 0:c00f2464eee3 | 213 | |
| PixArtVY | 0:c00f2464eee3 | 214 | deltaX = 0; //Resets deltaX and Y values to zero, otherwise previous data is stored until overwritten. |
| PixArtVY | 0:c00f2464eee3 | 215 | deltaY = 0; |
| PixArtVY | 0:c00f2464eee3 | 216 | } |
PMW3901MB | Far-Field Optical Motion Tracking Sensor