Forum: Mikrocontroller und Digitale Elektronik Nunchuk-Problem - komische Werte


von Stefan (Gast)


Lesenswert?

Hallo!
Ich hoffe, einer von Euch kann mir sagen wo ich hier den Denkfehler 
habe.. Ich glaube, dass ich bei dem Auslesen der Bytes aus den Registern 
einen Fehler mache in Routine getnunchuk().
Es ist aber richtig, dass in einem Register 16Bytes enthalten sind, ja?? 
Hatte bisher über I²C immer nur ein Byte pro Register.
Naja. Jedenfalls kann ich schon erkennen, on die Tasten gedrückt werden. 
Mehr jedoch nicht..

Das hier ist mein Code für einen ATMEGA88P


1
#define F_CPU 18432000L
2
#define myBRR0 9   //115200 bps 18.432MHz
3
4
#include <avr/io.h>
5
#include <stdint.h>
6
#include <stdlib.h>
7
#include <inttypes.h>
8
#include <avr/signal.h>
9
#include <avr/interrupt.h>
10
#include <avr/delay.h>
11
12
13
14
unsigned char buffer[10];
15
long data=0;
16
17
//Routinen
18
void uart_init(void)
19
{
20
    UBRR0H = (unsigned char)(myBRR0 >> 8);
21
      UBRR0L = (unsigned char)myBRR0;  
22
    UCSR0B = (1<<TXEN0);
23
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); // 8data, 1stopbit   
24
}
25
26
27
void uart_send(unsigned char data)
28
{
29
  while (!(UCSR0A & (1<<UDRE0)) );
30
  UDR0 = data;
31
}
32
33
  
34
35
36
void uart_send_string(char *datastring)
37
{
38
   for (;*datastring !='\0';datastring++)
39
  {    
40
    loop_until_bit_is_set (UCSR0A, UDRE0);  
41
    UDR0=*datastring;
42
  }   
43
}
44
45
46
void twi_init(void)
47
{
48
  PRR&=0x7F;
49
  TWBR=84;                                    //SCL=100@ Prescaler 1,
50
  TWSR&=0xFC;
51
  TWCR=0x04;                                          //Kein Interrupt; TWI aktivieren 0000 0100
52
}
53
54
void twi_transmit(char address, char reg, char data)//Subroutine fuer Datenuebertragung
55
{
56
  TWCR = 0xA4;                                // Start 1010 0100 TWINT, TWSTA, TWEN high
57
  while(!(TWCR & 0x80));                      // warten bis die TWINT low ist, heisst Transmission fertig 
58
  TWDR = address;                             // Adresse vom Sensor laden
59
  TWCR = 0x84;                                // Transmission anfangen (TWINT auf high setzen)
60
  while(!(TWCR & 0x80));                      // warten bis die TWINT low ist, heisst Transmission fertig
61
  TWDR = reg;                                 // Register Nr. laden
62
  TWCR = 0x84;                                // Transmission anfangen (TWINT auf high setzen)
63
  while(!(TWCR & 0x80));                      // warten bis die TWINT low ist, heisst Transmission fertig
64
  TWDR = data;                                // Befehl fuer Art der Messung laden
65
  TWCR = 0x84;                                // Transmissuion anfangen (TWINT auf high setzen)
66
  while(!(TWCR & 0x80));                      // warten bis die TWINT low ist, heisst Transmission fertig
67
  TWCR = 0x94;                                // Stopp 1001 0100 TWINT, TWSTO, TWEN high
68
69
}
70
71
void get_nunchuk(char address, char reg)       //Subroutine fuer Datenempfang
72
{
73
unsigned int read_data[16];
74
75
   TWCR = 0xA4;                                     // Start 1010 0100 TWINT, TWSTA, TWEN high
76
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig  
77
   TWDR = address;                                  // Adresse vom Sensor laden
78
   TWCR = 0x84;                                     // Transmission anfangen (TWINT auf high setzen)
79
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig 
80
   TWDR = reg;                                      // Register Nr. laden, von dem gelesen werden soll
81
   TWCR = 0x84;                                     // Transmission anfangen (TWINT auf high setzen)
82
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig 
83
84
 for (int row=0;row<16;row++)
85
{  
86
   TWCR = 0xA4;                                     // Start 1010 0100 TWINT, TWSTA, TWEN high (repeated start)
87
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig 
88
   TWDR = address+1;                                // Adresse vom Sensor mit Read bit laden (SLA+R)
89
   TWCR = 0xC4;                                     // Transmission anfangen ( TWINT high TWEA high)
90
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig 
91
   TWCR = 0x84;                                     // Transmission anfangen mit NACK (TWINT auf high setzen TWEA low)
92
   while(!(TWCR & 0x80));                           // warten bis die TWINT low ist, heisst Transmission fertig 
93
   read_data[row] = TWDR;                           // Messergebniss in die Variable speichern
94
   
95
}
96
97
   TWCR = 0x94;                                     // Stopp 1001 0100 TWINT, TWSTO, TWEN high
98
99
100
   for (int i=0;i<16;i++)
101
  {
102
    read_data[i]  = ((read_data[i]^0x17)+0x17);         //XOR-Verschlüsselung
103
    uart_send_string(itoa(read_data[i],buffer,10));           //Wert übermitteln
104
    uart_send_string(",");
105
  }  
106
107
}
108
109
110
111
112
113
int main(void)
114
{
115
  OSCCAL=0x9f;
116
  uart_init();
117
  
118
  uart_send(0x0C);
119
    twi_init();
120
121
  DDRD |= (1<<PD1)|(1<<PD2);
122
  sei();    // Enable Interrupts
123
124
  twi_transmit(0xA4, 0x40, 0x00);
125
  _delay_ms(1);
126
127
128
129
   while(1)
130
   {
131
    
132
    uart_send_string("$Nunchuk,");
133
    get_nunchuk(0xA4, 0x00);
134
135
    uart_send(0x0D);
136
    uart_send(0x0A);
137
  
138
139
  }
140
141
return 0;
142
}

Im Leerlauf bekomme ich folgendes:
$Nunchuk,255,256,255,256,255,256,255,256,255,256,255,259,255,256,255,256 
,

drücke ich die Tasten kommt sowas hier:
$Nunchuk,255,256,255,256,255,256,255,256,255,256,255,256,255,256,255,256 
,
                                                     ***
Ansonsten ändert sich absolut nichts :-(
Ich kann auch Register 20 auslesen und bekomme da viele 
untgerschiedliche Werte.. Also das abfangen der Bytes scheint ja doch 
irgendwie zu klappen, aber es ist der Wurm drin...

von Peter Z. (hangloose)


Lesenswert?

Bei mir funktionierte es so... vielleicht hilfts ja

1
//------------------------------------------------------------------------------
2
//         Nunchuck Initialisieren
3
//------------------------------------------------------------------------------
4
void Wii_Controller_init(void)
5
{
6
7
i2c_start();
8
i2c_write(0xa4); 
9
i2c_write(0x40);
10
i2c_write(0x00);
11
i2c_stop();
12
    
13
}
14
15
//------------------------------------------------------------------------------
16
//         Wii "Nunchuck" und "Classic Controller" Daten decodieren
17
//------------------------------------------------------------------------------
18
unsigned char Wii_Controller_decode_byte (unsigned char x)
19
{
20
x = (x ^ 0x17) + 0x17;
21
return x;
22
}
23
24
//------------------------------------------------------------------------------
25
//         Wii Nunchuck und Classic Controller Auslesen
26
//------------------------------------------------------------------------------
27
void Wii_Controller_read(void)
28
{
29
30
char x;
31
32
i2c_start();
33
i2c_write(0xa4); 
34
i2c_write(0x00);
35
i2c_stop();
36
      
37
i2c_start();
38
i2c_write(0xa4); 
39
i2c_start();
40
i2c_write(0xa4 | 1);
41
42
i2c_tx[0]=i2c_read(1);
43
i2c_tx[1]=i2c_read(1);
44
i2c_tx[2]=i2c_read(1);
45
i2c_tx[3]=i2c_read(1);
46
i2c_tx[4]=i2c_read(1);
47
i2c_tx[5]=i2c_read(0);        
48
i2c_stop();
49
        
50
//Daten Decodieren
51
for(x=0;x<6;x++){
52
    i2c_tx[x]=Wii_Controller_decode_byte(i2c_tx[x]);
53
        
54
}

von Stefan (Gast)


Lesenswert?

Hallo.. Ich weiß leider nicht wie Deine Routinen aussehen,die du 
aufrufst.warum meins  nicht geht konnte ich noch nicht klären.hab auch 
schon ein zweites nunchuk getestet und es hilft nix.

von Peter Z. (Gast)


Lesenswert?

Die Software I2C Routinen sind vom Codevision Compiler. Spielt aber auch 
nicht wirklich eine Rolle. Du siehst doch im Code was du senden und 
empfangen musst...

von Stefan (Gast)


Lesenswert?

Aber ist es richtig so viele Bytes ohne repeatet Start zu empfangen? Und 
vor dem adresse+R noch ein adresse+W senden?? Ist das vom Nunchuk 
gefordert?

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Hi!
So, ich hatte ja etwas Zeit seitdem es geklappt hat und ich habe mal das 
Original-Nunchuk mit dem Nachbau (ebay 7€) verglichen... sind in dem 
Nachbau Quecksilberschalter drin??? :-)   Naja, zumindest ist die 
Auflösung nicht wirklich vergleichbar mit dem Original.
Habt ihr da ähniche Erfahrungen gemacht?? Oder gibt es da 
unterschiedliche Modelle?
Zur Messung: Aufzeichnung mit Matlab, Drehung frei Hand, aber die 
Ausbrüche bei dem Nachbau liegen nicht unbedingt an der Bewegung (siehe 
Original).

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.