Hello. I'm in a team working with a Leonardo to develop a controller for a piece of software using Godot. There's an element of confidentiality associated with the project, but I can share the following C code and images:
#include <XInput.h>
// XInput accepts values from -32768 to 32767 on each stick axis.
// We want wheel range to be from -500 to +500 degrees
// and the range of the throttle to be from 0 to 50 degrees
// Adjust IN_MIN and IN_MAX as needed
// Wheel
#define WHEEL_IN_MIN -500
#define WHEEL_IN_MAX 500
#define WHEEL_OUT_MIN -32768
#define WHEEL_OUT_MAX 32767
// Throttle
#define THROTTLE_IN_MIN 0
#define THROTTLE_IN_MAX 50
//#define THROTTLE_OUT_MIN 0
#define THROTTLE_OUT_MIN -32768 / 5
#define THROTTLE_OUT_MAX 32767
// Pulses per rotation
#define PR 600
volatile unsigned int temp, temp2, counter, counter2 = 0; // This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin(9600);
XInput.begin();
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(3, INPUT_PULLUP); // internal pullup input pin 3
// Setting up interrupt
pinMode(12, INPUT);
pinMode(13, INPUT);
// A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on most Arduino.
attachInterrupt(0, ai0, RISING);
// B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on most Arduino.
attachInterrupt(1, ai1, RISING);
// A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on most Arduino.
attachInterrupt(4, ai4, RISING);
// B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on most Arduino.
attachInterrupt(5, ai5, RISING);
}
void loop() {
// Send the value of counter
if (counter != temp) {
Serial.println(counter);
temp = counter;
}
if (counter2 != temp2) {
Serial.println(counter);
temp2 = counter2;
}
// Scale counter to range from -32768 to 32767
int wheelOut = remap(
counter,
PR * WHEEL_IN_MIN / 360,
PR * WHEEL_IN_MAX / 360,
WHEEL_OUT_MIN,
WHEEL_OUT_MAX);
// Scale counter2 to range from 0 to 32767
int throttleOut = remap(
counter2,
PR * THROTTLE_IN_MIN / 360,
PR * THROTTLE_IN_MAX / 360,
THROTTLE_OUT_MIN,
THROTTLE_OUT_MAX);
// Output the left stick x axis (steering)
XInput.setJoystick(JOY_LEFT, wheelOut, 0);
// Output the right stick y axis (throttle)
XInput.setJoystick(JOY_RIGHT, 0, throttleOut);
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if (digitalRead(3) == LOW) {
counter++;
Serial.println(counter);
} else {
counter--;
Serial.println(counter);
}
}
void ai1() {
// ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check with pin 2 to determine the direction
if (digitalRead(2) == LOW) {
counter--;
Serial.println(counter);
} else {
counter++;
Serial.println(counter);
}
}
void ai4() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if (digitalRead(6) == LOW) {
counter2++;
Serial.println(counter2);
} else {
counter2--;
Serial.println(counter2);
}
}
void ai5() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if (digitalRead(7) == LOW) {
counter2++;
Serial.println(counter2);
} else {
counter2--;
Serial.println(counter2);
}
}
int remap(int value, int fromLow, int fromHigh, int toLow, int toHigh) {
if (value < fromLow) value = fromLow;
if (value > fromHigh) value = fromHigh;
return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
}
Here are some images of the project/project setup, two rotary encoders are being used to control throttle and steering:
Here's the XInput data that's being picked up by the Godot program:
throttle,steering
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
-0.16,1.00
and so on. I believe I properly have the avr boards manager installed along with the XInput libraries. XInput is from here: GitHub - dmadison/ArduinoXInput: XInput library for USB capable Arduino boards
Help would be appreciated, as I am completely prepared for the issue to be something stupid I missed. So it goes. If it helps, this is the verbose upload info:
FQBN: xinput:avr:leonardo
Using board 'leonardo' from platform in folder: C:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5
Using core 'arduino' from platform in folder: C:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5
Detecting libraries used...
C:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_LEONARDO -DARDUINO_ARCH_AVR -DUSB_VID=0x045E -DUSB_PID=0x028E -DUSB_MANUFACTURER="\xA9Microsoft" -DUSB_PRODUCT="Arduino Leonardo" -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\cores\arduino -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\variants\leonardo C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA\sketch\EncoderPother2.ino.cpp -o nul
Alternatives for XInput.h: [XInput@1.2.6]
ResolveLibrary(XInput.h)
-> candidates: [XInput@1.2.6]
C:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_LEONARDO -DARDUINO_ARCH_AVR -DUSB_VID=0x045E -DUSB_PID=0x028E -DUSB_MANUFACTURER="\xA9Microsoft" -DUSB_PRODUCT="Arduino Leonardo" -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\cores\arduino -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\variants\leonardo -Ic:\Users\User\Documents\Arduino\libraries\XInput\src C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA\sketch\EncoderPother2.ino.cpp -o nul
Using cached library dependencies for file: c:\Users\User\Documents\Arduino\libraries\XInput\src\XInput.cpp
Generating function prototypes...
C:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_LEONARDO -DARDUINO_ARCH_AVR -DUSB_VID=0x045E -DUSB_PID=0x028E -DUSB_MANUFACTURER="\xA9Microsoft" -DUSB_PRODUCT="Arduino Leonardo" -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\cores\arduino -IC:\Users\User\AppData\Local\Arduino15\packages\xinput\hardware\avr\1.0.5\variants\leonardo -Ic:\Users\User\Documents\Arduino\libraries\XInput\src C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA\sketch\EncoderPother2.ino.cpp -o C:\Users\User\AppData\Local\Temp\1863370242\sketch_merged.cpp
C:\Users\User\AppData\Local\Arduino15\packages\builtin\tools\ctags\5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives C:\Users\User\AppData\Local\Temp\1863370242\sketch_merged.cpp
Compiling sketch...
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_LEONARDO -DARDUINO_ARCH_AVR -DUSB_VID=0x045E -DUSB_PID=0x028E "-DUSB_MANUFACTURER=\"\\xA9Microsoft\"" "-DUSB_PRODUCT=\"Arduino Leonardo\"" "-IC:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\xinput\\hardware\\avr\\1.0.5\\cores\\arduino" "-IC:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\xinput\\hardware\\avr\\1.0.5\\variants\\leonardo" "-Ic:\\Users\\User\\Documents\\Arduino\\libraries\\XInput\\src" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA\\sketch\\EncoderPother2.ino.cpp" -o "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA\\sketch\\EncoderPother2.ino.cpp.o"
Compiling libraries...
Compiling library "XInput"
Using previously compiled file: C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA\libraries\XInput\XInput.cpp.o
Compiling core...
Using precompiled core: C:\Users\User\AppData\Local\Temp\arduino\cores\xinput_avr_leonardo_901d6950c734774a1eee60ef118a364d\core.a
Linking everything together...
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega32u4 -o "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.elf" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA\\sketch\\EncoderPother2.ino.cpp.o" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA\\libraries\\XInput\\XInput.cpp.o" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/..\\..\\cores\\xinput_avr_leonardo_901d6950c734774a1eee60ef118a364d\\core.a" "-LC:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA" -lm
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.elf" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.eep"
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.elf" "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.hex"
Using library XInput at version 1.2.6 in folder: C:\Users\User\Documents\Arduino\libraries\XInput
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\User\\AppData\\Local\\Temp\\arduino\\sketches\\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.elf"
Sketch uses 5476 bytes (19%) of program storage space. Maximum is 28672 bytes.
Global variables use 136 bytes (5%) of dynamic memory, leaving 2424 bytes for local variables. Maximum is 2560 bytes.
Performing 1200-bps touch reset on serial port COM4
Waiting for upload port...
Upload port found on COM3
"C:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude" "-CC:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf" -v -V -patmega32u4 -cavr109 "-PCOM3" -b57600 -D "-Uflash:w:C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.hex:i"
avrdude: Version 6.3-20190619
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\Users\User\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"
Using Port : COM3
Using Programmer : avr109
Overriding Baud Rate : 57600
AVR Part : ATmega32U4
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PA0
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 9000 9000 0x00 0x00
flash 65 6 128 0 yes 32768 128 256 4500 4500 0x00 0x00
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : butterfly
Description : Atmel AppNote AVR109 Boot Loader
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.
Programmer supports the following devices:
Device code: 0x44
avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "C:\Users\User\AppData\Local\Temp\arduino\sketches\22AAF75544393796FCFFC5F46C407FCA/EncoderPother2.ino.hex"
avrdude: writing flash (5476 bytes):
Writing | ################################################## | 100% 0.43s
avrdude: 5476 bytes of flash written
avrdude done. Thank you.