Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 13 of 13

Thread: Wii nunchuk/Classic controller

  1. #1
    Junior Member
    Join Date
    Dec 2015
    Posts
    11

    Wii nunchuk/Classic controller

    I'm not too much into electronics, more a software guy, so sorry if i say some mistakes

    I'd like to make a classic controller to usb adapter, to be able to use my wii arcade stick on raspberry/pc/ps3

    I've purchased a wiichuck adapter.

    can i use a teensy LC for this purpose?

    Is there any pitfall regarding powering, hid setup or other that i should be aware of?

    thank you for reading !

  2. #2
    Senior Member Ben's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    401
    the Wii-controllers use I2C if i remember that correctly. Teensies can register to the OS a Joystick+Mouse+Keyboard combo device and you can send mouse clicks, keystrokes and joystick axis positions to the PC/Mac.
    Teensy LC will be a good choice for this project. Your software needs to translate the I2C messages from the Wii-Device into HID messages to the OS.

  3. #3
    Junior Member
    Join Date
    Dec 2015
    Posts
    11
    Thank you for your answer!
    Do you know if I have to take care of voltage? I think USB delivers 5v, but teensy supports only 3.3v no?

    Well of course I will learn this in the manual :-)

  4. #4
    Senior Member Ben's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    401
    Quote Originally Posted by niocnioc View Post
    Do you know if I have to take care of voltage? I think USB delivers 5v, but teensy supports only 3.3v no?
    Not shure what you're asking here. Teensy LC runs on 3.3V logic voltage and is NOT 5V tolerant on its I/O pins. But it has an internal regulator so it can be supplied with 5V through it's USB port. This internal regulator is actually powerful enough to power some external devices as well, you may pull up to 100mA total for external use from Teensy LC's 3.3V pins.
    I don't know whether the Wii device uses 5V or 3.3V on it's Bus. If it needs 5V you must use a bidirectional level shifter. If the I2C bus is slow enough, you can use the "sparkfun approach" here: https://www.sparkfun.com/products/12009
    Note, however, that this level shifter is of "you get what you pay for"-quality. You can't use it for fast changing signals like high speed SPI. But for 100kHz I2C i guess it's ok.
    Ben

  5. #5
    Junior Member
    Join Date
    Dec 2015
    Posts
    11
    Like i said i'm more a software guy, i got confused with those notices on the teensy LC product page

    Thanks for all the valuable info. I think it will be fun

  6. #6
    Junior Member
    Join Date
    Dec 2015
    Posts
    11
    Finally i was able to get a teensy 2.0 and to move on to this side project. I have now my nunchuk acting as a joystick in windows, and it's pretty cool.

    I'm still concerned about the voltage output, nunchuks and wii classic devics operate on 3.3v, and using 5V could damage the stuff ( not 100% sure there)
    If I understand correctly i could use a voltage regulator on the Vcc output. Should i use capacitors?
    Last edited by niocnioc; 09-12-2016 at 12:52 AM.

  7. #7
    Senior Member Ben's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    401
    That's good news
    I'm impressed you followed through with this project and even reported back after such a long time. Much appreciated

    Ben

    Edit:
    Regarding the Teensy 2.0 and voltage levels, I'm sorry I don't know

  8. #8
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,823
    A quick run through google suggest nunchuks are indeed intended to run of 3.3V. The ugle hack solution is to just wire it up and see if it smokes, trusting the engineering in the nunchuck to cope, and replace it if things catch fire. The right solution is voltage conversion. First up that involves a regulator, which yes would normally need a cap on the output. You may also need to level convert the signals in and out, depending on how fussy the micro is about levels in, and if it truly reaches 3.3V on it's output levels.

    The possibly simpler solution is:
    https://www.pjrc.com/teensy/3volt.html and convert the whole Teensy 2 into a 3.3v Micro.

    Or just buying a 3.3V native micro. Depends a great deal on what you want to do, and how much time, money and existing parts you have to work with.

  9. #9
    Junior Member
    Join Date
    Dec 2015
    Posts
    11
    I was finally able to complete this project

    for the electronic part I've put a 3v3 AMS1117 regulator on the nunchuk adapter with a capacitor on the Vout

    for the software I've used the code from havencking https://github.com/havencking/teensy...sic-controller, with some tweaks to get Y axis in the right direction, and axis value in the correct range.

    I've not yet managed to get the wii home button mapped to the ps3 home, but that's a minor issue

    Code:
    /*   Copyright December 2015 - havencking@gmail.com
     *
     *   This program is free software: you can redistribute it and/or modify
     *   it under the terms of the GNU General Public License as published by
     *   the Free Software Foundation, either version 3 of the License, or
     *   (at your option) any later version.
     *
     *   This program is distributed in the hope that it will be useful,
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *   GNU General Public License for more details.
     *
     *   You should have received a copy of the GNU General Public License
     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     *
     * This is for a Wii Classic Controller adapted to connect as a joystick over
     * USB using a Teensy LC.  See http://havencking.blogspot.com for more info.
     *
     * When compiling using the Arduino IDE, you must select Joystick from the
     * "Tools > USB Type" menu.
     *
     * For more info about the Wii Classic Controller, see:
     * http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Classic_Controller
     */
    
    // the improved Wire I2C library
    // see:  https://www.pjrc.com/teensy/td_libs_Wire.html
    #include "i2c_t3.h"
    #include <Wire.h>             // fake include - points back to i2c_t3
    // an array to store the six bytes of controller status
    int buttons[6];
    
    // the analog controls
    int LX;
    int LY;
    int LT;
    int RX;
    int RY;
    int RT;
    
    // the digital controls
    bool BDR;
    bool BDD;
    bool BLT;
    bool Bminus;
    bool BH;
    bool Bplus;
    bool BRT;
    bool BZL;
    bool BB;
    bool BY;
    bool BA;
    bool BX;
    bool BZR;
    bool BDL;
    bool BDU;
    
    void setup() {
      // initialize Wii I2C using "the new way"
      // see: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
      Wire.begin();
      Wire.beginTransmission(0x52); // Wii Classic 7-bit I2C address is 0x52
      Wire.write(0xF0);
      Wire.write(0x55);
      Wire.endTransmission();
      Wire.beginTransmission(0x52);
      Wire.write(0xFB);
      Wire.write(0x00);
      Wire.endTransmission();
    
      // initialize Joystick
      // see: https://www.pjrc.com/teensy/td_joystick.html
      Joystick.useManualSend(true);
    }
    
    void loop() {
      // request the 6 bytes of controller status and store in the buttons array
      Wire.requestFrom(0x52, 6);
      while (Wire.available()) {
        for (int i = 0; i < 6; i++) {
          buttons[i] = Wire.receive();
        }
    
        // parse the controller data
        // analog controls
        LX = buttons[0] & B00111111;
        LY = buttons[1] & B00111111;
        LT = ((buttons[2] >> 2) & B00011000) | ((buttons[3] >> 5) & B00000111);
        RX = ((buttons[0] >> 3) & B00011000) | ((buttons[1] >> 5) & B00000110) | ((buttons[2] >> 7) & B00000001);
        RY = buttons[2] & B00011111;
        RT = buttons[3] & B00011111;
    
        // digital controls
        BDR = (buttons[4] >> 7) & B00000001;
        BDD = (buttons[4] >> 6) & B00000001;
        BLT = (buttons[4] >> 5) & B00000001;
        Bminus = (buttons[4] >> 4) & B00000001;
        BH = (buttons[4] >> 3) & B00000001;
        Bplus = (buttons[4] >> 2) & B00000001;
        BRT = (buttons[4] >> 1) & B00000001;
        BZL = (buttons[5] >> 7) & B00000001;
        BB = (buttons[5] >> 6) & B00000001;
        BY = (buttons[5] >> 5) & B00000001;
        BA = (buttons[5] >> 4) & B00000001;
        BX = (buttons[5] >> 3) & B00000001;
        BZR = (buttons[5] >> 2) & B00000001;
        BDL = (buttons[5] >> 1) & B00000001;
        BDU = buttons[5] & B00000001;
    
        // set the status of the controls mapped as a USB Joystick
        // see: https://www.pjrc.com/teensy/td_joystick.html
        // analog controls
        // on my fighting stick values are read as 0, 32,63, and i'm unable to calibrate on the ps3
        // so i shift to get 0,512, 1023
        Joystick.X(LX<<4);// / 64 * 1024);        // "value" is from 0 to 1023
        // y is inversed
        Joystick.Y((64-LY)<<4);// / 64 * 1024);        //   512 is resting position
        Joystick.Z(RX);// / 32 * 1024);
        Joystick.Zrotate(RY);// / 32 * 1024);
        Joystick.sliderLeft(LT);// / 32 * 1024);
        Joystick.sliderRight(RT);// / 32 * 1024);
        // digital controls
        // renumber these buttons as you see fit
        Joystick.button(15, !BDR);
        Joystick.button(13, !BDD);
        Joystick.button(8, !BLT);
        Joystick.button(9, !Bminus);
        Joystick.button(11, !BH);
        Joystick.button(10, !Bplus);
        Joystick.button(6, !BRT);
        Joystick.button(7, !BZL);
        Joystick.button(2, !BB);
        Joystick.button(1, !BY);
        Joystick.button(3, !BA);
        Joystick.button(4, !BX);
        Joystick.button(5, !BZR);
        Joystick.button(14, !BDL);
        Joystick.button(12, !BDU);
    
        // send the controls over USB as a Joystick
        Joystick.send_now();
      }
      // restart at the beginning of the address space
      Wire.beginTransmission(0x52);
      Wire.write(0x00);
      Wire.endTransmission();

  10. #10
    Junior Member
    Join Date
    May 2013
    Posts
    6
    Hello,

    I am trying to connnect a nunchuk to a Teensy 3.2 and I can't make it work.

    I am using the code available here (https://github.com/GabrielBianconi/arduino-nunchuk) and I got it working properly with a Teensy 2++ without issues. On the 3.2 I have added 10K pullup resistors to the SDA and SCL pins (18 and 19). The code is simple:

    Code:
    #include <Wire.h>
    #include <ArduinoNunchuk.h>
    
    #define BAUDRATE 19200
    
    ArduinoNunchuk nunchuk = ArduinoNunchuk();
    
    void setup()
    {
      Serial.begin(BAUDRATE);
      nunchuk.init();
    }
    
    void loop()
    {
      nunchuk.update();
    
      Serial.print(nunchuk.analogX, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.analogY, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.accelX, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.accelY, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.accelZ, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.zButton, DEC);
      Serial.print(' ');
      Serial.println(nunchuk.cButton, DEC);
      delay(100); //The only modification I have made to the code
    }
    The ArduinoNunchuk.h file is:
    Code:
    /*
     * ArduinoNunchuk.h - Improved Wii Nunchuk library for Arduino
     *
     * Copyright 2011-2013 Gabriel Bianconi, http://www.gabrielbianconi.com/
     *
     * Project URL: http://www.gabrielbianconi.com/projects/arduinonunchuk/
     *
     * Based on the following resources:
     *   http://www.windmeadow.com/node/42
     *   http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/
     *   http://wiibrew.org/wiki/Wiimote/Extension_Controllers
     *
     */
    
    #ifndef ArduinoNunchuk_H
    #define ArduinoNunchuk_H
    
    #include <Arduino.h>
    
    class ArduinoNunchuk
    {
      public:
        int analogX;
        int analogY;
        int accelX;
        int accelY;
        int accelZ;
        int zButton;
        int cButton;
    
        void init();
        void update();
    
      private:
        void _sendByte(byte data, byte location);
    };
    
    #endif
    ANd the ArduionNunchuk.cpp file:

    Code:
    /*
     * ArduinoNunchuk.cpp - Improved Wii Nunchuk library for Arduino
     *
     * Copyright 2011-2013 Gabriel Bianconi, http://www.gabrielbianconi.com/
     *
     * Project URL: http://www.gabrielbianconi.com/projects/arduinonunchuk/
     *
     * Based on the following resources:
     *   http://www.windmeadow.com/node/42
     *   http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/
     *   http://wiibrew.org/wiki/Wiimote/Extension_Controllers
     *
     */
    
    #include <Arduino.h>
    #include <Wire.h>
    #include "ArduinoNunchuk.h"
    
    #define ADDRESS 0x52
    
    void ArduinoNunchuk::init()
    {
      Wire.begin();
    
      ArduinoNunchuk::_sendByte(0x55, 0xF0);
      ArduinoNunchuk::_sendByte(0x00, 0xFB);
    
      ArduinoNunchuk::update();
    }
    
    void ArduinoNunchuk::update()
    {
      int count = 0;
      int values[6];
    
      Wire.requestFrom(ADDRESS, 6);
    
      while(Wire.available())
      {
        values[count] = Wire.read();
        count++;
      }
    
      ArduinoNunchuk::analogX = values[0];
      ArduinoNunchuk::analogY = values[1];
      ArduinoNunchuk::accelX = (values[2] << 2) | ((values[5] >> 2) & 3);
      ArduinoNunchuk::accelY = (values[3] << 2) | ((values[5] >> 4) & 3);
      ArduinoNunchuk::accelZ = (values[4] << 2) | ((values[5] >> 6) & 3);
      ArduinoNunchuk::zButton = !((values[5] >> 0) & 1);
      ArduinoNunchuk::cButton = !((values[5] >> 1) & 1);
    
      ArduinoNunchuk::_sendByte(0x00, 0x00);
    }
    
    void ArduinoNunchuk::_sendByte(byte data, byte location)
    {
      Wire.beginTransmission(ADDRESS);
    
      Wire.write(location);
      Wire.write(data);
    
      Wire.endTransmission();
    
      delay(10);
    }
    I get data sent to the serial port, but the numbers don't change, except that periodically (every 2 seconds or so), the values change a few times (5 or 6 datasets sent to the serial port are different), then they go back to their previous values. I am feeding the nunchuk with the 3.3v pin of the Teensy. I have also tried the Vcc in, which is 5V, from the computer usb port (just in case, since it worked for the Teensy 2++, which runs on 5V), but that doesn't make a difference. As I said before, I am using 10K pullup resistors.

    Any idea of what I could try?

    Admittedly I have not tried niocnioc's code, but I will try it this evening when I am at home.

    I know this is an old thread but I thought it would be better to bring this one back to life and have all the related information in a single thread than starting a new one. Also, sorry for the long post with a lot of code, I thought it would save us some time if I was thorough with the explanation from the beginning.

    Thank you all in advance,

    Pixe

  11. #11
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,774
    Hi Pixe,
    try the I2C Scanner from the wire library first!
    If does not work, too, i'd use stronger pullups, like 3k3.

  12. #12
    Junior Member
    Join Date
    May 2013
    Posts
    6
    Thank you Frank. I used the code posted above, and after a few modifications I got it working.

    I used 3k3 pullup resistors as you suggested, but it seems to work without them as well. Is it ok to remove them?

    The thing is the code posted above is for the classic wii controller, I wanted to use it for the nunchuk and the mapping of the data is different.

    So, I use the code above (which in turn is based on the code that can be found here), with the mapping I found in a project by Gabriel Bianconi (the code is here).

    And in case somenone needs my final code in the future, I am posting it below. It reads the data from a wii nunchuk and sends it to the serial port. This page explains the data format of the nunchuk.

    My code:
    Code:
    // the improved Wire I2C library
    // see:  https://www.pjrc.com/teensy/td_libs_Wire.html
    #include "i2c_t3.h"
    
    // an array to store the six bytes of controller status
    int values[6];
    
    // the analog controls
    int analogX;
    int analogY;
    int acceanalogX;
    int acceanalogY;
    int acceanalogZ;
    int zButton;
    int cButton;
    
    
    void setup() {
      // initialize Wii I2C using "the new way"
      // see: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
      Wire.begin();
      Wire.beginTransmission(0x52); // Wii Classic 7-bit I2C address is 0x52
      Wire.write(0xF0);
      Wire.write(0x55);
      Wire.endTransmission();
      Wire.beginTransmission(0x52);
      Wire.write(0xFB);
      Wire.write(0x00);
      Wire.endTransmission();
    
      // initialize Serial
      Serial.begin(19200);
    }
    
    
    void loop() {
      // request the 6 bytes of controller status and store in the buttons array
      Wire.requestFrom(0x52, 6);
      while (Wire.available()) {
        for (int i = 0; i < 6; i++) {
          values[i] = Wire.receive();
        }
    
    
        // parse the controller data
        // analog controls
        analogX = values[0] & B11111111; 
        analogY = values[1] & B11111111; 
        acceanalogX = (values[2] << 2) | ((values[5] >> 2) & B00000011); 
        acceanalogY = (values[3] << 2) | ((values[5] >> 4) & B00000011); 
        acceanalogZ = (values[4] << 2) | ((values[5] >> 6) & B00000011);
        zButton = !((values[5] >> 0) & 1);
        cButton = !((values[5] >> 1) & 1);
    
    
      Serial.print("analogX ");
      Serial.print(analogX, DEC);
      Serial.print("; analogY ");
      Serial.print(analogY, DEC);
      Serial.print("; acceanalogX ");
      Serial.print(acceanalogX, DEC);
      Serial.print("; acceanalogY ");
      Serial.print(acceanalogY, DEC);
      Serial.print("; acceanalogZ ");
      Serial.print(acceanalogZ, DEC);
      Serial.print("; zButton ");
      Serial.print(zButton, DEC);
      Serial.print("cButton ");
      Serial.print(cButton, DEC);
      Serial.println(' ');
      }
         
      // restart at the beginning of the address space
      Wire.beginTransmission(0x52);
      Wire.write(0x00);
      Wire.endTransmission();
    
      delay(200); // don't read too fast
    }
    Thanks again,

    Pixe

  13. #13
    Junior Member
    Join Date
    Dec 2015
    Posts
    11
    Glad to know you got it to work
    I'm still using my code with the classic controller, it's working nice even if I've never been able to make the home button work on the ps3- there's a trick at the hid level

    Thank you for sharing your code, I will have a look, I plan to use a nunchuk to make a gatt hid Bluetooth controller for the hololens with an esp32 😁

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •