Hello, I'm trying to use the data from a potentiometer as a virtual joystick with my Arduino Uno. I've tried tools like vJoy, EMC, etc., but I haven't been able to get it working. I'm not sure if it's a skill issue on my side or if I should just buy an Arduino Leonardo so my PC can recognize it directly as an HID device. (I'm on Windows.)
Thanks for helping a rookie.
Joysticks are potentiomters down inside! 2x of them only.
Grab pen and paper and draw how You connected the pot, and post the code using the code function in this window.
We will fix it!
Hi! Welcome to the Forum.
If by Uno you’re talking about the Uno R3, it doesn’t have HID capabilities. The Leonardo has.
That's the thing: is there any possibility to make it work using vJoy Gremlin, UnoJoy, or something similar?
*
* To use this library to make a controller, you'll need to do 3 things:
* Call setupUnoJoy(); in the setup() block
* Create and populate a dataForController_t type variable and fill it with your data
* The getBlankDataForController() function is good for that.
* Call setControllerData(yourData); where yourData is the variable from above,
* somewhere in your loop(), once you're ready to push your controller data to the system.
* If you forget to call sendControllerData in your loop, your controller won't ever do anything
*
* You can then debug the controller with the included Processing sketch, UnoJoyProcessingVisualizer
*
* To turn it into an actual USB video game controller, you'll reflash the
* Arduino's communication's chip using the instructions found in the 'Firmware' folder,
* then unplug and re-plug in the Arduino.
*
* Details about the dataForController_t type are below, but in order to create and use it,
* you'll declare it like:
*
* dataForController_t sexyControllerData;
*
* and then control button presses and analog stick movement with statements like:
*
* sexyControllerData.triangleOn = 1; // Marks the triangle button as pressed
* sexyControllerData.squareOn = 0; // Marks the square button as unpressed
* sexyControllerData.leftStickX = 90; // Analog stick values can range from 0 - 255
*/
#ifndef UNOJOY_H
#define UNOJOY_H
#include <stdint.h>
#include <util/atomic.h>
#include <Arduino.h>
// This struct is the core of the library.
// You'll create an instance of this and manipulate it,
// then use the setControllerData function to send that data out.
// Don't change this - the order of the fields is important for
// the communication between the Arduino and it's communications chip.
typedef struct dataForController_t
{
uint8_t triangleOn : 1; // Each of these member variables
uint8_t circleOn : 1; // control if a button is off or on
uint8_t squareOn : 1; // For the buttons,
uint8_t crossOn : 1; // 0 is off
uint8_t l1On : 1; // 1 is on
uint8_t l2On : 1;
uint8_t l3On : 1; // The : 1 here just tells the compiler
uint8_t r1On : 1; // to only have 1 bit for each variable.
// This saves a lot of space for our type!
uint8_t r2On : 1;
uint8_t r3On : 1;
uint8_t selectOn : 1;
uint8_t startOn : 1;
uint8_t homeOn : 1;
uint8_t dpadLeftOn : 1;
uint8_t dpadUpOn : 1;
uint8_t dpadRightOn : 1;
uint8_t dpadDownOn : 1;
uint8_t padding : 7; // We end with 7 bytes of padding to make sure we get our data aligned in bytes
uint8_t leftStickX : 8; // Each of the analog stick values can range from 0 to 255
uint8_t leftStickY : 8; // 0 is fully left or up
uint8_t rightStickX : 8; // 255 is fully right or down
uint8_t rightStickY : 8; // 128 is centered.
// Important - analogRead(pin) returns a 10 bit value, so if you're getting strange
// results from analogRead, you may need to do (analogRead(pin) >> 2) to get good data
} dataForController_t;
// Call setupUnoJoy in the setup block of your program.
// It sets up the hardware UnoJoy needs to work properly
void setupUnoJoy(void);
// You can also call the set
void setupUnoJoy(int);
// This sets the controller to reflect the button and
// joystick positions you input (as a dataForController_t).
// The controller will just send a zeroed (joysticks centered)
// signal until you tell it otherwise with this function.
void setControllerData(dataForController_t);
// This function gives you a quick way to get a fresh
// dataForController_t with:
// No buttons pressed
// Joysticks centered
// Very useful for starting each loop with a blank controller, for instance.
// It returns a dataForController_t, so you want to call it like:
// myControllerData = getBlankDataForController();
dataForController_t getBlankDataForController(void);
//----- End of the interface code you should be using -----//
//----- Below here is the actual implementation of
// This dataForController_t is used to store
// the controller data that you want to send
// out to the controller. You shouldn't mess
// with this directly - call setControllerData instead
dataForController_t controllerDataBuffer;
// This updates the data that the controller is sending out.
// The system actually works as following:
// The UnoJoy firmware on the ATmega8u2 regularly polls the
// Arduino chip for individual bytes of a dataForController_t.
//
void setControllerData(dataForController_t controllerData){
// Probably unecessary, but this guarantees that the data
// gets copied to our buffer all at once.
ATOMIC_BLOCK(ATOMIC_FORCEON){
controllerDataBuffer = controllerData;
}
}
// serialCheckInterval governs how many ms between
// checks to the serial port for data.
// It shouldn't go above 20 or so, otherwise you might
// get unreliable data transmission to the UnoJoy firmware,
// since after it sends a request, it waits 25 ms for a response.
// If you really need to make it bigger than that, you'll have to
// adjust that timeout in the UnoJoy ATmega8u2 firmware code as well.
volatile int serialCheckInterval = 1;
// This is an internal counter variable to count ms between
// serial check times
int serialCheckCounter = 0;
// This is the setup function - it sets up the serial communication
// and the timer interrupt for actually sending the data back and forth.
void setupUnoJoy(void){
// First, let's zero out our controller data buffer (center the sticks)
controllerDataBuffer = getBlankDataForController();
// Start the serial port at the specific, low-error rate UnoJoy uses.
// If you want to change the rate, you'll have to change it in the
// firmware for the ATmega8u2 as well. 250,000 is actually the best rate,
// but it's not supported on Macs, breaking the processing debugger.
Serial.begin(38400);
// Now set up the Timer 0 compare register A
// so that Timer0 (used for millis() and such)
// also fires an interrupt when it's equal to
// 128, not just on overflow.
// This will fire our timer interrupt almost
// every 1 ms (1024 us to be exact).
OCR0A = 128;
TIMSK0 |= (1 << OCIE0A);
}
// If you really need to change the serial polling
// interval, use this function to initialize UnoJoy.
// interval is the polling frequency, in ms.
void setupUnoJoy(int interval){
serialCheckInterval = interval;
setupUnoJoy();
}
// This interrupt gets called approximately once per ms.
// It counts how many ms between serial port polls,
// and if it's been long enough, polls the serial
// port to see if the UnoJoy firmware requested data.
// If it did, it transmits the appropriate data back.
ISR(TIMER0_COMPA_vect){
serialCheckCounter++;
if (serialCheckCounter >= serialCheckInterval){
serialCheckCounter = 0;
// If there is incoming data stored in the Arduino serial buffer
while (Serial.available() > 0) {
pinMode(13, OUTPUT);
//digitalWrite(13, HIGH);
// Get incoming byte from the ATmega8u2
byte inByte = Serial.read();
// That number tells us which byte of the dataForController_t struct
// to send out.
Serial.write(((uint8_t*)&controllerDataBuffer)[inByte]);
//digitalWrite(13, LOW);
}
}
}
// Returns a zeroed out (joysticks centered)
// dataForController_t variable
dataForController_t getBlankDataForController(void){
// Create a dataForController_t
dataForController_t controllerData;
// Make the buttons zero
controllerData.triangleOn = 0;
controllerData.circleOn = 0;
controllerData.squareOn = 0;
controllerData.crossOn = 0;
controllerData.l1On = 0;
controllerData.l2On = 0;
controllerData.l3On = 0;
controllerData.r1On = 0;
controllerData.r2On = 0;
controllerData.r3On = 0;
controllerData.dpadLeftOn = 0;
controllerData.dpadUpOn = 0;
controllerData.dpadRightOn = 0;
controllerData.dpadDownOn = 0;
controllerData.selectOn = 0;
controllerData.startOn = 0;
controllerData.homeOn = 0;
//Set the sticks to 128 - centered
controllerData.leftStickX = 128;
controllerData.leftStickY = 128;
controllerData.rightStickX = 128;
controllerData.rightStickY = 128;
// And return the data!
return controllerData;
}
#endif
This isn't my code btw... Its the one i was trying to use on the vjoy thing, as mine didn't work. If its too much time-consuming for you, its not a problem, i know i made a mistake not buying the Leonardo. I have conected 1 potentiometer, as I was just trying if I could make it work somehow. The wiring is as simple as 5V to Pin 1, Ground to Pin 3, Data to A0.
void setup() {
Serial.begin(9600);
}
void loop() {
int x = analogRead(A0);
int y = analogRead(A1);
Serial.print(x);
Serial.print(",");
Serial.println(y);
delay(10);
}
Inicial code I had. Much easier
Good, thanks. Mind making a pen and paper drawing showing the connections. That code just can’t fail.
Yes, there is… but… well, I went to Unojoy GitHub and and I stopped right from the first lines.
“It is a three-part system:
Drivers - Needed to re-flash the Arduino's USB communication chip
…
Firmware - Code to load onto Arduino's USB communication chip”
I don’t know your background using Arduino, but reflashing the USB communication chip is not a task for begginers. And this will only work if you have an Original Uno.
So, I think you’ll be better off getting a Leonardo.
What do you want to do with the "joystick" signal (0 to 1023)?
I think the only way this
void setup() {
Serial.begin(9600);
}
void loop() {
int x = analogRead(A0);
int y = analogRead(A1);
Serial.print(x);
Serial.print(",");
Serial.println(y);
delay(10);
}
wouldn't work is sloppy wiring.
Not minding breaking or learning new things on the arduino :P
A clutch signal :)
(Axis)
Problem is I couldnt get the re-flash to work
Hope you can see that correctly, if not, tomorrow I will do a pen and paper diagram, as its too late for me now. :( Thanks for helping!!!
Wait! Your picture only shows one POT. Your code reads two POTS.
I uploaded it and used one POT. That POT worked. The other POT pin that is left floating kind of follows the POT that is wired.
Did you say this code did not work? Or did I misread between the lines?
I can’t accurately tell how it’s wired.
It works, but I cant convert the signal into a digital one, like an Axis. Did I answered you question...?
You don't convert it to a digital signal. You use it to know how far along the axis you are. You can map the analog value (0-1023) to other things like distance, output, speed, angles, etc…
For example, i am playing around with a timer right now. I use the POT to adjust the timer. I mapped 0-1023 to be 0-180 seconds.
If you want to treat it similar to a digital signal, you would have to do something if the the analogRead value is above or below a threshold you choose.
Your uno can acquire a value between 0 and 1023 representing the potentiometer's position.
With a bit of math, the 0..1023 can become a larger or smaller interval (with potential gaps if you want a larger interval) - so you can get a numerical value from this.
My questions are:
- what do you call a digital signal like an Axis ?
- do you expect your UNO to appear as a joystick on your PC?
I believe so, and that’s the whole point since the beggining.
OP mentions in post #4 code that depends on reflashing the ATmega16U2 chip in order for the Uno to behave like an HID device. Also says in post #14 they could not “re-flash” (the communications chip). Despite being told that this operation is not easy…
Even so, the pic at post #15 shows a knock-off Uno with a CH340 chip.
I admire OPs
Many of us started this way. But the path followed in this thread will lead nowhere.
