Hallo,
es geht darum einen Handgriff zu bauen. Er soll nicht ganz rumdrehen, also ca. 350°. Werte von 0 bis 1023, wird via Arduino Micro als Joystick verwendet.
Für Poti oder Drehencoder finde ich keine Möglichkeit.
Man könnte ja 2 digitale Hall-Sensoren mit vielen Magneten im Griff wie einen Drehencoder benutzen, aber dann ist mir die Auflösung zu gering.
Meine letzte Idee sind 2 lineare Hall-Sensoren zu benutzen, aber da reichen meine Programmierkenntnisse nicht.
Gibt es vielleicht schon ein fertiges Projekt, oder ein Schubbs in die richtige Richtung?
Ich habe mal einen Test mit 2 digitalen Hall-Sensoren (A3144) und 6 Magneten gemacht (alle der Reihe nach mit wechselnder Polarität).
Damit kann ich 0 bis 12 Schritte auswerten.
Aber wie gesagt, benötige ich eine höhere Auflösung, deshalb meine idee mit den linearen Hall-Sensoren (49E).
Interessant. Ich komme jedoch leider nicht an den Mittelpunkt heran, weshalb sich Poti und RE ausschließen. Ich benötige etwas was mit mehreren Magneten funktioniert.
Ich habe mir eine Konstruktion ausgedacht mit 52 kleinen Magneten (1mm Durchmesser x 1mm Länge). Macht 104 Schritte hochgerechnet und auf 1023 begrenzt.
Das reicht vermutlich dicke, da brauche ich keine echten 1023 Schritte
Funktioniert tadellos, WENN man langsam dreht. Dreht man zu schnell, gibt es Schrittverluste. Mal sehen, ob Interrupts das Problem verbessern, derzeit arbeite ich ohne. Ich galube aber eher, dass die Magnete zu schwach sind.
#include <Encoder.h>
#include <Joystick.h>
bool report = true;
//bool report = false;
float maxenccount = 150; // max 154
/* Joystick */
uint8_t hidReportId = 0x03; // - Default: 0x03 - Indicates the joystick's HID report ID. This value must be unique if you are creating multiple instances of Joystick. Do not use 0x01 or 0x02 as they are used by the built-in Arduino Keyboard and Mouse libraries.
uint8_t joystickType = JOYSTICK_TYPE_JOYSTICK; // - Default: JOYSTICK_TYPE_JOYSTICK or 0x04 - Indicates the HID input device type. Supported values:
uint8_t buttonCount = 10; //- Default: 32 - Indicates how many buttons will be available on the joystick.
uint8_t hatSwitchCount = 0; // - Default: 2 - Indicates how many hat switches will be available on the joystick. Range: 0 - 2
bool includeXAxis = 0; // - Default: true - Indicates if the X Axis is available on the joystick.
bool includeYAxis = 0; // - Default: true - Indicates if the Y Axis is available on the joystick.
bool includeZAxis = 0; // - Default: true - Indicates if the Z Axis (in some situations this is the right X Axis) is available on the joystick.
bool includeRxAxis = 1; // - Default: true - Indicates if the X Axis Rotation (in some situations this is the right Y Axis) is available on the joystick.
bool includeRyAxis = 1; // - Default: true - Indicates if the Y Axis Rotation is available on the joystick.
bool includeRzAxis = 0; // - Default: true - Indicates if the Z Axis Rotation is available on the joystick.
bool includeRudder = 0; // - Default: true - Indicates if the Rudder is available on the joystick.
bool includeThrottle = 0; // - Default: true - Indicates if the Throttle is available on the joystick.
bool includeAccelerator = 0; // - Default: true - Indicates if the Accelerator is available on the joystick.
bool includeBrake = 0; // - Default: true - Indicates if the Brake is available on the joystick.
bool includeSteering = 0; // - Default: true - Indicates if the Steering is available on the joystick.
/* Gyro */
float smooth = 50;
float sPitch=0, j=10;
float smoothPin = A2;
#include <Wire.h>
#include <Adafruit_MCP23X17.h>
#include<ADXL345_WE.h> // https://wolles-elektronikkiste.de/adxl345-teil-1
#define ADXL345_I2CADDR 0x53
ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR);
Adafruit_MCP23X17 mcp1;
Joystick_ Joystick(hidReportId, joystickType, buttonCount, hatSwitchCount, includeXAxis, includeYAxis, includeZAxis, includeRxAxis, includeRyAxis, includeRzAxis, includeRudder, includeThrottle, includeAccelerator, includeBrake, includeSteering);
bool reportpitch = false;
float throttle = 0;
int HSTPinA = 5;
int HSTPinB = 6;
Encoder myEnc(HSTPinA, HSTPinB); // RotaryEncoder 154 Steps
void setup() {
pinMode(HSTPinA,INPUT_PULLUP);
pinMode(HSTPinB,INPUT_PULLUP);
pinMode(smoothPin,INPUT);
Wire.begin();
while(!myAcc.init()){
Serial.println("ADXL345 not connected!");
delay(1000);
}
if (report) Serial.println("ADXL345 connected...");
myAcc.setCorrFactors(-266.0, 285.0, -268.0, 278.0, -291.0, 214.0);
myAcc.setDataRate(ADXL345_DATA_RATE_50); // 50 Hz
myAcc.setRange(ADXL345_RANGE_2G); // 2g
if (!mcp1.begin_I2C()) {
Serial.println("MCP23017 not connected!");
while (1);
} else
if (report) Serial.println("MCP23017 connected");
mcp1.begin_I2C(0x20); // Init MCP23017 at address 0x20
Joystick.begin();
Joystick.setRxAxisRange(0, 1023);
Joystick.setRyAxisRange(0, 1023);
Joystick.sendState();
for (int i=0; i<10; i++) { // 10 Button & Switches
mcp1.pinMode(i, INPUT_PULLUP);
}
if (report) Serial.println("los gehts...");
}
int lastButtonState[10] = {0,0,0,0,0,0,0,0,0,0};
void checkPitch() {
xyzFloat corrAngles = myAcc.getCorrAngles();
float pitch = ( (myAcc.getRoll()-90) /40 *1023);
if(pitch<0) pitch=0;
if(pitch>1023) pitch=1023;
Filtern(sPitch,pitch,smooth);
Joystick.setRxAxis(sPitch);
if (reportpitch) {
Serial.print("Pitch:");
Serial.print(pitch);
Serial.print(", ");
Serial.print("sPitch:");
Serial.print(sPitch);
Serial.print(", ");
reportpitch = false;
}
}
void loop() {
for (int i=0;i<10;i++) {
bool currentButtonState = !mcp1.digitalRead(i);
if (currentButtonState != lastButtonState[i]) {
Joystick.setButton(i, currentButtonState);
lastButtonState[i] = currentButtonState;
}
if ( myEnc.read() < 0 ) myEnc.write(0);
if ( myEnc.read() > maxenccount ) myEnc.write(maxenccount);
throttle = myEnc.read();
Joystick.setRyAxis(throttle/maxenccount*1023);
if (report) {
if ( i == 9 )
reportpitch = true;
Serial.print("Btn");
Serial.print(i);
Serial.print(":");
Serial.print(currentButtonState);
Serial.print(", ");
}
checkPitch();
}
if (report) {
Serial.print("Thr:");
Serial.print(throttle/maxenccount*1023);
Serial.println();
}
}
Was ist dagegen einzuwenden? An A2 kommt ein Poti.
Warum? Doch nur, wenn er sich zwischenzeitlich ändert. Warum sollte er das? Es geht hier lediglich um die selbstkalibrierende Eingrenzung.
Da ja Schritte verloren werden, kommt man so durch drehen von min bis max und wieder zurück in sein nutzbares Fenster.
Was wird da? Du dividierst throttle/maxenccount Nicht mehr und nicht weniger. Erkläre mir, warum maxenccount float sein muss.
Davom abgesehen, das myEnc.read() bestimmt keinen float liefert und somit throttle eben auch nur ein (unsigned) int ist.
.setRyAxis erwartet einen int32_t
Nachzulesen in der joystick.cpp
Ich sehe also nirgendwo irgendwas mit float.
Das ist egal, was da ran kommt. A2 ist die PIN-Nummer. Im Arduino-Pinout wird aus A2 eine Ganzzahl.
Das kannst Du ausprobieren, indem Du einfach folgenden Sketch auf den arduino spielst und Dir die ausgabe auf dem SerMon anschaust:
Im Übrigen solltest Du die Zeit messen, die drei read() benötigen.
Dem gegenüber kannst Du dann den dreifachen Vergleich mit einmalig eingelesenen Variable anstellen.
Und egal wie Du es drehst. Du wirst nicht umhin kommen Deinen Code effizienter zu machen. Da gehört sowas wichtiges wie das begrenzen der Variablen auf die möglich geringste Verarbeitungsbreite der CPU dazu.