Skip to content

Commit

Permalink
Merge branch 'ArsenioDev-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
ataffanel committed Jan 8, 2020
2 parents 00bdb17 + 575dc44 commit 6c4a25b
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 7 deletions.
100 changes: 100 additions & 0 deletions examples/PMW3901_Framebuffer_LCD/PMW3901_Framebuffer_LCD.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "Bitcraze_PMW3901.h"


#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
//defines for TFT
#define TFT_CS 9
#define TFT_RST 8
#define TFT_DC 7
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
int PixelScale = 3;


// Using digital pin 10 for chip select
Bitcraze_PMW3901 flow(10);
char frame[35*35]; //array to hold the framebuffer

const PROGMEM uint16_t ironhot[] =
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0020,0x0020,
0x0020,0x0020,0x0020,0x0841,0x0841,0x0841,0x0841,
0x0841,0x0841,0x0861,0x0861,0x0861,0x0861,0x0861,
0x1082,0x1082,0x1082,0x1082,0x1082,0x10a2,0x10a2,
0x10a2,0x10a2,0x10a2,0x18c3,0x18c3,0x18c3,0x18c3,
0x18c3,0x18e3,0x18e3,0x18e3,0x18e3,0x18e3,0x2104,
0x2104,0x2104,0x2104,0x2104,0x2124,0x2124,0x2124,
0x2124,0x2124,0x2124,0x2945,0x2945,0x2945,0x2945,
0x2945,0x2965,0x2965,0x2965,0x2965,0x2965,0x3186,
0x3186,0x3186,0x3186,0x31a6,0x31a6,0x31a6,0x31a6,
0x31a6,0x39c7,0x39c7,0x39c7,0x39c7,0x39c7,0x39e7,
0x39e7,0x39e7,0x39e7,0x39e7,0x4208,0x4208,0x4208,
0x4208,0x4208,0x4228,0x4228,0x4228,0x4228,0x4228,
0x4a49,0x4a49,0x4a49,0x4a49,0x4a49,0x4a69,0x4a69,
0x4a69,0x4a69,0x4a69,0x528a,0x528a,0x528a,0x528a,
0x528a,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x5acb,
0x5acb,0x5acb,0x5acb,0x5acb,0x5aeb,0x5aeb,0x5aeb,
0x5aeb,0x5aeb,0x630c,0x630c,0x630c,0x630c,0x630c,
0x632c,0x632c,0x632c,0x632c,0x632c,0x632c,0x6b4d,
0x6b4d,0x6b4d,0x6b4d,0x6b4d,0x6b6d,0x6b6d,0x6b6d,
0x6b6d,0x6b6d,0x738e,0x738e,0x738e,0x738e,0x738e,
0x73ae,0x73ae,0x73ae,0x73ae,0x73ae,0x7bcf,0x7bcf,
0x7bcf,0x7bcf,0x7bcf,0x7bef,0x7bef,0x7bef,0x7bef,
0x7bef,0x7bef,0x8410,0x8410,0x8410,0x8410,0x8410,
0x8430,0x8430,0x8430,0x8430,0x8430,0x8c51,0x8c51,
0x8c51,0x8c51,0x8c51,0x8c71,0x8c71,0x8c71,0x8c71,
0x8c71,0x9492,0x9492,0x9492,0x9492,0x9492,0x94b2,
0x94b2,0x94b2,0x94b2,0x9cd3,0x9cd3,0x9cd3,0x9cd3,
0x9cd3,0x9cd3,0x9cf3,0x9cf3,0x9cf3,0x9cf3,0x9cf3,
0xa514,0xa514,0xa514,0xa514,0xa514,0xa534,0xa534,
0xa534,0xa534,0xa534,0xad55,0xad55,0xad55,0xad55,
0xad55,0xad75,0xad75,0xad75,0xad75,0xb596,0xb596,
0xb5b6,0xb5b6,0xb5b6,0xbdd7,0xbdd7,0xbdd7,0xbdf7,
0xbdf7,0xbdf7,0xc618,0xc618,0xc638,0xc638,0xc638,
0xce59,0xce59,0xce59,0xce79,0xce79,0xd69a,0xd69a,
0xd69a,0xd6ba,0xd6ba,0xd6ba,0xdedb,0xdedb,0xdefb,
0xdefb,0xdefb,0xe71c};

void setup() {
Serial.begin(115200);
tft.initR(INITR_GREENTAB); // initialize a ST7735S chip, 144 is 1.44 in display
tft.fillScreen(ST7735_BLACK); //Fill black
tft.setRotation(3); //this specifies the rotation

if (!flow.begin()) {
Serial.println("Initialization of the flow sensor failed");
tft.fillScreen(ST7735_RED);
delay(100);
tft.fillScreen(ST7735_BLACK); //Flash screen red to indicate error
delay(100);
tft.fillScreen(ST7735_RED);
while(1) { }
}

flow.enableFrameBuffer();
Serial.println("framebuffer init");
}


void loop() {
flow.readFrameBuffer(frame);
Serial.println("framebuffer read");
int i,j,k;
for(i=0, k=0; i<35; i++){ //i is Y pixel pos
for(j=0; j<35; j++, k++){ //j is X pixel pos
//Serial.print(asciiart(frame[k]));
Serial.print(' ');
uint8_t colorIndex = frame[k];
Serial.print(frame[k]); //print pixel count contained data
//draw the pixels!
tft.fillRect(4+PixelScale * i, 4+PixelScale * j, PixelScale, PixelScale, ironhot[colorIndex]); //Scale up function to fill screen
}
Serial.println();
}
Serial.println();
}


char asciiart(int k){ //converter magic? Higher value shunts more right in char array
static char foo[] = "WX86*3I>!;~:,`. ";
return foo[k>>4]; //return shunted from array value character
}
41 changes: 41 additions & 0 deletions examples/PMW3901_Framebuffer_test/PMW3901_Framebuffer_test.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//"THE BEER-WARE LICENSE" (Revision 42): Arsenio Dev wrote this file. As long as you retain this notice you can do whatever you want with this stuff.
//If we meet some day, and you think this stuff is worth it, you can buy me a beer in return.

#include "Bitcraze_PMW3901.h"

// Using digital pin 10 for chip select
Bitcraze_PMW3901 flow(10);
char frame[35*35]; //array to hold the framebuffer


void setup() {
Serial.begin(115200);
if (!flow.begin()) {
Serial.println("Initialization of the flow sensor failed");
while(1) { }
}

flow.enableFrameBuffer();
Serial.println("framebuffer init");
}


void loop() {
flow.readFrameBuffer(frame);
Serial.println("framebuffer read");
int i,j,k;
for(i=0, k=0; i<35; i++){ //i is Y pixel pos
for(j=0; j<35; j++, k++){ //j is X pixel pos
Serial.print(asciiart(frame[k]));
Serial.print(' ');
}
Serial.println();
}
Serial.println();
}


char asciiart(int k){ //converter magic? Higher value shunts more right in char array
static char foo[] = "WX86*3I>!;~:,`. ";
return foo[k>>4]; //return shunted from array value character
}
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Bitcraze_PMW3901 KEYWORD1
readMotionCount KEYWORD2
enableFrameBuffer KEYWORD2
readFrameBuffer KEYWORD2
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ As soon as it is initialized, the sensor will start accumulating motion count. C
flow.readMotionCount(&deltaX, &deltaY);
```

Alternatively, to use the framebuffer system to use it as a camera of sorts you will need to do a bit more. After the *begin* function, call the *enableFrameBuffer* function to switch modes, then in your loop call *readFrameBuffer* while passing it a 35*35 array to dump pixels into.

``` C++
// Get pixels from framebuffer into an array
flow.readFrameBuffer(int *FBuffer);
```


## Output interpretation

The sensor outputs unitless ticks that corresponds to the amount of movement that has been observed in front of the sensor. These ticks can be converted to a distance if we know the distance to the tracked surface and we assume the tracked surface is flat.
Expand Down
82 changes: 75 additions & 7 deletions src/Bitcraze_PMW3901.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ boolean Bitcraze_PMW3901::begin(void) {
// Setup SPI port
SPI.begin();
pinMode(_cs, OUTPUT);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE3));
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE3));

// Make sure the SPI bus is reset
digitalWrite(_cs, HIGH);
Expand All @@ -47,8 +47,7 @@ boolean Bitcraze_PMW3901::begin(void) {
// Power on reset
registerWrite(0x3A, 0x5A);
delay(5);

// Test the SPI communication, checking chipId and inverse chipId
// Test the SPI communication, checking chipId and inverse chipId
uint8_t chipId = registerRead(0x00);
uint8_t dIpihc = registerRead(0x5F);

Expand Down Expand Up @@ -76,11 +75,80 @@ void Bitcraze_PMW3901::readMotionCount(int16_t *deltaX, int16_t *deltaY)
*deltaY = ((int16_t)registerRead(0x06) << 8) | registerRead(0x05);
}

void Bitcraze_PMW3901::enableFrameBuffer()
{

registerWrite(0x7F, 0x07); //Magic frame readout registers
registerWrite(0x41, 0x1D);
registerWrite(0x4C, 0x00);
registerWrite(0x7F, 0x08);
registerWrite(0x6A, 0x38);
registerWrite(0x7F, 0x00);
registerWrite(0x55, 0x04);
registerWrite(0x40, 0x80);
registerWrite(0x4D, 0x11);

registerWrite(0x70, 0x00); //More magic?
registerWrite(0x58, 0xFF);

int temp = registerRead(0x58); //Read status register
int check = temp>>6; //rightshift 6 bits so only top two stay

while(check == 0x03){ //while bits aren't set denoting ready state
temp = registerRead(0x58); //keep reading and testing
check = temp>>6; //shift again
}
delayMicroseconds(50);
}

void Bitcraze_PMW3901::readFrameBuffer(char *FBuffer)
{
int count = 0;
uint8_t a; //temp value for reading register
uint8_t b; //temp value for second register
uint8_t hold; //holding value for checking bits
uint8_t mask = 0x0c; //mask to take bits 2 and 3 from b
uint8_t pixel = 0; //temp holding value for pixel

for (int ii = 0; ii < 1225; ii++) { //for 1 frame of 1225 pixels (35*35)
//check status bits 6 and 7
//if 01 move upper 6 bits into temp value
//if 00 or 11, reread
//else lower 2 bits into temp value
a = registerRead(0x58); //read register
hold = a >> 6; //right shift to leave top two bits for ease of check.

while ((hold == 0x03) || (hold == 0x00)) { //if data is either invalid status
a = registerRead(0x58); //reread loop
hold = a >> 6;
}
if (hold == 0x01) { //if data is upper 6 bits
b = registerRead(0x58); //read next set to get lower 2 bits
pixel = a; //set pixel to a
pixel = pixel << 2; //push left to 7:2
pixel += (b & mask); //set lower 2 from b to 1:0
FBuffer[count++] = pixel; //put temp value in fbuffer array
//delayMicroseconds(100);
}
else {}
}
registerWrite(0x70, 0x00); //More magic?
registerWrite(0x58, 0xFF);

int temp = registerRead(0x58); //Read status register
int check = temp>>6; //rightshift 6 bits so only top two stay

while(check == 0x03){ //while bits aren't set denoting ready state
temp = registerRead(0x58); //keep reading and testing
check = temp>>6; //shift again
}
}

// Low level register access
void Bitcraze_PMW3901::registerWrite(uint8_t reg, uint8_t value) {
reg |= 0x80u;

SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE3));
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE3));

digitalWrite(_cs, LOW);

Expand All @@ -99,19 +167,19 @@ void Bitcraze_PMW3901::registerWrite(uint8_t reg, uint8_t value) {
uint8_t Bitcraze_PMW3901::registerRead(uint8_t reg) {
reg &= ~0x80u;

SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE3));
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE3));

digitalWrite(_cs, LOW);

delayMicroseconds(50);
SPI.transfer(reg);
delayMicroseconds(50);
uint8_t value = SPI.transfer(0);
delayMicroseconds(200);
delayMicroseconds(100);

digitalWrite(_cs, HIGH);

delayMicroseconds(200);
//delayMicroseconds(200);

SPI.endTransaction();

Expand Down
2 changes: 2 additions & 0 deletions src/Bitcraze_PMW3901.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Bitcraze_PMW3901 {
boolean begin(void);

void readMotionCount(int16_t *deltaX, int16_t *deltaY);
void enableFrameBuffer();
void readFrameBuffer(char *FBuffer);

private:
uint8_t _cs;
Expand Down

0 comments on commit 6c4a25b

Please sign in to comment.