Help! Arduino Joystick

I want to make a processing drawing project control by the joystick
I found this tutorial code online,
But it comes to errors, could anyone check what's wrong for me? Thanks a lot!!!

The code for both processing and Arduino is attached.

Thanks a lot!!!!!! :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :fearful:

ap_ReadMultiAnalog_2 (1).pde (1.31 KB)

pa_Joystick.zip (13.9 KB)

What errors do you get, where do you get them?

First: Did you check the code ? Ardiuno and Processing ... I try to check both codes, my Arduino IDE can not load it, so I copy & paste using Notepad into the Arduino IDE. I check the code, the "sending data" is wrong... And also the Processing, it look OK, but a few mistakes ( port variable name ), framerate(); <--? my IDE show me error. More check up is needed.

My opinion.

  int analogInput_1 = 2;  analogInput_2 = 3;
  int value_1 = 0;  value_2 = 0;

Multiple declarations in one statement are separated by commas, not semicolons. Even better, though, would be to simply not do this. Use one statement per variable declaration. Trust me, you'll really appreciate doing this as your code gets larger.

  beginSerial(9600);

That should be Serial.begin(9600); That author was using some pre-release version of the Arduino software, many, many years ago, apparently. Otherwise, the author is an idiot.

Thanks a lot!!!!

I corrected these mistakes but still errors appear

'printByte' was not declared in this scope.
'printInteger' was not declared in this scope.

Is it supposed to be 'byte.print'?
And I don't understand what does printInteger means..

I would think they are supposed to be Serial.write() or Serial.print().

OK, here my modification of this code. I fix the "bugs" you simply do the rest.

I hope I am correct.... Not tested yet...

/*
*  ap_ReadMultiAnalog_2
*  
*  Reads an two analog inputs and sends their values over the serial port.
*  Values are preceeded by an identifier (here letters 'A' and 'B') and after 
*  each value a line break is sent.
*  
*  This file is part of the Arduino meets Processing Project.
*  For more information visit http://www.arduino.cc.
*
*  copyleft 2005 by Melvin Ochsmann for Malmš University
*
*/

// two variables for each input pin to read and store the values 
  int analogInput_1 = 2; 
  int analogInput_2 = 3;
  int  value_1 = 0;
  int  value_2 = 0;

// an identifier for each value 
  char id_1 = 'A'; 
  char id_2 = 'B';      

void setup() {   

// declaration of pins modes    
  pinMode(analogInput_1, INPUT);
  pinMode(analogInput_2, INPUT);

// begin sending over serial port
  Serial.begin(9600);
}

void loop() 
{
// read the values od the analog pins and store them in variables
  value_1 = analogRead(analogInput_1);  
  value_2 = analogRead(analogInput_2);

// print out the variables preceeded by their IDs and followed by a carriage return 
// (that allows us to know where the values end and when to expect the id)
    Serial.print(id_1); 
    Serial.print(value_1);
    Serial.print(10,BYTE);
    
// Now, it your turn to change thoses...
    printByte(id_2); 
    printInteger(value_2);  printByte(10);
        
// and wait shortly to not overload the port/board?
    delay(10);
      
}

THANKS A LOT???
The arduino file is running well now :sweat_smile:

I uploaded the arduino file to the arduino uno
and run the processing file, but nothing happened when I move the joystick.. The processing background remained black.
I was thinking maybe its because of the processing file? or the connection ..

// importing the processing serial class
  import processing.serial.*;
// the display item draws background and grid
  DisplayItems di;
// definition of window size and framerate
  int xWidth = 512;
  int yHeight = 512;
  int fr = 24;
// attributes of the display
  boolean bck = true;
  boolean grid = false;
  boolean g_vert = true;
  boolean g_horiz = true;
  boolean g_values = false;
  boolean output = true;
// variables for serial connection, portname and baudrate have to be set 
  Serial myPort;
  
  int value = 0; 
// buffer and value variable for each value and boolean to switch between values
  String bufA="", bufB="";  
  boolean buf;  // boolean switch to distinguish values
  int value1, value2;  // value1, value2 that then are passed on to xpos and ypos
// variables for drawing function
  int xpos, ypos;
  int prevX, prevY;
  boolean paint = false;
  int curCol = 1;
  int strWght = 1;
  
// lets user control DisplayItems properties, value output and drawing attributes
void keyPressed(){
  if (key == 'b' || key == 'B') bck=!bck;  // background black/white
  if (key == 'g' || key == 'G') grid=!grid;  // grid ON/OFF 
  if (key == 'v' || key == 'V') g_values=!g_values;  // grid values ON/IFF   
  if (key == 'o' || key == 'O') output=!output;   //turns value output ON/OFF
  if (keyCode == ENTER) paint=!paint; // enter turn paint ON/OFF
  if (keyCode == BACKSPACE) clear(); //backspace clears screen
  // + and - increase/decrease stroke weight 
  if (key == '+') { if(strWght == 5){strWght = 5;}else{strWght++;}}
  if (key == '-') { if(strWght == 1){strWght = 1;}else{strWght--;}}
  // c switches colors between red/blue/green
  if (key == 'c' || key == 'C') { curCol++; if(curCol > 3)curCol=1; }; 
}

void setup(){
  // set size and framerate
  size(xWidth, yHeight);
 
  // establish serial port connection  


  myPort = new Serial(this, "/dev/tty.usbmodemfd121", 9600);

  // create DisplayItems object
  di = new DisplayItems();
}

void clear(){
   background( (bck) ? (0) : (255) );
}

void drawLine(int x, int y, int px, int py){
   line(x, y, px, py);
}

void drawCursor(int x, int y){
  background(  (bck) ? (0) : (255) );
  stroke( (bck) ? (255) : (32) );
  strokeWeight(1);
  line(x-(width/128), y , x+(width/128), y );
  line(x, y-(width/128), x, y+(width/128) );
}

// reads the serial events, stores events in buffer and asigns values
void serialEvent(int serial){
  if(serial!=10) {      
      if (serial=='A') buf = true;
      if (serial=='B') buf = false;
      if (buf){ if (serial!='A') bufA += char(serial);
                }else{
                if (serial!='B') bufB+= char(serial);
                }
      } else {
                if (buf){  value1 = int(bufA); bufA="";
                } else {   value2 = int(bufB); bufB="";
                }
      }      
}

void startDrawing(){
  if (!paint)  { drawCursor( xpos, ypos ); }
  if (paint) { strokeWeight(strWght); drawLine( xpos, ypos, prevX, prevY ); }
}

void draw(){
// set previous x and y position to current x and y position
  prevX=xpos;
  prevY=ypos;
// listen to serial port and trigger serial event     
  while(myPort.available() > 0){
        value = myPort.read();
        serialEvent(value);
   }
// read values 1 and 2 and transform in x and y position
  xpos = constrain(  ((value1-100)*(width+100))/width , 0, width );
  ypos = constrain(  ((value2-100)*(height+100))/height , 0, height );
// paint background if paint is false                        
  if(!paint) di.drawBack();
// set color if paint is true
  if(paint){
    switch(curCol){
        case 1: stroke(255, 0, 0); break;
        case 2: stroke(0, 255, 0); break;
        case 3: stroke(0, 0, 255); break;
        }
   }
    // begin drawing and drawItems
   startDrawing();
   di.drawItems();
   if (output) println("xpos: "+xpos+" - ypos: "+ypos);
}

BTW.Attached is the processing file

pa_Joystick.zip (15.2 KB)

void serialEvent(int serial){
  if(serial!=10) {      
      if (serial=='A') buf = true;
      if (serial=='B') buf = false;
      if (buf){ if (serial!='A') bufA += char(serial);
                }else{
                if (serial!='B') bufB+= char(serial);
                }
      } else {
                if (buf){  value1 = int(bufA); bufA="";
                } else {   value2 = int(bufB); bufB="";
                }
      }      
}

The argument to this function is supposed to be a Serial instance. Where you got the idea that you could just make up stuff is beyond me.

@PaulS

Thank PaulS for that "section", The Processing code was "buggy". Hum, that bug is a functional one. More tests is needed.

@zhubiyin

Can you change this section of the code in the Processing

myPort = new Serial(this, "/dev/tty.usbmodemfd121", 9600);

To:

muPort = new Serial(this,Serial.list()[0], 9600);  // The 0 is COM1 in my system

// The zero is the port location. Your system is different, bear that in mind

Can you try this code to check what port your Arduino is connected. And simply put the array number in your Processing code.
Example : Port 7 - Ardiuno --> [3] - COM7 The number is 3.

The Processing code to check the port array number

import processing.serial.*;
// The serial port:
Serial myPort; 
// List all the available serial ports:
println(Serial.list());

@zhubiyin

I just tested the joystick program. I modify it and I add two switch to monitor. So the program will send the x-axis value, y-axis value, the first switch value and the second switch value. So the output is :

X234 <--- X-axis value from 0 to 1023
Y456 <-- Y-axis value from 0 to 1023
A0 <-- Switch A , 0 is off, 1 is on
B1 <-- Switch B , 0 is off, 1 is on

My hardware is : TANDY Deluxe Joystick cat 26-3012B -- Analog joystick with two push-on button. Don't try to get this, That joystick is over 20 years old. It is from an old Color Computer 2. I simply don't have your type of joystick.

The Processing code section will be investigated.

Here the Arduino code : Code is compiled and tested

/*
*  
*  Reads an two analog inputs and two push-on swtiches sends 
*  their values over the serial port.
*  Values are preceeded by an identifier ( X for x-axis and
*  Y for y-axis and A for Swtich 1 and B for Switch 2 ) and after 
*  each value a line break is sent. 
*  
*  This file is part of the Arduino meets Processing Project.
*  For more information visit http://www.arduino.cc.
*
*  original file - copyleft 2005 by Melvin Ochsmann for Malmš University
*
*  Modify by Serge J Desjardins - aka techone / tech37
*/

// Analog pins and Digital pins   
  byte analogInput_1 = 1; 
  byte analogInput_2 = 2;
  byte inpin[2] = {12,11};
  
// The push button values  
  int sw1 = 1;
  int sw2 = 1;

// The Joystick value using x and y axis   
  int  xvalue = 0;
  int  yvalue = 0;

// an identifier for each value 
  char id_1 = 'X'; 
  char id_2 = 'Y';      
  char id_3 = 'A';
  char id_4 = 'B';
  
void setup()
{   

// init pins    
  pinMode(inpin[0], INPUT);
  pinMode(inpin[1], INPUT);

// init serial port
  Serial.begin(9600);
}

void loop() 
{
// read the values of the analog pins and the digital pins and store them in variables
  xvalue = analogRead(analogInput_1);  
  yvalue = analogRead(analogInput_2);
  sw1 = digitalRead(inpin[0]);
  sw2 = digitalRead(inpin[1]);

// print out the variables preceeded by their IDs and followed by a carriage return 
// (that allows us to know where the values end and when to expect the id)
    Serial.print(id_1); 
    Serial.print(xvalue);
    Serial.print(10,BYTE);
    
    Serial.print(id_2); 
    Serial.print(yvalue);
    Serial.print(10, BYTE);
    
    Serial.print(id_3);
    Serial.print(sw1);
    Serial.print(10, BYTE);

    Serial.print(id_4);
    Serial.print(sw2);
    Serial.print(10, BYTE);    
// and wait shortly to not overload the port/board?
    delay(100);
      
}

@zhubiyin

Again, I re-program the Arduino program. Here is the final code.

The Processing program is next post.

/*
*  
*  Reads an two analog inputs  sends 
*  their values over the serial port.
*  Values are preceeded by an identifier ( X for x-axis and
*  Y for y-axis  and after 
*  each value a line break is sent. 
*  
*  This file is part of the Arduino meets Processing Project.
*  For more information visit http://www.arduino.cc.
*
*  original file - copyleft 2005 by Melvin Ochsmann for Malmš University
*
*  Modify by Serge J Desjardins - aka techone / tech37
*
*  Compiled and Tested - - Worked with the Processing Joystick program.
*/

// Analog pins and Digital pins   
  byte analogInput_1 = 1; 
  byte analogInput_2 = 2;
    
// The Joystick value using x and y axis   
  int  xvalue = 0;
  int  yvalue = 0;

// an identifier for each value 
  char id_1 = 'X'; 
  char id_2 = 'Y';      
   
void setup()
{   
// init serial port
  Serial.begin(9600);
}

void loop() 
{
// read the values of the analog pins  and store them in variables
  xvalue = analogRead(analogInput_1);  
  yvalue = analogRead(analogInput_2);
 
// print out the variables preceeded by their IDs and followed by a carriage return 
// (that allows us to know where the values end and when to expect the id)
    Serial.print(id_1); 
    Serial.print(xvalue);
    Serial.print(10,BYTE);
    
    Serial.print(id_2); 
    Serial.print(yvalue);
    Serial.print(10, BYTE);

   //Wait shortly to not overload the port/board
    delay(100);
      
}

Here the Processing program. I modify it to make it work with the joystick that I have on-hand -- Tandy deluxe joystick. The only file was not modify is the class file DisplayItems. That file work fine.

here is the Processing file : Compile and Tested.... Work with the Arduino program post before.

/*
*  pa_Joystick
*  
*  A drawing program, the cursur is controlled by a joystick or two potentiometers.
*  Use keys to control the following functions:
*   'ENTER' to start/stop drawing
*   'BACKSPACE' to clear the screen
*   'C' to switch between red/green/blue as drawing colors
*   '+' and '-' to increase/decrease stroke weight
* 
*  This file is part of the Arduino meets Processing Project.
*  For more information visit http://www.arduino.cc.
*
*  copyleft 2005 by Melvin Ochsmann for Malm? University
*
* Modify by Serge J Desjardins aka techone / tech37
*/

// importing the processing serial class
  import processing.serial.*;
// the display item draws background and grid
  DisplayItems di;
// definition of window size and framerate
  int xWidth = 512;
  int yHeight = 512;
  int fr = 24;
// attributes of the display
  boolean bck = true;
  boolean grid = false;
  boolean g_vert = true;
  boolean g_horiz = true;
  boolean g_values = false;
  boolean output = true;
// variables for serial connection, portname and baudrate have to be set 
  Serial port;
  int portname =3; // <-- change this number to your port number 
  int baudrate = 9600;
  int value = 0;
  int lf=10;  // <-- I add that variable
  
// buffer and value variable for each value and boolean to switch between values
  String bufA="", bufB="";  
  boolean buf;  // boolean switch to distinguish values
  int value1, value2;  // value1, value2 that then are passed on to xpos and ypos
// variables for drawing function
  int xpos, ypos;
  int prevX, prevY;
  boolean paint = false;
  int curCol = 1;
  int strWght = 1;
  
// lets user control DisplayItems properties, value output and drawing attributes
void keyPressed(){
  if (key == 'b' || key == 'B') bck=!bck;  // background black/white
  if (key == 'g' || key == 'G') grid=!grid;  // grid ON/OFF 
  if (key == 'v' || key == 'V') g_values=!g_values;  // grid values ON/IFF   
  if (key == 'o' || key == 'O') output=!output;   //turns value output ON/OFF
  if (keyCode == ENTER) paint=!paint; // enter turn paint ON/OFF
  if (keyCode == BACKSPACE) clear(); //backspace clears screen
  // + and - increase/decrease stroke weight 
  if (key == '+') { if(strWght == 5){strWght = 5;}else{strWght++;}}
  if (key == '-') { if(strWght == 1){strWght = 1;}else{strWght--;}}
  // c switches colors between red/blue/green
  if (key == 'c' || key == 'C') { curCol++; if(curCol > 3)curCol=1; }; 
}

void setup(){
  // set size and framerate
  size(xWidth, yHeight);
  frameRate(fr); // The original was bad, I change it 
  // establish serial port connection      
  port = new Serial(this,Serial.list()[portname], baudrate); // also the original was bad. I change that to
  println(Serial.list()[portname]);
  // create DisplayItems object
  di = new DisplayItems();
  xpos=xWidth/2; // That was missing
  ypos=yHeight/2; // That was missing
  port.bufferUntil(lf); // The routine serialevent() need this statement, I add that line
}

void clear(){
   background( (bck) ? (0) : (255) );
}

void drawLine(int x, int y, int px, int py){
   line(x, y, px, py);
}

void drawCursor(int x, int y){
  background(  (bck) ? (0) : (255) );
  stroke( (bck) ? (255) : (32) );
  strokeWeight(1);
  line(x-(width/128), y , x+(width/128), y );
  line(x, y-(width/128), x, y+(width/128) );
}

// reads the serial events, stores events in buffer and asigns values
// Sorry PaulS, I did not change that, I keep it as is.
void serialEvent(int serial){
  if(serial!=10) {      
      if (serial=='X') buf = true;
      if (serial=='Y') buf = false;
      if (buf){ if (serial!='X') bufA += char(serial);
                }else{
                if (serial!='Y') bufB+= char(serial);
                }
      } else {
                if (buf){  value1 = int(bufA); bufA="";
                } else {   value2 = int(bufB); bufB="";
                }
      }      
}

void startDrawing(){
  if (!paint)  { drawCursor( xpos, ypos ); }
  if (paint) { strokeWeight(strWght); drawLine( xpos, ypos, prevX, prevY ); }
}

void draw(){
// set previous x and y position to current x and y position
  prevX=xpos;
  prevY=ypos;
// listen to serial port and trigger serial event     
  while(port.available() > 0){
        value = port.read();
        serialEvent(value);
   }
// read values 1 and 2 and transform in x and y position
  
  xpos = int(map(value1,0,1023,0,xWidth)); // The cursor was not center properly
  ypos = int(map(value2,0,1023,0,yHeight)); // I simply change it to a map() function
 
// paint background if paint is false                        
  if(!paint) di.drawBack();
// set color if paint is true
  if(paint){
    switch(curCol){
        case 1: stroke(255, 0, 0); break;
        case 2: stroke(0, 255, 0); break;
        case 3: stroke(0, 0, 255); break;
        }
   }
    // begin drawing and drawItems
   startDrawing();
   di.drawItems();
   println("xpos: "+xpos+" - ypos: "+ypos); // To monitor what is going on. The original was "not proper"
}