Archiv verlassen und diese Seite im Standarddesign anzeigen : Wii Nunchuck an Arduino
hallo,
ich versuche erfolglos, einen Wii Nunchuck an Arduino (3.3V ARM Cortex) auszulesen. Ich habe 2 Nunchucks ausprobiert, beide verhalten sich identisch.
Vom i2c Scanner wird jeder einzelne bei Adresse 0x52 erkannt, sowohl bei 100kHz als auch bei 400kHz. Pullups sind jew. 4.7k, an den Nunchucks oder i2c Bus liegt es also nicht. (Auch alternativ testweise angeschlossener MCP6050 funktioniert auf i2c)
Spannungsversorgung über 3.3V und GND Buchse.
Seltsamerweise aber liefert der i2c-Scanner auch gleichzeitig i2c Devices an x01 x02 x03 x04 x05 x06 x07 (zusätzlich zu x52), die verschwinden, wenn er abgesteckt ist.
Es sind original-Nunchucks aus einem Wii-Set (IIRC).
Egal mit welchem Programm und welcher Lib ich versuche, Joy, Acc und Btns auszulesen: immer nur 255 oder 1 oder Fantasiewerte, nichts zuverlässiges oder reproduzierbares. In versciedenen Foren wird ähnliches beschrieben, ohne verwertbare Lösung
(z.B. https://www.makerblog.at/2016/01/wii-nunchuk-controller-am-arduino-teil-1/ mit https://github.com/timtro/wiinunchuck-h )
bei anderen Testprogrammen, z.B. https://github.com/infusion/Fritzing/blob/master/Nunchuk/demo.ino gibt es auch ganz wirre Werte (ruhig liegender Nunchuck, aber auch keine Änderung wenn bewegt/gedrückt):
joy: -127, -128 acc:-512, -512, -512 but:1, 1
joy: -127, -128 acc:-512, -510, 144 but:1, 1
joy: -127, -128 acc:-512, -512, -512 but:1, 1
joy: -127, -125 acc:-512, -512, -512 but:1, 1
joy: -127, -128 acc:-512, -512, -512 but:1, 1
joy: -127, -128 acc:-509, 511, 511 but:0, 0
joy: 128, 127 acc:511, 511, 511 but:0, 0
joy: 128, -3 acc:4, -1, -470 but:1, 1
joy: 54, 49 acc:-273, 395, -395 but:0, 1
joy: 101, -97 acc:-9, -345, -7 but:0, 1
joy: 2, -1 acc:-472, 195, 214 but:0, 1
Wer kennt eine Wii Nunchuck Arduino Lib bzw. ein Testprogramm, das er schon erfolgreich verwendet hat?
es gibt da wohl 2 Varianten
versuchs mal mit dem workaround den ich im arduino forum gefunden habe (Zusammengefasst übersetzt: In der init muss eine andere Sequenz gesendet werden)
https://forum.arduino.cc/index.php?topic=45924.msg333160#msg333160
(https://forum.arduino.cc/index.php?topic=45924.msg333160#msg333160)
leider auch nicht, gibt auch nur:
2 joy:255,255 acc:258,258,258 but:1,1
3 joy:255,255 acc:258,258,258 but:1,1
4 joy:255,255 acc:258,258,258 but:1,1
5 joy:255,255 acc:258,258,258 but:1,1
6 joy:255,255 acc:258,258,258 but:1,1
7 joy:255,255 acc:258,258,258 but:1,1
8 joy:255,255 acc:258,258,258 but:1,1
9 joy:255,255 acc:258,258,258 but:1,1
10 joy:255,255 acc:258,258,258 but:1,1
11 joy:255,255 acc:258,258,258 but:1,1
12 joy:255,255 acc:258,258,258 but:1,1
13 joy:255,255 acc:258,258,258 but:1,1
14 joy:255,255 acc:258,258,258 but:1,1
15 joy:255,255 acc:258,258,258 but:1,1
und zwischendurch mal völlig unmotoviert, ohne mein Zutun:
113 joy:255,255 acc:255,255,170 but:0,0
114 joy:0,0 acc:0,0,0 but:0,0
115 joy:0,0 acc:0,1,164 but:0,0
116 joy:0,0 acc:0,0,0 but:0,0
117 joy:0,3 acc:0,0,0 but:0,0
118 joy:0,0 acc:0,0,0 but:0,0
119 joy:0,0 acc:3,258,258 but:1,1
120 joy:255,255 acc:258,258,258 but:1,1
#include <Wire.h>;
void setup(){
Serial.begin(115200);
//nunchuck_setpowerpins();
nunchuck_init();
Serial.print("Nunchuck ready\n");
}
void loop(){
nunchuck_get_data();
nunchuck_print_data();
delay(1000);
}
//================================================== =======================//
//Do not modify!!!!!!!!
//================================================== =======================//
//
// Nunchuck functions
//
static uint8_t nunchuck_buf[6]; // array to store nunchuck data,
// Uses port C (analog in) pins as power & ground for Nunchuck
static void nunchuck_setpowerpins() {
/*
#define pwrpin PC3
#define gndpin PC2
DDRC |= _BV(pwrpin) | _BV(gndpin);
PORTC &=~ _BV(gndpin);
PORTC |= _BV(pwrpin);
*/
delay(100); // wait for things to stabilize
}
// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{ /*
Wire.begin(); // join i2c bus as master
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write(0x40); // sends memory address
Wire.write(0x00); // sends sent a zero.
Wire.endTransmission(); // stop transmitting
*/
byte cnt;
uint8_t ctrlr_type[6];
Wire.begin();
// init controller
delay(1);
Wire.beginTransmission(0x52); // device address
Wire.write(0xF0); // 1st initialisation register
Wire.write(0x55); // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.write(0xFB); // 2nd initialisation register
Wire.write(0x00); // 2nd initialisation value
Wire.endTransmission();
delay(1);
// read the extension type from the register block
Wire.beginTransmission(0x52);
Wire.write(0xFA); // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6); // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
if (Wire.available()) {
ctrlr_type[cnt] = Wire.read(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
}
}
Wire.endTransmission();
delay(1);
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.write(0xF0); // crypto key command register
Wire.write(0xAA); // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.write(0x40); // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
Wire.write(0x00); // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.write(0x40); // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
Wire.write(0x00); // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.write(0x40); // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
Wire.write(0x00); // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init
}
// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request() {
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write(0x00); // sends one byte
Wire.endTransmission(); // stop transmitting
}
// Receive data back from the nunchuck,
// returns 1 on successful read. returns 0 on failure
int nunchuck_get_data() {
int cnt=0;
Wire.requestFrom (0x52, 6); // request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.read());
cnt++;
}
nunchuck_send_request(); // send request for next data payload
// If we recieved the 6 bytes, then go print them
if (cnt >= 5) {
return 1; // success
}
return 0; //failure
}
// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits. That is why I
// multiply them by 2 * 2
void nunchuck_print_data() {
static int i=0;
int joy_x_axis = nunchuck_buf[0];
int joy_y_axis = nunchuck_buf[1];
int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;
int z_button = 0;
int c_button = 0;
// byte nunchuck_buf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((nunchuck_buf[5] >> 0) & 1)
z_button = 1;
if ((nunchuck_buf[5] >> 1) & 1)
c_button = 1;
if ((nunchuck_buf[5] >> 2) & 1)
accel_x_axis += 2;
if ((nunchuck_buf[5] >> 3) & 1)
accel_x_axis += 1;
if ((nunchuck_buf[5] >> 4) & 1)
accel_y_axis += 2;
if ((nunchuck_buf[5] >> 5) & 1)
accel_y_axis += 1;
if ((nunchuck_buf[5] >> 6) & 1)
accel_z_axis += 2;
if ((nunchuck_buf[5] >> 7) & 1)
accel_z_axis += 1;
Serial.print(i,DEC);
Serial.print("\t");
Serial.print("joy:");
Serial.print(joy_x_axis,DEC);
Serial.print(",");
Serial.print(joy_y_axis, DEC);
Serial.print(" \t");
Serial.print("acc:");
Serial.print(accel_x_axis, DEC);
Serial.print(",");
Serial.print(accel_y_axis, DEC);
Serial.print(",");
Serial.print(accel_z_axis, DEC);
Serial.print("\t");
Serial.print("but:");
Serial.print(z_button, DEC);
Serial.print(",");
Serial.print(c_button, DEC);
Serial.print("\r\n"); // newline
i++;
}
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x) {
x = (x ^ 0x17) + 0x17;
return x;
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_zbutton() {
return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_cbutton() {
return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo
}
// returns value of x-axis joystick
int nunchuck_joyx() {
return nunchuck_buf[0];
}
// returns value of y-axis joystick
int nunchuck_joyy() {
return nunchuck_buf[1];
}
// returns value of x-axis accelerometer
int nunchuck_accelx() {
return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data
}
// returns value of y-axis accelerometer
int nunchuck_accely() {
return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data
}
// returns value of z-axis accelerometer
int nunchuck_accelz() {
return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data
}
puuhh da findet sich irgendwie nicht viel nützliches drüber
sicher dass du nicht eventuell data und clock vertauscht hast?!
als schuss ins blaue: tausch sonst einfach mal die data und clock pins, mehr als datensalat passiert da nicht :)
edit: quark was red ich da ... der scanner hats ja erkannt XD
https://www.hackster.io/infusion/using-a-wii-nunchuk-with-arduino-597254
das ist leider ein englischer post aber der beschäftigt sich recht detailliert mit dem ding, vielleicht kannst du damit dein programm nachverfolgen und debuggen!?
nee, i2c läuft ja, auch per i2c-scanner erkannt
(getestet: umgestöpselt gehts gar nicht)
das Programm von dem Post https://www.hackster.io/infusion/using-a-wii-nunchuk-with-arduino-597254 habe ich ja auch erfolglos ausprobiert
PS, ich nutze so einen Adapter:
https://www.ebay.de/sch/i.html?_from=R40&_trksid=m570.l1313&_nkw=232700702990&_sacat=0
Hallo HaWe,
schau mal bitte hier rein:
https://allaboutmcu.wordpress.com/2012/11/05/interfacing-a-wii-nunchuck-with-a-dspic30f4011-using-i2cabout-time-ps-this-is-a-draft/
Auszug:
This will not work with the Wii nunchuck, even though we know its write address(which is 52 by the way, A4 in hex).
For the communication to work – after sending the write adress for the first time – “0x40” must be sent before 0.
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0x40);
MasterWriteI2C(0x00);
StopI2C();
And again for the knockoff versions of the nunchuck it’s different once more,
there are not only one but TWO handshakes this time around, the cheeky bastards:
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0xF0);
MasterWriteI2C(0x55);
StopI2C();
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0xFB);
MasterWriteI2C(0x00);
StopI2C();
Siro
Hallo HaWe,
schau mal bitte hier rein:
https://allaboutmcu.wordpress.com/2012/11/05/interfacing-a-wii-nunchuck-with-a-dspic30f4011-using-i2cabout-time-ps-this-is-a-draft/
Auszug:
This will not work with the Wii nunchuck, even though we know its write address(which is 52 by the way, A4 in hex).
For the communication to work – after sending the write adress for the first time – “0x40” must be sent before 0.
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0x40);
MasterWriteI2C(0x00);
StopI2C();
And again for the knockoff versions of the nunchuck it’s different once more,
there are not only one but TWO handshakes this time around, the cheeky bastards:
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0xF0);
MasterWriteI2C(0x55);
StopI2C();
StartI2C();
IdleI2C();
MasterWriteI2C(0xA4);
MasterWriteI2C(0xFB);
MasterWriteI2C(0x00);
StopI2C();
Siro
das kann doch nicht richtig sein - die Nunchuk adresse ist 0x52, nicht 0xA4 und nicht (DEC) 52 !
0x52 wird ja auch von meinem i2c Scanner erkannt...!
Scanning at 400k
0 ** 01 02 03 04 05 06 07 -- -- -- -- -- -- -- --
1 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
4 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
5 -- -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
6 -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
7 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- **
Scan result for i2cclock 400k
found: 9 devices
das einzige, wirklich seltsame ist, dass außer x52 immer auch x01...x07 erkannt werden...
(x68 ist ein zusätzlicher MPU6050 zu Testzwecken)
hallo,
ich versuche erfolglos, einen Wii Nunchuck an Arduino (3.3V ARM Cortex) auszulesen. Ich habe 2 Nunchucks ausprobiert, beide verhalten sich identisch.
Vom i2c Scanner wird jeder einzelne bei Adresse 0x52 erkannt, sowohl bei 100kHz als auch bei 400kHz. Pullups sind jew. 4.7k, an den Nunchucks oder i2c Bus liegt es also nicht. (Auch alternativ testweise angeschlossener MCP6050 funktioniert auf i2c)
Spannungsversorgung über 3.3V und GND Buchse.
Seltsamerweise aber liefert der i2c-Scanner auch gleichzeitig i2c Devices an x01 x02 x03 x04 x05 x06 x07 (zusätzlich zu x52), die verschwinden, wenn er abgesteckt ist.
Es sind original-Nunchucks aus einem Wii-Set (IIRC).
Ich benutze zwar kein Arduino, hab aber schon einen Nunchuk (Clone) verschiedentlich zum Laufen gebracht. Wenn man einen funktionierenden I2C Master hat, ist das kein Hexenwerk. Ist halt ein I2C Device wie tausend andere auch. Ich zeig den Code mal in Portionen, damit ich dazwischen ein paar Erläuterungen machen kann.
#include "I2cMaster.h"
#define NUNCHUK_ADDR 0x52
typedef struct {
int x;
int y;
int acc_x;
int acc_y;
int acc_z;
int c_button;
int z_button;
} nunchuk_data_t;
int NunchukInit(void);
int NunchukStart(void);
int NunchukRead(nunchuk_data_t *data);
Die Adresse ist natürlich 0x52, nur die Arduino-Jünger popeln da immer noch das R/W-Bit mit rein, weil die wohl die I2C-Spec nie gelesen haben oder weil ihnen die Aufteilung eines Bytes in verschiedene Bitfelder intellektuell zu anspruchsvoll ist. Hier wird nur die Struktur für das Ergebnis beschrieben. Das packt man gerne in ein Headerfile.
int NunchukInit(void) {
I2cStart();
if(I2cWriteAddress(NUNCHUK_ADDR, I2C_WRITE)){
I2cStop();
return -1;
}
if(I2cWriteByte(0x40)){
I2cStop();
return -1;
}
if(I2cWriteByte(0x00)){
I2cStop();
return -1;
}
I2cStop();
return 0;
}
Das ist meine Init-Funktion. Hier werden dann die Funktionen aus meiner I2C lib verwendet. I2CStart() bzw I2CStop() erzeugt die entsprechenden Zustände auf dem Bus. I2cWriteAddress() setzt aus der Adresse und R/W das erste Byte des I2C Telegramms zusammen. Die Funktion liefert ACK/NAK zurück, wie es vom Bus kommt. Kommt NAK, wird die Sache abgebrochen. Bei I2cWriteAddress() heißt das typischerweise, es gibt kein Device auf dieser Adresse. So testen die I2C Scanner. Dann wird in das Nunchuk-Register mit der Adresse 0x40 eine 0 geschrieben, um den Nunchuk zu starten. Das findet man in Beispielen im Netz.
Das erste Byte nach dem Adressbyte bei einem Write setzt bei I2C typischerweise den Registerpointer im Device. Hier wird er auf 0 gesetzt.
int NunchukStart(void) {
// set register address
I2cStart();
if(I2cWriteAddress(NUNCHUK_ADDR, I2C_WRITE)){
I2cStop();
return -1; // nunchuk didn't respond
}
if(I2cWriteByte(0x00)){
I2cStop();
return -1;
}
I2cStop();
}
Die interessanten Register im Nunchuk liegen ab Adresse 0, daher muß NunchukStart() vor jedem Auslesen ausgeführt werden. Beim Interpretieren der gelesenen Daten gibt es ein Problem. Die Datenbytes sind "verschlüsselt". Es ist aber eine wirklich simple Funktion, die man auch im Netz findet und bei mir NunchukDecode() heißt.
int NunchukDecode(int data){
return ((data ^ 0x17) + 0x17) & 0xff;
}
int NunchukRead(nunchuk_data_t *data) {
int temp;
I2cStart();
if (I2cWriteAddress(NUNCHUK_ADDR, I2C_READ)) {
I2cStop();
return -1; // nunchuk didn't respond
}
data->x = NunchukDecode(I2cReadByte(I2C_ACK));
data->x -= 128; // center the value
data->y = NunchukDecode(I2cReadByte(I2C_ACK));
data->y -= 128;
data->acc_x = NunchukDecode(I2cReadByte(I2C_ACK)) << 2;
data->acc_y = NunchukDecode(I2cReadByte(I2C_ACK)) << 2;
data->acc_z = NunchukDecode(I2cReadByte(I2C_ACK)) << 2;
temp = NunchukDecode(I2cReadByte(I2C_NACK));
I2cStop();
// decode the last byte
if(temp & 0x01)
data->z_button = 0;
else
data->z_button = 1;
if(temp & 0x02)
data->c_button = 0;
else
data->c_button = 1;
data->acc_x |= (temp >> 2) & 0x03;
data->acc_y |= (temp >> 4) & 0x03;
data->acc_z |= (temp >> 6) & 0x03;
return 0;
}
Hier wird ein Byte nach dem anderen eingelesen, dekodiert und in die Struktur gepackt. Zum Schluß wird das letzte Byte gelesen und die Bits ausgewertet. Wenn ich mich recht erinnere, ist der Nunchuk pingelig, wenn das letzte Byte nicht mit NAK quittiert wird. Er bleibt dann hängen und blockiert den Bus.
Hier noch ein Kommentar zu einer der gezeigten Arduino-lib. Dort wird nie ACK ausgewertet sondern immer weiter gemacht. Das führt dazu, daß selbst wenn der BUS leer ist, immer 0xff bzw 255 gelesen wird. Die Pullups sorgen für eine 1 auf dem Bus. Wenn ich also lese: "ich bekomme immer 255" oder auch andere Zweierpotenzen, die sich aus Umrechnungen ergeben können, weiß ich, daß der Bus klemmt oder das Device nicht angesprochen wird ohne in den Code zu schauen oder das Scope anzumachen.
MfG Klebwax
hallo,
vielen Dank für deine Infos!
Was jetzt ntl super wäre, wenn man das alles in einen lauffähigen Arduino-kompatiblen Code packen könnte (ich selber kann es wirklich nicht).
Die Arduino Wire class für i2c ist ja schon ein bisschen eigen, aber grundsätzlich ist mir i2c sowieso recht unverständlich: ich selber habe es noch NIE geschafft, irgendeinen i2c-Code für ein Device selber zu schreiben, weder in Arduinisch noch mit Raspi-C/wiringPi noch in Lego-Mindstorms-NXC...)
(PS, ein Scope besitze ich ntl auch nicht, ich bin absolut kein Techniker und habe auch überhaupt keine Ahnung, wie so was funktioniert oder wie man damit umgeht: alles was ich habe ist ein 5EUR Multimeter für Notfälle ;) )
Update:
dieser Code funktioniert bei einem Arduino Uno und Mega, aber NICHT bei einem Arduino Due (M3) oder Adafruit M4, dort ständig Fehlmessungen:
periodisch immer solche Blöcke:
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
ohne mein Zutun dann plötzlich:
Data,255,255,255,255,255,0,100
Data,0,0,0,0,0,100,100
Data,0,0,0,0,1,100,100
Data,32,0,0,0,0,100,100
Data,0,0,3,0,0,100,100
Data,0,0,0,0,0,100,100
Data,0,0,0,0,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,125,129,127,100,0
Data,176,181,177,59,226,0,100
Data,125,228,31,125,41,100,0
Data,125,129,127,10,176,0,100
Data,177,59,226,29,125,100,100
Data,31,125,41,126,255,0,0
dann danach plötzlich wieder ohne mein Zutun:
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
Data,255,255,255,255,255,0,0
und absolut keine Beeinflussung der Ausgaben durch Tastendrücke, Potibewegung oder Wii-Bewegung
Sourcecode:
/*
* Nunchuk auslesen
*
* funktioniert mit original Nunchuck
* UND mit Wirelesse Nunchuck
*
* Pinbelegung:
* 3.3V (Kabel rot)
* GND (Kabel weiß)
* A4 (Kabel grün)
* A5 (Kabel gelb)
*/
#include <Wire.h>
const int dataLength = 6; // numer ob bytes to request
static byte rawData[dataLength]; // array to store nunchuck data
// construct to create an enumerated list of the sonsor values returned from the nunchuck
enum nunchuckItems { joyX, joyY, accelX, accelY, accelZ, btnZ, btnC };
void setup()
{
Serial.begin(57600);
delay(500);
Serial.println("Labels,Xjoy,Yjoy,Xaccel,Yaccel,Zaccel,Z-btn,C-btn,");
delay(500);
nunchuckInit();
}
void loop()
{
if (nunchuckRead() == true)
{
Serial.print("Data,"); // Data-Header
Serial.print(getValue(joyX), DEC);
Serial.write(",");
Serial.print(getValue(joyY), DEC);
Serial.write(",");
Serial.print(getValue(accelX), DEC);
Serial.write(",");
Serial.print(getValue(accelY), DEC);
Serial.write(",");
Serial.print(getValue(accelZ), DEC);
Serial.write(",");
Serial.print(getValue(btnZ), DEC);
Serial.write(",");
Serial.print(getValue(btnC), DEC);
// Serial.write(",0");
// Serial.write("\n");
Serial.println();
}
delay(20); // time between redraws
}
void nunchuckInit()
{
Wire.begin(); // join i2c bus as master
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0xF0); // send memory adress
Wire.write((byte)0x55); // send a zero
if (Wire.endTransmission() == 0) {
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0xA5); // send memory adress
Wire.write((byte)0x00);
} // stop transmission
}
// send a request for data to the nunchuck
static void nunchuckRequest()
{
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0x00); // send one byte
Wire.endTransmission(); // stop transmission
}
// receive data back from the nunchuck,
// returns true if read successful, else false
boolean nunchuckRead()
{
int cnt=0;
Wire.requestFrom (0x52, dataLength); // request data from nunchuck
while (Wire.available ()) {
rawData[cnt] = Wire.read();
cnt++;
}
nunchuckRequest(); // send request for next dat payload
if (cnt >= dataLength)
return true; // success if all 6 bytes received
else
return false; // failure
}
// encode data to format that most wiimote drivers accept
// static char nunchuckDecode (byte x) {
// return (x ^ 0x17) + 0x17;
// return x;
// }
int getValue(int item) {
if (item <= accelZ)
return (int)rawData[item];
else if (item == btnZ)
return bitRead(rawData[5], 0) ? 0: 100;
else if (item == btnC)
return bitRead(rawData[5], 1) ? 0: 100;
}
Nachdem alle anderen bisher von mir verwendeten i2c-Geräte (OLED SSD1306, MPU6050, CMPS11, CMPS12, BME280, BMP280, PCF8574, MCP9808, ADS1115) auf allen meinen ARMs (Due=M3, Itsybitsy M0, Feather M4) funktionieren, auch bei jeder Bus-Geschwindigkeit (insb. 100kHz und 400kHz), und der Scanner auch alle Geräte findet, kann es nicht an der i2c-Verbindung oder dem i2c-Bus liegen, und nachdem der Nunchuk an AVR mit dem Code läuft, sind auch der Nunchuk ok und auch der Code grundsätzlich ok.
Was sein kann wegen AVR/ARM Unterschieden, ist:
die ARMs laufen mit 3.3v, allerdings ist auch der Nunchuk für 3.3V ausgelegt (5V sind an sich zu hoch, werden aber wohl toleriert).
AVRs verwenden als "char" signed char, während ARMs bei "char" unsigned char verwenden.
Ich sehe aber noch nicht, wo das im Code (zB. dem obigen) zu Konflikten führen könnte.
Was jetzt weiterhelfen würde zur Bestätigung und zum Debuggen:
wenn jemand einen funktionierenden Nunchuk besitzt und einen Arduino Due (oder Adafruit M4) und dann guckt, ob er meine Fehlmessungen z.B. mit dem Code von uxomm bestätigen kann.
was für eine clock-rate hat dein i2c eigentlich?! nicht dass der 400kHz versucht und dein nunchuck einfach nicht mitkommt?
ich konnte jetzt konkret keine infos dazu in den vorherigen posts finden oder habs übersehen
vielleicht muss tdu einfach mal einen gang zurückschalten :)
wie gesagt, ich habe grundsätzlich 100kHz und 400kHz mit anderen Geräten und auch einem Scanner (inkl. Nunchuk) einwandfrei getestet, aber per default verwendet Arduino immer 100kHz (auch im Beisp. oben). Auch die AVRs laufen mit dem Code also einwandfrei mit 100kHz mit dem Nunchuk-Code, daran kann es also nicht liegen.
Auch die Pullups waren in beiden Fällen je 4k7.
Auch die AVRs laufen mit dem Code also einwandfrei mit 100kHz mit dem Nunchuk-Code, daran kann es also nicht liegen.
nicht zwingend, im I2C protokoll gibt es auch sog. clock stretching und das kann je nach konfiguration (auf die du angeblich laut arduino foren keinen einfluss nehmen kannst) vielleicht zu lange dauern
ich weis zum beispiel aus eigener leidlicher erfahrung, dass ein gewöhnlicher atmega z.b. nur clockstretching bis maximal 25mS erlaubt und dann stumpf weiter taktet (eine konvention des SMBus, weil atmel keine i2c lizenz hatte haben sie einfach den baugleichen SMBus als referenz genommen) ... aber das ist nur als beispiel gemeint, das betrifft dein problem nicht
aber vielleicht gibt es noch andere effekte die mit irgendwelchen timings zusammen hängen
(auch ein kleines beispiel: ein pic schafft es unter umständen mit dem timing im UART einen atmega ins stolpern zu bringen weil der pic die bit timings "zu exakt" einhält und der atmega das stopbit "verpasst")
hmmmhhh...
das wäre ntl blöde, aber vlt kennt jemand DOCH Tricks, um den Nunchuk mit Arduino-Code auf ARMs anzusteuern...?
Wie gesagt,
Was jetzt weiterhelfen würde zur Bestätigung und zum Debuggen:
wenn jemand einen funktionierenden Nunchuk besitzt und einen Arduino Due (oder Adafruit M4) und dann guckt, ob er meine Fehlmessungen z.B. mit dem Code oben (und seinen Patchs/Änderungen) bestätigen kann.
ein weiterer Hinweis den ich gefunden habe, zwischen der "Busfreigabe und Busübernahme" (was zum geier auch damit gemeint ist, ich behaupte mal zwischen einem stop und dem folgenden start bzw. zwischen dem stop und restart beim lesen) sollten wohl mind. 300uS Pause sein da sich der Chuck sonst weghängen kann (gerade das klingt plausibel, da die ARMs deutlich schneller arbeiten als atmegas)
wie du das aber realisierst entzieht sich leider meienr kenntnis, aber es klingt stark danach dass der chuck selbst kein clock stretching beherrscht und einfach darauf hofft dass der master nicht zu schnell nachfragt (hab ich auhc schon mit einem signalwandler erlebt, kein clock stretch und einfach nur aufgehängt, weil ich nicht genug gewartet habe)
danke für die Infos!
Jetzt bräuchte ich allerdings wen, der die Fehler tatsächlich findet und sie "fixen" kann... 8)
Ich habe evtl. noch eine Idee.
Ich hatte mal Probleme weil ich mein NACK nicht oder zu spät gesendet hatte,
wenn ich mir den Code ansehe, kommt dein NACK evtl. zu spät.
Du liest alle Daten ein, jeweils mit einem ACK
Am Ende liest Du nochmal ein "Dummy" ein mit dem NACK. Da gibt es garnichts mehr zulesen.
Das NACK muss meines Wissen nach direkt beim letzten Byte gesendet werden
(Das ist nur ein Vermutung)
Kannst Du das mal ausprobieren:
data->acc_z = NunchukDecode(I2cReadByte(I2C_NACK)) << 2; // hier schon das NACK
// temp = NunchukDecode(I2cReadByte(I2C_NACK)); // die Zeile weg.
Verschiedene Chips scheinen sich hier unterschiedlich zu verhalten.
Bei mir ging es zunächst, dann hab ich ein anderes EEPROM gehabt und da trat erstmals der Fehler auf.
Siro
die Zeile finde ich nicht...
/*
* Nunchuk auslesen
*
* funktioniert mit original Nunchuck
* UND mit Wirelesse Nunchuck
*
* Pinbelegung:
* 3.3V (Kabel rot)
* GND (Kabel weiß)
* A4 (Kabel grün)
* A5 (Kabel gelb)
*/
#include <Wire.h>
const int dataLength = 6; // numer ob bytes to request
static byte rawData[dataLength]; // array to store nunchuck data
// construct to create an enumerated list of the sonsor values returned from the nunchuck
enum nunchuckItems { joyX, joyY, accelX, accelY, accelZ, btnZ, btnC };
void setup()
{
Serial.begin(57600);
delay(500);
Serial.println("Labels,Xjoy,Yjoy,Xaccel,Yaccel,Zaccel,Z-btn,C-btn,");
delay(500);
nunchuckInit();
}
void loop()
{
if (nunchuckRead() == true)
{
Serial.print("Data,"); // Data-Header
Serial.print(getValue(joyX), DEC);
Serial.write(",");
Serial.print(getValue(joyY), DEC);
Serial.write(",");
Serial.print(getValue(accelX), DEC);
Serial.write(",");
Serial.print(getValue(accelY), DEC);
Serial.write(",");
Serial.print(getValue(accelZ), DEC);
Serial.write(",");
Serial.print(getValue(btnZ), DEC);
Serial.write(",");
Serial.print(getValue(btnC), DEC);
// Serial.write(",0");
// Serial.write("\n");
Serial.println();
}
delay(20); // time between redraws
}
void nunchuckInit()
{
Wire.begin(); // join I2C bus as master
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0xF0); // send memory adress
Wire.write((byte)0x55); // send a zero
if (Wire.endTransmission() == 0) {
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0xA5); // send memory adress
Wire.write((byte)0x00);
} // stop transmission
}
// send a request for data to the nunchuck
static void nunchuckRequest()
{
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.write((byte)0x00); // send one byte
Wire.endTransmission(); // stop transmission
}
// receive data back from the nunchuck,
// returns true if read successful, else false
boolean nunchuckRead()
{
int cnt=0;
Wire.requestFrom (0x52, dataLength); // request data from nunchuck
while (Wire.available ()) {
rawData[cnt] = Wire.read();
cnt++;
}
nunchuckRequest(); // send request for next dat payload
if (cnt >= dataLength)
return true; // success if all 6 bytes received
else
return false; // failure
}
// encode data to format that most wiimote drivers accept
// static char nunchuckDecode (byte x) {
// return (x ^ 0x17) + 0x17;
// return x;
// }
int getValue(int item) {
if (item <= accelZ)
return (int)rawData[item];
else if (item == btnZ)
return bitRead(rawData[5], 0) ? 0: 100;
else if (item == btnC)
return bitRead(rawData[5], 1) ? 0: 100;
}
Achso, sorry, das war der Code von Klebwax :p
der Code oben von mir läuft ja nachweislich mit meinem AVR, nur nicht mit meinen ARMs M3/M4.
Hast Du die Pullups mal auf 1K gesetzt. Ich benutze generell 1K bei 400 KHz.
das ist aber sehr weit außerhalb vom Standard, zumal der Due schon eingebaute Pullups hat (nur mit denen allein geht es aber auch nicht). Aber ich kann 2k2 mal am Due probieren - Momentchen...
- - - Aktualisiert - - -
update:
auch kein Unterschied
Ich denke, das einzige was hilft ist, wenn hier jemand , der selber die Hardware hat, es bei sich selber testet.
Ich sehe grad, Klebwax erwähnte schon:
"Wenn ich mich recht erinnere, ist der Nunchuk pingelig, wenn das letzte Byte nicht mit NAK quittiert wird. Er bleibt dann hängen und blockiert den Bus."
Das war auch meine Vermutung gewesen.
Wie das bei deinem Code genau abläuft lässt sich schlecht nachvollziehen, das kommt ja aus einer Bibliothek.
Bleibt wohl wirklich nur jemand übrig, der es schon lauffähig geschaft hat.
Ein Versuch war es wert.
Siro
ja klar, danke, die 2 Widerstände zu wechseln war ja kein Aufwand 8)
Mit i2c Steuer-Code kenne ich mich allerdings überhaupt nicht aus.
Ich hab hier auch noch etwas gefunden.
https://oscarliang.com/wii-nunchuck-arduino-tutorial/
Nach jedem kompletten Empfang ruft er anscheinend diese Funktion auf,
sonst funktioniert die Synchronisation wohl nicht.
void NunC_SendNextByteRequest()
{
// I don't know why, but it only works correct when doing this exactly 3 times
// otherwise only each 3rd call reads data from the controller (cnt will be 0 the other times)
for(byte i = 0; i < 3; i++)
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR); // transmit to device 0x52
Wire.send (0x00); // sends one byte
Wire.endTransmission (); // stop transmitting
}
}
Das spricht irgendwie dafür, dass der nunchuck sich "verheddert"
Siro
was soll ich davon wann und wo aufrufen, bzw. wie sieht dann mein neuer Komplett-Code aus?
der Autor bezieht sich allerdings auch auf AVRs, und mit AVRs klappt es ja bei mir mit dem obigen Code von uxomm - nur nicht mit ARMs...:confused:
Ich muss mich wohl entschuldigen HaWe,
ich hatte das Problem nicht (eigentlich garicht) richtig verstanden (schäm) :p
Es tritt nur auf, wenn dein DUE mit dem nunchuk verbunden wird.
Die anderen I2C Chips am DUE laufen einwandfrei.
Der nunchunk am AVR hingegen läuft auch wiederum einwandfrei.
Der Scanner zwischen DUE und nunchuk laufen auch richtig.
ABER: jedoch sieht das nur so aus weil x01...x07 nicht sein dürfte.
Ich grüble schon ne Weile woran das liegen kann.
Um den I2C BUS zu scannen gibt es 2 Möglichkeiten,
mit Read oder mit Write, das könnte ein Problem werden.
Eventuell scannt die AVR Lib anders als die DUE Lib
Kannst Du mal das Scannen ausklammern, vielleicht passiert dabei irgendeine Schweinerei.
Vielleicht haben die sich bei Nintendo da irgendwas implementiert, man weis es ja nicht.
Ich weis nicht ob Du das beim Starten generell machst.
Oder nächster Versuch, gibt das Scannen am AVR auch die 0x1..0x7 raus ?
Siro
:)
am AVR (Mega):
bei 400kHz: ja, ebenfalls; seltsamerweise sogar auch noch 78...7E
bei 100kHz auch, aber mit i2c Error 4 (dargestellt als ?? )
https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/Wire/src/utility/twi.c#L224
Scanning at 100k
0 ** ?? ?? ?? ?? ?? ?? ?? -- -- -- -- -- -- -- --
1 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
4 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
5 -- -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
6 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
7 -- -- -- -- -- -- -- -- ?? ?? ?? ?? ?? ?? ?? **
Scan result for i2cclock 100k
found: 1 devices
error: 14 devices
Scanning at 400k
0 ** 01 02 03 04 05 06 07 -- -- -- -- -- -- -- --
1 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
4 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
5 -- -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
6 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
7 -- -- -- -- -- -- -- -- 78 79 7A 7B 7C 7D 7E **
Scan result for i2cclock 400k
found: 15 devices
error: 0 devices
- - - Aktualisiert - - -
dies ist mein Scanner Code:
// --------------------------------------
// i2c_scanner
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
#include <Wire.h>
#define ESP_SCL D1 //GPIO5=D1 SCL ESP8266 default
#define ESP_SDA D2 //GPIO4=D2 SDA ESP8266 default
byte error, address;
int nDevices, nDeverr;
void setup()
{
//Wire.pins(D2, D1); // change only if not default
Wire.begin();
Serial.begin(115200);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nI2C Scanner");
}
void loop() {
static uint32_t i2cclock = 10000;
int iores;
nDevices = 0;
nDeverr = 0;
if(i2cclock==10000) i2cclock=100000;
else
if(i2cclock==100000) i2cclock=400000;
/*else
if(i2cclock==400000) i2cclock=1000000;
*/
else
if(i2cclock==400000) i2cclock=10000;
Wire.setClock(i2cclock);
Serial.print("\nScanning at "); Serial.print(i2cclock/1000); Serial.println("k");
for(address = 0; address < 128; address++ ) {
if (address%16 == 0) {
Serial.println();
Serial.print( (address+1)/16);
Serial.print(" ");
}
if(address==0 || address==127) {
Serial.print("** ");
continue;
}
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
if (address<16) Serial.print("0");
Serial.print(address,HEX); Serial.print(" ");
nDevices++;
}
else if (error==4)
{
Serial.print("?? ");
nDeverr++;
}
else
{
Serial.print("-- ");
}
}
Serial.println();
Serial.print("Scan result for i2cclock "); Serial.print(i2cclock/1000); Serial.println("k");
Serial.print("found: "); Serial.print(nDevices); Serial.println(" devices ");
Serial.print("error: "); Serial.print(nDeverr ); Serial.println(" devices \n");
delay(5000);
}
- - - Aktualisiert - - -
(bei ARMs habe ich nie diese error 4 = ?? , allerdings auch nie die Adressen 78...7E)
Ich habe evtl. noch eine Idee.
Ich hatte mal Probleme weil ich mein NACK nicht oder zu spät gesendet hatte,
wenn ich mir den Code ansehe, kommt dein NACK evtl. zu spät.
Du liest alle Daten ein, jeweils mit einem ACK
Am Ende liest Du nochmal ein "Dummy" ein mit dem NACK. Da gibt es garnichts mehr zulesen.
Das NACK muss meines Wissen nach direkt beim letzten Byte gesendet werden
(Das ist nur ein Vermutung)
Kannst Du das mal ausprobieren:
data->acc_z = NunchukDecode(I2cReadByte(I2C_NACK)) << 2; // hier schon das NACK
// temp = NunchukDecode(I2cReadByte(I2C_NACK)); // die Zeile weg.
Du beziehst dich auf meinen Code. Zuerst, er funktioniert. Und das nicht zufällig. Ich lese das letzte Datenbyte nach temp ein, weil ich es anschließend weiter bearbeiten muß. Das ist, wie man aus dem weitern Code leicht sehen kann, kein Dummy-Read. Und da es das letzte ist, quittiere ich es mit NAK. Im letzten Byte stehen die Tasten und die Restbits der ACC-Werte.
Verschiedene Chips scheinen sich hier unterschiedlich zu verhalten.
Richtig. Mache funktionieren, obwohl man das letzte Byte nicht mit NAK quitiert, sich nicht an die I2C Spec hält. Da sieht man mal, wie gut I2C funktioniert, selbst wenn man etwas falsch macht. Hättest du es gleich richtig gemacht, wäre dir ein unterschiedliches Verhalten gar nicht aufgefallen.
Aber, wie schon gesagt, HaWe verwendet anderen Code.
MfG Klebwax
Richtig. Mache funktionieren, obwohl man das letzte Byte nicht mit NAK quitiert, sich nicht an die I2C Spec hält. Da sieht man mal, wie gut I2C funktioniert, selbst wenn man etwas falsch macht. Hättest du es gleich richtig gemacht, wäre dir ein unterschiedliches Verhalten gar nicht aufgefallen.
Aber, wie schon gesagt, HaWe verwendet anderen Code.
MfG Klebwax
wenn ich dich richtig verstehe, benutzt du aber (auch) nur einen AVR, oder?
Mit AVRs funktioniert es aber doch auch mit "meinem" Code!
Oder hast du es bei dir mit einem Due oder M4 erfolgreich getestet? Das wäre ja erstmal die erste Hürde.
wenn ich dich richtig verstehe, benutzt du aber (auch) nur einen AVR, oder?
Nein, ich habe keine AVR/Arduino. Ich benutze PICs. Der Code funktioniert auf PIC16xx (8 Bit) und auf PIC24xxx (16 Bit). Das Ganze nach lua umgesetzt funktioniert auch auf dem ESP8266 (ich benutze die lua-Firmware). Und der Python-Code für den Raspi, den ich im Netz gesehen habe, macht das genauso. Bin aber noch nicht dazu gekommen, meinen Nunchuk am Pi zu betreiben (zu viele Projekte). Ich verwende I2C häufig, baue mir auch meine eigenen Slaves aus kleinen µC, Um der Frage zuvorzukommen, ich verwende i.d.R. keine libs. Ich benutze die nur als Anhaltspunkt, wenn mir etwas im Datenblatt unklar ist. Im Vergleich zu anderen Prokollen/Schnittstellen ist I2C so simpel, das es eigentlich schneller ist eigenen Code zu schreiben, als fremde Libraries wirklich zu verstehen.
Mit AVRs funktioniert es aber doch auch mit "meinem" Code!
Oder hast du es bei dir mit einem Due oder M4 erfolgreich getestet? Das wäre ja erstmal die erste Hürde.
Wenn C-Code (oder auch C++) nur auf bestimmten Prozessoren funktioniert, ist er Schrott und da, wo er geht, ist es eher Zufall.
Wire.write((byte)0x55); // send a zero
Wenn ich dann auch noch so etwas lese, wundert mich das nicht. Was nun, 0x00 oder 0x55? Das kann beim Debuggen mal vorkommen, aber das veröffentlichen? Da hat jemand, das was er gemacht hat nicht wirklich ernst genommen.
MfG Klebwax
Andere Codes, die wenigstens bei Arduino-AVRs funktionieren, hier schlecht zu reden, ist ziemlich billig....
Allerdings: PICs sind hier nicht das Thema, und auch Arduino AVRs sind nicht das Thema, sondern alleine Arduino-Code für die M3 und M4 Cores. Außerdem steht immer noch im Raum, dass möglicherweise der Nunchuk wegen clock-stretching oder wegen elektrischer Probleme etc. noch nicht mal 100%ig sicher auf jedem i2c-Bus mit jedem Board läuft.
Solange also dein Code nicht Arduino-ARM-kompatibel ist und noch nichtmal getestet werden konnte, nützt es nichts, und dein Code müssste dazu auch erstmal für M3/M4 in Arduinisch überhaupt zur Verfügung stehen - und darauf wäre ich wirklich gespannt.
Darf ich hier mal kurz reingrätschen und darauf hinweisen, dass wir nciht bare-metal sondern arduino und nodeMCU (das meintest du doch mit lua oder?) bibliotheken reden?
das bedeutet dass die implementation der lib für das jeweilige board durchaus äußerst unterschiedlichen sein könnte und @HaWe dein Problem gehört streng genommen in den Arduino Bugtracker, denn es kristallisiert sich immer mehr heraus dass wohl an der lib für die due boards etwas nicht stimmt dass dein nunchuck ins stlpern bringt!
ich lege nochmal dringend ans herz zu prüfen ob du irgendwie delays zwischen dem start und stop conditions einfügen kannst oder beim auslesen zwischen schreiben der registeradresse und dem beginn des lesens, vielleicht löst das dein problem schon aber ganz ohne oszilloskop um die signale zwischen den boards zu vergleichen wird das nichts
schau mal ob du dir nicht einen günstigen logic analyzer besorgen kannst oder vielleicht sogar mit einem zusätzlichen board einen DIY logic analyzer bauen kannst
mir ist klar dass du normal immer auf libs setzt um dich nciht mit sowas auseinandersetzen zu müssen, aber die libs werden auch nur von menschen geschrieben und könen fehler beinhalten (und darauf wette ich in diesem fall sogar)
@Ceos:
mein Code oben (von uxomm) nutzt keine weiteren Libs, und wenn du meinst, dass der Code anders aussehen müsste, dann ändere ihn mal bitte so um, das er in der geänderten Form getestet werden kann.
Auch ist es nicht nur der Due, sondern auch der Adafruit M4, der betroffen ist, und beide hatten bisher NIE Probleme mit meinen Standard-I2C-Geräten (OLED SSD1306, MPU6050, CMPS11, CMPS12, BME280, BMP280, PCF8574, MCP9808, ADS1115).
Wir sind hier ja auch im Arduino-Unterforum, daher ist es klar, dass eine funktionierende Arduino-Lösung (für i2c-Wire-class) gebraucht wird.
@Klebwax:
Sorry, das sollte in keinster Weise Kritik am Code sein.,
zumal Du völlig recht hast. Der Code ist so richtg.
Ich hab mich durch "temp" verwirren lassen. Dein temp wird ja tatsächlich ausgewertet.
Ich dachte zuerst, das ist so eine Art dummy read.
Da steht der Tastenstatus und es wird auch das NACK gesendet.
Also alles völlig okay.
Zum Problem:
Es ist schon mehrfach bei mir aufgetreten, dass alter Code, der auf verschieden Controllern lief,
plötzlich auf dem ARM nicht mehr lief. Bei mir ARM-Cortex M3
Dazu gehört z.B. atomarer Code. Nur mit Verrenkungen geht das überhaupt.
Das betrifft pre und postincrement, das kann er nicht atomar.
Habe auch I2C Interrupts bekommen mit Status 0xF8.
den gibt es garnicht, das wäre nämlich "idle modus" alles erledigt.
Interrupt Problem, tritt nur mit C-Compiler O3 Option auf. Auch hier ein typisches Cortex-M3 Phänomen
durch die internen Write Buffer.
Da bei HaWe aber schon diverse andere Chips am I2C laufen, müssen es wohl noch andere Problem geben.
Ich tippe auch auf die LIB.
Siro
Ich tippe auch auf die LIB.
@Siro: welche LIB??
uxomms Code nutzt keine LIB, nur das ganz normale Arduino-Wire() für i2c, und was anderes gibt es für Arduino standardmäßig nicht!
arduino IST eine c-lib ... es geht hier nicht um externe sondern um die eigentliche basis lib arduino
wenn du kein arduino nutzt müsstest du die register händisch adressieren udn dem datenblatt folgenden inistailiseren um I2C nutzen zu können. mit arduino geht das nur weil irgendjemand anderes für dich das interface geschrieben hat udn wieder jemand anderes die anbindung an die entsprechende hardware geschrieben hat.
arduino ist kein compiler sondern nur eine library zum erleichterten programmieren in c, du compilierst imernoch grundlegenden und boardspezisfischen c code mit einem einfachen gcc
Die Wire Lib für den Due und die von Adafruit müssen sich ja intern unterscheiden, da da ein ganz anderer Controllertyp verwendet wird.
Und die liefern beide die gleichen falschen Ergebnisse ? Sind die Arduinos, mit denen es funktioniert, 5V Typen ? Wenn keine Messtechnik zur Verfügung steht, gibt es eventuell einen 3,3 V AVR Arduino zum testen ? Nur um auszuschliessen, dass es nicht ein Spannungsproblem ist ...
um die Diskussion hier mal in die richtige Richtung zurückzuführen:
Es geht hier nicht um Grundsatzdiskussionen.
Es geht um die Arduino-API und -IDE und M3-Due und Adafruit-M4 Boards, und dafür wird ein funktionierender Code zum Auslesen gesucht.
Wenn jemand eine Version hat (oder abgeändert hat), die ich hochladen und testen kann, sehr gerne!
(PS, der Nunchuk arbeitet nach allem was man liest mit 3.3V und ist nur grenzwertig 5V-tolerant - ich habe allerdings auch keinen 3.3V AVR zum Testen. M3 und M4 aber liefern exakt dieselben (falschen) Ergebnisse beim Auslesen)
ich habe mir dein Link aus dem ersten Beispiel nochmal angesehen udn entdeckt, dass dort überall delay(1) verbaut sind aber auskommentiert
https://github.com/infusion/Fritzing/blob/f4d170da11285897b48763efccb36e10a0d387f3/Nunchuk/Nunchuk.h
kommentier doch mal probehalber die ganzen delay(1) ein und schau ob das zu besseren ergebnissen führt, damit wäre zumindest schonmal sichergestellt dass dein reine ablauf ein timing problem hat oder nicht
wenn es nicht klappt sehe ich das problem defintiv in der wire-lib implementation für die boards due und M4 und kann nurnoch empfehlen sich an deren entwickler zu wenden oder hier auf antwort von jemand mit der gleichen hardware zu hoffen (support aber eben leider nur in englisch ... PS da ist schon ein issue das das gleiche problem beschreibt, kannst du mal die prozessoren benennen die auf den boards verbaut sind, dann könnte ich mal eine antwort in das topic für dich setzen)
ich habe mir dein Link aus dem ersten Beispiel nochmal angesehen udn entdeckt, dass dort überall delay(1) verbaut sind aber auskommentiert
https://github.com/infusion/Fritzing/blob/f4d170da11285897b48763efccb36e10a0d387f3/Nunchuk/Nunchuk.h
kommentier doch mal probehalber die ganzen delay(1) ein und schau ob das zu besseren ergebnissen führt, damit wäre zumindest schonmal sichergestellt dass dein reine ablauf ein timing problem hat oder nicht
wenn es nicht klappt sehe ich das problem defintiv in der wire-lib implementation für die boards due und M4 und kann nurnoch empfehlen sich an deren entwickler zu wenden oder hier auf antwort von jemand mit der gleichen hardware zu hoffen (support aber eben leider nur in englisch ... PS da ist schon ein issue das das gleiche problem beschreibt, kannst du mal die prozessoren benennen die auf den boards verbaut sind, dann könnte ich mal eine antwort in das topic für dich setzen)
edit
falsch verstanden, du meinst ja den Code vom Link!
probiere ich gleich aus!
- - - Aktualisiert - - -
getestet überall mit delay(1) auskommentiert: keine Verbesserung leider (alle Änderungen sporadisch, keine Reaktion auf Tastendruck, Poti, Bewegung)
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,508,-172,-512,1,1
-127,-128,-512,-512,-512,1,1
-127,-128,-512,144,-384,1,1
-127,-128,-512,-512,-512,1,1
-124,-128,-512,-512,-512,1,1
-127,-128,-512,-512,-512,1,1
-127,-128,511,511,511,0,0
128,127,511,511,511,0,0
-2,1,-3,-469,194,0,1
50,-69,393,-394,-9,1,1
-96,-3,-348,-8,-10,0,1
0,-118,194,215,196,0,0
99,-99,-9,403,-387,0,1
-86,-2,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,508,508,-172,1,1
-127,-128,-512,-512,-512,1,1
-127,-128,-512,-510,144,1,1
-127,-128,-512,-512,-512,1,1
-127,-125,-512,-512,-512,1,1
-127,-128,-512,-512,-512,1,1
-127,-128,-509,511,511,0,0
128,127,511,511,511,0,0
128,-3,4,-1,-470,1,1
54,49,-273,395,-395,0,1
101,-97,-9,-345,-7,0,1
2,-1,-472,195,214,0,1
-68,98,-393,-11,400,0,0
-2,-87,-5,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
128,127,511,511,511,0,0
meine Boards sind Arduino Due (Original) mit M3 (SAM3X8E) und Adafruit Feather M4 (ATSAMD51)
- - - Aktualisiert - - -
update 2:
der Code von deinem Link
https://github.com/infusion/Fritzing/blob/f4d170da11285897b48763efccb36e10a0d387f3/Nunchuk/Nunchuk.h
funktioniert mit un-kommentiertem delay(1) anfangs immerhin mit meinem Mega2560 und reagiert auch auf Tasten/Poti, aber dann hängt er sich nach wenigen Sekunden komplett auf
In der Originalfassung (auskommentiertes delay(1) ) dagegen ist er immerhin auf dem Mega absolut stabil, genau wie der uxomm-Code.
Nur ergänzend nochmal:
KEINER der auf dem Mega2560 funktionierenden Codes läuft allerdings auf M3 oder M4.
Der Nunchuk ist wie gesagt das erste Gerät, das solche Probleme mit i2c macht, speziell auf den ARM Boards.
ich tippe langsam auch auf clock-stretching Probleme...
Aber ich brauche eben eine Arduino-Lösung mit den dortigen Wire() Bordmitteln.
(editiert)
wahrscheinlich habe ich es überlesen aber welche Arduino-lib-, Wire-lib- und Boardfile-Versionen verwendest du in der IDE? (Du könntest auch mal versuchen dzu prüfen ob es neuere Boardfiles gibt)
Arduino IDE 1.8.8, das ist ziemlich die neueste - die 1.8.9 ist noch etwas verbugged.
Adafruit M4: 1.3.0 (neueste)
Arduino Due 1.6.12 (neueste)
die jew. Wire() Libs sind immer in allen IDE-Versionen fest integriert.
(ich hatte anfangs ältere Board-Cores, aber nachdem sie da schon nicht funktionierten, habe ich ntl geupgradet)
habs mal so weitergegeben, jetzt müssen wa halt hoffen :)
wo genau hast du das weitergegeben?
Oh, herrjemine! Der darf das gar nicht - Datenschutz.
;)
edit:
danke, ceos, habe deinen issue report gefunden!
Update:
die delay(1) zu un-kommentieren hatte ja keinen Effekt, aber wenn man stattdessen die zwei delayMicroseconds un-kommentiert, dann scheint es ziemlich gut am Due und auch am M4 zu funktionieren!
danke nochmal @Ceos, das war der entscheidende Tipp mit dem Repo! 8)
ooookayyyy ?! O_o weniger pause und es geht besser ... mhh okay ich meine die frage irgendwo gelesen zu haben, sind das original nunchucks ? vielleicht sitzt da ein atmel drin der kein clock stretch mag XD
edit: aber im ernst ... auf die blöde idee, dass die gegenstelle keine pausen mag kommt man irgendwie auch nicht so ohne weiteres XD
ja, soweit ich weiß original, bin aber nicht mehr ganz sicher - wir hatten die mal in oder mit einer Wii-Box in einem Webshop für die Kiddies gekauft, aber ich meine, die Nunchuks waren schon drin.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.