Forum: Mikrocontroller und Digitale Elektronik Digitaler Infrarotentfernungssensor Sharp GP2Y0E03


von Jan B. (diphthong)


Lesenswert?

Hallo an alle,
hab’ gerade bei Digikey diesen Sensor und dieses Datenblatt gefunden:
http://www.sharp.co.jp/products/device/lineup/data/pdf/datasheet/gp2y0e03_e.pdf
Der Sensor scheint sehr interessant zu sein. Im Gegensatz zu den alten 
analogen Entfernungssensoren hat er eine digitale I²C Schnittstelle, die 
Reichweite ist mit 4cm - 50cm auch recht umfassend. Zusätzlich wird die 
Entfernung analog ausgegeben, das Ganze aber linear.
Was mich aber nun wundert, ist, dass man, wenn man die Bezeichnung 
googelt, keine Projekte oder sonstige Informationen findet. Außerdem 
finde ich im Datenblatt keine genauen Informationen zur I²C 
Kommunikation (Register etc.).
Wo liegt da der Haken? Verstehe ich etwas falsch? Oder ist der Sensor 
einfach so neu?
Hat damit evtl. schon jemand hier gearbeitet?
Viele Grüße
Jan

von Johm (Gast)


Lesenswert?

Hey!

hab den sensor vor mir liegen und versuch ihn mittels I2C und einem 
arduino auszulesen. das datasheet ist mittlerweile ausführlicher. nur 
frage ich mich ob man für die messung manuell ein register setzten muss 
oder der sensor dies automatisch kontinuierlich macht.

von spess53 (Gast)


Lesenswert?


von Johm (Gast)


Lesenswert?

Hey spess!

ja die habe ich auch bereits vor mir liegen. ich greif auch bereits auf 
die Register zu, nur bin ich mir nicht so sicher ob ich das Protokoll 
richtig verstanden habe.

Dies wär mein Code soweit (ich versuch das 3Bit lange Distance register 
zu lesen):
1
int adress = 64;// 64 == 0x40, adress of SHARP, eigentlich 0x80 aber 7 bits (MSB!) => 0x40
2
3
  // 1st cycle
4
  Wire.beginTransmission(adress); // 
5
  Wire.write(byte(0x80));
6
  Wire.write(byte(0x5F));
7
  int err = Wire.endTransmission(adress);
8
  Serial.print("Error: ");
9
  Serial.print(err, DEC);
10
  Serial.print("\n");
11
  
12
  Wire.beginTransmission(adress);
13
  Wire.write(byte(0x81));
14
  err = Wire.endTransmission(adress);
15
  Serial.print("Error: ");
16
  Serial.print(err, DEC);
17
  Serial.print("\n");
18
  
19
  delay(100);
20
  
21
  Wire.requestFrom(64, 3);    
22
23
  Serial.print("Bytes available: ");   Serial.println(Wire.available());
24
  
25
  if(3 <= Wire.available())    
26
  {
27
    reading = Wire.read();  // receive high byte (overwrites previous reading)
28
    Serial.println(reading, DEC);   // print the reading
29
  }

von Johm (Gast)


Lesenswert?

ok habs zum laufen bekommen, die Wire doku is rech spärlich und man muss 
aufpassen was bereits alles schon erledigt wird. hier ein beispiel code 
um ein register auszulesen:
1
int get_data(int adress, int num_bits,int reg_adress, int monitor){
2
  
3
  int reading = 0;
4
5
  Wire.beginTransmission(adress);
6
  //Wire.write(byte(0x80)); // Not necessary as already included in Wire.beginTransmission(adress);
7
  Wire.write(reg_adress);
8
  int err = Wire.endTransmission(adress);
9
  
10
  if (monitor){
11
  Serial.print("Error: ");
12
  Serial.print(err, DEC);
13
  Serial.print("\n");
14
  }
15
16
  Wire.requestFrom(adress, num_bits);    
17
18
  if (monitor){
19
  Serial.print("Bytes available: ");
20
  Serial.println(Wire.available());
21
  }
22
23
  if(num_bits <= Wire.available())    
24
  {
25
    reading = Wire.read();  // receive high byte (overwrites previous reading)
26
    if(monitor){
27
    Serial.print("Content of ");
28
    Serial.print("Register ");
29
    Serial.print(reg_adress, HEX);
30
    Serial.print(" : ");
31
    Serial.print(reading, DEC);   // print the reading
32
    Serial.print("\n"); 
33
    }
34
  }
35
  return reading;
36
37
}

von Jan B. (diphthong)


Lesenswert?

Nach einiger Zeit habe ich mich jetzt auch mal mit den Sensoren 
auseinandergesetzt. Hab nun 12 Stück an einem Bus am Laufen. Das Ändern 
der Adresse ist recht kompliziert und so 10%ig funktioniert das bei mir 
auch nicht - also wenn der Sensor noch nie konfiguriert wurde, lässt 
sich die Adresse mit dieser Funktion problemlos ändern (zu beachten ist 
dabei, dass der Vpp Pin verbunden ist, dieser Pin muss gesetzt werden, 
wenn ins eeprom geschrieben werden soll), wenn die Adresse aber einmal 
auf 0x00 gesetzt wurde, lässt sie sich anscheinend nicht mehr ändern.

Hier auf jeden Fall mein Code, vielleicht hilft es ja irgendjemanden 
weiter. Die Funktion geht automatisch alle möglichen I²C Adressen durch 
und ändert die erste Adresse, die sie findet. Am Bus darf also nur 
dieser eine Sensor angeschlossen sein.
Ist nicht so ganz hübsch programmiert, aber zum Ändern der Adresse 
reicht es. Ist für einen STM32 programmiert, aber sollte sich auch 
einfach auf andere Controller portieren - es muss nur der Pin für Vpp 
sowie die I²C Funktionen angepasst werden. UB_I2C3_WriteByte(a, b, c) 
schreibt das Byte c ins Register b des Sensors mit der Adresse a. 
UB_I2C3_ReadByte(a, b) liest das Register b des Sensors mit der Adresse 
a, UB_I2C3_ReadMultiByte(a, b, c) liest c aufeinanderfolgende Register 
beginnend bei Register b aus dem Sensor mit der Adresse a.
Das sollte es sein. Ich hoffe, das ist soweit verständlich.
1
void delayLoop(volatile uint32_t nCount)
2
{
3
  while(nCount--)
4
  {
5
    asm("NOP");
6
    asm("NOP");
7
    asm("NOP");
8
    asm("NOP");
9
    asm("NOP");
10
  }
11
}
12
13
void sharp_ir_setAdr(uint8_t adr_new)
14
{
15
  for(u8 i = 0; i < 127; i++) //Scan for every adress on bus
16
  {
17
    int16_t distvar = UB_I2C3_ReadMultiByte(i<<1, 0x5E, 2);
18
    if(!(distvar < 0)) //Detected a sensor
19
    {
20
      distvar = (I2C3_DATA[0] << 4) + I2C3_DATA[1];
21
      foutf(&debugOS, "Detected sensor at adr %i, distance: %i\n", i<<1, distvar);
22
23
      //Change Adress:
24
      UB_I2C3_WriteByte(i<<1, 0xEC, 0xFF); //Stage 1
25
      GPIOA->BSRRL = GPIO_Pin_9; //high
26
      delayLoop(20000); //Wait until pin has reached high level
27
      UB_I2C3_WriteByte(i<<1, 0xC8, 0x00); //Stage 2 (E-Fuse map)
28
      UB_I2C3_WriteByte(i<<1, 0xC9, 0x45); //Stage 3 (Address E-Fuse register)
29
      UB_I2C3_WriteByte(i<<1, 0xCD, adr_new); //Stage 4 (new address)
30
      UB_I2C3_WriteByte(i<<1, 0xCA, 0x01); //Stage 5
31
      delayLoop(30000); //Nessesary!!! Wait 500us (see App note)
32
      UB_I2C3_WriteByte(i<<1, 0xCA, 0x00); //Stage 6
33
      GPIOA->BSRRH = GPIO_Pin_9; //low
34
      delayLoop(20000); //Wait until pin has reached low level
35
      UB_I2C3_WriteByte(i<<1, 0xEF, 0x00); //Stage 7
36
      UB_I2C3_WriteByte(i<<1, 0xC8, 0x40);
37
      UB_I2C3_WriteByte(i<<1, 0xC8, 0x00);
38
      UB_I2C3_WriteByte(i<<1, 0xEE, 0x06); //Stage 8
39
      UB_I2C3_WriteByte(i<<1, 0xEC, 0xFF); //Stage 9
40
      UB_I2C3_WriteByte(i<<1, 0xEF, 0x03);
41
      int16_t ret = UB_I2C3_ReadByte(i<<1, 0x27);
42
      UB_I2C3_WriteByte(i<<1, 0xEF, 0x00);
43
      UB_I2C3_WriteByte(i<<1, 0xEC, 0x7F);
44
      //Change Adress end
45
46
      //ret &= 0x1f; //mask only first four bytes
47
48
      delayLoop(200000);
49
50
      int16_t dist_new = UB_I2C3_ReadMultiByte(adr_new, 0x5E, 2); //Check new Adress while reading out to new adress
51
      if(!(dist_new < 0))
52
      {
53
        dist_new = (I2C3_DATA[0] << 4) + I2C3_DATA[1];
54
      }
55
      foutf(&debugOS, "adr changed? check ret: %i, adrNew: %i, newDist: %i\n", ret, adr_new, dist_new);
56
      break;
57
    }
58
    else if(i == 126)
59
    {
60
      foutf(&debugOS, "No sensor detected on bus!");
61
    }
62
  }
63
}

von Mike A. (Gast)


Lesenswert?


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.