Crazy Potentiometer behaviour

Hey Guys,

it’s me again with a new issue. I have a crazy potentiometer problem. I want to read in the analog values of it and calculate it to a factor. Works fine with this example code:

/* Analog Read to LED
 * ------------------ 
 * turns on and off a light emitting diode(LED) connected to digital  
 * pin 13. The amount of time the LED will be on and off depends on
 * the value obtained by analogRead(). In the easiest case we connect
 * a potentiometer to analog pin 2.
 * Created 1 December 2005
 * copyleft 2005 DojoDave <>

int potPin = 3;    // select the input pin for the potentiometer
int ledPin = 13;   // select the pin for the LED
int val = 0;       // variable to store the value coming from the sensor

void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT

void loop() {
 float ausgelesen = analogRead(potPin);
 double faktor = ((ausgelesen / 1023) + 0.5);
 //Serial.println(faktor);    //Ausgabe

now, I want to implement exactly this code in my main code. But if i try this, i can only use 1/3 of the full potentiometer and it shows me 1023. So the other 2/3 of the potentiometer turn, is also 1023.
So there is only 1/3 “active” potentiometer… Why!!!

bytheway: Hardware didn’t changed!

Crazy Code-snippet:

potentiometerWert = analogRead(POTI_PIN);
            potentiometerFaktor = (potentiometerWert / 1023) + 0.5;  //Potentiometer Wert in den Faktor umwandeln
            Serial.print("\t\t\Faktor: ");

Full implemented code:

void loop() {
    if (!dmpReady) return;    // if programming failed, don't try to do anything
    // wait for MPU interrupt or extra packet(s) available
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    // get current FIFO count
    fifoCount = mpu.getFIFOCount();
    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        Serial.println(F("FIFO overflow!"));
    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize); 
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            buttonState = digitalRead(BUTTON_PIN);          //Knopf Zustand abfragen
                if(buttonState == HIGH)                     //Wenn Knopf gedrückt ist
                  kalibrierwertKompass = (ypr[0]*rad2deg);                    //aktueller Compass-Wert wird in c_cal gespeichert
                  kalibrierwertNeigung = (ypr[2]*rad2deg);                    //aktueller Neigung-Wert wird in n_cal gespeichert
                  Serial.println("Knopf gedrueckt!");
            kompasswertNeu = (ypr[0]*180/M_PI);
            if((ypr[0]*rad2deg)-kalibrierwertKompass <= -180)
              kompasswertNeu = (ypr[0]*rad2deg) + 360;
            else if((ypr[0]*rad2deg)-kalibrierwertKompass >= 180)
              kompasswertNeu = (ypr[0]*rad2deg) - 360;
            potentiometerWert = analogRead(POTI_PIN);
            potentiometerFaktor = (potentiometerWert / 1023) + 0.5;  //Potentiometer Wert in den Faktor umwandeln
            Serial.print("\t\t\Faktor: ");
            uebertragenderWertKompass = (int)((kompasswertNeu * potentiometerFaktor) + 2001 - kalibrierwertKompass);  //Berechnung vom zu übertragenden Kompasswert. 2001: ID und Korrekturfaktor; -c_cal: Kalibrierungswert
            dtostrf(uebertragenderWertKompass, 5, 1, msg);           //konvertiert val_1 in eine ASCII Zeichenkette (char)
            //Serial.print("Kompass: ");
            //Serial.print(msg);                                //Testausgabe der versendeten Data
            vw_send((uint8_t *)msg, strlen(msg));               //Data wird versendet
            if(vx_tx_active() == true)
              blinkState = !blinkState;                         //blinks
              digitalWrite(LED_PIN, blinkState);
            vw_wait_tx();                                       //Es wird solange gewartet bis Data versendet wurde
            uebertragenderWertNeigung = (int)((ypr[2] * rad2deg * potentiometerFaktor) + 3001 - kalibrierwertNeigung);
            dtostrf(uebertragenderWertNeigung, 5, 1, msg);
            //Serial.print("Neigung: ");
           // Serial.println(msg);
            vw_send((uint8_t *)msg, strlen(msg));
            if(vx_tx_active() == true)
              blinkState = !blinkState;                         //blinks
              digitalWrite(LED_PIN, blinkState);

I thought, that maybe the “analogRead()”-Function is mentioned in Virtualwire/i2c. So I had a look on the headers, but there isn’t such a function.

Any ideas??

Make sure you have a linear pot and not an audio pot which has a logarithmic scale, in the center position it should read 1/2 the total value if it is linear.

Also, make sure the AREF is the same and the voltage on the end terminals of the pot is the same on both setups.

might help to show the full code, not just the loop

#include "I2Cdev.h"
#include <VirtualWire.h>
#include "MPU6050_6Axis_MotionApps20.h"
    #include "Wire.h"
MPU6050 mpu;
#define LED_PIN 13      // (Arduino is 13, Teensy is 11, Teensy++ is 6)
#define BUTTON_PIN 3    // Taster Pin
#define POTI_PIN 3      // Potentio-Meter Pin
#define SENDE_PIN 4     // Sende-Modul Pin
#define rad2deg 57.29577951308  // fester Umrechnungswert von Bogenmaß in Radian
bool blinkState = false;// Blinkstatus der Status-LED

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

char msg[24];           // Chararray zum Versenden der Sensordaten
int buttonState;        // Knopfzustand
int kalibrierwertKompass, kalibrierwertNeigung;       // Kalibrier-Korrektur
int kompasswertNeu;              // neuer Wert
int uebertragenderWertKompass;   // fertiger Kompasswert, welcher übermittelt wird
int uebertragenderWertNeigung;   // fertiger Neigungswert, welcher übermittelt wird
float potentiometerWert;         // reinner PotentiometerWert
double potentiometerFaktor = 1;       // einzuberechnenden Geschwindigkeitsfaktor

uint8_t teapotPacket[14] = { '

@outsider: I use the same hardware like the working code, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, ‘\r’, ‘\n’ };// packet structure for InvenSense teapot demo
// ================================================================
// ===              INTERRUPT DETECTION ROUTINE                ===
// ================================================================
volatile bool mpuInterrupt = false;    // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
// ================================================================
// ===                      INITIAL SETUP                      ===
// ================================================================
void setup() {
    // join I2C bus (I2Cdev library doesn’t do this automatically)
        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
        Fastwire::setup(400, true);
    Serial.begin(115200);                                // Geschwindigkeit UART-Kommunikation zu PC
    vw_set_tx_pin(SENDE_PIN);                            // Sende-Modul liegt auf Pin 4
    vw_setup(5500);                                      // Übertragungsgeschwindigkeit 433 MHz
    pinMode(BUTTON_PIN, INPUT);                          // Pin 3 als Input definieren
    devStatus = mpu.dmpInitialize();
    // supply your own gyro offsets here, scaled for min sensitivity
    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        attachInterrupt(0, dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();
        dmpReady = true;
        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
    pinMode(LED_PIN, OUTPUT);
    kalibrierwertKompass = 0;                                // Compass-Kalibrierwert auf 0 setzen
    kalibrierwertNeigung = 0;                                // Neigung-Kalibrierwert auf 0 setzen

@outsider: I use the same hardware like the working code

Might have something to do with the fact that in your successful test case, you didn't use the internal analog reference, but in the crazy code, you do.


Thank you very much! That was the reason. Now it works fine.

When do I use this reference?

You're welcome.

The internal reference is approximately 1.1 volts, so with the 10-bit ADC you get a resolution of about 1 mV per bit (whereas with the "default" 5v reference, it's 5 mV per bit). Generally, use it if you have a small signal (less than 1.1 v) to convert and want better resolution.

Also, the internal reference is quite stable.