Thursday, December 28, 2023

0000 0000 1101 1011

Mailbag #36

Well after the shocking reviews for my last two videos I've decided to do the old favourite - a mailbag!

Algorithm alone knows these are so popular, but as I'm behind on opening up my late night purchases I'd better get to it!

The only extra bit is the code I had to write for the two joystick Arduino module - I couldn't find anything online and so I cobbled together the following - which works fine.

/*
 *  Found this twin joystick module online here:
 *  https://www.aliexpress.com/item/1005001882246352.html
 *  
 *  ..but with no code I had to find out the pins for
 *  input and output, then made the code below to demonstrate
 *  the use of the module - enjoy!
 *  
 *  Exponential function provided by BARD
 *  https://bard.google.com/
 *  
 *  OneCircuit - https://www.youtube.com/@onecircuit-as
 *  Tue 26 Dec 2023 16:28:52 AEDT
 */
 
#define LjoyXaxis_pin A0
#define LjoyYaxis_pin A1
#define RjoyXaxis_pin A3
#define RjoyYaxis_pin A2
#define LSW_pin 2
#define RSW_pin 4
#define LLEDPin 9
#define RLEDPin 10

int LYLED = 0;
int RYLED = 0;
boolean LButton = 0;
boolean RButton = 0;

int exponentialMap(int S) {
  float base = 3.0;
  float normalizedS = S / 1023.0;
  float L = pow(normalizedS, base) * 255.0;
  return constrain(L, 0, 255);
}

void setup() {

  pinMode(LjoyXaxis_pin, INPUT);
  pinMode(LjoyYaxis_pin, INPUT);
  pinMode(RjoyXaxis_pin, INPUT);
  pinMode(RjoyYaxis_pin, INPUT);
  pinMode(LSW_pin, INPUT);
  pinMode(RSW_pin, INPUT);
  pinMode(LLEDPin, OUTPUT);
  pinMode(RLEDPin, OUTPUT);
  digitalWrite(LSW_pin, HIGH);
  digitalWrite(RSW_pin, HIGH);
  Serial.begin(115200);

}

void loop() {

  // Left joystick routines 
Serial.print("LX-axis:"); Serial.print(analogRead(LjoyXaxis_pin)); Serial.print(":"); LButton = 1 - digitalRead(LSW_pin); LYLED = 1023 - analogRead(LjoyYaxis_pin); Serial.print("LY-axis:"); Serial.print(LYLED); Serial.print(":"); if (LButton == 0) { // LYLED = map(LYLED, 0, 1023, 0, 255); // linear map // LYLED = pow(1.0054,LYLED); // exponential map LYLED = exponentialMap(LYLED); analogWrite(LLEDPin, LYLED); } else { analogWrite(LLEDPin, 0); } Serial.print("LSW:"); Serial.print(LButton);
  // Right joystick routines 
  Serial.print(" RX-axis:");
  Serial.print(analogRead(RjoyXaxis_pin));
  Serial.print(":");
  RButton = 1 - digitalRead(RSW_pin);
  RYLED = 1023 - analogRead(RjoyYaxis_pin);
  Serial.print("RY-axis:");
  Serial.print(RYLED);
  Serial.print(":");
  if (RButton == 0) {
    // RYLED = map(RYLED, 0, 1023, 0, 255); // linear map
    // RYLED = pow(1.0054,RYLED); // exponential map
    RYLED = exponentialMap(RYLED);
    analogWrite(RLEDPin, RYLED);
  }
  else
  {
    analogWrite(RLEDPin, 0);
  }
  Serial.print("RSW:");
  Serial.println(RButton);
  
  delay(100);
}

Thank you to BARD for the exponential mapping function - increase "float base = 3.0;" for a flatter curve.

User:
Can you suggest an Arduino function that maps 
numbers 0-1023 (S: from a joystick source)
to 0-255 (L: for an LED output), but instead of
mapping linearly it maps exponentially so that
values of S such as 300 map quite low to, for
instance, to an L value of 5, and a value of
L=600 maps to, for instance, S=25?

Bard:
Here's an Arduino function that maps
numbers 0-1023 to 0-255 exponentially,
as you described:

Arduino
int exponentialMap(int S) {
  // Adjust this base value to fine-tune the curve
  float base = 2.0;

  // Normalize S to a range of 0.0 to 1.0
  float normalizedS = S / 1023.0;

  // Apply exponential curve using pow() function
  float L = pow(normalizedS, base) * 255.0;

  // Clamp L to 0-255 range to ensure valid output
  return constrain(L, 0, 255);
}
Use code with caution. Learn more

Explanation:

Normalization: The normalizedS calculation ensures 
the input value S is within a 0.0 to 1.0 range, 
making it suitable for exponential calculations.

Exponential Mapping: The pow(normalizedS, base) 
expression applies the exponential curve. The base 
variable controls the steepness of the curve:

Higher base values result in a more pronounced 
exponential response.

Lower base values lead to a more gradual curve.

Scaling: The result of pow() is multiplied 
by 255.0 to scale it back to the 0-255 range 
for LED output.

Clamping: The constrain(L, 0, 255) function 
ensures the final output value L stays within 
the valid 0-255 range, even if the calculation 
produces a value outside this range.

Usage:

Arduino
int S = analogRead(joystickPin);  // Read joystick value
int L = exponentialMap(S);         // Apply exponential mapping
analogWrite(ledPin, L);            // Set LED brightness
Use code with caution. Learn more
Customization:

Experiment with different base values to achieve 
the desired mapping curve.

Consider adjusting the normalization and scaling 
factors if your input or output ranges differ.

User:
Works beautifully - well done! 👏👏👏

Bard:
I'm glad it works well for you! Thank you for 
the appreciation, it makes helping fun! If you 
have any other questions or challenges related 
to Arduino or code, feel free to ask. I'm always 
happy to assist.

And here is the video - enjoy!





No comments:

Post a Comment