Forum: Mikrocontroller und Digitale Elektronik Maussensor PMW 3310 firmware (ASCII - textfile) einspielen


von Johannes R. (farin_leest)


Angehängte Dateien:

Lesenswert?

Hallo liebe Community,


ich schreibe momentan meine Bachelorarbeit und verwende dafür einen PMW 
3310 Gamingmaus-Sensor. Es geht darum kleine Längenänderungen zu messen. 
Da die Längenänderungen sehr klein sein sollen, benötige ich auch die 
höchste Auflösung von 5000 dpi.

Ich verwende als IDE Eclipse. Als Controller dient ein STM32L476.
Die Kommunikation über SPI funktioniert wunderbar. Ich kann alle 
Register auslesen und auch beschreiben. Möchte ich allerdings das 
Register mit dem entsprechenden Wert (0x64) für die höchste Auflösung 
beschreiben, so steht im Register nach anschließendem Auslesen nur der 
Wert 0x32. Pixart meinte auf Anfrage, dass ich die im Anhang befindliche 
Firmware in den Sensor übertragen muss. Dabei handelt es sich um ein 
ASCII textfile. So müsste ich also diese Daten über SPI in den Sensor 
übertragen.

Kann mir vielleicht jemand helfen und hat eine Idee, wie man das machen 
könnte? Ich habe auch schon ein, zwei Sachen ausprobiert. Nur leider 
ohne Erfolg.


Vielen Dank und liebe Grüße

von bla (Gast)


Lesenswert?

Register 0x64 beschreiben kannst du auch nicht. Das ist rein 
Read-Only-Register.

Was sollen die Configuration A-D sein? gibt es noch ein anderes 
Datasheet?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Ah, auch das uC.net gefunden :-)

von Jack (Gast)


Lesenswert?

Johannes R. schrieb:
> Pixart meinte auf Anfrage, dass ich die im Anhang befindliche
> Firmware in den Sensor übertragen muss. Dabei handelt es sich um ein
> ASCII textfile. So müsste ich also diese Daten über SPI in den Sensor
> übertragen.

Vermutlich nachdem du eine Wandlung HEX -> Binär durchgeführt hast.

> Kann mir vielleicht jemand helfen und hat eine Idee, wie man das machen
> könnte?

Da wirst du Pixart fragen müssen. Das Datenblatt gibt nicht her, wie man 
einen Firmware-Download macht. Ohne diesen Teil des Puzzles stocherst du 
im Nebel.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Das ASCII Textfile einfach in deinen Sourcecode kopieren, und folgendes 
drumherumbauen:
1
const char* image = {
2
  0x03,
3
  0x11,
4
  0xb1,
5
  0xc2,
6
  0xc6,
7
...
8
};

Das geht sehr gut per Block Edit. "const" nicht vergessen, sonst landet 
der Kram im RAM. Grösse bekommst per sizeof(). Dann durch den SPI (ggf. 
DMA) in den Sensor klappern.

VG,
/th.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Random .. schrieb:
> Grösse bekommst per sizeof().
Aber nur wenn man das Array mit "const char image [] = { ... };" anlegt 
statt mit "const char* ...", sonst erhält man lediglich die Größe von 
Pointern.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

stimmt :-)
1
const char image[] = { ... }
2
3
int elements = sizeof(image) / sizeof(image[0]);

von Georg Gast 1 (Gast)


Lesenswert?

Was ist an Seite 18: SROM Download in 
https://www.codico.com/shop/media/datasheets/PixArt_PMW3310DH.pdf nicht 
zu verstehen?

Georg

PS: Ja, die hex-Zahlen aus der Textdatei sind vorher in Bytes 
umzuwandeln.

von Jack (Gast)


Lesenswert?

Georg Gast 1 schrieb:
> Was ist an Seite 18: SROM Download in
> https://www.codico.com/shop/media/datasheets/PixAr... nicht
> zu verstehen?

Dass das Datenblatt, das ich auf die Schnelle auf der PixArt Webseite 
gefunden habe, gerade mal 10 Seiten hat?
http://www.pixart.com.tw/upload/PMW3310DH-AWQT_NNDS_02022016_20160902193420.pdf

von Johannes R. (farin_leest)


Angehängte Dateien:

Lesenswert?

Vielen Dank erstmal für die vielen Hinweise!

Ich hätte schon vorher schreiben sollen, was ich versucht hatte. 
Entschuldigung dafür!

Ich hatte zuerst die ASCII-Werte in MATLAB geladen und sie in 
Dezimalwerte umgewandelt (ob dies nun sinnvoll ist oder nicht sei 
erstmal dahin gestellt - in jedem Fall sollte das doch eigentlich 
funktionieren). MATLAB hat auch die Zeilenumbrüche mit in Dezimalzahlen 
umgewandelt, wobei dann sowas hier entstand:

Aus diesem Ausschnitt (ASCII)

03
11
b1



wurde dann(dezimal):

48
51
13
10
49
49
13
10
98
49
13
10


Die  13 und die 10 wiederholen sich also immer (Umbrüche). Die habe ich 
dann entfernt und eine Reihe von Dezimalzahlen erhalten.

Daraus habe ich dann ein Array gebastelt und in meinen Code eingefügt 
(siehe Anhang: srom.c)


Dann folgte meine routine um die Daten an den chip zu übertragen.
1
// write 0x1d to SROM_Enable register
2
sendData(0x13, 0x1d);   //(address, data)
3
HAL_Delay(1);
4
5
//write 0x18 to SROM_Enable register to start SROM Download
6
sendData(0x13, 0x18);  //(address, data)
7
HAL_Delay(1);
8
9
10
chipSelect();  //chipselect -> CS low to select PMW3310
11
12
HAL_Delay(1);
13
14
//address of SROM_LOAD_BURST register
15
uint8_t SROM_LOAD_BURST_add = (0x62| 0x80);  
16
17
//transmit data over SPI (address)
18
HAL_SPI_Transmit(&hspi1, &SROM_LOAD_BURST_add, 1, HAL_MAX_DELAY); 
19
HAL_Delay(1);
20
21
//transmit data
22
for(int i=0; i<6140; i++)
23
{  
24
  
25
data = (SROM1[i] | 0x80);
26
27
HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
28
HAL_Delay(1);
29
}
30
31
HAL_Delay(1);
32
chipDeselect();


Die geforderte Prozedur dafür ist im .png im Anhang zu sehen


Wenn die Übertragung der Firmware erfolgreich war, kann das Register 
"SROM_ID" (0x2a) ausgelesen werden. Wenn es erfolgreich war, steht dort 
die Firmware-nummer drin, sonst 0x00. Bei mir steht danach leider nur 
0x00....



Übrigens: die langen delays von 1ms sind natürlich zu lang. Eine 
Funktion o.ä. die kürzere delays kann muss ich erst noch implementieren; 
sollte doch aber eigentlich trotzdem damit funktionieren.

von Johannes R. (farin_leest)


Angehängte Dateien:

Lesenswert?

bla schrieb:
> Register 0x64 beschreiben kannst du auch nicht. Das ist rein
> Read-Only-Register.
>
> Was sollen die Configuration A-D sein? gibt es noch ein anderes
> Datasheet?

0x64 sollte der maximale Wert für die höchste Auflösung sein (siehe 
Anhang).

Mit den config A-D kann man den chip konfigurieren: Auslösung, 
Angle_snapping an/aus, Winkel einstellen für angle_tune usw.

von Guest (Gast)


Lesenswert?

Johannes R. schrieb:
> Aus diesem Ausschnitt (ASCII)
>
> 03
> 11
> b1
>
> wurde dann(dezimal):
>
> 48
> 51
> 13
> 10
> 49
> 49
> 13
> 10
> 98
> 49
> 13
> 10

\o/

Sinnhaftigkeit braucht nicht weiter diskutiert zu werden.

von Harald (Gast)


Lesenswert?

Johannes R. schrieb:
> Aus diesem Ausschnitt (ASCII)
>
> 03
> 11
> b1
>
> wurde dann(dezimal):
>
> 48
> 51
> 13
> 10
> 49
> 49
> 13

Das war ASCII (Character) und bleibt ASCII (Darstellung in Dezimal). Was 
gefordert ist, ist eine Umwandlung ASCII ZU HEX.

Dann wird aus
03 —> HEX 0x03 —> DEZ 3
11 —> HEX 0x11 —> DEZ 17
B1 —> HEX 0xB1 —> DEZ 177

von Harald (Gast)


Lesenswert?

Wenn du Buße für deinen Fauxpas machen möchtest, könntest du einfach 
deinen Header
#include <inttypes.h>
#include "srom.h"

 uint8_t SROM[]= {

an den Anfang der originalen Datei setzen und dann 3000x ein „0x“ an den 
Anfang jeder folgenden Zeile und ein Komma an das Ende setzen (nicht 
beim letzten Eintrag). Dann ist alles fertig.

von Johannes R. (farin_leest)


Angehängte Dateien:

Lesenswert?

Harald schrieb:
> Wenn du Buße für deinen Fauxpas machen möchtest, könntest du einfach
> deinen Header
> #include <inttypes.h>
> #include "srom.h"
>
>  uint8_t SROM[]= {
>
> an den Anfang der originalen Datei setzen und dann 3000x ein „0x“ an den
> Anfang jeder folgenden Zeile und ein Komma an das Ende setzen (nicht
> beim letzten Eintrag). Dann ist alles fertig.







Vielen dank nochmal für den Hinweis. Das habe ich gemacht (siehe 
Anhang). Leider bleibt alles beim Alten..... :(

von Harald A. (embedded)


Lesenswert?

Nach dem letzten Byte hast ja DOCH ein Komma... aber das dürfte den 
Fehler nicht auslösen, weil Du im Source eine feste Größe angibst.

Warum werden aber 6140Bytes gesendet und wieso veroderst du jedes Byte 
mit 0x80. Das kann nicht richtig sein.

for(int i=0; i<6140; i++)
{

data = (SROM1[i] | 0x80);

Ansonsten bitte einen LogicAnalyzer besorgen (HW kostet <10€), dazu die 
Software SIGROK. Dann kannst du sehen, was tatsächlich gesendet wird und 
ob das zum Datenblatt passt.

von Harald A. (embedded)


Lesenswert?

Sehe gerade, der Rest des Source (also vor der Hauptschleife) ist auch 
total falsch.

sendData(0x13, 0x1d);   //(address, data)
HAL_Delay(1);


Warum hier sendData??? Unten wird HAL_SPI_Transmit verwendet...


//write s of SROM_LOAD_BURST register
uint8_t SROM_LOAD_BURST_add = (0x62| 0x80);

Warum 0x80???


//transmit data over SPI (address)
HAL_SPI_Transmit(&hspi1, &SROM_LOAD_BURST_add, 1, HAL_MAX_DELAY);

Was soll das bewirken?

von Johannes (Gast)


Lesenswert?

Ja richtig, hab im Eifer des Gefechtes vergessen das Komma hinter dem 
letzen byte zu löschen .... schon erledigt.


1
for(int i=0; i<6140; i++)

Die Zahl 6140 stammt noch von meinem falsch umgewandelten ascii-file.


Die sendData-Funktion übermittel Daten an ein bestimmtes Register. 
Darain enthalten ist auch das
1
HAL_SPI_Transmit(&hspi1, &SROM_LOAD_BURST_add, 1, HAL_MAX_DELAY);
 und die chipselects.

1
void sendData(uint8_t address, uint8_t data)
2
{
3
  chipSelect();
4
  HAL_Delay(10);
5
6
  //set MSB to "1"
7
  address = address | 0x80 ;
8
9
10
  HAL_SPI_Transmit(&hspi1, &address, 1, HAL_MAX_DELAY);
11
  HAL_Delay(1);
12
  HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
13
14
  HAL_Delay(10);
15
16
  chipDeselect();
17
18
  }

Auch hier taucht wieder der ODER-Verknüpfung mit 0x80 auf. Der Sensor 
weiß, dass Daten SENDEN soll, wenn das MSB eine "0" ist. Dass er Daten 
EMPFANGEN soll sagt man ihm, indem das MSB auf "1" gesetzt wird.

Deshalb sage ich ihm hier, dass das MSB der Adresse eine "1" ist und er 
Daten empfangen soll:
1
uint8_t SROM_LOAD_BURST_add = (0x62| 0x80);


An dieser Stelle ist es falsch:
1
 data = (SROM1[i] | 0x80);

von Johannes (Gast)


Lesenswert?

Es hat jetzt funktioniert!!!

Ich hatte nach dem Übertragen der Firmware noch eine Funktion vergessen 
zu deaktiviren, die den Chip resettet. Beim Auslesen der Register war 
dann natürlich nicht der Erfolg zu sehen.


Dank eurer Hinweise zu meiner ASCII-HEX-Verwirrung, hat es dann also 
funktioniert.

Vielen Dank für die Unterstützung.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.