Skip to content

Commit 010d56c

Browse files
committed
map potentiometer resistance to output range
Add independent mappings for each potentiometer so they can be calibrated based on measured resistances at the limits of the physical range of movement.
1 parent 727daa9 commit 010d56c

File tree

6 files changed

+416
-54
lines changed

6 files changed

+416
-54
lines changed

examples/phoenix-arduino-test/phoenix-arduino-test.ino

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* https://playground.arduino.cc/Code/ShiftRegSN74HC165N
2020
*/
2121
#include "hc165.h"
22+
#include "Potentiometer.h"
2223

2324
/* Optional delay between shift register reads.
2425
*/
@@ -52,55 +53,46 @@ hc165_collection_t hc165_collection = {
5253
.size = numButtonGroups,
5354
};
5455

56+
const size_t numAxes = 4;
57+
58+
const Potentiometer axesPotentiometers[numAxes] = {
59+
{Potentiometer::Parameters{
60+
.name = "X",
61+
.analogInputPin = A0,
62+
.referenceResistance = 100,
63+
.resistanceRange = {.min = 0, .max = 87},
64+
.outputRange = {.min = 0, .max = 127},
65+
}},
66+
{Potentiometer::Parameters{
67+
.name = "Y",
68+
.analogInputPin = A1,
69+
.referenceResistance = 100,
70+
.resistanceRange = {.min = 0, .max = 85},
71+
.outputRange = {.min = 0, .max = 127},
72+
}},
73+
{Potentiometer::Parameters{
74+
.name = "R",
75+
.analogInputPin = A4,
76+
.referenceResistance = 100,
77+
.resistanceRange = {.min = 0, .max = 94},
78+
.outputRange = {.min = 0, .max = 127},
79+
}},
80+
{Potentiometer::Parameters{
81+
.name = "T",
82+
.analogInputPin = A5,
83+
.referenceResistance = 100,
84+
.resistanceRange = {.min = 0, .max = 92},
85+
.outputRange = {.min = 0, .max = 127},
86+
}},
87+
};
88+
5589
void setup()
5690
{
5791
Serial.begin(9600);
5892

5993
hc165_collection_setup(hc165_collection);
6094
hc165_collection_read(hc165_collection);
6195
hc165_collection_print(hc165_collection);
62-
63-
analogReference(DEFAULT);
64-
pinMode(A0, INPUT);
65-
pinMode(A1, INPUT);
66-
pinMode(A4, INPUT);
67-
pinMode(A5, INPUT);
68-
}
69-
70-
/*
71-
* Attempting to read the voltage across only a potentiometer will always
72-
* return 1023. The voltage difference is 5V because there is nothing else in
73-
* the circuit. To measure the resistance, we use a reference resistor in
74-
* series with the potentiometer:
75-
*
76-
* 5V --v^v^v-- V1 --v^v^v-- GROUND
77-
* Rpot Rref
78-
*
79-
* To solve for Rpot, use Ohm's law and the fact that 2 resistors in series
80-
* must have the same current:
81-
*
82-
* (Vsupply - V1) / Rpot = (V1 - 0V) / Rref
83-
* (Vsupply - V1) * Rref = V1 * Rpot
84-
* (Vsupply / V1 - 1) * Rref = Rpot
85-
* Vsupply * Rref / V1 - Rref = Rpot
86-
*
87-
* The ADC maps 5V (assumed to be both the ADC reference voltage and the supply
88-
* voltage) to a value 0 - 1023 (kAdcOutputMax). Since only the ratio of
89-
* Vsupply and V1 is important, we can treat both as ADC outputs instead of
90-
* converting from ADC to voltage on both sides.
91-
*
92-
* See http://www.built-to-spec.com/blog/2009/09/10/using-a-pc-joystick-with-the-arduino/
93-
*/
94-
const long kDivResistanceKOhm = 100;
95-
const long kAdcOutputMax = 1023;
96-
97-
uint8_t get_potentiometer_resistance(int adc_in)
98-
{
99-
if(adc_in > 0) {
100-
return uint8_t((kAdcOutputMax * kDivResistanceKOhm) / adc_in - kDivResistanceKOhm);
101-
} else {
102-
return 0;
103-
}
10496
}
10597

10698
void loop()
@@ -119,17 +111,13 @@ void loop()
119111
}
120112

121113
if(!isButtonPressed) {
122-
Serial.print("Axes: x:");
123-
Serial.print(get_potentiometer_resistance(analogRead(A0)));
124-
Serial.print(" y:");
125-
Serial.print(get_potentiometer_resistance(analogRead(A1)));
126-
Serial.print(" r:");
127-
Serial.print(get_potentiometer_resistance(analogRead(A4)));
128-
Serial.print(" t:");
129-
Serial.print(get_potentiometer_resistance(analogRead(A5)));
130-
Serial.print("\r\n");
114+
Serial.print("axes:");
115+
for(const Potentiometer& axesPotentiometer : axesPotentiometers) {
116+
Serial.print(' ');
117+
Serial.print(axesPotentiometer);
118+
}
119+
Serial.println();
131120
}
132121

133122
delay(POLL_DELAY_MSEC);
134-
}
135-
123+
}

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ paragraph=Replaces the main logic board in the Gravis Phoenix with an Arduino.
77
category=Other
88
url=https://github.com/BinaryMan32/phoenix-arduino
99
architectures=avr
10-
includes=hc165.h
10+
includes=hc165.h,Potentiometer.h,Fraction.h

src/Fraction.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include <Print.h>
2+
3+
#include "Fraction.h"
4+
5+
long gcf(long a, long b)
6+
{
7+
return (b == 0) ? a : gcf(b, a % b);
8+
}
9+
10+
long simplifyFraction(long& numerator, long& denominator)
11+
{
12+
long factor = gcf(numerator, denominator);
13+
if(factor > 1) {
14+
numerator /= factor;
15+
denominator /= factor;
16+
}
17+
return factor;
18+
}
19+
20+
Fraction::Fraction(long numerator, long denominator)
21+
: mNumerator{numerator}, mDenominator{denominator}
22+
{
23+
simplifyFraction(mNumerator, mDenominator);
24+
if(mDenominator < 0) {
25+
mNumerator = -mNumerator;
26+
mDenominator = -mDenominator;
27+
}
28+
}
29+
30+
Fraction Fraction::getInverse() const
31+
{
32+
return Fraction{mDenominator, mNumerator, AlreadySimplifiedTag{}};
33+
}
34+
35+
long Fraction::getResultRounded() const
36+
{
37+
return (mNumerator + mDenominator / 2) / mDenominator;
38+
}
39+
40+
size_t Fraction::printTo(Print& p) const
41+
{
42+
return p.print('(') + p.print(mNumerator) + p.print('/')
43+
+ p.print(mDenominator) + p.print(")~=") + p.print(getResultRounded());
44+
}
45+
46+
Fraction Fraction::operator-() const
47+
{
48+
return Fraction{-mNumerator, mDenominator, AlreadySimplifiedTag{}};
49+
}
50+
51+
Fraction::Fraction(long numerator, long denominator, AlreadySimplifiedTag)
52+
: mNumerator{numerator}, mDenominator{denominator}
53+
{
54+
}
55+
56+
Fraction operator + (long factor, const Fraction& fraction)
57+
{
58+
return Fraction{factor * fraction.mDenominator + fraction.mNumerator,
59+
fraction.mDenominator};
60+
}
61+
62+
Fraction operator + (const Fraction& fraction, long factor)
63+
{
64+
return factor + fraction;
65+
}
66+
67+
Fraction operator + (const Fraction& a, const Fraction& b)
68+
{
69+
const long factor = gcf(a.mDenominator, b.mDenominator);
70+
return Fraction{a.mNumerator * (b.mDenominator / factor) +
71+
b.mNumerator * (a.mDenominator / factor),
72+
(a.mDenominator / factor) * b.mDenominator};
73+
}
74+
75+
Fraction operator - (long factor, const Fraction& fraction)
76+
{
77+
return (-factor) + fraction;
78+
}
79+
80+
Fraction operator - (const Fraction& fraction, long factor)
81+
{
82+
return (-factor) + fraction;
83+
}
84+
85+
Fraction operator - (const Fraction& a, const Fraction& b)
86+
{
87+
return a + (-b);
88+
}
89+
90+
Fraction operator * (long factor, const Fraction& fraction)
91+
{
92+
return Fraction(factor * fraction.mNumerator, fraction.mDenominator);
93+
}
94+
95+
Fraction operator * (const Fraction& fraction, long factor)
96+
{
97+
return factor * fraction;
98+
}
99+
100+
Fraction operator * (const Fraction& a, const Fraction& b)
101+
{
102+
Fraction(a.mNumerator * b.mNumerator, a.mDenominator * b.mDenominator);
103+
}
104+
105+
Fraction operator / (long factor, const Fraction& fraction)
106+
{
107+
return factor * fraction.getInverse();
108+
}
109+
110+
Fraction operator / (const Fraction& fraction, long factor)
111+
{
112+
return fraction * Fraction{1, factor, Fraction::AlreadySimplifiedTag{}};
113+
}
114+
115+
Fraction operator / (const Fraction& a, const Fraction& b)
116+
{
117+
return a * b.getInverse();
118+
}

src/Fraction.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#ifndef PHOENIX_ARDUINO_FRACTION_H
2+
#define PHOENIX_ARDUINO_FRACTION_H
3+
4+
#include <Printable.h>
5+
6+
/*
7+
* Euclid's algorithm to find GCF (Greatest Common Factor) of a and b.
8+
* Note that gcf(0, X) == gcf(X, 0) == X.
9+
*/
10+
long gcf(long a, long b);
11+
12+
/*
13+
* Simplify a fraction by dividing the numerator and denominator by the GCF
14+
* (Greatest Common Factor). Return the GCF.
15+
*/
16+
long simplifyFraction(long& numerator, long& denominator);
17+
18+
class Fraction : public Printable
19+
{
20+
public:
21+
/**
22+
* Create from numerator and denominator
23+
*/
24+
Fraction(long numerator, long denominator);
25+
26+
/**
27+
* Returns a new Fraction (denominator / numerator).
28+
*/
29+
Fraction getInverse() const;
30+
31+
/**
32+
* Get result of (numerator / denomonator as a rounded whole number
33+
*/
34+
long getResultRounded() const;
35+
36+
/**
37+
* Enables printing the Fraction via Serial.print(Fraction{1, 2})
38+
*/
39+
size_t printTo(Print& p) const override;
40+
41+
/** Unary negation */
42+
Fraction operator-() const;
43+
44+
protected:
45+
/**
46+
* Tag used internally to construct an already simplified fraction.
47+
*/
48+
struct AlreadySimplifiedTag {};
49+
50+
/**
51+
* Construct a Fraction which is already simplified.
52+
*/
53+
Fraction(long numerator, long denominator, AlreadySimplifiedTag);
54+
55+
long mNumerator;
56+
long mDenominator;
57+
58+
friend Fraction operator + (long factor, const Fraction& fraction);
59+
friend Fraction operator + (const Fraction& fraction, long factor);
60+
friend Fraction operator + (const Fraction& a, const Fraction& b);
61+
62+
friend Fraction operator - (long factor, const Fraction& fraction);
63+
friend Fraction operator - (const Fraction& fraction, long factor);
64+
friend Fraction operator - (const Fraction& a, const Fraction& b);
65+
66+
friend Fraction operator * (long factor, const Fraction& fraction);
67+
friend Fraction operator * (const Fraction& fraction, long factor);
68+
friend Fraction operator * (const Fraction& a, const Fraction& b);
69+
70+
friend Fraction operator / (long factor, const Fraction& fraction);
71+
friend Fraction operator / (const Fraction& fraction, long factor);
72+
friend Fraction operator / (const Fraction& a, const Fraction& b);
73+
};
74+
75+
Fraction operator + (long factor, const Fraction& fraction);
76+
Fraction operator + (const Fraction& fraction, long factor);
77+
Fraction operator + (const Fraction& a, const Fraction& b);
78+
79+
Fraction operator - (long factor, const Fraction& fraction);
80+
Fraction operator - (const Fraction& fraction, long factor);
81+
Fraction operator - (const Fraction& a, const Fraction& b);
82+
83+
Fraction operator * (long factor, const Fraction& fraction);
84+
Fraction operator * (const Fraction& fraction, long factor);
85+
Fraction operator * (const Fraction& a, const Fraction& b);
86+
87+
Fraction operator / (long factor, const Fraction& fraction);
88+
Fraction operator / (const Fraction& fraction, long factor);
89+
Fraction operator / (const Fraction& a, const Fraction& b);
90+
91+
#endif /* PHOENIX_ARDUINO_FRACTION_H */

0 commit comments

Comments
 (0)