Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Issue with Teensy LC + Pot 10k for Steering Wheel

  1. #1
    Junior Member
    Join Date
    Aug 2020
    Posts
    2

    Issue with Teensy LC + Pot 10k for Steering Wheel

    Good morning all,
    I have a project to build a flywheel using a 10K potentiometer only on the X axis. I am new to arduino and the language but managed to get the potentiometer to work with some code I have recovered.
    The problem I get in is that I never manage to keep the car upright, it always moves left to right without ever being able to drive straight even when moving very slowly. I don't know what to do to get there and my programming level is too low. Yet when I do my tests with joy.cpl, I manage to place in the center without it wavering.

    Do you have any idea so that I can keep my steering wheel straight when I straighten the steering wheel please? an other idea ?

    Thank you in advance for your precious help !

    Regards,

    Code:
    #include <Bounce.h>
    
    // hat angles
    #define center -1
    #define up 0
    #define up_right 45
    #define right 90
    #define down_right 135
    #define down 180
    #define down_left 225
    #define left 270
    #define up_left 315
    
    // TeensyLC pin assignments
    #define up_pin 0 
    #define down_pin 1
    #define left_pin 2
    #define right_pin 3
    
    #define a_pin 4
    #define b_pin 5
    #define x_pin 6
    #define y_pin 7
    
    #define L1_pin 8
    #define R1_pin 10
    
    
    #define an_L_x_pin A0 // 14 digital
    #define L3_pin 16
    
    
    #define start_pin 20
    #define select_pin 21
    
    #define joy_min 0
    #define joy_max 1023
    
    // Test joysticks and record lowest and highest observed values here
    #define L_x_min_observed 600
    #define L_x_max_observed 350
    
    
    // Record "resting values" min and max
    #define L_x_min_rest 488
    #define L_x_max_rest 470
    
    #define joyX_center 512
    #define joyY_center 511
    
    // D-pad -> hat state
    int oldHatAngle = center;
    int newHatAngle = center;
    
    // D-Pad
    Bounce btn_Up = Bounce(up_pin, 10);
    Bounce btn_Down = Bounce(down_pin, 10);
    Bounce btn_Left = Bounce(left_pin, 10);
    Bounce btn_Right = Bounce(right_pin, 10);
    
    // Action Buttons
    Bounce btn_A = Bounce(a_pin, 10);
    Bounce btn_B = Bounce(b_pin, 10);
    Bounce btn_X = Bounce(x_pin, 10);
    Bounce btn_Y = Bounce(y_pin, 10);
    
    // Shoulder Buttons
    Bounce btn_L1 = Bounce(L1_pin, 10);
    Bounce btn_R1 = Bounce(R1_pin, 10);
    
    
    // Select/Start Buttons
    Bounce btn_Select = Bounce(select_pin, 10);
    Bounce btn_Start = Bounce(start_pin, 10);
    
    // Analog Stick Buttons
    
    
    // uncomment these variables to test the min and max values, also uncomment the code that uses them down below
    //int minPin = 1023;
    //int maxPin = 0;
    
    
    void setup() {
      pinMode(up_pin, INPUT_PULLUP);
      pinMode(down_pin, INPUT_PULLUP);
      pinMode(left_pin, INPUT_PULLUP);
      pinMode(right_pin, INPUT_PULLUP);
    
      pinMode(a_pin, INPUT_PULLUP);
      pinMode(b_pin, INPUT_PULLUP);
      pinMode(x_pin, INPUT_PULLUP);
      pinMode(y_pin, INPUT_PULLUP);
    
      pinMode(L1_pin, INPUT_PULLUP);
      pinMode(R1_pin, INPUT_PULLUP);
    
      pinMode(select_pin, INPUT_PULLUP);
      pinMode(start_pin, INPUT_PULLUP);
    
      pinMode(an_L_x_pin, INPUT);
    
      Joystick.hat(oldHatAngle);
    }
    
    
    
    void loop() {
      // Update all the buttons
      btn_Up.update();
      btn_Down.update();
      btn_Left.update();
      btn_Right.update();
    
      btn_A.update();
      btn_B.update();
      btn_Y.update();
      btn_X.update();
    
      btn_L1.update();
      btn_R1.update();
    
      btn_Select.update();
      btn_Start.update();
    
      newHatAngle = oldHatAngle;
    
      // Check each button for "falling" edge (= low (pressed - button connects pin to ground))
      if(btn_Up.fallingEdge()) {
        switch (newHatAngle) {
          case left  : newHatAngle = up_left; break;
          case right : newHatAngle = up_right; break;
          default    : newHatAngle = up; break;
        }
      }
      if(btn_Down.fallingEdge()) {
        switch (newHatAngle) {
          case left  : newHatAngle = down_left; break;
          case right : newHatAngle = down_right; break;
          default    : newHatAngle = down; break;
        }
      }
      if(btn_Left.fallingEdge()) {
        switch (newHatAngle) {
          case up   : newHatAngle = up_left; break;
          case down : newHatAngle = down_left; break;
          default   : newHatAngle = left; break;
        }
      }
      if(btn_Right.fallingEdge()) {
        switch (newHatAngle) {
          case up   : newHatAngle = up_right; break;
          case down : newHatAngle = down_right; break;
          default   : newHatAngle = right; break;
        }
      }
    
      if (btn_A.fallingEdge()) Joystick.button(1, 1);
      if (btn_B.fallingEdge()) Joystick.button(2, 1);
      if (btn_Y.fallingEdge()) Joystick.button(3, 1);
      if (btn_X.fallingEdge()) Joystick.button(4, 1);
    
      if (btn_L1.fallingEdge()) Joystick.button(5, 1);
      if (btn_R1.fallingEdge()) Joystick.button(6, 1);
    
      if (btn_Select.fallingEdge()) Joystick.button(9, 1);
      if (btn_Start.fallingEdge()) Joystick.button(10, 1);
    
    
      // Check each button for "rising" edge (= high (not pressed - voltage from pullup resistor))
      if(btn_Up.risingEdge()) {
        switch (newHatAngle) {
          case up_left  : newHatAngle = left; break;
          case up_right : newHatAngle = right; break;
          case up       : newHatAngle = center; break;
        }
      }
      if(btn_Down.risingEdge()) {
        switch (newHatAngle) {
          case down_left  : newHatAngle = left; break;
          case down_right : newHatAngle = right; break;
          case down       : newHatAngle = center; break;
        }
      }
      if(btn_Left.risingEdge()) {
        switch (newHatAngle) {
          case up_left   : newHatAngle = up; break;
          case down_left : newHatAngle = down; break;
          case left      : newHatAngle = center; break;
        }
      }
      if(btn_Right.risingEdge()) {
        switch (newHatAngle) {
          case up_right   : newHatAngle = up; break;
          case down_right : newHatAngle = down; break;
          case right      : newHatAngle = center; break;
        }
      }
    
      if (btn_A.risingEdge()) Joystick.button(1, 0);
      if (btn_B.risingEdge()) Joystick.button(2, 0);
      if (btn_Y.risingEdge()) Joystick.button(3, 0);
      if (btn_X.risingEdge()) Joystick.button(4, 0);
    
      if (btn_L1.risingEdge()) Joystick.button(5, 0);
      if (btn_R1.risingEdge()) Joystick.button(6, 0);
    
      if (btn_Select.risingEdge()) Joystick.button(9, 0);
      if (btn_Start.risingEdge()) Joystick.button(10, 0);  
    
    
      if (oldHatAngle != newHatAngle) {
        Joystick.hat(newHatAngle);
        oldHatAngle = newHatAngle;
      }
    
      // Get raw joystick input values
      int lx = analogRead(an_L_x_pin);
    
    
      // Check for less than or greater than zero, to keep the axis centered
      if (lx < L_x_min_rest) {
        Joystick.X(constrain(map(lx, L_x_min_observed, L_x_min_rest, joy_min, joyX_center), joy_min, joy_max));
      }
      else if (lx > L_x_max_rest) {
        Joystick.X(constrain(map(lx, L_x_max_rest, L_x_max_observed, joyX_center, joy_max), joy_min, joy_max));
      }
      else {
        Joystick.X(joyX_center);
    
      }
    
    
    // uncomment this code to test the min and max values, also uncomment the variables it needs up above.
    // Change the analogRead(an_L_x_pin) to the axis you would like to check. Use the "Serial monitor"
    // button to view the outputs. If testing the resting values, don't move the joystick and instead take
    // the min and max values when it is resting.
    // All in all, the min and max values, and min and max resting values, will need to be tested for every axis and recorded in the macros above.
    
    //  int pin = analogRead(an_L_x_pin);
    //  bool show = false;
    //  if (pin < minPin) {
    //    minPin = pin;
    //    show = true;
    //  }
    //  if (pin > maxPin) {
    //    maxPin = pin;
    //    show = true;
    //  }
    //  if(show) {
    //    String minString = String(minPin);
    //    String maxString = String(maxPin);
    //    Serial.println(minString + ":" + maxString);
    //    show = false;
    //  }
    }

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    382
    Its reasonable to have a central dead-zone for a steering input, so that a little variation is ignored when the
    control is centred. If there's noise on the signals this will prevent jitteriness on straight running.
    You can also try to reduce noise in the first place, in hardware, by adding a capacitor on the signal,
    and avoiding ground loops.

  3. #3
    Junior Member
    Join Date
    Aug 2020
    Posts
    2
    Quote Originally Posted by MarkT View Post
    Its reasonable to have a central dead-zone for a steering input, so that a little variation is ignored when the
    control is centred. If there's noise on the signals this will prevent jitteriness on straight running.
    You can also try to reduce noise in the first place, in hardware, by adding a capacitor on the signal,
    and avoiding ground loops.
    Hello MarKT,
    Thanks for your advice, I'll add a capacitor but could you help me make this central dead-zone please?
    Thank you verry much

  4. #4
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,936
    You can probably add a deadzone in the computer settings and or the game itself, but otherwise have a look at

    // Record "resting values" min and max
    #define L_x_min_rest 488
    #define L_x_max_rest 470
    #define joyX_center 512

    and
    Code:
      // Check for less than or greater than zero, to keep the axis centered
      if (lx < L_x_min_rest) {
        Joystick.X(constrain(map(lx, L_x_min_observed, L_x_min_rest, joy_min, joyX_center), joy_min, joy_max));
      }
      else if (lx > L_x_max_rest) {
        Joystick.X(constrain(map(lx, L_x_max_rest, L_x_max_observed, joyX_center, joy_max), joy_min, joy_max));
      }
      else {
        Joystick.X(joyX_center);
    
      }
    that is already doing a deadzone by checking if the input valu is between L_Xmin_rest and L_x_max_rest and outputing a fixed value, otherwise using an re-mapped value but possibly not quite right. If the drift is continous try adjusting the JoyX_centre value if it is noisy then maybe you need to make the deadzone bigger. And if it not working at all then maybe something is completely messed up with the code when run in a teensy in some non obvious way. Doing some Serial.println(lx); may be informative.

  5. #5
    It almost sounds to me that your wheel is too sensitive. On a real car there shouldn't be a dead zone in the wheel (unless it's a 1960s Chevy), so I think that the wheel is too sensitive. In aviation they call this PIO (Pilot Induced Oscillations) because each time you try to correct the car you over-compensate and end up steering too far.

    I agree to first see if the game program has some settings that might help with the problem.

    If not, this is where a digital voltmeter would be handy to verify that the signal from the pot at the microprocessor is steady. A capacitor might help, but only if the circuit is noisy. If there is noise, I would start with a .1 uF cap. Noise is probably not the issue unless your wiring is flakey.

    If this is a steering wheel like a car, then you need something that allows you to turn the wheel multiple times (for instance 3 or 4 revolutions). You can do this with a belt and some pulleys or even a 3-turn or 5-turn pot. Essentially, you want to gear-down the pot so that it takes more rotation of the wheel to turn the pot.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •