V USB mouse with PS2 joystick board

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone,

I have a useless raspberry pi 1 from an old project but minecraft works pretty well with it.

I want to build a minecraft portable gaming station and make two homemade boards ( or one with two projects on it).

The first one will translate push buttons to keyboard shortcuts (for action and movements).

The second one will translate the PS2 joystick into mouse moove (for the viewing).

Both will use V-USB library.

The first project will be simple cause i've done quite the same once for a boat raspberry navigation project (thanks again for helping me).

The second one will be harder for me cause i've never had experience with mouse and usbasp.

Maybe it would be simple to hack some raspberry code and wire the joystick on it but i like AVR very much and i'm worst than a noob in java and python.

Do you think it's possible ?

Do you think i can use a second joystick and translate the mooves into shortcut with V-USB ? It would be more convinient to play with joystick than buttons.

Thanks for advices

I use ATMEL STUDIO 6 and work now on ATMEGA328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If this is your first USB project I'd use real USB so get some form of AT90USB and LUFA. V-USB could otherwise prove a major stumbling block.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for reply.
This is my second USB project.
I want to use v-usb and ATMEGA328P cause i got everything at home. But i've never experimented v-usb as a mouse but i don't think it's much more complicated than keyboard HID.

I use ATMEL STUDIO 6 and work now on ATMEGA328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The thing about V-USB is that the "USB trick" consumes a lot of what the CPU has available. I guess if it's doing nothing more than acting as a mouse, keyboard or joystick controller then perhaps that does not matter. But if that's the case then why not simply use a mouse/joystick/etc that already has its own controller? What does the AVR actually add? If this is about converting mouse to joystick moves or something then why not just do that after reception on the RPi?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If this is your first USB project I'd use real USB so get some form of AT90USB and LUFA.
... or Teensy

C code for Teensy: USB Mouse

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't mind about CPU usage cause both ATMEGA328p will be used only to emulate a keyboard and a mouse.

I thing the simpliest way will be to wire the right joystick on input of the raspberry (i've seen tutos about how to do that) and make a DIY board to emulate a keyboard.

So that i'll concentrate all my attention on the way to translate joystick movements to HID keyboard values with V-USB. I'll save one ATMEGA328p for something else..

 

I use ATMEL STUDIO 6 and work now on ATMEGA328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In fact, the tuto i've seen is for a arduino nano so, the code would be easily compiled for a 328p chip.

Her it is

I use ATMEL STUDIO 6 and work now on ATMEGA328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If this is your first USB project I'd use real USB so get some form of AT90USB and LUFA. V-USB could otherwise prove a major stumbling block.

I was thinking exactly the opposite.

 

With a project like LUFA I quickly get completely lost in the configuration.

I might be able to get it to work relatively quickly, but trying to understand what it all does and how it works is almost impossible for me.

 

With V-USB you have a few kB of source code, almost all written in C (C++?, haven't looked lately) and that is something I am familiar with and can understand. A few years ago I had a brief look at V-USB and it looked pretty profesionally written and understandable.

A lot easier to understand the concepts of USB than to try to read to thousands of dry pages of USB specifications.

 

When starting with a working HID example and V-USB you have a great platform for learning the USB protocols, stack, and how it works.

 

V-USB has a bunch of limitations. It only does low-speed USB, and therefore does not do things like audio and several of the other higher level USB protocols, which need at least Full-Speed USB.

 

Low-speed USB also has a pretty nice advantage.

I have sucesssfully captured Low-speed USB with an USD 10 Logic Analyser and Sigrok/Pulseview has software decoders for the low level USB protocols and initialisation.

With this combination you have both compact sourcecode with no need to dive into complex configuration of USB hardware peripherals, and a way to directly snif onto the hardware wires.

Sigrok can show a lot of stuff on the low level USB protocool. It recognises T-states, bit stuffing, keep alive messages, checksums and a lot of other things, and it can also flag errors in USB messages.

I think this makes it an excellent learning platform for getting to know the LOW level USB stuff.

 

After that, I would probably quickly start using a uC with hardware USB support for the better performance and lower software overhead.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For anyone who isn't an expert in USB, but is wishing to learn more,  I suggest getting an Arduino Leonardo R3 module development board for a learning platform.  Even if you have started development on another platform it doesn't hurt to have a second approach under development at the same time.   In case you run into an insurmountable hurdle with one of the USB libraries that function at a lower CPU level, you can still get a working demo of the project functioning with the Leonardo.  With Arduino you can focus your brain power on becoming an expert on your application instead of spending the same mental effort becoming an expert on the USB/CPU interfacing details.

 

The Arduino Leonardo R3 has an ATmega32u4 CPU with a USB interface built into the CPU.   These boards sell for about $6 USD each on eBay because they are mass-produced.  The (freely downloadable) Arduino IDE includes a mouse/keyboard library that permits the Arduino program to emulate a mouse/kbd that is plugged into a PC.   In other words, you can program a sequence of mouse movements and clicks (or keyboard presses) that will be sent to the PC when you press a button (or activate a sensor) on the Arduino board.   This library is open-sourced for study and modification to your needs.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
After that, I would probably quickly start using a uC with hardware USB support for the better performance and lower software overhead.
An alternative to the PJRC Teensy HalfKay (512 byte) mega32U4 bootloader :

GitHub - rrevans/ubaboot: USB bootloader for atmega32u4 in 512 bytes

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

My ATMEGA8 board is done. The ps2 joystick breakout board is powerded withe the 5v of usb cable.

The joystick is made of two pots which are half course when not used.

The x and y channels are cabled to PC4 and PC3.

I need to get the input value and translate this to mouse reports (from -127 to +127).

The code is very simple but it does not work as expected. When i plug the board, my cursor goes to the upper left corner, even if i moov the joystick.

At middle course, the pots would be around 512 (10bits / 2). So, the mouse should return zero. up/left, positive values and bottom right, negative values (or the opposit ???).

The 0.01 coeficient deals with mouse speed.

 

static void LireJoystick(void) {

cli();    //Interruptions désactivées
joyx= read(4)-512;                        //Lecture ADC4 (PC4)
joyy= read(3)-512;                        //Lecture ADC3 (PC3)
if ((abs(joyx)) > 10) {                   //
reportBuffer.dx= ((signed char)joyx) * 0.01; }    //On sauvegarde la valeur dans le registre dx
else reportBuffer.dx=0;
if ((abs(joyy)) > 10) {
reportBuffer.dy= ((signed char)joyy) * 0.01; }    //On sauvegarde la valeur dans le registre dy
else reportBuffer.dy=0;

}

I don't think the problem would come from my ADC routine, as it's a very simple routine but i also post it :

void adc_init()
{
	DDRC =0;
	PORTC =0;
	// AREF = AVcc
	ADMUX = (1<<REFS0);
	// ADC Enable (ADEN) and prescaler of 128 (ADPS)
	ADCSRA = (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);      // F_CPU/8
}

uint16_t read(uint8_t ch)
{
	ch &= 0b00000111;				// Masque pour éviter les erreurs ch entre 0 et 7 (3bits)
	ADMUX|=ch;					// sélection du canal
	ADCSRA |= (1<<ADSC);			        //Début de conversion
	while(ADCSRA & (1<<ADIF));		        //Attente fin de conversion ADIF=1
  	ADCSRA|=(1<<ADIF);				//On reforce ADIF à 1 (normalement 0 mais le datasheet dit de faire ainsi
	return (ADC);					//On retourne les 16 bits de l'ADC
}

Thanks

I use ATMEL STUDIO 6 and work now on ATMEGA328p

Last Edited: Sat. Apr 20, 2019 - 01:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You only OR ch bits into ADMUX. This can only ever set bits, not clear them. So you will only be reading channel 7.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've modify the code like this :

char read(uint8_t ch)
{
    ch &= 0b01100111;                // Masque pour éviter les erreurs ch entre 0 et 7 (3bits) REFS0, ADLAR et MUX2, MUX1, MUX0
    ADMUX=ch;                        // sélection du canal
    ADCSRA |= (1<<ADSC);             //Début de conversion
    while(ADCSRA & (1<<ADIF));       //Attente fin de conversion ADIF=1
    ADCSRA|=(1<<ADIF);               //On reforce ADIF à 1 (normalement 0 mais le datasheet dit de faire ainsi
    return (ADCH);                   //On retourne les 8 bits de poids fort de l'ADC
}
static void LireJoystick(void)
{
    //cli();    //Interruptions désactivées
    joyx= read(100)-126;                   //Lecture ADC4 (PC4) ADMUX = 01100100  PC4 + REFS0 + ADLAR
    joyy= read(99)-126;                    //Lecture ADC3 (PC3) ADMUX = 01100011  PC3 + REFS0 + ADLAR
    
    if ((abs(joyx)) > 4) {
        reportBuffer.dx= joyx * 0.2; }     //On sauvegarde la valeur dans le registre dx
    else reportBuffer.dx=0;
    if ((abs(joyy)) > 4) {
        reportBuffer.dy= joyy * 0.2; }     //On sauvegarde la valeur dans le registre dy
    else reportBuffer.dy=0;
    //sei();
}

It's alive but only move from upper left to lower right when mooving the Y axis.

Strange thing !!!

I use ATMEL STUDIO 6 and work now on ATMEGA328p

Last Edited: Sat. Apr 20, 2019 - 09:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code now loses REFS0 ?? You do seem to over complicating this! Why not simply:

ADMUX = (1 << REFS0) | (ch & 0x07);

in the read() routine.

 

While you are there drop the ADIF stuff and block on ADSC instead.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

While you are there drop the ADIF stuff and block on ADSC instead.

 

I'm sorry, i don't understand what you are saying.

 

My code is not very nice looking but it works now.

There where 2 problems :

* I added a 1ms delay between the two ADC calls.

* I add a >>1 in ADCH value and get rid of my reversing trouble.

The mouse was working well with very small values but always go to negative values with bigger.

I'm quite proud of me cause, this time, i've found the solution by myself ...

 

The resulting problem is that, now, the joystick's working range is tiny, so, the precision is lower but in MINECRAFT (raspberry), it does not matter.

 

Thanks for your advices, you're always there when i need your help.

 

If someone is interrested into building this kind of device, do not hesitate to contact me, i'll share my layout and code.

I use ATMEL STUDIO 6 and work now on ATMEGA328p