I can't share the schematics as they are not mine, I'm trying to add an analog thumbstick (4 pins, Vcc/GND/x/y) to my atmega32u4 powered keyboard.
The thumbstick pins are connected to pins PB4 (ADC11) and PB5 (ADC12) on the atmega chip (I did a continuity test to be sure).
I did do some measurements with my multimeter, so here are the facts I gathered:
- AVcc <> GND : 5V
- When the analog joystick is plugged in:
- GND <> PB4: 2.5V (and it fluctuates when I move the joystick)
- GND <> PB5: 2.5V (same)
- When the analog joystick is unplugged:
- GND <> PB4: 0V
- GND <> PB5: 0V
I always get 1023
, even when the joystick is not plugged in !
I tried the following methods, which all yield the same result:
- manually settings the bits in the registers (ADCSRA, ADMUX)
- using LUFA
- using QMK's
adc_read
helper function
Here is the code I used (which I hacked from the LUFA VirtualSerial) example (original can be found here); I guess the interesting parts are in the my_adc_init
& my_adc_read
function.
#include "VirtualSerial.h"
#include <LUFA/Drivers/Peripheral/ADC.h>
#include "../../../../LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h"
void my_adc_init(void)
{
ADC_Init(ADC_SINGLE_CONVERSION | ADC_PRESCALE_32);
ADC_SetupChannel(11); // Y
ADC_SetupChannel(12); // X
}
uint16_t my_adc_read(void)
{
ADC_StartReading(ADC_REFERENCE_INT2560MV | ADC_CHANNEL11);
while (!(ADC_IsReadingComplete()));
return ADC_GetResult();
}
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
{
.Config =
{
.ControlInterfaceNumber = INTERFACE_ID_CDC_CCI,
.DataINEndpoint =
{
.Address = CDC_TX_EPADDR,
.Size = CDC_TXRX_EPSIZE,
.Banks = 1,
},
.DataOUTEndpoint =
{
.Address = CDC_RX_EPADDR,
.Size = CDC_TXRX_EPSIZE,
.Banks = 1,
},
.NotificationEndpoint =
{
.Address = CDC_NOTIFICATION_EPADDR,
.Size = CDC_NOTIFICATION_EPSIZE,
.Banks = 1,
},
},
};
static FILE USBSerialStream;
int i = 0;
int main(void)
{
SetupHardware();
CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream);
GlobalInterruptEnable();
for (;;)
{
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
if (++i % 50 == 0)
{
i = 0;
fprintf(&USBSerialStream, "w00t: %d\r\n", my_adc_read());
}
}
}
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif
/* Hardware Initialization */
USB_Init();
my_adc_init();
}
void EVENT_USB_Device_Connect(void)
{
}
void EVENT_USB_Device_Disconnect(void)
{
}
void EVENT_USB_Device_ConfigurationChanged(void)
{
CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
}
void EVENT_USB_Device_ControlRequest(void)
{
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
}
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)
{
bool HostReady = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) != 0;
(void)HostReady;
}
Disclaimer, I'm very new to all of this, trying to learn as I go (: