Direction Needed - Add analog input to existing Teensy LC Game Controller

Status
Not open for further replies.
Hi,

I'm hoping you people can help me.

I have an Off-the-shelf USB game controller which uses a Teensy-LC.

My PC is Windows 10.

It is currently is set up using 16 inputs (10 buttons and 2 rotary encoders with push button).

The board is mounted to a PCB with pins on risers but the pins on the end are unpopulated. Pin 26 is one of those unpopulated pins. Which is an analog input.

I'd like to add an analog input to pin 26 while making sure the rest of the controller continues to function a snormal..

What is the best way to achieve this?

Can I just add the potentiometer and some code to the existing sketch?

I have this bit of code but I am not sure where to add it to the existing sketch.

void setup()
{
Serial.begin(38400);
}

int val;

void loop()
{
val = analogRead(0);
Serial.print("analog 0 is: ");
Serial.println(val);
delay(250);
}

Thanks in advance!
 
So, Learning alot about Teensy.

I know I can leave out some stuff from the above sample sketch.

It should look more like this:



int clutch;

{
clutch = analogRead(26);
}

Do I need to tell it where to send the value or will it automatically send it with the rest of the information it is sending over USB to the PC?

My guess is there is some part of the code that is telling the processor to send particular variable values and I would need to declare/add 'clutch' to that list.

I'll know more when I get a chance to look at the code itself with the Arduino IDE and Teensy Loader.

I'll try to load a copy of the existing sketch here if I don't just figure it out on my own.
 
Bummer

So I downloaded Teensyduino and Teensy Loader and got them installed but......Oh, no. It turns out the source code cannot be read once loaded onto the Teensy. I did not know that.

So change of plans....I guess I will have to write the entire sketch. I'm sure I will have many questions.

The inputs are already soldered to the Teensy and the Teensy is soldered to a PCB which acts as a breakout and mount for the components So I cannot remove the board.

My plan is to ring out the current layout and map which inputs the buttons and encoders are currently using then use those pin numbers in the sketch.

Right now I know that when connected to the PC I can see that the encoders are using pins 7, 8 and 9 and 10,11 and 12. There are three inputs used by each encoder because they are also pushbuttons.

I'll figure out which pins the buttons are using and start there.

The good news is that I know I can make it work because it is working currently.

I've messed around with Arduinos several times in the past so I have a little experience but I'm sure it will still be a challenge.


What I'm looking to accomplish is to have a sketch on the Teensy LC that accepts digital inputs from 10 momentary pushbuttons and two CTS288 Rotary Encoders and one analog input from a potentiometer.

All the inputs will have to be mapped to their current locations except the potentiometer which will be on pin 26 as It is the only available analog input.
 
If your board hasn't used them, there are also pins 24/25 which are analog input only pins (A10, A11) that are on the inside row of pins (pin 25 is next to pin 21, and pin 24 is next to pin 22). You would need to solder one or two wires to the two through hole pins in the Teensy.
 
Thanks, Michael.

I believe those pins are unpopulated as well. Is it simpler to use a dedicated analog input pin?

I was planning on using pin 26(A12) because it is right next to the power and gnd pins and that would make wiring easier but if using a dedicated analog pin is easier to code then I would choose one of them.
 
Note pin 26 (A12) is also a dedicated analog pin. From a coding point of view, it doesn't matter which pin you use.

Note, you might want to use A10/A11, and reserve pin A12 if you ever wanted to add sound effects. Pin A12 can do both analog input and analog output (A10/A11 are analog input only). This is a true analog output that varies the voltage from 0..3.3v (or 1.2v). Using analog output on the other pins uses PWM mode to rapidly turn the pin on/off, which gives an effect over time of changing the voltage.

With a true analog output, you can hook a speaker with an amplifier to the pin and ground and you can play sounds. The Teensy LC is memory constrained, so you might not have the memory to hold long pre-recorded sounds. But simple tones, etc. might add to your enjoyment.

I like this speaker, since it includes an amplifier:
 
Ah. Good to know. I don't foresee using a speaker on this as it is steering wheel for controlling an online racing Simulator called iRacing.
 
So it still needs some work but this is what I have now:

#include*<Encoder.h>

Encoder knobLeft(8, 9); // Declare pins we will use for encoders
Encoder knobRight(11, 12);


void setup() {
pinMode(0, INPUT_PULLUP); // Declare the pins we will use for pushbuttons
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);

}

long positionLeft = -999; // Not sure what this is for but I think it is needed for the encoders to work?
long positionRight = -999;


void loop() {

long newLeft, newRight;
newLeft = knobLeft.read(); // read encoders knobLeft and knobRight
newRight = knobRight.read();

// read analog input A12 (pin 26) and set X position
Joystick.X(analogRead(12));

// read the digital inputs and set the buttons

Joystick.button(1, digitalRead(0));
Joystick.button(2, digitalRead(0));
Joystick.button(3, digitalRead(0));
Joystick.button(4, digitalRead(0));
Joystick.button(5, digitalRead(0));
Joystick.button(6, digitalRead(0));
Joystick.button(7, digitalRead(0));
Joystick.button(10, digitalRead(0));
Joystick.button(13, digitalRead(0));
Joystick.button(14, digitalRead(0));
Joystick.button(15, digitalRead(0));
Joystick.button(16, digitalRead(0));



// a brief delay, so this runs 20 times per second
delay(50);
}
 
So change of plan.

I changed the encoder library from encoder.h to Rotary.h and added debounced the button inputs.

This is what I have so far. Havent loaded it yet, Probably wont get a chance to do that until tomorrow night.

#include <Bounce.h>
#include <elapsedMillis.h>
#include <Rotary.h>


Bounce r_button_1 = Bounce(20,10);
Bounce r_button_2 = Bounce(21,10);
Bounce r_button_3 = Bounce(22,10);
Bounce r_button_4 = Bounce(5,10);
Bounce r_button_5 = Bounce(4,10);
Bounce r_button_6 = Bounce(3,10);
Bounce r_button_7 = Bounce(12,10);
Bounce r_button_8 = Bounce(1,10);
Bounce r_button_9 = Bounce(15,10);
Bounce r_button_10 = Bounce(23,10);

Bounce enc_button_1 = Bounce(9,10);
Bounce enc_button_2 = Bounce(8,10);


elapsedMillis timeElapsed;
unsigned int t_interval = 200; //interval to hold buttons on for when needed
unsigned int enc_interval = 20; //interval for encoders


Rotary rotary1 = Rotary(6, 7);
Rotary rotary2 = Rotary(10, 11);


void setup() {

attachInterrupt(6, rotate, CHANGE);
attachInterrupt(7, rotate, CHANGE);
attachInterrupt(10, rotate, CHANGE);
attachInterrupt(11, rotate, CHANGE);


pinMode(1, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);

}

void loop() {

//UPDATE


r_button_1.update();
r_button_2.update();
r_button_3.update();
r_button_4.update();
r_button_5.update();
r_button_6.update();
r_button_7.update();
r_button_8.update();
r_button_9.update();
r_button_10.update();

enc_button_1.update();
enc_button_2.update();




//HANDLE BUTTONS

if (r_button_1.fallingEdge()) {
Joystick.button(20,1);
}
if (r_button_1.risingEdge()) {
Joystick.button(20,0);
}

if (r_button_2.fallingEdge()) {
Joystick.button(21,1);
}
if (r_button_2.risingEdge()) {
Joystick.button(21,0);
}

if (r_button_3.fallingEdge()) {
Joystick.button(22,1);
}
if (r_button_3.risingEdge()) {
Joystick.button(22,0);
}

if (r_button_4.fallingEdge()) {
Joystick.button(5,1);
}
if (r_button_4.risingEdge()) {
Joystick.button(5,0);
}

if (r_button_5.fallingEdge()) {
Joystick.button(4,1);
}
if (r_button_5.risingEdge()) {
Joystick.button(4,0);
}

if (r_button_6.fallingEdge()) {
Joystick.button(3,1);
}
if (r_button_6.risingEdge()) {
Joystick.button(3,0);
}

if (r_button_7.fallingEdge()) {
Joystick.button(12,1);
}
if (r_button_7.risingEdge()) {
Joystick.button(12,0);
}

if (r_button_8.fallingEdge()) {
Joystick.button(1,1);
}
if (r_button_8.risingEdge()) {
Joystick.button(1,0);
}

if (r_button_9.fallingEdge()) {
Joystick.button(15,1);
}
if (r_button_9.risingEdge()) {
Joystick.button(15,0);
}

if (r_button_10.fallingEdge()) {
Joystick.button(23,1);
}
if (r_button_10.risingEdge()) {
Joystick.button(23,0);
}


//HANDLE ENCODER BUTTONS

if (enc_button_1.fallingEdge()) {
Joystick.button(9,1);
}
if (enc_button_1.risingEdge()) {
Joystick.button(9,0);
}

if (enc_button_2.fallingEdge()) {
Joystick.button(8,1);
}
if (enc_button_2.risingEdge()) {
Joystick.button(8,0);
}

}

void rotate() {

// HANDLE ENCODER 1
unsigned char result1 = rotary1.process();
if (result1 == DIR_CW) {
timeElapsed = 0;
Joystick.button(6,1);
Joystick.button(7,0);
} else if (result1 == DIR_CCW) {
timeElapsed = 0;
Joystick.button(7,1);
Joystick.button(6,0);
}

// HANDLE ENCODER 2
unsigned char result2 = rotary2.process();
if (result2 == DIR_CW) {
timeElapsed = 0;
Joystick.button(10,1);
Joystick.button(11,0);
} else if (result2 == DIR_CCW) {
timeElapsed = 0;
Joystick.button(11,1);
Joystick.button(10,0);
}


}
 
Doh, I forgot to add the analog input.

I have a question.

I will be putting the Teensy into a Serial/Keyboard,Mouse/Joystick mode.

Do I have to include any other libraries to use:

int val;

void loop()
{
val = analogRead(0);

}
 
Second question:

In the above example for telling the Teensy to read the anaolg input, Do I use 26 or A12 in the parentheses for identifying which pin to read?

For example:

val = analogRead(26);

or

val = analogRead(A12);
 
Update: I am about 90% there I think,

All the inputs are recognized in Devices--> Game Controller--> Properties however their behavior is unexpected.

All buttons work as expected, so that is good.

The analog input bounces around alot and it's travel is limited to about a third of the total possible travel. I remember seeing something about this but I don't remember exactly what it was or where I saw it. I don't foresee this being a difficult problem to solve.

The other unexplained behavior is with the encoders. They send a button press sporadically. They do not send a pulse every click. When they do work it is correct for the direction in which the knob is turned but it is hit and miss. They will often work on the fourth click or a multiple of four, i.e 4,8,12...etc, but not always. Occasionally it is off by one number in either direction but usually, if it fires at all, it will be on a fourth click. This behavior exists whether I turn the knob fast or slow.

The encoders I am using are CTS288V232R161B2.

http://www.leobodnar.com/files/288-2255.pdf

They are quadrature encoders which the library I am using is designed for.

I am using the Rotate.H library. It can be found here:

Ben Buxtronics Website: https://github.com/MHeironimus/ArduinoJoystickLibrary

GitHub Rotary.H: https://github.com/buxtronix/arduino/tree/master/libraries/Rotary


On A Side note, I found a YT video and website from a guy who has done exactly what I want to do minus analog.

He built a button box with pushbuttons and encoders using Teensy LC. I was stoked when I found this. I thought my problems were solved.


AMStudio 32 Button box YT: https://www.youtube.com/watch?v=Z7Sc4MJ8RPM

GitHub Joystick.H: https://github.com/MHeironimus/ArduinoJoystickLibrary


I loaded his sketch and added the library he recommended to the IDE but when I verify I get this error:


Arduino: 1.8.9 (Windows 10), TD: 1.53, Board: "Teensy LC, Serial, 48 MHz, Smallest Code, US English"

In file included from C:\Users\John\Documents\Arduino\libraries\ArduinoJoystickLibrary-master\src/Joystick.h:24:0,

from C:\Users\John\Desktop\Sketches\32-FUNCTION-BUTTON-BOX-master\32-FUNCTION-BUTTON-BOX-master\ARDUINO_BUTTON_BOXV2\ARDUINO_BUTTON_BOXV2.ino:5:

C:\Users\John\Documents\Arduino\libraries\ArduinoJoystickLibrary-master\src/DynamicHID/DynamicHID.h:37:28: fatal error: PluggableUSB.h: No such file or directory

compilation terminated.

Error compiling for board Teensy LC.



After a quick internet search I found this error is happening with some people and they can fix it by downgrading to a previous version of the Arduino IDE. I tried that but it did not help.

Anyone know how to fix that error?


For reference, here is the sketch I am using that is close to working but is giving me the encoder and analog input problems I mentioned above. I have also attached the sketch file to this post:

#include <Bounce.h>
#include <elapsedMillis.h>
#include <Rotary.h>


Bounce r_button_1 = Bounce(20,10);
Bounce r_button_2 = Bounce(21,10);
Bounce r_button_3 = Bounce(22,10);
Bounce r_button_4 = Bounce(5,10);
Bounce r_button_5 = Bounce(4,10);
Bounce r_button_6 = Bounce(3,10);
Bounce r_button_7 = Bounce(12,10);
Bounce r_button_8 = Bounce(1,10);
Bounce r_button_9 = Bounce(15,10);
Bounce r_button_10 = Bounce(23,10);

Bounce enc_button_1 = Bounce(9,10);
Bounce enc_button_2 = Bounce(8,10);


elapsedMillis timeElapsed;
unsigned int enc_interval = 20; //interval for encoders


Rotary rotary1 = Rotary(6, 7);
Rotary rotary2 = Rotary(10, 11);


void setup() {

attachInterrupt(6, rotate, CHANGE);
attachInterrupt(7, rotate, CHANGE);
attachInterrupt(10, rotate, CHANGE);
attachInterrupt(11, rotate, CHANGE);


pinMode(1, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);

}

void loop() {

//UPDATE


r_button_1.update();
r_button_2.update();
r_button_3.update();
r_button_4.update();
r_button_5.update();
r_button_6.update();
r_button_7.update();
r_button_8.update();
r_button_9.update();
r_button_10.update();

enc_button_1.update();
enc_button_2.update();


// READ ANALOG INPUT A12 (pin 26) AND SET X POSITION

Joystick.X(analogRead(A12));


//HANDLE BUTTONS

if (r_button_1.fallingEdge()) {
Joystick.button(20,1);
}
if (r_button_1.risingEdge()) {
Joystick.button(20,0);
}

if (r_button_2.fallingEdge()) {
Joystick.button(21,1);
}
if (r_button_2.risingEdge()) {
Joystick.button(21,0);
}

if (r_button_3.fallingEdge()) {
Joystick.button(22,1);
}
if (r_button_3.risingEdge()) {
Joystick.button(22,0);
}

if (r_button_4.fallingEdge()) {
Joystick.button(5,1);
}
if (r_button_4.risingEdge()) {
Joystick.button(5,0);
}

if (r_button_5.fallingEdge()) {
Joystick.button(4,1);
}
if (r_button_5.risingEdge()) {
Joystick.button(4,0);
}

if (r_button_6.fallingEdge()) {
Joystick.button(3,1);
}
if (r_button_6.risingEdge()) {
Joystick.button(3,0);
}

if (r_button_7.fallingEdge()) {
Joystick.button(12,1);
}
if (r_button_7.risingEdge()) {
Joystick.button(12,0);
}

if (r_button_8.fallingEdge()) {
Joystick.button(1,1);
}
if (r_button_8.risingEdge()) {
Joystick.button(1,0);
}

if (r_button_9.fallingEdge()) {
Joystick.button(15,1);
}
if (r_button_9.risingEdge()) {
Joystick.button(15,0);
}

if (r_button_10.fallingEdge()) {
Joystick.button(23,1);
}
if (r_button_10.risingEdge()) {
Joystick.button(23,0);
}


//HANDLE ENCODER BUTTONS

if (enc_button_1.fallingEdge()) {
Joystick.button(9,1);
}
if (enc_button_1.risingEdge()) {
Joystick.button(9,0);
}

if (enc_button_2.fallingEdge()) {
Joystick.button(8,1);
}
if (enc_button_2.risingEdge()) {
Joystick.button(8,0);
}

if (timeElapsed > enc_interval) {
Joystick.button(6, 0)
Joystick.button(7,0)
Joystick.button(10,0)
Joystick.button(11,0)
}

void rotate() {

// HANDLE ENCODER 1
unsigned char result1 = rotary1.process();
if (result1 == DIR_CW) {
timeElapsed = 0;
Joystick.button(6,1);
Joystick.button(7,0);
} else if (result1 == DIR_CCW) {
timeElapsed = 0;
Joystick.button(7,1);
Joystick.button(6,0);
}

// HANDLE ENCODER 2
unsigned char result2 = rotary2.process();
if (result2 == DIR_CW) {
timeElapsed = 0;
Joystick.button(10,1);
Joystick.button(11,0);
} else if (result2 == DIR_CCW) {
timeElapsed = 0;
Joystick.button(11,1);
Joystick.button(10,0);
}


}
Thanks, John
 

Attachments

  • Wheel sketch.txt
    4.4 KB · Views: 38
Last edited:
Status
Not open for further replies.
Back
Top