Forum: Mikrocontroller und Digitale Elektronik Arduino SPI read Infineon TLE5012B


von Raphael (Gast)


Lesenswert?

Hallo,
ich versuche mit einem Arduino Uno einen Winkelsensor auszulesen. Der 
Sensor ist von Infineon (TLE5012B) 
http://www.infineon.com/dgdl/Infineon-Angle_Sensor_TLE5012B-UM-v01_00-en.pdf?fileId=5546d46146d18cb40146ec2eeae4633b

In Arduino gibt es schon eine libary die SPI.h heist und die ich dafür 
auch benutze. Mein Problem ist jetzt, dass der Chip nur ein Data Pin hat 
und nicht MISO/MOSI getrennt hat. Ich habe hier im Forum schon einen 
Beitrag gefunden(Beitrag "SPI mit bidirektionale Datenverbindung"). Leider 
klappt es mit dem 4k7 Widerstand auch nicht.
Des Weiteren bin ich mir über den Commandbefehl zum lesen nicht ganz 
sicher, ob es der Richtige ist?
Oder liegt es an meinen Einstellungen von SPI?

hier mein Code:

1
 #include <SPI.h>
2
3
int angleValue_command = 0x4010; // Register command für Anglevalue read
4
int ss = 10;    //Chipselect pin
5
6
void setup() 
7
{ 
8
  SPI.begin();
9
  SPI.setBitOrder(MSBFIRST);
10
  SPI.setDataMode(SPI_MODE0);
11
  SPI.setClockDivider(SPI_CLOCK_DIV2);
12
  Serial.begin(9600);
13
  pinMode(ss, OUTPUT);    //Chipselect als Ausgang
14
  pinMode(SCK, OUTPUT);   //Clock pin als Ausgang 
15
  pinMode(MISO, INPUT);  
16
  pinMode(MOSI, OUTPUT);
17
}
18
19
void loop()
20
{
21
 int miso_data = spi_read(angleValue_command);
22
 Serial.println(miso_data);
23
24
}
25
byte spi_read (byte read_command)
26
 {
27
    digitalWrite(ss, LOW);      // Chipselect auf low 
28
    SPI.transfer(read_command); // Befehl an den Slave   
29
    delay(0.2);
30
    byte miso= SPI.transfer(0); // Antwort vom Slave
31
    digitalWrite(ss, HIGH);     // Chipselect auf high
32
    return miso;
33
 }
Ich bin für jede Hilfe dankbar!

von Rudolph (Gast)


Lesenswert?

Ich habe mir gerade mal das Datenblatt von dem Sensor angesehen und wie 
man die SSC Schnittstelle per SPI bedient steht da doch drin -> Seite 
34.

Was bei Dir oben noch fehlt ist, den MOSI Pin auf Eingang umzuschalten.

Mal davon abgesehen, dass die Datentypen durcheinander sind in dem 
Gewurschtel da oben, aus dem angleValue_command mit 16 Bit wird mal eben 
read_command mit 8 Bit.

Da müsstest Du schon die beiden Bytes von angleValue_command 
nacheinander schicken, dann MOSI auf Eingang umschalten und dann noch 
zwei Transfers machen, damit die Antwort vom Sensor gelesen werden kann.

von Raphael (Gast)


Lesenswert?

@Rudolph: Danke für die Hinweise :)

Habe hier mal den erweiterten Code
1
#include <SPI.h>
2
3
int angleValue_command = 0x8021; // Register command für Anglevalue read
4
int ss = 10;    //Chipselect pin
5
6
void setup() 
7
{ 
8
  SPI.begin();
9
  SPI.setBitOrder(MSBFIRST);        
10
  SPI.setDataMode(SPI_MODE0);
11
  SPI.setClockDivider(SPI_CLOCK_DIV2);  // CLOCK speed einstellen 16MHZ/2 -> 8 MHZ
12
  Serial.begin(9600);
13
  pinMode(ss, OUTPUT);    //Chipselect als Ausgang
14
  pinMode(SCK, OUTPUT);   //Clock pin als Ausgang 
15
  pinMode(MISO, INPUT);   //MISO auf Eingang stellen
16
  pinMode(MOSI, OUTPUT);  //MOSI auf Ausgang stellen
17
}
18
19
void loop()
20
{
21
 int miso_data = spi_read(angleValue_command);
22
 int angle = miso_data * (360/(pow(2, 15)));
23
 Serial.println(angle);
24
25
}
26
int spi_read (int read_command)
27
{
28
    int data1 = 0;
29
    int data2 = 0;
30
    int safety = 0;
31
 
32
    digitalWrite(ss, LOW);      // Chipselect auf low
33
    /*------------ Anfrage an den Slave schicken ------------------------
34
    16 Bit Kommando senden */
35
    pinMode(MOSI, OUTPUT);
36
    SPI.transfer((byte)(read_command >> 8));    // 8 High-Bits an den Slave senden
37
    delay(0.2);
38
    SPI.transfer((byte)(read_command & 0x00FF)); // 8 Low-Bits an den Slave senden
39
    pinMode(MOSI, INPUT);                        // MOSI Pin Hochohmig schalten
40
    delay(0.2);
41
    /* ende 16 Bit Kommando */
42
    /* 16Bit Data 1 empfangen */
43
    
44
    /*-----------------Antwort vom Slave----------------------*/
45
    data1= SPI.transfer(0); 
46
 
47
    // Für den Fall wenn der Sensor einen 16 Bit Wert zurücksendet ...
48
    data1 <<= 8;
49
    data1 |= SPI.transfer(0);
50
    
51
    /* 16Bit Data 2 empfangen */
52
    data2= SPI.transfer(0); // Antwort vom Slave
53
 
54
    // Für den Fall wenn der Sensor einen 16 Bit Wert zurücksendet ...
55
    data2 <<= 8;
56
    data2 |= SPI.transfer(0);
57
    
58
    /* 16Bit safety empfangen */
59
    safety= SPI.transfer(0); // Antwort vom Slave
60
61
    // Für den Fall wenn der Sensor einen 16 Bit Wert zurücksendet ...
62
    safety <<= 8;
63
    safety |= SPI.transfer(0);
64
    int miso= data1;
65
    digitalWrite(ss, HIGH);     // Chipselect auf high
66
    return miso;
67
}

Das Problem was ich noch habe ist, dass ich die Miso und Mosi Leitung 
nicht direkt anschließen kann. Die MOSI Leitung geht dabei erst noch 
über einen 4k7 Ohm Widerstand, wie in dem anderen Beitrag schon gezeigt 
wurde.
Wennn ich den 4k7 Widerstand weg lasse ist kein Datenempfang möglich. 
Auch durch hochohmig schalten der MOSI Leitung beim Datenempfang.

von berndl (Gast)


Lesenswert?

Ich habe den TLE5012B vor ca. 4 Jahren mal an einem FPGA am laufen 
gehabt, so ca. mit 2,5 MHz auf der SCK.
Dabei bin ich auch mal ueber die "schlappe" Flanke des Chips gestolpert, 
kann mit PAD_DRV in irgeneinem Register konfiguriert werden. Ich musste 
dann den Sample Zeitpunkt im FPGA noch 'nach hinten schieben', weil die 
Daten vom TLE eben elendig spaet nach der SCK-Flanke gekommen sind. Ok, 
ich hatte die SSC auch noch ueber LVDS-Treiber angebunden, das macht's 
nochmal langsamer (Latenz)...

Nicht, dass du da ins gleiche Problem reinrennst... Evtl. mal die SPI 
deutlich langsamer takten (ca. 1MHz fuer Versuche)

von Rudolph (Gast)


Lesenswert?

Also zumindest nach Datenblatt vom Mega328 ist die Datenrichtung für 
MOSI im SPI Master-Mode "User Defined".
Der Widerstand sollte also nicht notwendig sein, oder könnte 
sicherheitshalber zumindest kleiner ausfallen.

Aber was die Arduino-IDE aus "pinMode(MOSI, INPUT);" macht ist die 
Frage, das muss ja nicht unbedingt zum gewünschten Ergebnis führen. :-)

Und wie sieht überhaupt der Schaltplan zu dem Sensor aus, also wie der 
wirklich benutzt wird, und nicht sowas wie "nach Seite 5 im Datenblatt"?

von Raphael (Gast)


Lesenswert?

@berndl:
Danke für den Tipp. Ich werde mal ein wenig mit dem SCK und den 
Registern rum probieren um zu sehen, ob dies eine Veränderung bringt. Du 
sagst, dass du schon einmal mit dem Chip zu tun hattest, wie ist denn so 
Deine Bewertung im großen und ganzen von dem Chip?

@Rudolph:

Rudolph schrieb:
> Aber was die Arduino-IDE aus "pinMode(MOSI, INPUT);" macht ist die
> Frage, das muss ja nicht unbedingt zum gewünschten Ergebnis führen. :-)

Das habe ich mich auch schon gefragt :D. Vor allem kann es auch gut 
möglich sein, dass der Befehlt gar nichts bringt, wenn in der Funktion 
"SPI.transfer() evtl. der MOSI wieder auf output gesetzt wird. Da muss 
ich mich mal durch die Libary wühlen.

Rudolph schrieb:
> Und wie sieht überhaupt der Schaltplan zu dem Sensor aus, also wie der
> wirklich benutzt wird, und nicht sowas wie "nach Seite 5 im Datenblatt"?

Momentan geht es erstmal nur darum den Chip zu test und zu gucken wie 
ich die Daten ausgelesen kann. Mit anderen Worten, ich habe noch keinen 
exakten Schaltplan bis auf ein paar Skizzen, aber am Ende des Tages soll 
ein funktionierender Winkelsensor dabei rum kommen.

von Rudolph (Gast)


Lesenswert?

Ich habe den auch schon benutzt, allerdings mit PWM als Ausgang und dann 
per Input-Capture eingelesen -> komplett anders.
Vom Ergebnis her war das schon nett, umgerechnet habe ich das auf 0,1°.
Das lief, war aber nur ein Demonstrator, Referenzmessungen um die 
Abweichung zum tatsächlichen Winkel festzustellen wollte da keiner 
haben. :-)

von Vita H. (Firma: FH-Bielefeld) (thevit1989)


Lesenswert?

Hi,

ich brauche bei folgendem Hilfe.

Mit dem Sensor von Infenion TLE 5012B kann ich bereits den Winkel über 
SPI auslesen.

Zur Info, der Sensor ist in der nähe eines Magneten angebracht. Der 
Magnet sitzt an der der Welle eines Motors.

Nun möchte ich gerne das Angle Revolution Register ansprechen. Das lesen 
funktioniert und es werden Inkremente hoch gezählt von 0 bis 255.

void UmlaufAusgabe(void)
{
  unsigned Frame_Counter;
  int Num_Revolution;
  int miso_data = (spi_read(angleRevolution_command));//& 0x7FFF);

  Num_Revolution = 0x00FF & miso_data;

  Serial.print( "\t\t Aktueller Umlauf: ");
  Serial.println(Num_Revolution);

}

Was ich aber nicht so ganz vertsehe ist, dass laut Datenblatt das 
Register 9 Bit für die Umdrehungen hat. Somit habe ich folgendes 
probiert und es kommt nur blödsinn raus.

Num_Revolution = 0x01FF & miso_data;

Zusätzlich habe ich das Problem, dass ein Inkerement immer hochgezählt 
wird, bei 2 Umdrehungen des Motors.

Nun glaube ich, dass entweder mein auslesen falsch ist oder die 
einstellungen die ich im Register benutze.



/*Auslesen des Umlaufs / Angle Revolution (Revolution = Umlauf) Register 
*/
int angleRevolution_command = 0x8040;

/*Auslesen der Winkelposition*/
int angleValue_command = 0x8021; // Register command für Anglevalue read

/*Adressen und Befehle für Interface Mode2*/
int mode2_command = 0x5081;        // Register command für interface 
Mode2
int write_mode2 =   0x0809;        //Wirte Befehl interface Mode2, Set 
ANG_Range 080H, ANG_DIR: 1B, PREDICT: 0B, AUTOCAL: 01B

ich bin für jede Hilfe Dankbar.

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.