Forum: Mikrocontroller und Digitale Elektronik Wii Nunchuk und Atmega88P - Daten nur 0xFF


von A. B. (developer_x)


Lesenswert?

Liebes Forum,
ich bins mal wieder. Ich habe folgendes vor:
Ich habe einen Atmega88P mit UART Verbindung zum PC, ein 
Terminalprogramm namens H-Term, ein originales WII Nun Chuck und einen 
Wii Nun Chuk Adapter.
Ich will die Daten des Nun Chuk auslesen, dazu benutze ich den Code 
folgender Website:
http://davidegironi.blogspot.it/2012/11/avr-atmega-wii-nunchuck-library-01.html#.VBxOlRY2x_R
Ich habe am Code folgendes geändert: F_CPU = 8000000L
(8Mhz ist wirklich richtig, der MC läuft mit dieser Geschwindigkeit)

In meiner Konsole von HTerm erhalte ich folgende Ausgabe von meinem MC:
1
Hello world...<\r>
2
<\n>Reading Byte 0: 255<\r>
3
<\n>Reading Byte 1: 255<\r>
4
<\n>Reading Byte 2: 255<\r>
5
<\n>Reading Byte 3: 255<\r>
6
<\n>Reading Byte 4: 255<\r>
7
<\n>Reading Byte 5: 255<\r>
8
<\n>Reading Byte 6: 255<\r>
9
<\n>Byte 0 sent: 1<\r>
10
<\n>Byte 1 sent: 2<\r>
11
<\n>Byte 2 sent: 3<\r>
12
<\n>Byte 3 sent: 4<\r>
13
<\n>Byte 4 sent: 5<\r>
14
<\n>Byte 5 sent: 6<\r>
15
<\n>Reading Byte 0: 255<\r>
16
<\n>Reading Byte 1: 255<\r>
17
<\n>Reading Byte 2: 255<\r>
18
<\n>Reading Byte 3: 255<\r>
19
<\n>Reading Byte 4: 255<\r>
20
<\n>Reading Byte 5: 255<\r>
21
<\n>Reading Byte 6: 255<\r>
22
<\n>Byte 0 sent: 7<\r>
23
<\n>Byte 1 sent: 8<\r>
24
<\n>Byte 2 sent: 9<\r>
25
<\n>Byte 3 sent: 10<\r>
26
<\n>Byte 4 sent: 11<\r>
27
<\n>Byte 5 sent: 12<\r>
28
<\n>Reading Byte 0: 255<\r>
29
<\n>Reading Byte 1: 255<\r>
30
<\n>Reading Byte 2: 255<\r>
31
<\n>Reading Byte 3: 255<\r>
32
<\n>Reading Byte 4: 255<\r>
33
<\n>Reading Byte 5: 255<\r>
34
<\n>Reading Byte 6: 255<\r>
35
...

Das Problem immer ein und denselben Wert zu empfangen, habe nicht nur 
ich, wenn man im Internet danach sucht stößt man oft auf dieses Problem, 
aber ich habe in all den Threads keine richtige Antwort finden können.

Ich habe auch schon ein zweites Nunchuck ausprobiert, beide 
funktionieren an meiner Konsole definitiv.

Ich habe auch schon Pullup widerstände angeschlossen, habe auch mal das 
Programm ohne angeschlossenen Nunchuk getestet, da hat das Programm es 
aber erkannt, was ja am Quellcode sichtbar ist.

Was genau kann man da jetzt machen, habt ihr noch irgendwie was im 
Internet gefunden bzw. eine Idee?

Danke,
m.f.G.: K.R.

von A. B. (developer_x)


Lesenswert?

Dieser Artikel beispielsweise (hab ich erst jetzt entdeckt)
schließt damit, dass man zwischen den einzelnen Abfragen der Bytes 
pausieren soll, und eine TWI Frequenz von 100kHz nutzen sollte:
http://www.mikroe.com/forum/viewtopic.php?t=11121
1
/*
2
 * get new data
3
 */
4
void wiinunchuck_update() 
5
{
6
  uint8_t i=0;
7
  uint8_t buff[WIINUNCHUCK_READBYTES];
8
  memset(buff, 0, sizeof(buff));
9
10
  //request data
11
  i2c_start_wait(WIINUNCHUCK_ADDR | I2C_WRITE);
12
  i2c_write(0x00);
13
  i2c_stop();
14
  i2c_start_wait(WIINUNCHUCK_ADDR | I2C_READ);
15
  for(i=0; i<WIINUNCHUCK_READBYTES; i++) 
16
  {
17
    if(i==WIINUNCHUCK_READBYTES-1)
18
      buff[i] = i2c_readNak();
19
    else
20
      buff[i] = i2c_readAck();
21
    _delay_us(500); // HIER!
22
  }
23
  i2c_stop();
24
25
  //decodebyte
26
  #if WIINUNCHUCK_DECODEBYTE == 1
27
  for(i=0; i<WIINUNCHUCK_READBYTES; i++) {
28
    buff[i] = wiinunchuck_decode(buff[i]);
29
  }
30
  #endif
31
32
  //record old records
33
  #if WIINUNCHUCK_PULSEBUTTON == 1
34
  wiinunchuck_lastbuttonZ = wiinunchuck_buttonZ;
35
  wiinunchuck_lastbuttonC = wiinunchuck_buttonC;
36
  #endif
37
38
  //get joypad
39
  wiinunchuck_joyX = buff[0];
40
  wiinunchuck_joyY = buff[1];
41
42
  //get button
43
  wiinunchuck_buttonZ = !(buff[5] & 0b00000001);
44
  wiinunchuck_buttonC = !((buff[5] & 0b00000010) >> 1);
45
46
  //get angle
47
  wiinunchuck_angleX = (buff[2] << 2) + ((buff[5] & (0b00000011 << (1*2)) >> (1*2)));
48
  wiinunchuck_angleY = (buff[3] << 2) + ((buff[5] & (0b00000011 << (2*2)) >> (2*2)));
49
  wiinunchuck_angleZ = (buff[4] << 2) + ((buff[5] & (0b00000011 << (3*2)) >> (3*2)));
50
51
  //filter angle
52
  #if WIINUNCHUCK_ANGLEFILTER == 1
53
  wiinunchuck_angleX = wiinunchuck_avaragefilter(wiinunchuck_angleX, (int *)wiinunchuck_avarageangleX);
54
  wiinunchuck_angleY = wiinunchuck_avaragefilter(wiinunchuck_angleY, (int *)wiinunchuck_avarageangleY);
55
  wiinunchuck_angleZ = wiinunchuck_avaragefilter(wiinunchuck_angleZ, (int *)wiinunchuck_avarageangleZ);
56
  #endif
57
}
Es will aber immer noch nicht, Vorschläge?
Ich habe auch schon Pausierungen von 1ms, 2ms und 10ms getestet.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

K. R. schrieb:
> Es will aber immer noch nicht, Vorschläge?
> Ich habe auch schon Pausierungen von 1ms, 2ms und 10ms getestet.

 Antwortet Nunchuk(nie gehört) auch ?
 ACK, NACK richtig ?
 Werden da auch tatsächlich FFs als Antwort gesendet ?
 FF kriegst du ja auch mit Pullup.

 Wenn ja, muss da beim Nunchuk(nie gehört) vielleicht etwas
 voreingestellt werden, irgendwelche Register beschrieben
 oder so was ?

von Oliver R. (orb)


Lesenswert?

Marc Vesely schrieb:
> Nunchuk(nie gehört)

Warum antwortest Du wenn Du keine Ahnung hast worum es geht?
Das Nunchuk ist eine Erweiterung für den WII-Controller mit Joystick, 
Tasten und einem 3-Achsen-Beschleunigungssensor. Angesprochen wird der 
über I2C.

Genaueres findest Du unter 
http://www.cc-zwei.de/wiki/index.php?title=Wii-Nunchuk_Hintergrundwissen

von Nop (Gast)


Lesenswert?

Ist doch Sch***egal.
I2C ist I2C.
Und ich hätte auch darauf getippt das er erst garnicht antwortet und 
deshalb FFen kommen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Oliver R. schrieb:
> Warum antwortest Du wenn Du keine Ahnung hast worum es geht?
 Ich hab schon Ahnung worum es geht, nur kenne ich das Teil nicht.

Nop schrieb:
> Ist doch Sch***egal.
> I2C ist I2C.
 Genau.

Oliver R. schrieb:
> Genaueres findest Du unter...
 Gefunden. Und jetzt ?

von A. B. (developer_x)


Lesenswert?

Also gut, ich bin wieder da.
Ich habe den Artikel vom CCC schon gelesen,
und weiter? Es will immer noch nicht.

Hat denn niemand eine Idee woran es liegen könnte?

von Bernhard F. (bernhard_fr)


Lesenswert?

K. R. schrieb:
> was ja am Quellcode sichtbar ist.

Welcher Quellcode? Ich kann deinen Quellcode nicht sehen...

Ich bin mal dem Link gefolgt. Da findet sich dann auch eine Datei:
avr_lib_wiinunchuck_02.zip
Ist das aus dem Code den du auch hast?
1
/* define CPU frequency in Mhz here if not defined in Makefile */
2
#ifndef F_CPU
3
#define F_CPU 4000000UL
4
#endif
5
6
/* I2C clock in Hz */
7
#define SCL_CLOCK  10000L
8
9
10
/*************************************************************************
11
 Initialization of the I2C bus interface. Need to be called only once
12
*************************************************************************/
13
void i2c_init(void)
14
{
15
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
16
  
17
  TWSR = 0;                         /* no prescaler */
18
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
19
20
}/* i2c_init */

Da scheint ein kleiner Tippfehler zu sein bei der Definition von 
SCL_Clock
K. R. schrieb:
> und eine TWI Frequenz von 100kHz nutzen sollte:

Wenn du den Code so übernommen hast, ist das z.B. nicht erfüllt.
Grundsätzlich kann man den I²C natürlich mit 10kHz nutzen. Aber wenn 
hier 100khz angedacht sind, sollte man das vieleicht versuchen?

Genauso hast du auf die Frage von Marc Vesely nicht geantwortet.
Du sprichst das Wii-Teil (Nuwasauchimmer) mit
1
 //request data
2
  i2c_start_wait(WIINUNCHUCK_ADDR | I2C_WRITE);
3
  i2c_write(0x00);
4
  i2c_stop();
an.
Auf den ersten Blick sieht das nicht so aus, als ob da irgendwo auf ein 
"ACK" bzw "NACK" abgefragt wird... und wenn, wird das überhaupt 
ausgewertet? Hast du das mal verifiziert?
Kannst du dich mal bitte durch die entsprechenden Funktionen wühlen oder 
sie bereitstellen wie sie in deinem Projekt implementiert sind, wenn das 
schon wer anderes für dich machen soll?

von A. B. (developer_x)


Lesenswert?

1. Ja genau diesen Code nutze ich.

2. Ich habe das mit der Frequenz auch schon n paar mal gemacht.

3. Ja, Ack und Nack gibt es zwar als Funktionen
(ganz unten in der Datei twimaster.c)

Wenn du in die wiinunchuk.c guckst, in die letzten beiden Funktionen,
dort werden die verwendet in "wiinunchuck_update()" und 
"wiinunchuck_init()"
Dort kommen die beiden Funktionen auch relativ gut zum Einsatz.
Und dort funktioniert die Kommunikation wie im Tutorial vom CCC

4.
Könntest du mir vielleicht sagen, wie man konkret mit dem Nunchuk 
kommunizieren könnte?
http://www.cc-zwei.de/wiki/index.php?title=Wii-Nunchuk_Hintergrundwissen#Daten.C3.BCbertragung

Bzw. warum funktioniert der Code des Tutorials nicht, ich wüsste nicht 
wie ich es anders machen sollte.


Danke,
m.f.G.: Developer_X

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernhard F. schrieb:
> Auf den ersten Blick sieht das nicht so aus, als ob da irgendwo auf ein
> "ACK" bzw "NACK" abgefragt wird... und wenn, wird das überhaupt
> ausgewertet? Hast du das mal verifiziert?

K. R. schrieb:
> 3. Ja, Ack und Nack gibt es zwar als Funktionen
> (ganz unten in der Datei twimaster.c)

 Das war nicht die Frage.
 Wenn du irgendeine Device auf dem Bus adressierst, muss diese Device
 das auch bestätigen. Und zwar so, dass die adressierte Device SDA auf
 LOW zieht. Das nennt man ACK.
 Wenn keine Device anwesend ist, oder die Adresse nicht richtig ist,
 kriegst du (durch die Pullups an der SDA) FF als Antwort und danach
 NACK (SDA bleibt HIGH).
 Also:
 Woher weisst du ob du ACK oder NACK erhalten hast ?

von A. B. (developer_x)


Lesenswert?

Also, wenn ich das NunChuk raus ziehe und das Programm starte meldet er 
mir dies.

Zum Thema Code, so wird initialisiert:
wiinunchuk.c
1
/*
2
 * init wiinunchuck
3
 */
4
void wiinunchuck_init() {
5
  #if WIINUNCHUCK_I2CINIT == 1
6
  //init i2c
7
  i2c_init();
8
  _delay_us(100);
9
  #endif
10
11
  //standard init: 0x40 -> 0x00
12
  //alternative init: 0xF0 -> 0x55 followed by 0xFB -> 0x00, lets us use 3rd party nunchucks
13
  //no longer need to decode bytes in _nunchuk_decode_byte
14
  i2c_start_wait(WIINUNCHUCK_ADDR | I2C_WRITE);
15
  i2c_write(0xF0);
16
  i2c_write(0x55);
17
  i2c_stop();
18
  i2c_start_wait(WIINUNCHUCK_ADDR | I2C_WRITE);
19
  i2c_write(0xFB);
20
  i2c_write(0x00);
21
  i2c_stop();
22
  //update
23
  wiinunchuck_update();
24
}
So sieht i2c_init aus, in twimaster.c
1
unsigned char i2c_start(unsigned char address)
2
{
3
    uint8_t   twst;
4
5
  // send START condition
6
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
7
8
  // wait until transmission completed
9
  while(!(TWCR & (1<<TWINT)));
10
11
  // check value of TWI Status Register. Mask prescaler bits.
12
  twst = TW_STATUS & 0xF8;
13
  if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
14
15
  // send device address
16
  TWDR = address;
17
  TWCR = (1<<TWINT) | (1<<TWEN);
18
19
  // wail until transmission completed and ACK/NACK has been received
20
  while(!(TWCR & (1<<TWINT)));
21
22
  // check value of TWI Status Register. Mask prescaler bits.
23
  twst = TW_STATUS & 0xF8;
24
  if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
25
26
  return 0;
27
28
}/* i2c_start */

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

K. R. schrieb:
> Also, wenn ich das NunChuk raus ziehe und das Programm starte meldet er
> mir dies.
 Was ?

 Und noch:
1
  #if WIINUNCHUCK_I2CINIT == 1
2
  //init i2c
3
  i2c_init();
4
  _delay_us(100);
5
  #endif

 Soll heissen:
 Wenn WIINUNCHUCK_I2CINIT fehlerhaft, mache normales I2C_Init.
 Danach wird aber auch nicht auf Resultat abgefragt.

: Bearbeitet durch User
von A. B. (developer_x)


Lesenswert?

Lol. Ich habe den kompletten Code durchsucht, tatsächlich dürfte
keine Fehlermeldung kommen, allerdings bekomme ich tatsächlich folgenden 
String übermittelt:
1
<\n>Could not start TWI Bus for READ<\r>

Vielleicht ist der Atmega so schlau dass er standardmäßig sowas sendet.

Ich bin echt am Ende, und weiß net weiter woran es liegen könnte.

Wenn ich mitten im laufenden Programm das Nunchuk entferne kommt diese 
Fehlermeldung, sobald der Nunchuk wieder drin ist, kommen diese "FF" 
Bytes.

von A. B. (developer_x)


Lesenswert?

mh

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.